From 8243013779ec3f27f4a68b414fda004f82014141 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Mon, 3 Apr 2023 17:25:58 -0500 Subject: [PATCH 01/48] WIP: making numba optional --- .github/workflows/test_and_build.yml | 51 +++++- graphblas/binary/numpy.py | 13 +- graphblas/core/__init__.py | 9 + graphblas/core/matrix.py | 21 ++- graphblas/core/operator/agg.py | 6 +- graphblas/core/operator/base.py | 165 +++++++++---------- graphblas/core/operator/binary.py | 85 +++++++--- graphblas/core/operator/indexunary.py | 19 +-- graphblas/core/operator/select.py | 2 + graphblas/core/operator/semiring.py | 18 +- graphblas/core/operator/unary.py | 16 +- graphblas/core/scalar.py | 19 ++- graphblas/core/ss/matrix.py | 49 +++--- graphblas/core/ss/vector.py | 3 +- graphblas/core/vector.py | 53 +++++- graphblas/dtypes.py | 130 ++++++++++++--- graphblas/io.py | 2 +- graphblas/monoid/numpy.py | 15 +- graphblas/op/numpy.py | 6 +- graphblas/semiring/numpy.py | 13 +- graphblas/tests/test_io.py | 1 + graphblas/tests/test_matrix.py | 104 +++++++----- graphblas/tests/test_numpyops.py | 54 ++++-- graphblas/tests/test_op.py | 220 ++++++++++++++++--------- graphblas/tests/test_operator_types.py | 6 + graphblas/tests/test_pickle.py | 6 + graphblas/tests/test_scalar.py | 18 +- graphblas/tests/test_vector.py | 33 ++-- graphblas/unary/numpy.py | 10 +- pyproject.toml | 6 + scripts/check_versions.sh | 2 +- 31 files changed, 782 insertions(+), 373 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 04ffd3eb5..04e3216bc 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -81,7 +81,7 @@ jobs: shell: bash -l {0} strategy: # To "stress test" in CI, set `fail-fast` to `false` and perhaps add more items to `matrix.slowtask` - fail-fast: true + fail-fast: false # The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype]. # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. @@ -103,16 +103,20 @@ jobs: with: # We should support major Python versions for at least 36-42 months # We could probably support pypy if numba were optional - # 3.8.16 0_73_pypy - # 3.9.16 0_73_pypy contents: | 3.8 3.9 3.10 + 3.11 + 3.8.16 0_73_pypy + 3.9.16 0_73_pypy weights: | 1 1 1 + 1 + 1 + 1 - name: RNG for source of python-suitesparse-graphblas uses: ddradar/choose-random-action@v2.0.2 id: sourcetype @@ -138,8 +142,8 @@ jobs: miniforge-version: latest use-mamba: true python-version: ${{ steps.pyver.outputs.selected }} - channels: conda-forge,nodefaults - channel-priority: strict + channels: conda-forge,${{ contains(steps.pyver.outputs.selected, 'pypy') && 'defaults' || 'nodefaults' }} + channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }} activate-environment: graphblas auto-activate-base: false - name: Setup conda @@ -150,8 +154,8 @@ jobs: with: auto-update-conda: true python-version: ${{ steps.pyver.outputs.selected }} - channels: conda-forge,nodefaults - channel-priority: strict + channels: conda-forge,${{ contains(steps.pyver.outputs.selected, 'pypy') && 'defaults' || 'nodefaults' }} + channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }} activate-environment: graphblas auto-activate-base: false - name: Update env @@ -213,11 +217,40 @@ jobs: else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))') fi + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') }} == true || $(python -c 'import random ; print(random.random() < .1)') == True ]]; then + # Some packages aren't available for pypy (and 10% chance to not install these otherwise) + numba="" + sparse="" + awkward="" + fmm="" + numbaver=NA + sparsever=NA + akver=NA + fmmver=NA + # XXX: temporarily be more flexible + npver="" + spver="" + pdver="" + akver="" + nxver="" + yamlver="" + sparsever="" + else + numba=numba${numbaver} + sparse=sparse${sparsever} + awkward=awkward${akver} + fmm=fast_matrix_market${fmmver} + if [[ ${{ contains(steps.pyver.outputs.selected, '3.11') }} == true ]]; then + # Numba is not yet available for Python 3.11 + numba="" + numbaver=NA + fi + fi echo "versions: np${npver} sp${spver} pd${pdver} ak${akver} nx${nxver} numba${numbaver} yaml${yamlver} sparse${sparsever} psgver${psgver}" $(command -v mamba || command -v conda) install packaging pytest coverage coveralls=3.3.1 pytest-randomly cffi donfig tomli \ - pyyaml${yamlver} sparse${sparsever} pandas${pdver} scipy${spver} numpy${npver} awkward${akver} \ - networkx${nxver} numba${numbaver} fast_matrix_market${fmmver} ${psg} \ + pyyaml${yamlver} ${sparse} pandas${pdver} scipy${spver} numpy${npver} ${awkward} \ + networkx${nxver} ${numba} ${fmm} ${psg} \ ${{ matrix.slowtask == 'pytest_bizarro' && 'black' || '' }} \ ${{ matrix.slowtask == 'notebooks' && 'matplotlib nbconvert jupyter "ipython>=7"' || '' }} \ ${{ steps.sourcetype.outputs.selected == 'upstream' && 'cython' || '' }} \ diff --git a/graphblas/binary/numpy.py b/graphblas/binary/numpy.py index 68764db05..d84fbb001 100644 --- a/graphblas/binary/numpy.py +++ b/graphblas/binary/numpy.py @@ -10,6 +10,7 @@ from .. import _STANDARD_OPERATOR_NAMES from .. import binary as _binary from .. import config as _config +from ..core import _supports_udfs _delayed = {} _binary_names = { @@ -130,7 +131,13 @@ def __dir__(): - return globals().keys() | _delayed.keys() | _binary_names + if not _supports_udfs and not _config["mapnumpy"]: + # float_power is special: it's constructed from builtin operators + return globals().keys() | {"float_power"} + attrs = _delayed.keys() | _binary_names + if not _supports_udfs: + attrs &= _numpy_to_graphblas.keys() + return attrs | globals().keys() def __getattr__(name): @@ -141,7 +148,7 @@ def __getattr__(name): return rv if name not in _binary_names: raise AttributeError(f"module {__name__!r} has no attribute {name!r}") - if _config.get("mapnumpy") and name in _numpy_to_graphblas: + if _config.get("mapnumpy") and name in _numpy_to_graphblas or name == "float_power": if name == "float_power": from ..core.operator import binary from ..dtypes import FP64 @@ -166,6 +173,8 @@ def __getattr__(name): globals()[name] = new_op else: globals()[name] = getattr(_binary, _numpy_to_graphblas[name]) + elif not _supports_udfs: + raise AttributeError(f"module {__name__!r} unable to compile UDF for {name!r}") else: numpy_func = getattr(_np, name) diff --git a/graphblas/core/__init__.py b/graphblas/core/__init__.py index c079a6e2f..7fd2dc526 100644 --- a/graphblas/core/__init__.py +++ b/graphblas/core/__init__.py @@ -1,3 +1,12 @@ +try: + import numba +except ImportError: + _has_numba = _supports_udfs = False +else: + _has_numba = _supports_udfs = True + del numba + + def __getattr__(name): if name in {"ffi", "lib", "NULL"}: from .. import _autoinit diff --git a/graphblas/core/matrix.py b/graphblas/core/matrix.py index 1935fcee7..ccab2082e 100644 --- a/graphblas/core/matrix.py +++ b/graphblas/core/matrix.py @@ -7,7 +7,7 @@ from .. import backend, binary, monoid, select, semiring from ..dtypes import _INDEX, FP64, INT64, lookup_dtype, unify from ..exceptions import DimensionMismatch, InvalidValue, NoValue, check_status -from . import automethods, ffi, lib, utils +from . import _supports_udfs, automethods, ffi, lib, utils from .base import BaseExpression, BaseType, _check_mask, call from .descriptor import lookup as descriptor_lookup from .expr import _ALL_INDICES, AmbiguousAssignOrExtract, IndexerResolver, Updater @@ -33,7 +33,7 @@ values_to_numpy_buffer, wrapdoc, ) -from .vector import Vector, VectorExpression, VectorIndexExpr, _select_mask +from .vector import Vector, VectorExpression, VectorIndexExpr, _isclose_recipe, _select_mask if backend == "suitesparse": from .ss.matrix import ss @@ -368,6 +368,8 @@ def isclose(self, other, *, rel_tol=1e-7, abs_tol=0.0, check_dtype=False, **opts return False if self._nvals != other._nvals: return False + if not _supports_udfs: + return _isclose_recipe(self, other, rel_tol, abs_tol, **opts) matches = self.ewise_mult(other, binary.isclose(rel_tol, abs_tol)).new( bool, name="M_isclose", **opts @@ -611,14 +613,15 @@ def build(self, rows, columns, values, *, dup_op=None, clear=False, nrows=None, if not dup_op_given: if not self.dtype._is_udt: dup_op = binary.plus - else: + elif backend != "suitesparse": dup_op = binary.any - # SS:SuiteSparse-specific: we could use NULL for dup_op - dup_op = get_typed_op(dup_op, self.dtype, kind="binary") - if dup_op.opclass == "Monoid": - dup_op = dup_op.binaryop - else: - self._expect_op(dup_op, "BinaryOp", within="build", argname="dup_op") + # SS:SuiteSparse-specific: we use NULL for dup_op + if dup_op is not None: + dup_op = get_typed_op(dup_op, self.dtype, kind="binary") + if dup_op.opclass == "Monoid": + dup_op = dup_op.binaryop + else: + self._expect_op(dup_op, "BinaryOp", within="build", argname="dup_op") rows = _CArray(rows) columns = _CArray(columns) diff --git a/graphblas/core/operator/agg.py b/graphblas/core/operator/agg.py index 036149b1f..18d85b51c 100644 --- a/graphblas/core/operator/agg.py +++ b/graphblas/core/operator/agg.py @@ -5,6 +5,7 @@ from ... import agg, backend, binary, monoid, semiring, unary from ...dtypes import INT64, lookup_dtype +from .. import _supports_udfs from ..utils import output_type @@ -341,9 +342,10 @@ def __reduce__(self): # hypot = Aggregator('hypot', monoid=semiring.numpy.hypot) agg.L0norm = agg.count_nonzero -agg.L1norm = Aggregator("L1norm", semiring="plus_absfirst", semiring2=semiring.plus_first) agg.L2norm = agg.hypot -agg.Linfnorm = Aggregator("Linfnorm", semiring="max_absfirst", semiring2=semiring.max_first) +if _supports_udfs: # XXX TODO + agg.L1norm = Aggregator("L1norm", semiring="plus_absfirst", semiring2=semiring.plus_first) + agg.Linfnorm = Aggregator("Linfnorm", semiring="max_absfirst", semiring2=semiring.max_first) # Composite diff --git a/graphblas/core/operator/base.py b/graphblas/core/operator/base.py index 38a76cbcf..394540241 100644 --- a/graphblas/core/operator/base.py +++ b/graphblas/core/operator/base.py @@ -1,16 +1,19 @@ -from functools import lru_cache, reduce -from operator import getitem, mul +from functools import lru_cache +from operator import getitem from types import BuiltinFunctionType, ModuleType -import numba -import numpy as np - from ... import _STANDARD_OPERATOR_NAMES, backend, op from ...dtypes import BOOL, INT8, UINT64, _supports_complex, lookup_dtype -from .. import lib +from .. import _has_numba, _supports_udfs, lib from ..expr import InfixExprBase from ..utils import output_type +if _has_numba: + import numba + from numba import NumbaError +else: + NumbaError = TypeError + UNKNOWN_OPCLASS = "UnknownOpClass" # These now live as e.g. `gb.unary.ss.positioni` @@ -158,96 +161,69 @@ def _call_op(op, left, right=None, thunk=None, **kwargs): ) -_udt_mask_cache = {} - - -def _udt_mask(dtype): - """Create mask to determine which bytes of UDTs to use for equality check.""" - if dtype in _udt_mask_cache: - return _udt_mask_cache[dtype] - if dtype.subdtype is not None: - mask = _udt_mask(dtype.subdtype[0]) - N = reduce(mul, dtype.subdtype[1]) - rv = np.concatenate([mask] * N) - elif dtype.names is not None: - prev_offset = mask = None - masks = [] - for name in dtype.names: - dtype2, offset = dtype.fields[name] - if mask is not None: - masks.append(np.pad(mask, (0, offset - prev_offset - mask.size))) - mask = _udt_mask(dtype2) - prev_offset = offset - masks.append(np.pad(mask, (0, dtype.itemsize - prev_offset - mask.size))) - rv = np.concatenate(masks) - else: - rv = np.ones(dtype.itemsize, dtype=bool) - # assert rv.size == dtype.itemsize - _udt_mask_cache[dtype] = rv - return rv - - -def _get_udt_wrapper(numba_func, return_type, dtype, dtype2=None, *, include_indexes=False): - ztype = INT8 if return_type == BOOL else return_type - xtype = INT8 if dtype == BOOL else dtype - nt = numba.types - wrapper_args = [nt.CPointer(ztype.numba_type), nt.CPointer(xtype.numba_type)] - if include_indexes: - wrapper_args.extend([UINT64.numba_type, UINT64.numba_type]) - if dtype2 is not None: - ytype = INT8 if dtype2 == BOOL else dtype2 - wrapper_args.append(nt.CPointer(ytype.numba_type)) - wrapper_sig = nt.void(*wrapper_args) - - zarray = xarray = yarray = BL = BR = yarg = yname = rcidx = "" - if return_type._is_udt: - if return_type.np_type.subdtype is None: - zarray = " z = numba.carray(z_ptr, 1)\n" - zname = "z[0]" +if _has_numba: + + def _get_udt_wrapper(numba_func, return_type, dtype, dtype2=None, *, include_indexes=False): + ztype = INT8 if return_type == BOOL else return_type + xtype = INT8 if dtype == BOOL else dtype + nt = numba.types + wrapper_args = [nt.CPointer(ztype.numba_type), nt.CPointer(xtype.numba_type)] + if include_indexes: + wrapper_args.extend([UINT64.numba_type, UINT64.numba_type]) + if dtype2 is not None: + ytype = INT8 if dtype2 == BOOL else dtype2 + wrapper_args.append(nt.CPointer(ytype.numba_type)) + wrapper_sig = nt.void(*wrapper_args) + + zarray = xarray = yarray = BL = BR = yarg = yname = rcidx = "" + if return_type._is_udt: + if return_type.np_type.subdtype is None: + zarray = " z = numba.carray(z_ptr, 1)\n" + zname = "z[0]" + else: + zname = "z_ptr[0]" + BR = "[0]" else: zname = "z_ptr[0]" - BR = "[0]" - else: - zname = "z_ptr[0]" - if return_type == BOOL: - BL = "bool(" - BR = ")" - - if dtype._is_udt: - if dtype.np_type.subdtype is None: - xarray = " x = numba.carray(x_ptr, 1)\n" - xname = "x[0]" - else: - xname = "x_ptr" - elif dtype == BOOL: - xname = "bool(x_ptr[0])" - else: - xname = "x_ptr[0]" - - if dtype2 is not None: - yarg = ", y_ptr" - if dtype2._is_udt: - if dtype2.np_type.subdtype is None: - yarray = " y = numba.carray(y_ptr, 1)\n" - yname = ", y[0]" + if return_type == BOOL: + BL = "bool(" + BR = ")" + + if dtype._is_udt: + if dtype.np_type.subdtype is None: + xarray = " x = numba.carray(x_ptr, 1)\n" + xname = "x[0]" else: - yname = ", y_ptr" - elif dtype2 == BOOL: - yname = ", bool(y_ptr[0])" + xname = "x_ptr" + elif dtype == BOOL: + xname = "bool(x_ptr[0])" else: - yname = ", y_ptr[0]" + xname = "x_ptr[0]" + + if dtype2 is not None: + yarg = ", y_ptr" + if dtype2._is_udt: + if dtype2.np_type.subdtype is None: + yarray = " y = numba.carray(y_ptr, 1)\n" + yname = ", y[0]" + else: + yname = ", y_ptr" + elif dtype2 == BOOL: + yname = ", bool(y_ptr[0])" + else: + yname = ", y_ptr[0]" - if include_indexes: - rcidx = ", row, col" + if include_indexes: + rcidx = ", row, col" - d = {"numba": numba, "numba_func": numba_func} - text = ( - f"def wrapper(z_ptr, x_ptr{rcidx}{yarg}):\n" - f"{zarray}{xarray}{yarray}" - f" {zname} = {BL}numba_func({xname}{rcidx}{yname}){BR}\n" - ) - exec(text, d) # pylint: disable=exec-used - return d["wrapper"], wrapper_sig + d = {"numba": numba, "numba_func": numba_func} + text = ( + f"def wrapper(z_ptr, x_ptr{rcidx}{yarg}):\n" + f"{zarray}{xarray}{yarray}" + f" {zname} = {BL}numba_func({xname}{rcidx}{yname}){BR}\n" + ) + exec(text, d) # pylint: disable=exec-used + return d["wrapper"], wrapper_sig class TypedOpBase: @@ -360,6 +336,8 @@ def __getitem__(self, type_): raise KeyError(f"{self.name} does not work with {type_}") else: return self._typed_ops[type_] + if not _supports_udfs: + raise KeyError(f"{self.name} does not work with {type_}") # This is a UDT or is able to operate on UDTs such as `first` any `any` dtype = lookup_dtype(type_) return self._compile_udt(dtype, dtype) @@ -376,7 +354,7 @@ def __delitem__(self, type_): def __contains__(self, type_): try: self[type_] - except (TypeError, KeyError, numba.NumbaError): + except (TypeError, KeyError, NumbaError): return False return True @@ -513,6 +491,11 @@ def _deserialize(cls, name, *args): return rv # Should we verify this is what the user expects? return cls.register_new(name, *args) + @classmethod + def _check_supports_udf(cls, method_name): + if not _supports_udfs: + raise RuntimeError(f"{cls.__name__}.{method_name} requires numba") + _builtin_to_op = {} # Populated in .utils diff --git a/graphblas/core/operator/binary.py b/graphblas/core/operator/binary.py index eeb72ea3b..8d41a097e 100644 --- a/graphblas/core/operator/binary.py +++ b/graphblas/core/operator/binary.py @@ -1,9 +1,9 @@ import inspect import re -from functools import lru_cache +from functools import lru_cache, reduce +from operator import mul from types import FunctionType -import numba import numpy as np from ... import _STANDARD_OPERATOR_NAMES, backend, binary, monoid, op @@ -24,7 +24,7 @@ lookup_dtype, ) from ...exceptions import UdfParseError, check_status_carg -from .. import ffi, lib +from .. import _has_numba, _supports_udfs, ffi, lib from ..expr import InfixExprBase from .base import ( _SS_OPERATORS, @@ -33,16 +33,46 @@ TypedOpBase, _call_op, _deserialize_parameterized, - _get_udt_wrapper, _hasop, - _udt_mask, ) +if _has_numba: + import numba + + from .base import _get_udt_wrapper if _supports_complex: from ...dtypes import FC32, FC64 ffi_new = ffi.new +if _has_numba: + _udt_mask_cache = {} + + def _udt_mask(dtype): + """Create mask to determine which bytes of UDTs to use for equality check.""" + if dtype in _udt_mask_cache: + return _udt_mask_cache[dtype] + if dtype.subdtype is not None: + mask = _udt_mask(dtype.subdtype[0]) + N = reduce(mul, dtype.subdtype[1]) + rv = np.concatenate([mask] * N) + elif dtype.names is not None: + prev_offset = mask = None + masks = [] + for name in dtype.names: + dtype2, offset = dtype.fields[name] + if mask is not None: + masks.append(np.pad(mask, (0, offset - prev_offset - mask.size))) + mask = _udt_mask(dtype2) + prev_offset = offset + masks.append(np.pad(mask, (0, dtype.itemsize - prev_offset - mask.size))) + rv = np.concatenate(masks) + else: + rv = np.ones(dtype.itemsize, dtype=bool) + # assert rv.size == dtype.itemsize + _udt_mask_cache[dtype] = rv + return rv + class TypedBuiltinBinaryOp(TypedOpBase): __slots__ = () @@ -601,6 +631,7 @@ def register_anonymous(cls, func, name=None, *, parameterized=False, is_udt=Fals Because it is not registered in the namespace, the name is optional. """ + cls._check_supports_udf("register_anonymous") if parameterized: return ParameterizedBinaryOp(name, func, anonymous=True, is_udt=is_udt) return cls._build(name, func, anonymous=True, is_udt=is_udt) @@ -621,6 +652,7 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal >>> dir(gb.binary) [..., 'max_zero', ...] """ + cls._check_supports_udf("register_new") module, funcname = cls._remove_nesting(name) if lazy: module._delayed[funcname] = ( @@ -681,21 +713,22 @@ def _initialize(cls): orig_op.gb_name, ) new_op._add(cur_op) - # Add floordiv - # cdiv truncates towards 0, while floordiv truncates towards -inf - BinaryOp.register_new("floordiv", _floordiv, lazy=True) # cast to integer - BinaryOp.register_new("rfloordiv", _rfloordiv, lazy=True) # cast to integer + if _supports_udfs: + # Add floordiv + # cdiv truncates towards 0, while floordiv truncates towards -inf + BinaryOp.register_new("floordiv", _floordiv, lazy=True) # cast to integer + BinaryOp.register_new("rfloordiv", _rfloordiv, lazy=True) # cast to integer - # For aggregators - BinaryOp.register_new("absfirst", _absfirst, lazy=True) - BinaryOp.register_new("abssecond", _abssecond, lazy=True) - BinaryOp.register_new("rpow", _rpow, lazy=True) + # For aggregators + BinaryOp.register_new("absfirst", _absfirst, lazy=True) + BinaryOp.register_new("abssecond", _abssecond, lazy=True) + BinaryOp.register_new("rpow", _rpow, lazy=True) - # For algorithms - binary._delayed["binom"] = (_register_binom, {}) # Lazy with custom creation - op._delayed["binom"] = binary + # For algorithms + binary._delayed["binom"] = (_register_binom, {}) # Lazy with custom creation + op._delayed["binom"] = binary - BinaryOp.register_new("isclose", _isclose, parameterized=True) + BinaryOp.register_new("isclose", _isclose, parameterized=True) # Update type information with sane coercion position_dtypes = [ @@ -777,14 +810,23 @@ def _initialize(cls): if right_name not in binary._delayed: if right_name in _SS_OPERATORS: right = binary._deprecated[right_name] - else: + elif _supports_udfs: right = getattr(binary, right_name) + else: + right = getattr(binary, right_name, None) + if right is None: + continue if backend == "suitesparse" and left_name in _SS_OPERATORS: right._commutes_to = f"ss.{left_name}" else: right._commutes_to = left_name for name in cls._commutative: - cur_op = getattr(binary, name) + if _supports_udfs: + cur_op = getattr(binary, name) + else: + cur_op = getattr(binary, name, None) + if cur_op is None: + continue cur_op._commutes_to = name for left_name, right_name in cls._commutes_to_in_semiring.items(): if left_name in _SS_OPERATORS: @@ -805,7 +847,10 @@ def _initialize(cls): (binary.any, _first), ]: binop.orig_func = func - binop._numba_func = numba.njit(func) + if _has_numba: + binop._numba_func = numba.njit(func) + else: + binop._numba_func = None binop._udt_types = {} binop._udt_ops = {} binary.any._numba_func = binary.first._numba_func diff --git a/graphblas/core/operator/indexunary.py b/graphblas/core/operator/indexunary.py index 5fdafb62a..23a9fdeb3 100644 --- a/graphblas/core/operator/indexunary.py +++ b/graphblas/core/operator/indexunary.py @@ -2,21 +2,16 @@ import re from types import FunctionType -import numba - from ... import _STANDARD_OPERATOR_NAMES, indexunary, select from ...dtypes import BOOL, FP64, INT8, INT64, UINT64, _sample_values, lookup_dtype from ...exceptions import UdfParseError, check_status_carg -from .. import ffi, lib -from .base import ( - OpBase, - ParameterizedUdf, - TypedOpBase, - _call_op, - _deserialize_parameterized, - _get_udt_wrapper, -) +from .. import _has_numba, ffi, lib +from .base import OpBase, ParameterizedUdf, TypedOpBase, _call_op, _deserialize_parameterized + +if _has_numba: + import numba + from .base import _get_udt_wrapper ffi_new = ffi.new @@ -249,6 +244,7 @@ def register_anonymous(cls, func, name=None, *, parameterized=False, is_udt=Fals Because it is not registered in the namespace, the name is optional. """ + cls._check_supports_udf("register_anonymous") if parameterized: return ParameterizedIndexUnaryOp(name, func, anonymous=True, is_udt=is_udt) return cls._build(name, func, anonymous=True, is_udt=is_udt) @@ -265,6 +261,7 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal >>> dir(gb.indexunary) [..., 'row_mod', ...] """ + cls._check_supports_udf("register_new") module, funcname = cls._remove_nesting(name) if lazy: module._delayed[funcname] = ( diff --git a/graphblas/core/operator/select.py b/graphblas/core/operator/select.py index 844565f3a..bf3e1cad8 100644 --- a/graphblas/core/operator/select.py +++ b/graphblas/core/operator/select.py @@ -124,6 +124,7 @@ def register_anonymous(cls, func, name=None, *, parameterized=False, is_udt=Fals Because it is not registered in the namespace, the name is optional. """ + cls._check_supports_udf("register_anonymous") if parameterized: return ParameterizedSelectOp(name, func, anonymous=True, is_udt=is_udt) iop = IndexUnaryOp._build(name, func, anonymous=True, is_udt=is_udt) @@ -140,6 +141,7 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal >>> dir(gb.select) [..., 'upper_left_triangle', ...] """ + cls._check_supports_udf("register_new") iop = IndexUnaryOp.register_new( name, func, parameterized=parameterized, is_udt=is_udt, lazy=lazy ) diff --git a/graphblas/core/operator/semiring.py b/graphblas/core/operator/semiring.py index 06450e007..ac716b9dd 100644 --- a/graphblas/core/operator/semiring.py +++ b/graphblas/core/operator/semiring.py @@ -17,7 +17,7 @@ _supports_complex, ) from ...exceptions import check_status_carg -from .. import ffi, lib +from .. import _supports_udfs, ffi, lib from .base import _SS_OPERATORS, OpBase, ParameterizedUdf, TypedOpBase, _call_op, _hasop from .binary import BinaryOp, ParameterizedBinaryOp from .monoid import Monoid, ParameterizedMonoid @@ -358,15 +358,17 @@ def _initialize(cls): for orig_name, orig in div_semirings.items(): cls.register_new(f"{orig_name[:-3]}truediv", orig.monoid, binary.truediv, lazy=True) cls.register_new(f"{orig_name[:-3]}rtruediv", orig.monoid, "rtruediv", lazy=True) - cls.register_new(f"{orig_name[:-3]}floordiv", orig.monoid, "floordiv", lazy=True) - cls.register_new(f"{orig_name[:-3]}rfloordiv", orig.monoid, "rfloordiv", lazy=True) + if _supports_udfs: + cls.register_new(f"{orig_name[:-3]}floordiv", orig.monoid, "floordiv", lazy=True) + cls.register_new(f"{orig_name[:-3]}rfloordiv", orig.monoid, "rfloordiv", lazy=True) # For aggregators cls.register_new("plus_pow", monoid.plus, binary.pow) - cls.register_new("plus_rpow", monoid.plus, "rpow", lazy=True) - cls.register_new("plus_absfirst", monoid.plus, "absfirst", lazy=True) - cls.register_new("max_absfirst", monoid.max, "absfirst", lazy=True) - cls.register_new("plus_abssecond", monoid.plus, "abssecond", lazy=True) - cls.register_new("max_abssecond", monoid.max, "abssecond", lazy=True) + if _supports_udfs: + cls.register_new("plus_rpow", monoid.plus, "rpow", lazy=True) + cls.register_new("plus_absfirst", monoid.plus, "absfirst", lazy=True) + cls.register_new("max_absfirst", monoid.max, "absfirst", lazy=True) + cls.register_new("plus_abssecond", monoid.plus, "abssecond", lazy=True) + cls.register_new("max_abssecond", monoid.max, "abssecond", lazy=True) # Update type information with sane coercion for lname in ["any", "eq", "land", "lor", "lxnor", "lxor"]: diff --git a/graphblas/core/operator/unary.py b/graphblas/core/operator/unary.py index 6b1319057..1432a9387 100644 --- a/graphblas/core/operator/unary.py +++ b/graphblas/core/operator/unary.py @@ -2,8 +2,6 @@ import re from types import FunctionType -import numba - from ... import _STANDARD_OPERATOR_NAMES, op, unary from ...dtypes import ( BOOL, @@ -22,7 +20,7 @@ lookup_dtype, ) from ...exceptions import UdfParseError, check_status_carg -from .. import ffi, lib +from .. import _has_numba, ffi, lib from ..utils import output_type from .base import ( _SS_OPERATORS, @@ -30,12 +28,15 @@ ParameterizedUdf, TypedOpBase, _deserialize_parameterized, - _get_udt_wrapper, _hasop, ) if _supports_complex: from ...dtypes import FC32, FC64 +if _has_numba: + import numba + + from .base import _get_udt_wrapper ffi_new = ffi.new @@ -276,6 +277,7 @@ def register_anonymous(cls, func, name=None, *, parameterized=False, is_udt=Fals Because it is not registered in the namespace, the name is optional. """ + cls._check_supports_udf("register_anonymous") if parameterized: return ParameterizedUnaryOp(name, func, anonymous=True, is_udt=is_udt) return cls._build(name, func, anonymous=True, is_udt=is_udt) @@ -289,6 +291,7 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal >>> dir(gb.unary) [..., 'plus_one', ...] """ + cls._check_supports_udf("register_new") module, funcname = cls._remove_nesting(name) if lazy: module._delayed[funcname] = ( @@ -372,7 +375,10 @@ def _initialize(cls): (unary.one, _one), ]: unop.orig_func = func - unop._numba_func = numba.njit(func) + if _has_numba: + unop._numba_func = numba.njit(func) + else: + unop._numba_func = None unop._udt_types = {} unop._udt_ops = {} cls._initialized = True diff --git a/graphblas/core/scalar.py b/graphblas/core/scalar.py index 93b5ebb4b..a7a251a1d 100644 --- a/graphblas/core/scalar.py +++ b/graphblas/core/scalar.py @@ -3,15 +3,19 @@ import numpy as np from .. import backend, binary, config, monoid -from ..binary import isclose from ..dtypes import _INDEX, FP64, lookup_dtype, unify from ..exceptions import EmptyObject, check_status -from . import automethods, ffi, lib, utils +from . import _has_numba, _supports_udfs, automethods, ffi, lib, utils from .base import BaseExpression, BaseType, call from .expr import AmbiguousAssignOrExtract from .operator import get_typed_op from .utils import _Pointer, output_type, wrapdoc +if _supports_udfs: + from ..binary import isclose +else: + from .operator.binary import _isclose as isclose + ffi_new = ffi.new @@ -261,6 +265,17 @@ def isclose(self, other, *, rel_tol=1e-7, abs_tol=0.0, check_dtype=False): return False # We can't yet call a UDF on a scalar as part of the spec, so let's do it ourselves isclose_func = isclose(rel_tol, abs_tol) + if not _has_numba: + # Check if types are compatible + get_typed_op( + binary.eq, + self.dtype, + other.dtype, + is_left_scalar=True, + is_right_scalar=True, + kind="binary", + ) + return isclose_func(self.value, other.value) isclose_func = get_typed_op( isclose_func, self.dtype, diff --git a/graphblas/core/ss/matrix.py b/graphblas/core/ss/matrix.py index b1869f198..ec0c74c08 100644 --- a/graphblas/core/ss/matrix.py +++ b/graphblas/core/ss/matrix.py @@ -1,9 +1,7 @@ import itertools import warnings -import numba import numpy as np -from numba import njit from suitesparse_graphblas.utils import claim_buffer, claim_buffer_2d, unclaim_buffer import graphblas as gb @@ -11,7 +9,7 @@ from ... import binary, monoid from ...dtypes import _INDEX, BOOL, INT64, UINT64, _string_to_dtype, lookup_dtype from ...exceptions import _error_code_lookup, check_status, check_status_carg -from .. import NULL, ffi, lib +from .. import NULL, _has_numba, ffi, lib from ..base import call from ..operator import get_typed_op from ..scalar import Scalar, _as_scalar, _scalar_index @@ -30,6 +28,16 @@ from .config import BaseConfig from .descriptor import get_descriptor +if _has_numba: + from numba import njit, prange +else: + + def njit(func=None, **kwargs): + if func is not None: + return func + return njit + + prange = range ffi_new = ffi.new @@ -4371,28 +4379,28 @@ def deserialize(cls, data, dtype=None, *, name=None, **opts): return rv -@numba.njit(parallel=True) +@njit(parallel=True) def argsort_values(indptr, indices, values): # pragma: no cover (numba) rv = np.empty(indptr[-1], dtype=np.uint64) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): rv[indptr[i] : indptr[i + 1]] = indices[ np.int64(indptr[i]) + np.argsort(values[indptr[i] : indptr[i + 1]]) ] return rv -@numba.njit(parallel=True) +@njit(parallel=True) def sort_values(indptr, values): # pragma: no cover (numba) rv = np.empty(indptr[-1], dtype=values.dtype) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): rv[indptr[i] : indptr[i + 1]] = np.sort(values[indptr[i] : indptr[i + 1]]) return rv -@numba.njit(parallel=True) +@njit(parallel=True) def compact_values(old_indptr, new_indptr, values): # pragma: no cover (numba) rv = np.empty(new_indptr[-1], dtype=values.dtype) - for i in numba.prange(new_indptr.size - 1): + for i in prange(new_indptr.size - 1): start = np.int64(new_indptr[i]) offset = np.int64(old_indptr[i]) - start for j in range(start, new_indptr[i + 1]): @@ -4400,17 +4408,17 @@ def compact_values(old_indptr, new_indptr, values): # pragma: no cover (numba) return rv -@numba.njit(parallel=True) +@njit(parallel=True) def reverse_values(indptr, values): # pragma: no cover (numba) rv = np.empty(indptr[-1], dtype=values.dtype) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): offset = np.int64(indptr[i]) + np.int64(indptr[i + 1]) - 1 for j in range(indptr[i], indptr[i + 1]): rv[j] = values[offset - j] return rv -@numba.njit(parallel=True) +@njit(parallel=True) def compact_indices(indptr, k): # pragma: no cover (numba) """Given indptr from hypercsr, create a new col_indices array that is compact. @@ -4420,7 +4428,7 @@ def compact_indices(indptr, k): # pragma: no cover (numba) indptr = create_indptr(indptr, k) col_indices = np.empty(indptr[-1], dtype=np.uint64) N = np.int64(0) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): start = np.int64(indptr[i]) deg = np.int64(indptr[i + 1]) - start N = max(N, deg) @@ -4433,7 +4441,7 @@ def compact_indices(indptr, k): # pragma: no cover (numba) def choose_random1(indptr): # pragma: no cover (numba) choices = np.empty(indptr.size - 1, dtype=indptr.dtype) new_indptr = np.arange(indptr.size, dtype=indptr.dtype) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): idx = np.int64(indptr[i]) deg = np.int64(indptr[i + 1]) - idx if deg == 1: @@ -4470,7 +4478,7 @@ def choose_random(indptr, k): # pragma: no cover (numba) # be nice to have them sorted if convenient to do so. new_indptr = create_indptr(indptr, k) choices = np.empty(new_indptr[-1], dtype=indptr.dtype) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): idx = np.int64(indptr[i]) deg = np.int64(indptr[i + 1]) - idx if k < deg: @@ -4551,7 +4559,7 @@ def choose_first(indptr, k): # pragma: no cover (numba) new_indptr = create_indptr(indptr, k) choices = np.empty(new_indptr[-1], dtype=indptr.dtype) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): idx = np.int64(indptr[i]) deg = np.int64(indptr[i + 1]) - idx if k < deg: @@ -4575,7 +4583,7 @@ def choose_last(indptr, k): # pragma: no cover (numba) new_indptr = create_indptr(indptr, k) choices = np.empty(new_indptr[-1], dtype=indptr.dtype) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): idx = np.int64(indptr[i]) deg = np.int64(indptr[i + 1]) - idx if k < deg: @@ -4608,19 +4616,20 @@ def indices_to_indptr(indices, size): # pragma: no cover (numba) """Calculate the indptr for e.g. CSR from sorted COO rows.""" indptr = np.zeros(size, dtype=indices.dtype) index = np.uint64(0) + one = np.uint64(1) for i in range(indices.size): row = indices[i] if row != index: - indptr[index + 1] = i + indptr[index + one] = i index = row - indptr[index + 1] = indices.size + indptr[index + one] = indices.size return indptr @njit(parallel=True) def indptr_to_indices(indptr): # pragma: no cover (numba) indices = np.empty(indptr[-1], dtype=indptr.dtype) - for i in numba.prange(indptr.size - 1): + for i in prange(indptr.size - 1): for j in range(indptr[i], indptr[i + 1]): indices[j] = i return indices diff --git a/graphblas/core/ss/vector.py b/graphblas/core/ss/vector.py index 343335773..e9b6edaa6 100644 --- a/graphblas/core/ss/vector.py +++ b/graphblas/core/ss/vector.py @@ -1,7 +1,6 @@ import itertools import numpy as np -from numba import njit from suitesparse_graphblas.utils import claim_buffer, unclaim_buffer import graphblas as gb @@ -23,7 +22,7 @@ ) from .config import BaseConfig from .descriptor import get_descriptor -from .matrix import _concat_mn +from .matrix import _concat_mn, njit from .prefix_scan import prefix_scan ffi_new = ffi.new diff --git a/graphblas/core/vector.py b/graphblas/core/vector.py index 8231691c6..6f42a64c3 100644 --- a/graphblas/core/vector.py +++ b/graphblas/core/vector.py @@ -3,10 +3,10 @@ import numpy as np -from .. import backend, binary, monoid, select, semiring +from .. import backend, binary, monoid, select, semiring, unary from ..dtypes import _INDEX, FP64, INT64, lookup_dtype, unify from ..exceptions import DimensionMismatch, NoValue, check_status -from . import automethods, ffi, lib, utils +from . import _supports_udfs, automethods, ffi, lib, utils from .base import BaseExpression, BaseType, _check_mask, call from .descriptor import lookup as descriptor_lookup from .expr import _ALL_INDICES, AmbiguousAssignOrExtract, IndexerResolver, Updater @@ -93,6 +93,38 @@ def _select_mask(updater, obj, mask): updater << obj.dup(mask=mask) +def _isclose_recipe(self, other, rel_tol, abs_tol, **opts): + # x == y or abs(x - y) <= max(rel_tol * max(abs(x), abs(y)), abs_tol) + isequal = self.ewise_mult(other, binary.eq).new(bool, name="isclose", **opts) + if isequal._nvals != self._nvals: + return False + if type(isequal) is Vector: + val = isequal.reduce(monoid.land, allow_empty=False).new(**opts).value + else: + val = isequal.reduce_scalar(monoid.land, allow_empty=False).new(**opts).value + if val: + return True + # x - y + abs_x_y = self.ewise_mult(other, binary.minus).new(FP64, mask=~isequal.V, **opts) + # abs(x - y) + abs_x_y(**opts) << abs_x_y.apply(unary.abs) + # abs(x) + x = self.apply(unary.abs).new(FP64, mask=~isequal.V, **opts) + # abs(y) + y = other.apply(unary.abs).new(FP64, mask=~isequal.V, **opts) + # max(abs(x), abs(y)) + max_x_y = x.ewise_mult(y, binary.max).new(**opts) + # rel_tol * max(abs(x), abs(y)) + max_x_y(**opts) << max_x_y.apply(binary.times, rel_tol) + # max(rel_tol * max(abs(x), abs(y)), abs_tol) + max_x_y(**opts) << max_x_y.apply(binary.max, abs_tol) + # abs(x - y) <= max(rel_tol * max(abs(x), abs(y)), abs_tol) + isequal(**opts) << abs_x_y.ewise_mult(max_x_y, binary.lt) + if type(isequal) is Vector: + return isequal.reduce(monoid.land, allow_empty=False).new(**opts).value + return isequal.reduce_scalar(monoid.land, allow_empty=False).new(**opts).value + + class Vector(BaseType): """Create a new GraphBLAS Sparse Vector. @@ -354,6 +386,8 @@ def isclose(self, other, *, rel_tol=1e-7, abs_tol=0.0, check_dtype=False, **opts return False if self._nvals != other._nvals: return False + if not _supports_udfs: + return _isclose_recipe(self, other, rel_tol, abs_tol, **opts) matches = self.ewise_mult(other, binary.isclose(rel_tol, abs_tol)).new( bool, name="M_isclose", **opts @@ -520,14 +554,15 @@ def build(self, indices, values, *, dup_op=None, clear=False, size=None): if not dup_op_given: if not self.dtype._is_udt: dup_op = binary.plus - else: + elif backend != "suitesparse": dup_op = binary.any - # SS:SuiteSparse-specific: we could use NULL for dup_op - dup_op = get_typed_op(dup_op, self.dtype, kind="binary") - if dup_op.opclass == "Monoid": - dup_op = dup_op.binaryop - else: - self._expect_op(dup_op, "BinaryOp", within="build", argname="dup_op") + # SS:SuiteSparse-specific: we use NULL for dup_op + if dup_op is not None: + dup_op = get_typed_op(dup_op, self.dtype, kind="binary") + if dup_op.opclass == "Monoid": + dup_op = dup_op.binaryop + else: + self._expect_op(dup_op, "BinaryOp", within="build", argname="dup_op") indices = _CArray(indices) values = _CArray(values, self.dtype) diff --git a/graphblas/dtypes.py b/graphblas/dtypes.py index 22d98b8f1..920610b95 100644 --- a/graphblas/dtypes.py +++ b/graphblas/dtypes.py @@ -1,15 +1,18 @@ import warnings as _warnings -import numba as _numba import numpy as _np from numpy import find_common_type as _find_common_type from numpy import promote_types as _promote_types from . import backend from .core import NULL as _NULL +from .core import _has_numba from .core import ffi as _ffi from .core import lib as _lib +if _has_numba: + import numba as _numba + # Default assumption unless FC32/FC64 are found in lib _supports_complex = hasattr(_lib, "GrB_FC64") or hasattr(_lib, "GxB_FC64") @@ -140,44 +143,126 @@ def register_anonymous(dtype, name=None): # For now, let's use "opaque" unsigned bytes for the c type. if name is None: name = _default_name(dtype) - numba_type = _numba.typeof(dtype).dtype + numba_type = _numba.typeof(dtype).dtype if _has_numba else None rv = DataType(name, gb_obj, None, f"uint8_t[{dtype.itemsize}]", numba_type, dtype) _registry[gb_obj] = rv _registry[dtype] = rv - _registry[numba_type] = rv - _registry[numba_type.name] = rv + if _has_numba: + _registry[numba_type] = rv + _registry[numba_type.name] = rv return rv -BOOL = DataType("BOOL", _lib.GrB_BOOL, "GrB_BOOL", "_Bool", _numba.types.bool_, _np.bool_) -INT8 = DataType("INT8", _lib.GrB_INT8, "GrB_INT8", "int8_t", _numba.types.int8, _np.int8) -UINT8 = DataType("UINT8", _lib.GrB_UINT8, "GrB_UINT8", "uint8_t", _numba.types.uint8, _np.uint8) -INT16 = DataType("INT16", _lib.GrB_INT16, "GrB_INT16", "int16_t", _numba.types.int16, _np.int16) +BOOL = DataType( + "BOOL", + _lib.GrB_BOOL, + "GrB_BOOL", + "_Bool", + _numba.types.bool_ if _has_numba else None, + _np.bool_, +) +INT8 = DataType( + "INT8", _lib.GrB_INT8, "GrB_INT8", "int8_t", _numba.types.int8 if _has_numba else None, _np.int8 +) +UINT8 = DataType( + "UINT8", + _lib.GrB_UINT8, + "GrB_UINT8", + "uint8_t", + _numba.types.uint8 if _has_numba else None, + _np.uint8, +) +INT16 = DataType( + "INT16", + _lib.GrB_INT16, + "GrB_INT16", + "int16_t", + _numba.types.int16 if _has_numba else None, + _np.int16, +) UINT16 = DataType( - "UINT16", _lib.GrB_UINT16, "GrB_UINT16", "uint16_t", _numba.types.uint16, _np.uint16 + "UINT16", + _lib.GrB_UINT16, + "GrB_UINT16", + "uint16_t", + _numba.types.uint16 if _has_numba else None, + _np.uint16, +) +INT32 = DataType( + "INT32", + _lib.GrB_INT32, + "GrB_INT32", + "int32_t", + _numba.types.int32 if _has_numba else None, + _np.int32, ) -INT32 = DataType("INT32", _lib.GrB_INT32, "GrB_INT32", "int32_t", _numba.types.int32, _np.int32) UINT32 = DataType( - "UINT32", _lib.GrB_UINT32, "GrB_UINT32", "uint32_t", _numba.types.uint32, _np.uint32 + "UINT32", + _lib.GrB_UINT32, + "GrB_UINT32", + "uint32_t", + _numba.types.uint32 if _has_numba else None, + _np.uint32, +) +INT64 = DataType( + "INT64", + _lib.GrB_INT64, + "GrB_INT64", + "int64_t", + _numba.types.int64 if _has_numba else None, + _np.int64, ) -INT64 = DataType("INT64", _lib.GrB_INT64, "GrB_INT64", "int64_t", _numba.types.int64, _np.int64) # _Index (like UINT64) is for internal use only and shouldn't be exposed to the user _INDEX = DataType( - "UINT64", _lib.GrB_UINT64, "GrB_Index", "GrB_Index", _numba.types.uint64, _np.uint64 + "UINT64", + _lib.GrB_UINT64, + "GrB_Index", + "GrB_Index", + _numba.types.uint64 if _has_numba else None, + _np.uint64, ) UINT64 = DataType( - "UINT64", _lib.GrB_UINT64, "GrB_UINT64", "uint64_t", _numba.types.uint64, _np.uint64 + "UINT64", + _lib.GrB_UINT64, + "GrB_UINT64", + "uint64_t", + _numba.types.uint64 if _has_numba else None, + _np.uint64, +) +FP32 = DataType( + "FP32", + _lib.GrB_FP32, + "GrB_FP32", + "float", + _numba.types.float32 if _has_numba else None, + _np.float32, +) +FP64 = DataType( + "FP64", + _lib.GrB_FP64, + "GrB_FP64", + "double", + _numba.types.float64 if _has_numba else None, + _np.float64, ) -FP32 = DataType("FP32", _lib.GrB_FP32, "GrB_FP32", "float", _numba.types.float32, _np.float32) -FP64 = DataType("FP64", _lib.GrB_FP64, "GrB_FP64", "double", _numba.types.float64, _np.float64) if _supports_complex and hasattr(_lib, "GxB_FC32"): FC32 = DataType( - "FC32", _lib.GxB_FC32, "GxB_FC32", "float _Complex", _numba.types.complex64, _np.complex64 + "FC32", + _lib.GxB_FC32, + "GxB_FC32", + "float _Complex", + _numba.types.complex64 if _has_numba else None, + _np.complex64, ) if _supports_complex and hasattr(_lib, "GrB_FC32"): # pragma: no cover (unused) FC32 = DataType( - "FC32", _lib.GrB_FC32, "GrB_FC32", "float _Complex", _numba.types.complex64, _np.complex64 + "FC32", + _lib.GrB_FC32, + "GrB_FC32", + "float _Complex", + _numba.types.complex64 if _has_numba else None, + _np.complex64, ) if _supports_complex and hasattr(_lib, "GxB_FC64"): FC64 = DataType( @@ -185,7 +270,7 @@ def register_anonymous(dtype, name=None): _lib.GxB_FC64, "GxB_FC64", "double _Complex", - _numba.types.complex128, + _numba.types.complex128 if _has_numba else None, _np.complex128, ) if _supports_complex and hasattr(_lib, "GrB_FC64"): # pragma: no cover (unused) @@ -194,7 +279,7 @@ def register_anonymous(dtype, name=None): _lib.GrB_FC64, "GrB_FC64", "double _Complex", - _numba.types.complex128, + _numba.types.complex128 if _has_numba else None, _np.complex128, ) @@ -246,8 +331,9 @@ def register_anonymous(dtype, name=None): _registry[dtype.gb_name.lower()] = dtype _registry[dtype.c_type] = dtype _registry[dtype.c_type.upper()] = dtype - _registry[dtype.numba_type] = dtype - _registry[dtype.numba_type.name] = dtype + if _has_numba: + _registry[dtype.numba_type] = dtype + _registry[dtype.numba_type.name] = dtype val = _sample_values[dtype] _registry[val.dtype] = dtype _registry[val.dtype.name] = dtype diff --git a/graphblas/io.py b/graphblas/io.py index bc57c2084..5d717b986 100644 --- a/graphblas/io.py +++ b/graphblas/io.py @@ -455,7 +455,7 @@ def to_awkward(A, format=None): indices, values = A.to_coo() form = RecordForm( contents=[ - NumpyForm(A.dtype.numba_type.name, form_key="node1"), + NumpyForm(A.dtype.numba_type.name, form_key="node1"), # XXX: is numba required? NumpyForm("int64", form_key="node0"), ], fields=["values", "indices"], diff --git a/graphblas/monoid/numpy.py b/graphblas/monoid/numpy.py index 1d687443f..6040d4037 100644 --- a/graphblas/monoid/numpy.py +++ b/graphblas/monoid/numpy.py @@ -5,15 +5,18 @@ https://numba.readthedocs.io/en/stable/reference/numpysupported.html#math-operations """ -import numba as _numba import numpy as _np from .. import _STANDARD_OPERATOR_NAMES from .. import binary as _binary from .. import config as _config from .. import monoid as _monoid +from ..core import _has_numba, _supports_udfs from ..dtypes import _supports_complex +if _has_numba: + import numba as _numba + _delayed = {} _complex_dtypes = {"FC32", "FC64"} _float_dtypes = {"FP32", "FP64"} @@ -86,7 +89,8 @@ # To increase import speed, only call njit when `_config.get("mapnumpy")` is False if ( _config.get("mapnumpy") - or type(_numba.njit(lambda x, y: _np.fmax(x, y))(1, 2)) # pragma: no branch (numba) + or _has_numba + and type(_numba.njit(lambda x, y: _np.fmax(x, y))(1, 2)) # pragma: no branch (numba) is not float ): # Incorrect behavior was introduced in numba 0.56.2 and numpy 1.23 @@ -155,7 +159,12 @@ def __dir__(): - return globals().keys() | _delayed.keys() | _monoid_identities.keys() + if not _supports_udfs and not _config.get("mapnumpy"): + return globals().keys() + attrs = _delayed.keys() | _monoid_identities.keys() + if not _supports_udfs: + attrs &= _numpy_to_graphblas.keys() + return attrs | globals().keys() def __getattr__(name): diff --git a/graphblas/op/numpy.py b/graphblas/op/numpy.py index 497a6037c..cadba17eb 100644 --- a/graphblas/op/numpy.py +++ b/graphblas/op/numpy.py @@ -1,4 +1,5 @@ from ..binary import numpy as _np_binary +from ..core import _supports_udfs from ..semiring import numpy as _np_semiring from ..unary import numpy as _np_unary @@ -10,7 +11,10 @@ def __dir__(): - return globals().keys() | _delayed.keys() | _op_to_mod.keys() + attrs = _delayed.keys() | _op_to_mod.keys() + if not _supports_udfs: + attrs &= _np_unary.__dir__() | _np_binary.__dir__() | _np_semiring.__dir__() + return attrs | globals().keys() def __getattr__(name): diff --git a/graphblas/semiring/numpy.py b/graphblas/semiring/numpy.py index e47ac0336..87f947c07 100644 --- a/graphblas/semiring/numpy.py +++ b/graphblas/semiring/numpy.py @@ -12,6 +12,7 @@ from .. import config as _config from .. import monoid as _monoid from ..binary.numpy import _binary_names +from ..core import _supports_udfs from ..monoid.numpy import _fmin_is_float, _monoid_identities _delayed = {} @@ -132,7 +133,17 @@ def __dir__(): - return globals().keys() | _delayed.keys() | _semiring_names + if not _supports_udfs and not _config.get("mapnumpy"): + return globals().keys() + attrs = _delayed.keys() | _semiring_names + if not _supports_udfs: + attrs &= { + f"{monoid_name}_{binary_name}" + for monoid_name, binary_name in _itertools.product( + dir(_monoid.numpy), dir(_binary.numpy) + ) + } + return attrs | globals().keys() def __getattr__(name): diff --git a/graphblas/tests/test_io.py b/graphblas/tests/test_io.py index ada092025..f3527412b 100644 --- a/graphblas/tests/test_io.py +++ b/graphblas/tests/test_io.py @@ -29,6 +29,7 @@ import awkward as ak except ImportError: # pragma: no cover (import) ak = None +ak = None # XXX try: import fast_matrix_market as fmm diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index 1d42035a3..a8571df39 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -1,6 +1,7 @@ import inspect import itertools import pickle +import platform import sys import types import weakref @@ -11,6 +12,7 @@ import graphblas as gb from graphblas import agg, backend, binary, dtypes, indexunary, monoid, select, semiring, unary +from graphblas.core import _supports_udfs as supports_udfs from graphblas.core import lib from graphblas.exceptions import ( DimensionMismatch, @@ -28,6 +30,7 @@ from graphblas import Matrix, Scalar, Vector # isort:skip (for dask-graphblas) suitesparse = backend == "suitesparse" +pypy = platform.python_implementation() == "PyPy" @pytest.fixture @@ -1283,6 +1286,7 @@ def test_select_bools_and_masks(A): A.select(A[0, :].new().S) +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_indexunary_udf(A): def threex_minusthunk(x, row, col, thunk): # pragma: no cover (numba) @@ -1353,15 +1357,17 @@ def test_reduce_agg(A): expected = unary.sqrt[float](squared).new() w5 = A.reduce_rowwise(agg.hypot).new() assert w5.isclose(expected) - w6 = A.reduce_rowwise(monoid.numpy.hypot[float]).new() - assert w6.isclose(expected) + if supports_udfs or hasattr(monoid.numpy, "hypot"): + w6 = A.reduce_rowwise(monoid.numpy.hypot[float]).new() + assert w6.isclose(expected) w7 = Vector(w5.dtype, size=w5.size) w7 << A.reduce_rowwise(agg.hypot) assert w7.isclose(expected) w8 = A.reduce_rowwise(agg.logaddexp).new() - expected = A.reduce_rowwise(monoid.numpy.logaddexp[float]).new() - assert w8.isclose(w8) + if supports_udfs or hasattr(monoid.numpy, "logaddexp"): + expected = A.reduce_rowwise(monoid.numpy.logaddexp[float]).new() + assert w8.isclose(w8) result = Vector.from_coo([0, 1, 2, 3, 4, 5, 6], [3, 2, 9, 10, 11, 8, 4]) w9 = A.reduce_columnwise(agg.sum).new() @@ -1598,6 +1604,7 @@ def test_reduce_agg_empty(): assert compute(s.value) is None +@pytest.mark.skipif("not supports_udfs") def test_reduce_row_udf(A): result = Vector.from_coo([0, 1, 2, 3, 4, 5, 6], [5, 12, 1, 6, 7, 1, 15]) @@ -2902,18 +2909,19 @@ def test_expr_is_like_matrix(A): "resize", "update", } - assert attrs - expr_attrs == expected, ( + ignore = {"__sizeof__"} + assert attrs - expr_attrs - ignore == expected, ( "If you see this message, you probably added a method to Matrix. You may need to " "add an entry to `matrix` or `matrix_vector` set in `graphblas.core.automethods` " "and then run `python -m graphblas.core.automethods`. If you're messing with infix " "methods, then you may need to run `python -m graphblas.core.infixmethods`." ) - assert attrs - infix_attrs == expected + assert attrs - infix_attrs - ignore == expected # TransposedMatrix is used differently than other expressions, # so maybe it shouldn't support everything. if suitesparse: expected.add("ss") - assert attrs - transposed_attrs == (expected | {"_as_vector", "S", "V"}) - { + assert attrs - transposed_attrs - ignore == (expected | {"_as_vector", "S", "V"}) - { "_prep_for_extract", "_extract_element", } @@ -2965,7 +2973,8 @@ def test_index_expr_is_like_matrix(A): "from_scalar", "resize", } - assert attrs - expr_attrs == expected, ( + ignore = {"__sizeof__"} + assert attrs - expr_attrs - ignore == expected, ( "If you see this message, you probably added a method to Matrix. You may need to " "add an entry to `matrix` or `matrix_vector` set in `graphblas.core.automethods` " "and then run `python -m graphblas.core.automethods`. If you're messing with infix " @@ -3110,10 +3119,12 @@ def test_infix_sugar(A): assert binary.times(2, A).isequal(2 * A) assert binary.truediv(A, 2).isequal(A / 2) assert binary.truediv(5, A).isequal(5 / A) - assert binary.floordiv(A, 2).isequal(A // 2) - assert binary.floordiv(5, A).isequal(5 // A) - assert binary.numpy.mod(A, 2).isequal(A % 2) - assert binary.numpy.mod(5, A).isequal(5 % A) + if supports_udfs or hasattr(binary, "floordiv"): + assert binary.floordiv(A, 2).isequal(A // 2) + assert binary.floordiv(5, A).isequal(5 // A) + if supports_udfs or hasattr(binary.numpy, "mod"): + assert binary.numpy.mod(A, 2).isequal(A % 2) + assert binary.numpy.mod(5, A).isequal(5 % A) assert binary.pow(A, 2).isequal(A**2) assert binary.pow(2, A).isequal(2**A) assert binary.pow(A, 2).isequal(pow(A, 2)) @@ -3140,26 +3151,27 @@ def test_infix_sugar(A): assert binary.ge(A, 4).isequal(A >= 4) assert binary.eq(A, 4).isequal(A == 4) assert binary.ne(A, 4).isequal(A != 4) - x, y = divmod(A, 3) - assert binary.floordiv(A, 3).isequal(x) - assert binary.numpy.mod(A, 3).isequal(y) - assert binary.fmod(A, 3).isequal(y) - assert A.isequal(binary.plus((3 * x) & y)) - x, y = divmod(-A, 3) - assert binary.floordiv(-A, 3).isequal(x) - assert binary.numpy.mod(-A, 3).isequal(y) - # assert binary.fmod(-A, 3).isequal(y) # The reason we use numpy.mod - assert (-A).isequal(binary.plus((3 * x) & y)) - x, y = divmod(3, A) - assert binary.floordiv(3, A).isequal(x) - assert binary.numpy.mod(3, A).isequal(y) - assert binary.fmod(3, A).isequal(y) - assert binary.plus(binary.times(A & x) & y).isequal(3 * unary.one(A)) - x, y = divmod(-3, A) - assert binary.floordiv(-3, A).isequal(x) - assert binary.numpy.mod(-3, A).isequal(y) - # assert binary.fmod(-3, A).isequal(y) # The reason we use numpy.mod - assert binary.plus(binary.times(A & x) & y).isequal(-3 * unary.one(A)) + if supports_udfs or hasattr(binary, "floordiv") and hasattr(binary.numpy, "mod"): + x, y = divmod(A, 3) + assert binary.floordiv(A, 3).isequal(x) + assert binary.numpy.mod(A, 3).isequal(y) + assert binary.fmod(A, 3).isequal(y) + assert A.isequal(binary.plus((3 * x) & y)) + x, y = divmod(-A, 3) + assert binary.floordiv(-A, 3).isequal(x) + assert binary.numpy.mod(-A, 3).isequal(y) + # assert binary.fmod(-A, 3).isequal(y) # The reason we use numpy.mod + assert (-A).isequal(binary.plus((3 * x) & y)) + x, y = divmod(3, A) + assert binary.floordiv(3, A).isequal(x) + assert binary.numpy.mod(3, A).isequal(y) + assert binary.fmod(3, A).isequal(y) + assert binary.plus(binary.times(A & x) & y).isequal(3 * unary.one(A)) + x, y = divmod(-3, A) + assert binary.floordiv(-3, A).isequal(x) + assert binary.numpy.mod(-3, A).isequal(y) + # assert binary.fmod(-3, A).isequal(y) # The reason we use numpy.mod + assert binary.plus(binary.times(A & x) & y).isequal(-3 * unary.one(A)) assert binary.eq(A & A).isequal(A == A) assert binary.ne(A.T & A.T).isequal(A.T != A.T) @@ -3182,14 +3194,16 @@ def test_infix_sugar(A): B /= 2 assert type(B) is Matrix assert binary.truediv(A, 2).isequal(B) - B = A.dup() - B //= 2 - assert type(B) is Matrix - assert binary.floordiv(A, 2).isequal(B) - B = A.dup() - B %= 2 - assert type(B) is Matrix - assert binary.numpy.mod(A, 2).isequal(B) + if supports_udfs or hasattr(binary, "floordiv"): + B = A.dup() + B //= 2 + assert type(B) is Matrix + assert binary.floordiv(A, 2).isequal(B) + if supports_udfs or hasattr(binary.numpy, "mod"): + B = A.dup() + B %= 2 + assert type(B) is Matrix + assert binary.numpy.mod(A, 2).isequal(B) B = A.dup() B **= 2 assert type(B) is Matrix @@ -3520,7 +3534,7 @@ def test_ndim(A): def test_sizeof(A): - if suitesparse: + if suitesparse and not pypy: assert sys.getsizeof(A) > A.nvals * 16 else: with pytest.raises(TypeError): @@ -3607,6 +3621,7 @@ def test_ss_iteration(A): assert next(A.ss.iteritems()) is not None +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_udt(): record_dtype = np.dtype([("x", np.bool_), ("y", np.float64)], align=True) @@ -4126,7 +4141,11 @@ def test_from_scalar(): A = Matrix.from_scalar(1, dtype="INT64[2]", nrows=3, ncols=4) B = Matrix("INT64[2]", nrows=3, ncols=4) B << [1, 1] - assert A.isequal(B, check_dtype=True) + if supports_udfs: + assert A.isequal(B, check_dtype=True) + else: + with pytest.raises(KeyError): # XXX: is this the best type of error? + assert A.isequal(B, check_dtype=True) def test_to_dense_from_dense(): @@ -4286,6 +4305,7 @@ def test_wait_chains(A): assert result == 47 +@pytest.mark.skipif("not supports_udfs") def test_subarray_dtypes(): a = np.arange(3 * 4, dtype=np.int64).reshape(3, 4) A = Matrix.from_coo([1, 3, 5], [0, 1, 3], a) diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 5b7e797f3..685bbb064 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -11,7 +11,8 @@ import graphblas.monoid.numpy as npmonoid import graphblas.semiring.numpy as npsemiring import graphblas.unary.numpy as npunary -from graphblas import Vector, backend +from graphblas import Vector, backend, config +from graphblas.core import _supports_udfs as supports_udfs from graphblas.dtypes import _supports_complex from .conftest import compute @@ -21,12 +22,14 @@ def test_numpyops_dir(): - assert "exp2" in dir(npunary) - assert "logical_and" in dir(npbinary) - assert "logaddexp" in dir(npmonoid) - assert "add_add" in dir(npsemiring) + udf_or_mapped = supports_udfs or config["mapnumpy"] + assert ("exp2" in dir(npunary)) == udf_or_mapped + assert ("logical_and" in dir(npbinary)) == udf_or_mapped + assert ("logaddexp" in dir(npmonoid)) == supports_udfs + assert ("add_add" in dir(npsemiring)) == udf_or_mapped +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_bool_doesnt_get_too_large(): a = Vector.from_coo([0, 1, 2, 3], [True, False, True, False]) @@ -70,9 +73,12 @@ def test_npunary(): # due to limitation of MSVC with complex blocklist["FC64"].update({"arcsin", "arcsinh"}) blocklist["FC32"] = {"arcsin", "arcsinh"} - isclose = gb.binary.isclose(1e-6, 0) + if supports_udfs or hasattr(gb.binary, "isclose"): + isclose = gb.binary.isclose(1e-6, 0) + else: + isclose = None for gb_input, np_input in data: - for unary_name in sorted(npunary._unary_names): + for unary_name in sorted(npunary._unary_names & npunary.__dir__()): op = getattr(npunary, unary_name) if gb_input.dtype not in op.types or unary_name in blocklist.get( gb_input.dtype.name, () @@ -99,6 +105,8 @@ def test_npunary(): list(range(np_input.size)), list(np_result), dtype=gb_result.dtype ) assert gb_result.nvals == np_result.size + if compare_op is None: + continue match = gb_result.ewise_mult(np_result, compare_op).new() if gb_result.dtype.name.startswith("F"): match(accum=gb.binary.lor) << gb_result.apply(npunary.isnan) @@ -149,9 +157,24 @@ def test_npbinary(): "FP64": {"floor_divide"}, # numba/numpy difference for 1.0 / 0.0 "BOOL": {"gcd", "lcm", "subtract"}, # not supported by numpy } - isclose = gb.binary.isclose(1e-7, 0) + if supports_udfs or hasattr(gb.binary, "isclose"): + isclose = gb.binary.isclose(1e-7, 0) + else: + isclose = None + if supports_udfs or hasattr(npbinary, "equal"): + equal = npbinary.equal + else: + equal = gb.binary.eq + if supports_udfs or hasattr(npbinary, "isnan"): + isnan = npunary.isnan + else: + isnan = gb.unary.isnan + if supports_udfs or hasattr(npbinary, "isinf"): + isinf = npunary.isinf + else: + isinf = gb.unary.isinf for (gb_left, gb_right), (np_left, np_right) in data: - for binary_name in sorted(npbinary._binary_names): + for binary_name in sorted(npbinary._binary_names & npbinary.__dir__()): op = getattr(npbinary, binary_name) if gb_left.dtype not in op.types or binary_name in blocklist.get( gb_left.dtype.name, () @@ -171,7 +194,7 @@ def test_npbinary(): if binary_name in {"arctan2"}: compare_op = isclose else: - compare_op = npbinary.equal + compare_op = equal except Exception: # pragma: no cover (debug) print(f"Error computing numpy result for {binary_name}") print(f"dtypes: ({gb_left.dtype}, {gb_right.dtype}) -> {gb_result.dtype}") @@ -179,12 +202,14 @@ def test_npbinary(): np_result = Vector.from_coo(np.arange(np_left.size), np_result, dtype=gb_result.dtype) assert gb_result.nvals == np_result.size + if compare_op is None: + continue match = gb_result.ewise_mult(np_result, compare_op).new() if gb_result.dtype.name.startswith("F"): - match(accum=gb.binary.lor) << gb_result.apply(npunary.isnan) + match(accum=gb.binary.lor) << gb_result.apply(isnan) if gb_result.dtype.name.startswith("FC"): # Divide by 0j sometimes result in different behavior, such as `nan` or `(inf+0j)` - match(accum=gb.binary.lor) << gb_result.apply(npunary.isinf) + match(accum=gb.binary.lor) << gb_result.apply(isinf) compare = match.reduce(gb.monoid.land).new() if not compare: # pragma: no cover (debug) print(compare_op) @@ -241,7 +266,7 @@ def test_npmonoid(): "BOOL": {"add"}, } for (gb_left, gb_right), (np_left, np_right) in data: - for binary_name in sorted(npmonoid._monoid_identities): + for binary_name in sorted(npmonoid._monoid_identities.keys() & npmonoid.__dir__()): op = getattr(npmonoid, binary_name) assert len(op.types) > 0, op.name if gb_left.dtype not in op.types or binary_name in blocklist.get( @@ -279,7 +304,8 @@ def test_npmonoid(): @pytest.mark.slow def test_npsemiring(): for monoid_name, binary_name in itertools.product( - sorted(npmonoid._monoid_identities), sorted(npbinary._binary_names) + sorted(npmonoid._monoid_identities.keys() & npmonoid.__dir__()), + sorted(npbinary._binary_names & npbinary.__dir__()), ): monoid = getattr(npmonoid, monoid_name) binary = getattr(npbinary, binary_name) diff --git a/graphblas/tests/test_op.py b/graphblas/tests/test_op.py index 3a80dbe52..c4f6bbb74 100644 --- a/graphblas/tests/test_op.py +++ b/graphblas/tests/test_op.py @@ -4,7 +4,20 @@ import pytest import graphblas as gb -from graphblas import agg, backend, binary, dtypes, indexunary, monoid, op, select, semiring, unary +from graphblas import ( + agg, + backend, + binary, + config, + dtypes, + indexunary, + monoid, + op, + select, + semiring, + unary, +) +from graphblas.core import _supports_udfs as supports_udfs from graphblas.core import lib, operator from graphblas.core.operator import BinaryOp, IndexUnaryOp, Monoid, Semiring, UnaryOp, get_semiring from graphblas.dtypes import ( @@ -142,6 +155,7 @@ def test_get_typed_op(): operator.get_typed_op(binary.plus, dtypes.INT64, "bad dtype") +@pytest.mark.skipif("not supports_udfs") def test_unaryop_udf(): def plus_one(x): return x + 1 # pragma: no cover (numba) @@ -182,6 +196,7 @@ def plus_one(x): UnaryOp.register_new("bad", lambda x: v) +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_unaryop_parameterized(): def plus_x(x=0): @@ -207,6 +222,7 @@ def inner(val): assert r10.isequal(v11, check_dtype=True) +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_binaryop_parameterized(): def plus_plus_x(x=0): @@ -268,6 +284,7 @@ def my_add(x, y): assert op.name == "my_add" +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_monoid_parameterized(): def plus_plus_x(x=0): @@ -363,6 +380,7 @@ def bad_identity(x=0): assert monoid.is_idempotent +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_semiring_parameterized(): def plus_plus_x(x=0): @@ -490,6 +508,7 @@ def inner(y): assert B.isequal(A.kronecker(A, binary.plus).new()) +@pytest.mark.skipif("not supports_udfs") def test_unaryop_udf_bool_result(): # numba has trouble compiling this, but we have a work-around def is_positive(x): @@ -516,6 +535,7 @@ def is_positive(x): assert w.isequal(result) +@pytest.mark.skipif("not supports_udfs") def test_binaryop_udf(): def times_minus_sum(x, y): return x * y - (x + y) # pragma: no cover (numba) @@ -545,6 +565,7 @@ def times_minus_sum(x, y): assert w.isequal(result) +@pytest.mark.skipif("not supports_udfs") def test_monoid_udf(): def plus_plus_one(x, y): return x + y + 1 # pragma: no cover (numba) @@ -579,6 +600,7 @@ def plus_plus_one(x, y): Monoid.register_anonymous(binary.plus_plus_one, {"BOOL": -1}) +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_semiring_udf(): def plus_plus_two(x, y): @@ -608,10 +630,12 @@ def test_binary_updates(): vec4 = Vector.from_coo([0], [-3], dtype=dtypes.INT64) result2 = vec4.ewise_mult(vec2, binary.cdiv).new() assert result2.isequal(Vector.from_coo([0], [-1], dtype=dtypes.INT64), check_dtype=True) - result3 = vec4.ewise_mult(vec2, binary.floordiv).new() - assert result3.isequal(Vector.from_coo([0], [-2], dtype=dtypes.INT64), check_dtype=True) + if supports_udfs or hasattr(binary, "floordiv"): + result3 = vec4.ewise_mult(vec2, binary.floordiv).new() + assert result3.isequal(Vector.from_coo([0], [-2], dtype=dtypes.INT64), check_dtype=True) +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_nested_names(): def plus_three(x): @@ -671,12 +695,17 @@ def test_op_namespace(): assert op.plus is binary.plus assert op.plus_times is semiring.plus_times - assert op.numpy.fabs is unary.numpy.fabs - assert op.numpy.subtract is binary.numpy.subtract - assert op.numpy.add is binary.numpy.add - assert op.numpy.add_add is semiring.numpy.add_add + if supports_udfs or hasattr(unary.numpy, "fabs"): + assert op.numpy.fabs is unary.numpy.fabs + if supports_udfs or hasattr(binary.numpy, "subtract"): + assert op.numpy.subtract is binary.numpy.subtract + if supports_udfs or hasattr(binary.numpy, "add"): + assert op.numpy.add is binary.numpy.add + if supports_udfs or hasattr(semiring.numpy, "add_add"): + assert op.numpy.add_add is semiring.numpy.add_add assert len(dir(op)) > 300 - assert len(dir(op.numpy)) > 500 + if supports_udfs: + assert len(dir(op.numpy)) > 500 with pytest.raises( AttributeError, match="module 'graphblas.op.numpy' has no attribute 'bad_attr'" @@ -740,10 +769,12 @@ def test_op_namespace(): @pytest.mark.slow def test_binaryop_attributes_numpy(): # Some coverage from this test depends on order of tests - assert binary.numpy.add[int].monoid is monoid.numpy.add[int] - assert binary.numpy.subtract[int].monoid is None - assert binary.numpy.add.monoid is monoid.numpy.add - assert binary.numpy.subtract.monoid is None + if supports_udfs or hasattr(monoid.numpy, "add"): + assert binary.numpy.add[int].monoid is monoid.numpy.add[int] + assert binary.numpy.add.monoid is monoid.numpy.add + if supports_udfs or hasattr(binary.numpy, "subtract"): + assert binary.numpy.subtract[int].monoid is None + assert binary.numpy.subtract.monoid is None @pytest.mark.slow @@ -756,18 +787,21 @@ def test_binaryop_attributes(): def plus(x, y): return x + y # pragma: no cover (numba) - op = BinaryOp.register_anonymous(plus, name="plus") - assert op.monoid is None - assert op[int].monoid is None + if supports_udfs: + op = BinaryOp.register_anonymous(plus, name="plus") + assert op.monoid is None + assert op[int].monoid is None + assert op[int].parent is op assert binary.plus[int].parent is binary.plus - assert binary.numpy.add[int].parent is binary.numpy.add - assert op[int].parent is op + if supports_udfs or hasattr(binary.numpy, "add"): + assert binary.numpy.add[int].parent is binary.numpy.add # bad type assert binary.plus[bool].monoid is None - assert binary.numpy.equal[int].monoid is None - assert binary.numpy.equal[bool].monoid is monoid.numpy.equal[bool] # sanity + if supports_udfs or hasattr(binary.numpy, "equal"): + assert binary.numpy.equal[int].monoid is None + assert binary.numpy.equal[bool].monoid is monoid.numpy.equal[bool] # sanity for attr, val in vars(binary).items(): if not isinstance(val, BinaryOp): @@ -790,22 +824,25 @@ def test_monoid_attributes(): assert monoid.plus.binaryop is binary.plus assert monoid.plus.identities == {typ: 0 for typ in monoid.plus.types} - assert monoid.numpy.add[int].binaryop is binary.numpy.add[int] - assert monoid.numpy.add[int].identity == 0 - assert monoid.numpy.add.binaryop is binary.numpy.add - assert monoid.numpy.add.identities == {typ: 0 for typ in monoid.numpy.add.types} + if supports_udfs or hasattr(monoid.numpy, "add"): + assert monoid.numpy.add[int].binaryop is binary.numpy.add[int] + assert monoid.numpy.add[int].identity == 0 + assert monoid.numpy.add.binaryop is binary.numpy.add + assert monoid.numpy.add.identities == {typ: 0 for typ in monoid.numpy.add.types} def plus(x, y): # pragma: no cover (numba) return x + y - binop = BinaryOp.register_anonymous(plus, name="plus") - op = Monoid.register_anonymous(binop, 0, name="plus") - assert op.binaryop is binop - assert op[int].binaryop is binop[int] + if supports_udfs: + binop = BinaryOp.register_anonymous(plus, name="plus") + op = Monoid.register_anonymous(binop, 0, name="plus") + assert op.binaryop is binop + assert op[int].binaryop is binop[int] + assert op[int].parent is op assert monoid.plus[int].parent is monoid.plus - assert monoid.numpy.add[int].parent is monoid.numpy.add - assert op[int].parent is op + if supports_udfs or hasattr(monoid.numpy, "add"): + assert monoid.numpy.add[int].parent is monoid.numpy.add for attr, val in vars(monoid).items(): if not isinstance(val, Monoid): @@ -826,25 +863,27 @@ def test_semiring_attributes(): assert semiring.min_plus.monoid is monoid.min assert semiring.min_plus.binaryop is binary.plus - assert semiring.numpy.add_subtract[int].monoid is monoid.numpy.add[int] - assert semiring.numpy.add_subtract[int].binaryop is binary.numpy.subtract[int] - assert semiring.numpy.add_subtract.monoid is monoid.numpy.add - assert semiring.numpy.add_subtract.binaryop is binary.numpy.subtract + if supports_udfs or hasattr(semiring.numpy, "add_subtract"): + assert semiring.numpy.add_subtract[int].monoid is monoid.numpy.add[int] + assert semiring.numpy.add_subtract[int].binaryop is binary.numpy.subtract[int] + assert semiring.numpy.add_subtract.monoid is monoid.numpy.add + assert semiring.numpy.add_subtract.binaryop is binary.numpy.subtract + assert semiring.numpy.add_subtract[int].parent is semiring.numpy.add_subtract def plus(x, y): return x + y # pragma: no cover (numba) - binop = BinaryOp.register_anonymous(plus, name="plus") - mymonoid = Monoid.register_anonymous(binop, 0, name="plus") - op = Semiring.register_anonymous(mymonoid, binop, name="plus_plus") - assert op.binaryop is binop - assert op.binaryop[int] is binop[int] - assert op.monoid is mymonoid - assert op.monoid[int] is mymonoid[int] + if supports_udfs: + binop = BinaryOp.register_anonymous(plus, name="plus") + mymonoid = Monoid.register_anonymous(binop, 0, name="plus") + op = Semiring.register_anonymous(mymonoid, binop, name="plus_plus") + assert op.binaryop is binop + assert op.binaryop[int] is binop[int] + assert op.monoid is mymonoid + assert op.monoid[int] is mymonoid[int] + assert op[int].parent is op assert semiring.min_plus[int].parent is semiring.min_plus - assert semiring.numpy.add_subtract[int].parent is semiring.numpy.add_subtract - assert op[int].parent is op for attr, val in vars(semiring).items(): if not isinstance(val, Semiring): @@ -881,9 +920,10 @@ def test_div_semirings(): assert result[0, 0].new() == -2 assert result.dtype == dtypes.FP64 - result = A1.T.mxm(A2, semiring.plus_floordiv).new() - assert result[0, 0].new() == -3 - assert result.dtype == dtypes.INT64 + if supports_udfs or hasattr(semiring, "plus_floordiv"): + result = A1.T.mxm(A2, semiring.plus_floordiv).new() + assert result[0, 0].new() == -3 + assert result.dtype == dtypes.INT64 @pytest.mark.slow @@ -902,25 +942,27 @@ def test_get_semiring(): def myplus(x, y): return x + y # pragma: no cover (numba) - binop = BinaryOp.register_anonymous(myplus, name="myplus") - st = get_semiring(monoid.plus, binop) - assert st.monoid is monoid.plus - assert st.binaryop is binop + if supports_udfs: + binop = BinaryOp.register_anonymous(myplus, name="myplus") + st = get_semiring(monoid.plus, binop) + assert st.monoid is monoid.plus + assert st.binaryop is binop - binop = BinaryOp.register_new("myplus", myplus) - assert binop is binary.myplus - st = get_semiring(monoid.plus, binop) - assert st.monoid is monoid.plus - assert st.binaryop is binop + binop = BinaryOp.register_new("myplus", myplus) + assert binop is binary.myplus + st = get_semiring(monoid.plus, binop) + assert st.monoid is monoid.plus + assert st.binaryop is binop with pytest.raises(TypeError, match="Monoid"): get_semiring(None, binary.times) with pytest.raises(TypeError, match="Binary"): get_semiring(monoid.plus, None) - sr = get_semiring(monoid.plus, binary.numpy.copysign) - assert sr.monoid is monoid.plus - assert sr.binaryop is binary.numpy.copysign + if supports_udfs or hasattr(binary.numpy, "copysign"): + sr = get_semiring(monoid.plus, binary.numpy.copysign) + assert sr.monoid is monoid.plus + assert sr.binaryop is binary.numpy.copysign def test_create_semiring(): @@ -958,17 +1000,22 @@ def test_commutes(): assert semiring.plus_times.is_commutative if suitesparse: assert semiring.ss.min_secondi.commutes_to is semiring.ss.min_firstj - assert semiring.plus_pow.commutes_to is semiring.plus_rpow + if supports_udfs or hasattr(semiring, "plus_pow") and hasattr(semiring, "plus_rpow"): + assert semiring.plus_pow.commutes_to is semiring.plus_rpow assert not semiring.plus_pow.is_commutative - assert binary.isclose.commutes_to is binary.isclose - assert binary.isclose.is_commutative - assert binary.isclose(0.1).commutes_to is binary.isclose(0.1) - assert binary.floordiv.commutes_to is binary.rfloordiv - assert not binary.floordiv.is_commutative - assert binary.numpy.add.commutes_to is binary.numpy.add - assert binary.numpy.add.is_commutative - assert binary.numpy.less.commutes_to is binary.numpy.greater - assert not binary.numpy.less.is_commutative + if supports_udfs or hasattr(binary, "isclose"): + assert binary.isclose.commutes_to is binary.isclose + assert binary.isclose.is_commutative + assert binary.isclose(0.1).commutes_to is binary.isclose(0.1) + if supports_udfs or hasattr(binary, "floordiv") and hasattr(binary, "rfloordiv"): + assert binary.floordiv.commutes_to is binary.rfloordiv + assert not binary.floordiv.is_commutative + if supports_udfs or hasattr(binary.numpy, "add"): + assert binary.numpy.add.commutes_to is binary.numpy.add + assert binary.numpy.add.is_commutative + if supports_udfs or hasattr(binary.numpy, "less") and hasattr(binary.numpy, "greater"): + assert binary.numpy.less.commutes_to is binary.numpy.greater + assert not binary.numpy.less.is_commutative # Typed assert binary.plus[int].commutes_to is binary.plus[int] @@ -985,15 +1032,20 @@ def test_commutes(): assert semiring.plus_times[int].is_commutative if suitesparse: assert semiring.ss.min_secondi[int].commutes_to is semiring.ss.min_firstj[int] - assert semiring.plus_pow[int].commutes_to is semiring.plus_rpow[int] + if supports_udfs or hasattr(semiring, "plus_rpow"): + assert semiring.plus_pow[int].commutes_to is semiring.plus_rpow[int] assert not semiring.plus_pow[int].is_commutative - assert binary.isclose(0.1)[int].commutes_to is binary.isclose(0.1)[int] - assert binary.floordiv[int].commutes_to is binary.rfloordiv[int] - assert not binary.floordiv[int].is_commutative - assert binary.numpy.add[int].commutes_to is binary.numpy.add[int] - assert binary.numpy.add[int].is_commutative - assert binary.numpy.less[int].commutes_to is binary.numpy.greater[int] - assert not binary.numpy.less[int].is_commutative + if supports_udfs or hasattr(binary, "isclose"): + assert binary.isclose(0.1)[int].commutes_to is binary.isclose(0.1)[int] + if supports_udfs or hasattr(binary, "floordiv") and hasattr(binary, "rfloordiv"): + assert binary.floordiv[int].commutes_to is binary.rfloordiv[int] + assert not binary.floordiv[int].is_commutative + if supports_udfs or hasattr(binary.numpy, "add"): + assert binary.numpy.add[int].commutes_to is binary.numpy.add[int] + assert binary.numpy.add[int].is_commutative + if supports_udfs or hasattr(binary.numpy, "less") and hasattr(binary.numpy, "greater"): + assert binary.numpy.less[int].commutes_to is binary.numpy.greater[int] + assert not binary.numpy.less[int].is_commutative # Stress test (this can create extra semirings) names = dir(semiring) @@ -1014,9 +1066,12 @@ def test_from_string(): assert unary.from_string("abs[float]") is unary.abs[float] assert binary.from_string("+") is binary.plus assert binary.from_string("-[int]") is binary.minus[int] - assert binary.from_string("true_divide") is binary.numpy.true_divide - assert binary.from_string("//") is binary.floordiv - assert binary.from_string("%") is binary.numpy.mod + if supports_udfs or config["mapnumpy"] or hasattr(binary.numpy, "true_divide"): + assert binary.from_string("true_divide") is binary.numpy.true_divide + if supports_udfs or hasattr(binary, "floordiv"): + assert binary.from_string("//") is binary.floordiv + if supports_udfs or hasattr(binary.numpy, "mod"): + assert binary.from_string("%") is binary.numpy.mod assert monoid.from_string("*[FP64]") is monoid.times["FP64"] assert semiring.from_string("min.plus") is semiring.min_plus assert semiring.from_string("min.+") is semiring.min_plus @@ -1053,6 +1108,7 @@ def test_from_string(): agg.from_string("bad_agg") +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_lazy_op(): UnaryOp.register_new("lazy", lambda x: x, lazy=True) # pragma: no branch (numba) @@ -1115,6 +1171,7 @@ def test_positional(): assert semiring.ss.any_secondj[int].is_positional +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_udt(): record_dtype = np.dtype([("x", np.bool_), ("y", np.float64)], align=True) @@ -1280,6 +1337,7 @@ def test_binaryop_commute_exists(): raise AssertionError("Missing binaryops: " + ", ".join(sorted(missing))) +@pytest.mark.skipif("not supports_udfs") def test_binom(): v = Vector.from_coo([0, 1, 2], [3, 4, 5]) result = v.apply(binary.binom, 2).new() @@ -1341,9 +1399,11 @@ def test_is_idempotent(): assert monoid.max[int].is_idempotent assert monoid.lor.is_idempotent assert monoid.band.is_idempotent - assert monoid.numpy.gcd.is_idempotent + if supports_udfs or hasattr(monoid.numpy, "gcd"): + assert monoid.numpy.gcd.is_idempotent assert not monoid.plus.is_idempotent assert not monoid.times[float].is_idempotent - assert not monoid.numpy.equal.is_idempotent + if supports_udfs or config["mapnumpy"] or hasattr(monoid.numpy, "equal"): + assert not monoid.numpy.equal.is_idempotent with pytest.raises(AttributeError): binary.min.is_idempotent diff --git a/graphblas/tests/test_operator_types.py b/graphblas/tests/test_operator_types.py index 522b42ad2..027f02fcc 100644 --- a/graphblas/tests/test_operator_types.py +++ b/graphblas/tests/test_operator_types.py @@ -2,6 +2,7 @@ from collections import defaultdict from graphblas import backend, binary, dtypes, monoid, semiring, unary +from graphblas.core import _supports_udfs as supports_udfs from graphblas.core import operator from graphblas.dtypes import ( BOOL, @@ -83,6 +84,11 @@ BINARY[(ALL, POS)] = { "firsti", "firsti1", "firstj", "firstj1", "secondi", "secondi1", "secondj", "secondj1", } +if not supports_udfs: + udfs = {"absfirst", "abssecond", "binom", "floordiv", "rfloordiv", "rpow"} + for funcnames in BINARY.values(): + funcnames -= udfs + BINARY = {key: val for key, val in BINARY.items() if val} MONOID = { (UINT, UINT): {"band", "bor", "bxnor", "bxor"}, diff --git a/graphblas/tests/test_pickle.py b/graphblas/tests/test_pickle.py index de2d9cfda..724f43d76 100644 --- a/graphblas/tests/test_pickle.py +++ b/graphblas/tests/test_pickle.py @@ -5,6 +5,7 @@ import pytest import graphblas as gb +from graphblas.core import _supports_udfs as supports_udfs # noqa: F401 suitesparse = gb.backend == "suitesparse" @@ -36,6 +37,7 @@ def extra(): return "" +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_deserialize(extra): path = Path(__file__).parent / f"pickle1{extra}.pkl" @@ -62,6 +64,7 @@ def test_deserialize(extra): assert d3["semiring_pickle"] is gb.semiring.semiring_pickle +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_serialize(): v = gb.Vector.from_coo([1], 2) @@ -232,6 +235,7 @@ def identity_par(z): return -z +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_serialize_parameterized(): # unary_pickle = gb.core.operator.UnaryOp.register_new( @@ -285,6 +289,7 @@ def test_serialize_parameterized(): pickle.loads(pkl) # TODO: check results +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_deserialize_parameterized(extra): path = Path(__file__).parent / f"pickle2{extra}.pkl" @@ -295,6 +300,7 @@ def test_deserialize_parameterized(extra): pickle.load(f) # TODO: check results +@pytest.mark.skipif("not supports_udfs") def test_udt(extra): record_dtype = np.dtype([("x", np.bool_), ("y", np.int64)], align=True) udt = gb.dtypes.register_new("PickleUDT", record_dtype) diff --git a/graphblas/tests/test_scalar.py b/graphblas/tests/test_scalar.py index 6ee70311c..63f9d6531 100644 --- a/graphblas/tests/test_scalar.py +++ b/graphblas/tests/test_scalar.py @@ -1,5 +1,6 @@ import inspect import pickle +import platform import random import sys import types @@ -17,6 +18,7 @@ from graphblas import Matrix, Scalar, Vector # isort:skip (for dask-graphblas) suitesparse = backend == "suitesparse" +pypy = platform.python_implementation() == "PyPy" @pytest.fixture @@ -209,12 +211,12 @@ def test_unsupported_ops(s): s[0] with pytest.raises(TypeError, match="does not support"): s[0] = 0 - with pytest.raises(TypeError, match="doesn't support"): + with pytest.raises(TypeError, match="doesn't support|does not support"): del s[0] def test_is_empty(s): - with pytest.raises(AttributeError, match="can't set attribute"): + with pytest.raises(AttributeError, match="can't set attribute|object has no setter"): s.is_empty = True @@ -358,14 +360,15 @@ def test_expr_is_like_scalar(s): } if s.is_cscalar: expected.add("_empty") - assert attrs - expr_attrs == expected, ( + ignore = {"__sizeof__"} + assert attrs - expr_attrs - ignore == expected, ( "If you see this message, you probably added a method to Scalar. You may need to " "add an entry to `scalar` set in `graphblas.core.automethods` " "and then run `python -m graphblas.core.automethods`. If you're messing with infix " "methods, then you may need to run `python -m graphblas.core.infixmethods`." ) - assert attrs - infix_attrs == expected - assert attrs - scalar_infix_attrs == expected + assert attrs - infix_attrs - ignore == expected + assert attrs - scalar_infix_attrs - ignore == expected # Make sure signatures actually match. `expr.dup` has `**opts` skip = {"__init__", "__repr__", "_repr_html_", "dup"} for expr in [v.inner(v), v @ v, t & t]: @@ -399,7 +402,8 @@ def test_index_expr_is_like_scalar(s): } if s.is_cscalar: expected.add("_empty") - assert attrs - expr_attrs == expected, ( + ignore = {"__sizeof__"} + assert attrs - expr_attrs - ignore == expected, ( "If you see this message, you probably added a method to Scalar. You may need to " "add an entry to `scalar` set in `graphblas.core.automethods` " "and then run `python -m graphblas.core.automethods`. If you're messing with infix " @@ -505,7 +509,7 @@ def test_scalar_expr(s): def test_sizeof(s): - if suitesparse or s._is_cscalar: + if (suitesparse or s._is_cscalar) and not pypy: assert 1 < sys.getsizeof(s) < 1000 else: with pytest.raises(TypeError): diff --git a/graphblas/tests/test_vector.py b/graphblas/tests/test_vector.py index 8505313e4..8cb31863d 100644 --- a/graphblas/tests/test_vector.py +++ b/graphblas/tests/test_vector.py @@ -1,6 +1,7 @@ import inspect import itertools import pickle +import platform import sys import types import weakref @@ -11,6 +12,7 @@ import graphblas as gb from graphblas import agg, backend, binary, dtypes, indexunary, monoid, select, semiring, unary +from graphblas.core import _supports_udfs as supports_udfs from graphblas.exceptions import ( DimensionMismatch, DomainMismatch, @@ -27,6 +29,7 @@ suitesparse = backend == "suitesparse" +pypy = platform.python_implementation() == "PyPy" @pytest.fixture @@ -798,6 +801,7 @@ def test_select_bools_and_masks(v): assert w8.isequal(w9) +@pytest.mark.skipif("not supports_udfs") @pytest.mark.slow def test_indexunary_udf(v): def twox_minusthunk(x, row, col, thunk): # pragma: no cover (numba) @@ -899,9 +903,11 @@ def test_reduce_agg(v): assert v.reduce(agg.stdp).new().isclose(0.5**0.5) assert v.reduce(agg.stds).new().isclose((2 / 3) ** 0.5) assert v.reduce(agg.L0norm).new() == 3 - assert v.reduce(agg.L1norm).new() == 4 + if supports_udfs: # XXX TODO + assert v.reduce(agg.L1norm).new() == 4 assert v.reduce(agg.L2norm).new().isclose(6**0.5) - assert v.reduce(agg.Linfnorm).new() == 2 + if supports_udfs: # XXX TODO + assert v.reduce(agg.Linfnorm).new() == 2 assert v.reduce(agg.exists).new() == 1 w = binary.plus(v, 1).new() assert w.reduce(agg.geometric_mean).new().isclose(12**0.25) @@ -1624,13 +1630,14 @@ def test_expr_is_like_vector(v): "resize", "update", } - assert attrs - expr_attrs == expected, ( + ignore = {"__sizeof__"} + assert attrs - expr_attrs - ignore == expected, ( "If you see this message, you probably added a method to Vector. You may need to " "add an entry to `vector` or `matrix_vector` set in `graphblas.core.automethods` " "and then run `python -m graphblas.core.automethods`. If you're messing with infix " "methods, then you may need to run `python -m graphblas.core.infixmethods`." ) - assert attrs - infix_attrs == expected + assert attrs - infix_attrs - ignore == expected # Make sure signatures actually match skip = {"__init__", "__repr__", "_repr_html_"} for expr in [binary.times(w & w), w & w]: @@ -1672,7 +1679,8 @@ def test_index_expr_is_like_vector(v): "from_values", "resize", } - assert attrs - expr_attrs == expected, ( + ignore = {"__sizeof__"} + assert attrs - expr_attrs - ignore == expected, ( "If you see this message, you probably added a method to Vector. You may need to " "add an entry to `vector` or `matrix_vector` set in `graphblas.core.automethods` " "and then run `python -m graphblas.core.automethods`. If you're messing with infix " @@ -1963,7 +1971,7 @@ def test_ndim(A, v): def test_sizeof(v): - if suitesparse: + if suitesparse and not pypy: assert sys.getsizeof(v) > v.nvals * 16 else: with pytest.raises(TypeError): @@ -2006,6 +2014,7 @@ def test_delete_via_scalar(v): assert v.nvals == 0 +@pytest.mark.skipif("not supports_udfs") def test_udt(): record_dtype = np.dtype([("x", np.bool_), ("y", np.float64)], align=True) udt = dtypes.register_anonymous(record_dtype, "VectorUDT") @@ -2380,6 +2389,7 @@ def test_to_coo_subset(v): assert vals.dtype == np.int64 +@pytest.mark.skipif("not supports_udfs") def test_lambda_udfs(v): result = v.apply(lambda x: x + 1).new() # pragma: no branch (numba) expected = binary.plus(v, 1).new() @@ -2506,7 +2516,8 @@ def test_from_scalar(): v = Vector.from_scalar(1, dtype="INT64[2]", size=3) w = Vector("INT64[2]", size=3) w << [1, 1] - assert v.isequal(w, check_dtype=True) + if supports_udfs: # XXX TODO + assert v.isequal(w, check_dtype=True) def test_to_dense_from_dense(): @@ -2559,9 +2570,10 @@ def test_ss_sort(v): v.ss.sort(binary.plus) # Like compactify - _, p = v.ss.sort(lambda x, y: False, values=False) # pragma: no branch (numba) - expected_p = Vector.from_coo([0, 1, 2, 3], [1, 3, 4, 6], size=7) - assert p.isequal(expected_p) + if supports_udfs: + _, p = v.ss.sort(lambda x, y: False, values=False) # pragma: no branch (numba) + expected_p = Vector.from_coo([0, 1, 2, 3], [1, 3, 4, 6], size=7) + assert p.isequal(expected_p) # reversed _, p = v.ss.sort(binary.pair[bool], values=False) expected_p = Vector.from_coo([0, 1, 2, 3], [6, 4, 3, 1], size=7) @@ -2569,6 +2581,7 @@ def test_ss_sort(v): w, p = v.ss.sort(monoid.lxor) # Weird, but user-defined monoids may not commute, so okay +@pytest.mark.skipif("not supports_udfs") def test_subarray_dtypes(): a = np.arange(3 * 4, dtype=np.int64).reshape(3, 4) v = Vector.from_coo([1, 3, 5], a) diff --git a/graphblas/unary/numpy.py b/graphblas/unary/numpy.py index 836da2024..bae2c3779 100644 --- a/graphblas/unary/numpy.py +++ b/graphblas/unary/numpy.py @@ -10,6 +10,7 @@ from .. import _STANDARD_OPERATOR_NAMES from .. import config as _config from .. import unary as _unary +from ..core import _supports_udfs from ..dtypes import _supports_complex _delayed = {} @@ -119,7 +120,12 @@ def __dir__(): - return globals().keys() | _delayed.keys() | _unary_names + if not _supports_udfs and not _config.get("mapnumpy"): + return globals().keys() + attrs = _delayed.keys() | _unary_names + if not _supports_udfs: + attrs &= _numpy_to_graphblas.keys() + return attrs | globals().keys() def __getattr__(name): @@ -132,6 +138,8 @@ def __getattr__(name): raise AttributeError(f"module {__name__!r} has no attribute {name!r}") if _config.get("mapnumpy") and name in _numpy_to_graphblas: globals()[name] = getattr(_unary, _numpy_to_graphblas[name]) + elif not _supports_udfs: + raise AttributeError(f"module {__name__!r} unable to compile UDF for {name!r}") else: numpy_func = getattr(_np, name) diff --git a/pyproject.toml b/pyproject.toml index 47cf1e67f..9eb39aa1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,10 @@ classifiers = [ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", "Intended Audience :: Developers", "Intended Audience :: Other Audience", "Intended Audience :: Science/Research", @@ -166,6 +169,9 @@ filterwarnings = [ # And this deprecation warning was added in setuptools v67.5.0 (8 Mar 2023). See: # https://setuptools.pypa.io/en/latest/history.html#v67-5-0 "ignore:pkg_resources is deprecated as an API:DeprecationWarning:pkg_resources", + + # pypy gives this warning + "ignore:can't resolve package from __spec__ or __package__:ImportWarning:", ] [tool.coverage.run] diff --git a/scripts/check_versions.sh b/scripts/check_versions.sh index 54b02d1f9..eb785df1c 100755 --- a/scripts/check_versions.sh +++ b/scripts/check_versions.sh @@ -14,4 +14,4 @@ conda search 'numba[channel=conda-forge]>=0.56.4' conda search 'pyyaml[channel=conda-forge]>=6.0' conda search 'flake8-bugbear[channel=conda-forge]>=23.3.23' conda search 'flake8-simplify[channel=conda-forge]>=0.20.0' -# conda search 'python[channel=conda-forge]>=3.8 *pypy*' +conda search 'python[channel=conda-forge]>=3.8 *pypy*' From a987553d6e7c7665d263d2f1a82b4afac6fce999 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Mon, 3 Apr 2023 19:57:57 -0500 Subject: [PATCH 02/48] No numba on Python 3.11; use conda --- .github/workflows/test_and_build.yml | 32 ++++++++++++++-------------- graphblas/tests/test_scalar.py | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 04e3216bc..e29a225a5 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -133,23 +133,23 @@ jobs: 1 1 1 - - name: Setup mamba - uses: conda-incubator/setup-miniconda@v2 - id: setup_mamba - continue-on-error: true - with: - miniforge-variant: Mambaforge - miniforge-version: latest - use-mamba: true - python-version: ${{ steps.pyver.outputs.selected }} - channels: conda-forge,${{ contains(steps.pyver.outputs.selected, 'pypy') && 'defaults' || 'nodefaults' }} - channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }} - activate-environment: graphblas - auto-activate-base: false +# - name: Setup mamba +# uses: conda-incubator/setup-miniconda@v2 +# id: setup_mamba +# continue-on-error: true +# with: +# miniforge-variant: Mambaforge +# miniforge-version: latest +# use-mamba: true +# python-version: ${{ steps.pyver.outputs.selected }} +# channels: conda-forge,${{ contains(steps.pyver.outputs.selected, 'pypy') && 'defaults' || 'nodefaults' }} +# channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }} +# activate-environment: graphblas +# auto-activate-base: false - name: Setup conda uses: conda-incubator/setup-miniconda@v2 id: setup_conda - if: steps.setup_mamba.outcome == 'failure' +# if: steps.setup_mamba.outcome == 'failure' continue-on-error: false with: auto-update-conda: true @@ -217,8 +217,8 @@ jobs: else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))') fi - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') }} == true || $(python -c 'import random ; print(random.random() < .1)') == True ]]; then - # Some packages aren't available for pypy (and 10% chance to not install these otherwise) + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') }} == true || ${{ startsWith(steps.pyver.outputs.selected, '3.11') }} == true || $(python -c 'import random ; print(random.random() < .1)') == True ]]; then + # Some packages aren't available for pypy or Python 3.11 (and 10% chance to not install these otherwise) numba="" sparse="" awkward="" diff --git a/graphblas/tests/test_scalar.py b/graphblas/tests/test_scalar.py index 63f9d6531..12e210453 100644 --- a/graphblas/tests/test_scalar.py +++ b/graphblas/tests/test_scalar.py @@ -228,7 +228,7 @@ def test_update(s): s << Scalar.from_value(3) assert s == 3 if s._is_cscalar: - with pytest.raises(TypeError, match="an integer is required"): + with pytest.raises(TypeError, match="an integer is required|expected integer"): s << Scalar.from_value(4.4) else: s << Scalar.from_value(4.4) From d31b3decb03cdfa118064e7703e87b3056538ced Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Mon, 3 Apr 2023 21:54:39 -0500 Subject: [PATCH 03/48] skip notebooks and try mamba --- .github/workflows/test_and_build.yml | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index e29a225a5..49b0ed30e 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -133,23 +133,23 @@ jobs: 1 1 1 -# - name: Setup mamba -# uses: conda-incubator/setup-miniconda@v2 -# id: setup_mamba -# continue-on-error: true -# with: -# miniforge-variant: Mambaforge -# miniforge-version: latest -# use-mamba: true -# python-version: ${{ steps.pyver.outputs.selected }} -# channels: conda-forge,${{ contains(steps.pyver.outputs.selected, 'pypy') && 'defaults' || 'nodefaults' }} -# channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }} -# activate-environment: graphblas -# auto-activate-base: false + - name: Setup mamba + uses: conda-incubator/setup-miniconda@v2 + id: setup_mamba + continue-on-error: true + with: + miniforge-variant: Mambaforge + miniforge-version: latest + use-mamba: true + python-version: ${{ steps.pyver.outputs.selected }} + channels: conda-forge,${{ contains(steps.pyver.outputs.selected, 'pypy') && 'defaults' || 'nodefaults' }} + channel-priority: ${{ contains(steps.pyver.outputs.selected, 'pypy') && 'flexible' || 'strict' }} + activate-environment: graphblas + auto-activate-base: false - name: Setup conda uses: conda-incubator/setup-miniconda@v2 id: setup_conda -# if: steps.setup_mamba.outcome == 'failure' + if: steps.setup_mamba.outcome == 'failure' continue-on-error: false with: auto-update-conda: true @@ -217,7 +217,7 @@ jobs: else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))') fi - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') }} == true || ${{ startsWith(steps.pyver.outputs.selected, '3.11') }} == true || $(python -c 'import random ; print(random.random() < .1)') == True ]]; then + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]]; then # Some packages aren't available for pypy or Python 3.11 (and 10% chance to not install these otherwise) numba="" sparse="" @@ -396,7 +396,7 @@ jobs: - name: codecov uses: codecov/codecov-action@v3 - name: Notebooks Execution check - if: matrix.slowtask == 'notebooks' + if: matrix.slowtask == 'notebooks' && !contains(steps.pyver.outputs.selected, 'pypy') && !startsWith(steps.pyver.outputs.selected, '3.11') run: jupyter nbconvert --to notebook --execute notebooks/*ipynb finish: From 9c6bb515368c71db5d440ae30c5c4b7ce7fba642 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Mon, 3 Apr 2023 22:18:05 -0500 Subject: [PATCH 04/48] Only test pypy --- .github/workflows/test_and_build.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 49b0ed30e..cc9a72e07 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -115,8 +115,8 @@ jobs: 1 1 1 - 1 - 1 + 1000 + 1000 - name: RNG for source of python-suitesparse-graphblas uses: ddradar/choose-random-action@v2.0.2 id: sourcetype @@ -218,7 +218,7 @@ jobs: numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))') fi if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]]; then - # Some packages aren't available for pypy or Python 3.11 (and 10% chance to not install these otherwise) + # Some packages aren't available for pypy or Python 3.11 numba="" sparse="" awkward="" @@ -231,10 +231,8 @@ jobs: npver="" spver="" pdver="" - akver="" - nxver="" + # nxver="" yamlver="" - sparsever="" else numba=numba${numbaver} sparse=sparse${sparsever} From 02d261cf34b1486261ad2fd885cce3d8f4029a9b Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Mon, 3 Apr 2023 22:27:58 -0500 Subject: [PATCH 05/48] bump pandas 2.0.0 --- .github/workflows/test_and_build.yml | 8 ++++---- scripts/check_versions.sh | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index cc9a72e07..cd46a0100 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -172,22 +172,22 @@ jobs: if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.8') }} == true ]]; then npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))') - pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", ""]))') + pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))') elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.9') }} == true ]]; then npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))') - pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", ""]))') + pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))') elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.10') }} == true ]]; then npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))') - pdver=$(python -c 'import random ; print(random.choice(["=1.3", "=1.4", "=1.5", ""]))') + pdver=$(python -c 'import random ; print(random.choice(["=1.3", "=1.4", "=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))') else # Python 3.11 npver=$(python -c 'import random ; print(random.choice(["=1.23", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", ""]))') - pdver=$(python -c 'import random ; print(random.choice(["=1.5", ""]))') + pdver=$(python -c 'import random ; print(random.choice(["=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.10", "=2.0", "=2.1", ""]))') fi if [[ ${{ steps.sourcetype.outputs.selected }} == "source" || ${{ steps.sourcetype.outputs.selected }} == "upstream" ]]; then diff --git a/scripts/check_versions.sh b/scripts/check_versions.sh index eb785df1c..3e798ecea 100755 --- a/scripts/check_versions.sh +++ b/scripts/check_versions.sh @@ -4,7 +4,7 @@ # This may be helpful when updating dependency versions in CI. # Tip: add `--json` for more information. conda search 'numpy[channel=conda-forge]>=1.24.2' -conda search 'pandas[channel=conda-forge]>=1.5.3' +conda search 'pandas[channel=conda-forge]>=2.0.0' conda search 'scipy[channel=conda-forge]>=1.10.1' conda search 'networkx[channel=conda-forge]>=3.0' conda search 'awkward[channel=conda-forge]>=2.1.1' From 61f56601b03e2262a9fadca9be9087932cf52c33 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Tue, 4 Apr 2023 09:54:47 -0500 Subject: [PATCH 06/48] Don't test against pypy in CI --- .github/workflows/test_and_build.yml | 46 +++++++++++++--------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index cd46a0100..9a5544ae7 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -81,7 +81,7 @@ jobs: shell: bash -l {0} strategy: # To "stress test" in CI, set `fail-fast` to `false` and perhaps add more items to `matrix.slowtask` - fail-fast: false + fail-fast: true # The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype]. # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. @@ -102,21 +102,19 @@ jobs: id: pyver with: # We should support major Python versions for at least 36-42 months - # We could probably support pypy if numba were optional + # We may be able to support pypy if anybody asks for it + # 3.8.16 0_73_pypy + # 3.9.16 0_73_pypy contents: | 3.8 3.9 3.10 3.11 - 3.8.16 0_73_pypy - 3.9.16 0_73_pypy weights: | 1 1 1 1 - 1000 - 1000 - name: RNG for source of python-suitesparse-graphblas uses: ddradar/choose-random-action@v2.0.2 id: sourcetype @@ -217,32 +215,28 @@ jobs: else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))') fi - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]]; then - # Some packages aren't available for pypy or Python 3.11 + fmm=fast_matrix_market${fmmver} + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.11') }} == true || $(python -c 'import random ; print(random.random() < .15)') == True ]]; then + # Some packages aren't available for pypy or Python 3.11; 15% otherwise numba="" sparse="" awkward="" - fmm="" numbaver=NA sparsever=NA akver=NA - fmmver=NA - # XXX: temporarily be more flexible - npver="" - spver="" - pdver="" - # nxver="" - yamlver="" + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') }} ]]; then + fmm="" + fmmver=NA + # Be more flexible until we determine what versions are supported by pypy + npver="" + spver="" + pdver="" + yamlver="" + fi else numba=numba${numbaver} sparse=sparse${sparsever} awkward=awkward${akver} - fmm=fast_matrix_market${fmmver} - if [[ ${{ contains(steps.pyver.outputs.selected, '3.11') }} == true ]]; then - # Numba is not yet available for Python 3.11 - numba="" - numbaver=NA - fi fi echo "versions: np${npver} sp${spver} pd${pdver} ak${akver} nx${nxver} numba${numbaver} yaml${yamlver} sparse${sparsever} psgver${psgver}" @@ -394,8 +388,12 @@ jobs: - name: codecov uses: codecov/codecov-action@v3 - name: Notebooks Execution check - if: matrix.slowtask == 'notebooks' && !contains(steps.pyver.outputs.selected, 'pypy') && !startsWith(steps.pyver.outputs.selected, '3.11') - run: jupyter nbconvert --to notebook --execute notebooks/*ipynb + if: matrix.slowtask == 'notebooks' + run: | + # Run notebooks only if numba is installed + if python -c 'import numba' 2> /dev/null ; then + jupyter nbconvert --to notebook --execute notebooks/*ipynb + fi finish: needs: build_and_test From 71af5e776895d08ac37ab35108f93fbca0cfa409 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Tue, 4 Apr 2023 11:14:00 -0500 Subject: [PATCH 07/48] Update classifiers (we don't officially support PyPy) --- pyproject.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9eb39aa1e..5a70033fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,8 +49,6 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", "Intended Audience :: Developers", "Intended Audience :: Other Audience", "Intended Audience :: Science/Research", From 6200a9f4ec359ca99902d881cbea9ce25c4cab95 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 5 Apr 2023 08:38:39 -0500 Subject: [PATCH 08/48] expand optional dependencies --- .pre-commit-config.yaml | 4 +-- pyproject.toml | 74 +++++++++++++++++++++++++++++------------ 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 13caf89e4..b092cdf0d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,7 +53,7 @@ repos: - id: black - id: black-jupyter - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.260 + rev: v0.0.261 hooks: - id: ruff args: [--fix-only, --show-fixes] @@ -81,7 +81,7 @@ repos: additional_dependencies: [tomli] files: ^(graphblas|docs)/ - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.260 + rev: v0.0.261 hooks: - id: ruff - repo: https://github.com/sphinx-contrib/sphinx-lint diff --git a/pyproject.toml b/pyproject.toml index 5a70033fb..66cf8114a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,11 +58,13 @@ classifiers = [ "Topic :: Software Development :: Libraries :: Python Modules", ] dependencies = [ - "suitesparse-graphblas >=7.4.0.0, <7.5", "numpy >=1.21", - "numba >=0.55", "donfig >=0.6", "pyyaml >=5.4", + # These won't be installed by default after 2024.3.0 + # Use e.g. "python-graphblas[suitesparse]" or "python-graphblas[default]" instead + "suitesparse-graphblas >=7.4.0.0, <7.5", + "numba >=0.55", ] [project.urls] @@ -72,37 +74,67 @@ repository = "https://github.com/python-graphblas/python-graphblas" changelog = "https://github.com/python-graphblas/python-graphblas/releases" [project.optional-dependencies] -repr = [ - "pandas >=1.2", +suitesparse = [ + "suitesparse-graphblas >=7.4.0.0, <7.5", ] -io = [ +networkx = [ "networkx >=2.8", +] +numba = [ + "numba >=0.55", +] +pandas = [ + "pandas >=1.2", +] +scipy = [ "scipy >=1.8", +] +suitesparse-udf = [ + "python-graphblas[suitesparse]", + "python-graphblas[numba]", +] +repr = [ + "python-graphblas[pandas]", +] +io = [ + "python-graphblas[networkx]", + "python-graphblas[numba]", + "python-graphblas[scipy]", "awkward >=1.9", - "sparse >=0.12", "fast-matrix-market >=1.4.5", + "sparse >=0.12", ] viz = [ + "python-graphblas[networkx]", + "python-graphblas[scipy]", "matplotlib >=3.5", ] +datashade = [ + "python-graphblas[numba]", + "python-graphblas[pandas]", + "python-graphblas[scipy]", + "datashader >=0.12", + "hvplot >=0.7", +] test = [ - "pytest", - "packaging", - "pandas >=1.2", - "scipy >=1.8", - "tomli", + "python-graphblas[suitesparse]", + "python-graphblas[pandas]", + "python-graphblas[scipy]", + "packaging >=21", + "pytest >=6.2", + "tomli >=1", +] +default = [ + "python-graphblas[suitesparse-udf]", + "python-graphblas[pandas]", + "python-graphblas[scipy]", ] complete = [ - "pandas >=1.2", - "networkx >=2.8", - "scipy >=1.8", - "awkward >=1.9", - "sparse >=0.12", - "fast-matrix-market >=1.4.5", - "matplotlib >=3.5", - "pytest", - "packaging", - "tomli", + "python-graphblas[default]", + "python-graphblas[io]", + "python-graphblas[viz]", + "python-graphblas[test]", + "python-graphblas[datashade]", ] [tool.setuptools] From d4ae2080a435d1f59b30e51a58f8b2540b98631f Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 5 Apr 2023 08:47:30 -0500 Subject: [PATCH 09/48] networkx 3.1 --- .github/workflows/test_and_build.yml | 2 +- scripts/check_versions.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 9a5544ae7..3525bf383 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -163,7 +163,7 @@ jobs: # # First let's randomly get versions of dependencies to install. # Consider removing old versions when they become problematic or very old (>=2 years). - nxver=$(python -c 'import random ; print(random.choice(["=2.7", "=2.8", "=3.0", ""]))') + nxver=$(python -c 'import random ; print(random.choice(["=2.7", "=2.8", "=3.0", "=3.1", ""]))') yamlver=$(python -c 'import random ; print(random.choice(["=5.4", "=6.0", ""]))') sparsever=$(python -c 'import random ; print(random.choice(["=0.12", "=0.13", "=0.14", ""]))') fmmver=$(python -c 'import random ; print(random.choice(["=1.4", ""]))') diff --git a/scripts/check_versions.sh b/scripts/check_versions.sh index 3e798ecea..2166c3eef 100755 --- a/scripts/check_versions.sh +++ b/scripts/check_versions.sh @@ -6,7 +6,7 @@ conda search 'numpy[channel=conda-forge]>=1.24.2' conda search 'pandas[channel=conda-forge]>=2.0.0' conda search 'scipy[channel=conda-forge]>=1.10.1' -conda search 'networkx[channel=conda-forge]>=3.0' +conda search 'networkx[channel=conda-forge]>=3.1' conda search 'awkward[channel=conda-forge]>=2.1.1' conda search 'sparse[channel=conda-forge]>=0.14.0' conda search 'fast_matrix_market[channel=conda-forge]>=1.4.5' @@ -14,4 +14,4 @@ conda search 'numba[channel=conda-forge]>=0.56.4' conda search 'pyyaml[channel=conda-forge]>=6.0' conda search 'flake8-bugbear[channel=conda-forge]>=23.3.23' conda search 'flake8-simplify[channel=conda-forge]>=0.20.0' -conda search 'python[channel=conda-forge]>=3.8 *pypy*' +# conda search 'python[channel=conda-forge]>=3.8 *pypy*' From 21ddb7fadccf909d06125ed014ffd943e4132ec3 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 5 Apr 2023 11:12:00 -0500 Subject: [PATCH 10/48] simplify/combine deps --- pyproject.toml | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 66cf8114a..7997b1ad3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -90,51 +90,37 @@ scipy = [ "scipy >=1.8", ] suitesparse-udf = [ - "python-graphblas[suitesparse]", - "python-graphblas[numba]", + "python-graphblas[suitesparse,numba]", ] repr = [ "python-graphblas[pandas]", ] io = [ - "python-graphblas[networkx]", - "python-graphblas[numba]", - "python-graphblas[scipy]", + "python-graphblas[networkx,numba,scipy]", "awkward >=1.9", "fast-matrix-market >=1.4.5", "sparse >=0.12", ] viz = [ - "python-graphblas[networkx]", - "python-graphblas[scipy]", + "python-graphblas[networkx,scipy]", "matplotlib >=3.5", ] datashade = [ - "python-graphblas[numba]", - "python-graphblas[pandas]", - "python-graphblas[scipy]", + "python-graphblas[numba,pandas,scipy]", "datashader >=0.12", "hvplot >=0.7", ] test = [ - "python-graphblas[suitesparse]", - "python-graphblas[pandas]", - "python-graphblas[scipy]", + "python-graphblas[suitesparse,pandas,scipy]", "packaging >=21", "pytest >=6.2", "tomli >=1", ] default = [ - "python-graphblas[suitesparse-udf]", - "python-graphblas[pandas]", - "python-graphblas[scipy]", + "python-graphblas[suitesparse-udf,pandas,scipy]", ] complete = [ - "python-graphblas[default]", - "python-graphblas[io]", - "python-graphblas[viz]", - "python-graphblas[test]", - "python-graphblas[datashade]", + "python-graphblas[default,io,viz,test,datashade]", ] [tool.setuptools] From 3af869ca6af7506c751e9484f27f12c36139cce0 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 7 Apr 2023 11:23:12 -0500 Subject: [PATCH 11/48] Make suitesparse_graphblas optional (in the future); don't install numba on 3.11 yet --- .github/workflows/imports.yml | 6 ++++-- README.md | 2 +- docs/getting_started/index.rst | 2 +- graphblas/__init__.py | 16 +++++++++++++++- pyproject.toml | 19 +++++++++++-------- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/.github/workflows/imports.yml b/.github/workflows/imports.yml index a9863a213..9cfc4bbb0 100644 --- a/.github/workflows/imports.yml +++ b/.github/workflows/imports.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest # strategy: # matrix: - # python-version: ["3.8", "3.9", "3.10"] + # python-version: ["3.8", "3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v3 - name: RNG for Python version @@ -22,14 +22,16 @@ jobs: 3.8 3.9 3.10 + 3.11 weights: | 1 1 1 + 1000 - uses: actions/setup-python@v4 with: python-version: ${{ steps.pyver.outputs.selected }} # python-version: ${{ matrix.python-version }} - run: python -m pip install --upgrade pip - - run: pip install -e . + - run: pip install -e .[default] - run: ./scripts/test_imports.sh diff --git a/README.md b/README.md index dab91782a..8bbd88d9c 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ $ conda install -c conda-forge python-graphblas ``` or pip: ``` -$ pip install python-graphblas +$ pip install python-graphblas[default] ``` This will also install the [SuiteSparse:GraphBLAS](https://github.com/DrTimothyAldenDavis/GraphBLAS) compiled C library. diff --git a/docs/getting_started/index.rst b/docs/getting_started/index.rst index d603df30b..3726131d2 100644 --- a/docs/getting_started/index.rst +++ b/docs/getting_started/index.rst @@ -15,7 +15,7 @@ Using pip: :: - pip install python-graphblas + pip install python-graphblas[default] Whether installing with conda or pip, the underlying package that is imported in Python is named ``graphblas``. The convention is to import as: diff --git a/graphblas/__init__.py b/graphblas/__init__.py index 87311599c..0aa7dff11 100644 --- a/graphblas/__init__.py +++ b/graphblas/__init__.py @@ -137,7 +137,21 @@ def _init(backend_arg, blocking, automatic=False): backend = backend_arg if backend in {"suitesparse", "suitesparse-vanilla"}: - from suitesparse_graphblas import ffi, initialize, is_initialized, lib + try: + from suitesparse_graphblas import ffi, initialize, is_initialized, lib + except ImportError: + raise ImportError( + f"suitesparse_graphblas is required for {backend!r} backend. " + "It may be installed with pip or conda:\n\n" + " $ pip install suitesparse-graphblas\n" + " $ conda install -c conda-forge python-suitesparse-graphblas\n\n" + "SuiteSparse:GraphBLAS is the primary C implementation and backend of " + "python-graphblas and is what we recommend to most users. If you are " + "installing python-graphblas with pip, we recommend installing with one " + "of the following to automatically include suitespare-graphblas:\n\n" + " $ pip install python-graphblas[suitesparse]\n" + " $ pip install python-graphblas[default]" + ) from None if is_initialized(): mode = ffi.new("int32_t*") diff --git a/pyproject.toml b/pyproject.toml index 7997b1ad3..2d81cf949 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,7 @@ dependencies = [ # These won't be installed by default after 2024.3.0 # Use e.g. "python-graphblas[suitesparse]" or "python-graphblas[default]" instead "suitesparse-graphblas >=7.4.0.0, <7.5", - "numba >=0.55", + "numba >=0.55; python_version<'3.11'", # make optional where numba is not supported ] [project.urls] @@ -89,23 +89,24 @@ pandas = [ scipy = [ "scipy >=1.8", ] -suitesparse-udf = [ +suitesparse-udf = [ # udf requires numba "python-graphblas[suitesparse,numba]", ] repr = [ "python-graphblas[pandas]", ] io = [ - "python-graphblas[networkx,numba,scipy]", - "awkward >=1.9", + "python-graphblas[networkx,scipy]", + "python-graphblas[numba]; python_version<'3.11'", + "awkward >=1.9; python_version<'3.11'", # make optional, b/c awkward needs numba + "sparse >=0.12; python_version<'3.11'", # make optional, b/c sparse needs numba "fast-matrix-market >=1.4.5", - "sparse >=0.12", ] viz = [ "python-graphblas[networkx,scipy]", "matplotlib >=3.5", ] -datashade = [ +datashade = [ # datashade requires numba "python-graphblas[numba,pandas,scipy]", "datashader >=0.12", "hvplot >=0.7", @@ -117,10 +118,12 @@ test = [ "tomli >=1", ] default = [ - "python-graphblas[suitesparse-udf,pandas,scipy]", + "python-graphblas[suitesparse,pandas,scipy]", + "python-graphblas[numba]; python_version<'3.11'", # make optional where numba is not supported ] complete = [ - "python-graphblas[default,io,viz,test,datashade]", + "python-graphblas[default,io,viz,test]", + "python-graphblas[datashade]; python_version<'3.11'", # make optional, b/c datashade needs numba ] [tool.setuptools] From 5cdaa317d63273e7e146b9ea96c5a3a6406cb44c Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 7 Apr 2023 11:31:32 -0500 Subject: [PATCH 12/48] Test numba 0.57.0rc1 --- .github/workflows/imports.yml | 2 +- .github/workflows/test_and_build.yml | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/imports.yml b/.github/workflows/imports.yml index 9cfc4bbb0..99a6d5e19 100644 --- a/.github/workflows/imports.yml +++ b/.github/workflows/imports.yml @@ -27,7 +27,7 @@ jobs: 1 1 1 - 1000 + 1 - uses: actions/setup-python@v4 with: python-version: ${{ steps.pyver.outputs.selected }} diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 3525bf383..09e173ed0 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -215,9 +215,10 @@ jobs: else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))') fi + numbaver="0.57.0rc1" # XXX: testing numba fmm=fast_matrix_market${fmmver} - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.11') }} == true || $(python -c 'import random ; print(random.random() < .15)') == True ]]; then - # Some packages aren't available for pypy or Python 3.11; 15% otherwise + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .15)') == True ]]; then + # Some packages aren't available for pypy or Python 3.12; 15% otherwise numba="" sparse="" awkward="" @@ -240,7 +241,8 @@ jobs: fi echo "versions: np${npver} sp${spver} pd${pdver} ak${akver} nx${nxver} numba${numbaver} yaml${yamlver} sparse${sparsever} psgver${psgver}" - $(command -v mamba || command -v conda) install packaging pytest coverage coveralls=3.3.1 pytest-randomly cffi donfig tomli \ + # XXX: added `-c numba` + $(command -v mamba || command -v conda) install -c numba packaging pytest coverage coveralls=3.3.1 pytest-randomly cffi donfig tomli \ pyyaml${yamlver} ${sparse} pandas${pdver} scipy${spver} numpy${npver} ${awkward} \ networkx${nxver} ${numba} ${fmm} ${psg} \ ${{ matrix.slowtask == 'pytest_bizarro' && 'black' || '' }} \ From 78c26669677d5e9d35a56c7ceee0acae0615e649 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 7 Apr 2023 11:34:18 -0500 Subject: [PATCH 13/48] oops --- .github/workflows/test_and_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 09e173ed0..cf39659e1 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -215,7 +215,7 @@ jobs: else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))') fi - numbaver="0.57.0rc1" # XXX: testing numba + numbaver="=0.57.0rc1" # XXX: testing numba fmm=fast_matrix_market${fmmver} if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .15)') == True ]]; then # Some packages aren't available for pypy or Python 3.12; 15% otherwise From ce0a667efda2de1ab0b452cfaaeffb1c63ffe1c0 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 7 Apr 2023 11:50:22 -0500 Subject: [PATCH 14/48] Ignore deprecation warning raised by awkward in Python 3.11 --- .github/workflows/test_and_build.yml | 8 ++++---- pyproject.toml | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index cf39659e1..d36f326e1 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -168,22 +168,22 @@ jobs: sparsever=$(python -c 'import random ; print(random.choice(["=0.12", "=0.13", "=0.14", ""]))') fmmver=$(python -c 'import random ; print(random.choice(["=1.4", ""]))') if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.8') }} == true ]]; then - npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))') + npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", "=1.24", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))') pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))') elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.9') }} == true ]]; then - npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))') + npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", "=1.24", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))') pdver=$(python -c 'import random ; print(random.choice(["=1.2", "=1.3", "=1.4", "=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))') elif [[ ${{ startsWith(steps.pyver.outputs.selected, '3.10') }} == true ]]; then - npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", ""]))') + npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", "=1.24", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))') pdver=$(python -c 'import random ; print(random.choice(["=1.3", "=1.4", "=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", "=2.0", "=2.1", ""]))') else # Python 3.11 - npver=$(python -c 'import random ; print(random.choice(["=1.23", ""]))') + npver=$(python -c 'import random ; print(random.choice(["=1.23", "=1.24", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.9", "=1.10", ""]))') pdver=$(python -c 'import random ; print(random.choice(["=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.10", "=2.0", "=2.1", ""]))') diff --git a/pyproject.toml b/pyproject.toml index 2d81cf949..381afddf3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -189,6 +189,9 @@ filterwarnings = [ # https://setuptools.pypa.io/en/latest/history.html#v67-5-0 "ignore:pkg_resources is deprecated as an API:DeprecationWarning:pkg_resources", + # sre_parse deprecated in 3.11; this is triggered by awkward 0.10 + "ignore:module 'sre_parse' is deprecated:DeprecationWarning:", + # pypy gives this warning "ignore:can't resolve package from __spec__ or __package__:ImportWarning:", ] From 0b6dcaf20ceae830489ad523410193d12ef1bb10 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 7 Apr 2023 12:00:11 -0500 Subject: [PATCH 15/48] try to ignore warning from sparse --- .github/workflows/test_and_build.yml | 2 +- pyproject.toml | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index d36f326e1..d09978a28 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -81,7 +81,7 @@ jobs: shell: bash -l {0} strategy: # To "stress test" in CI, set `fail-fast` to `false` and perhaps add more items to `matrix.slowtask` - fail-fast: true + fail-fast: false # The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype]. # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. diff --git a/pyproject.toml b/pyproject.toml index 381afddf3..0e9a32648 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,7 @@ dependencies = [ # These won't be installed by default after 2024.3.0 # Use e.g. "python-graphblas[suitesparse]" or "python-graphblas[default]" instead "suitesparse-graphblas >=7.4.0.0, <7.5", - "numba >=0.55; python_version<'3.11'", # make optional where numba is not supported + "numba >=0.55; python_version<'3.12'", # make optional where numba is not supported ] [project.urls] @@ -97,9 +97,9 @@ repr = [ ] io = [ "python-graphblas[networkx,scipy]", - "python-graphblas[numba]; python_version<'3.11'", - "awkward >=1.9; python_version<'3.11'", # make optional, b/c awkward needs numba - "sparse >=0.12; python_version<'3.11'", # make optional, b/c sparse needs numba + "python-graphblas[numba]; python_version<'3.12'", + "awkward >=1.9", + "sparse >=0.12; python_version<'3.12'", # make optional, b/c sparse needs numba "fast-matrix-market >=1.4.5", ] viz = [ @@ -119,11 +119,11 @@ test = [ ] default = [ "python-graphblas[suitesparse,pandas,scipy]", - "python-graphblas[numba]; python_version<'3.11'", # make optional where numba is not supported + "python-graphblas[numba]; python_version<'3.12'", # make optional where numba is not supported ] complete = [ "python-graphblas[default,io,viz,test]", - "python-graphblas[datashade]; python_version<'3.11'", # make optional, b/c datashade needs numba + "python-graphblas[datashade]; python_version<'3.12'", # make optional, b/c datashade needs numba ] [tool.setuptools] @@ -178,6 +178,7 @@ filterwarnings = [ "error", # MAINT: we can drop support for sparse <0.13 at any time "ignore:`np.bool` is a deprecated alias:DeprecationWarning:sparse._umath", # sparse <0.13 + "ignore:In the future `np.bool` will be defined as the corresponding NumPy scalar:FutureWarning:sparse._umath", # sparse 0.14.0 (2022-02-24) began raising this warning; it has been reported and fixed upstream. "ignore:coords should be an ndarray. This will raise a ValueError:DeprecationWarning:sparse._coo.core", From 67a5b716df10b31f28bd12bbf7f545efadd1da15 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 7 Apr 2023 12:27:22 -0500 Subject: [PATCH 16/48] drop sparse 0.12 (which is really old and annoying to support) --- .github/workflows/test_and_build.yml | 14 +++++++------- graphblas/io.py | 4 ++-- pyproject.toml | 5 +---- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index d09978a28..22528ddb1 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -165,7 +165,7 @@ jobs: # Consider removing old versions when they become problematic or very old (>=2 years). nxver=$(python -c 'import random ; print(random.choice(["=2.7", "=2.8", "=3.0", "=3.1", ""]))') yamlver=$(python -c 'import random ; print(random.choice(["=5.4", "=6.0", ""]))') - sparsever=$(python -c 'import random ; print(random.choice(["=0.12", "=0.13", "=0.14", ""]))') + sparsever=$(python -c 'import random ; print(random.choice(["=0.13", "=0.14", ""]))') fmmver=$(python -c 'import random ; print(random.choice(["=1.4", ""]))') if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.8') }} == true ]]; then npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", "=1.24", ""]))') @@ -217,15 +217,16 @@ jobs: fi numbaver="=0.57.0rc1" # XXX: testing numba fmm=fast_matrix_market${fmmver} - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .15)') == True ]]; then - # Some packages aren't available for pypy or Python 3.12; 15% otherwise + awkward=awkward${akver} + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .20)') == True ]]; then + # Some packages aren't available for pypy or Python 3.12; 20% otherwise numba="" - sparse="" - awkward="" numbaver=NA + sparse="" sparsever=NA - akver=NA if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') }} ]]; then + awkward="" + akver=NA fmm="" fmmver=NA # Be more flexible until we determine what versions are supported by pypy @@ -237,7 +238,6 @@ jobs: else numba=numba${numbaver} sparse=sparse${sparsever} - awkward=awkward${akver} fi echo "versions: np${npver} sp${spver} pd${pdver} ak${akver} nx${nxver} numba${numbaver} yaml${yamlver} sparse${sparsever} psgver${psgver}" diff --git a/graphblas/io.py b/graphblas/io.py index 5d717b986..2b8e71b33 100644 --- a/graphblas/io.py +++ b/graphblas/io.py @@ -455,7 +455,7 @@ def to_awkward(A, format=None): indices, values = A.to_coo() form = RecordForm( contents=[ - NumpyForm(A.dtype.numba_type.name, form_key="node1"), # XXX: is numba required? + NumpyForm(A.dtype.np_type.name, form_key="node1"), NumpyForm("int64", form_key="node0"), ], fields=["values", "indices"], @@ -489,7 +489,7 @@ def to_awkward(A, format=None): RecordForm( contents=[ NumpyForm("int64", form_key="node3"), - NumpyForm(A.dtype.numba_type.name, form_key="node4"), + NumpyForm(A.dtype.np_type.name, form_key="node4"), ], fields=["indices", "values"], ), diff --git a/pyproject.toml b/pyproject.toml index 0e9a32648..a168174c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -99,7 +99,7 @@ io = [ "python-graphblas[networkx,scipy]", "python-graphblas[numba]; python_version<'3.12'", "awkward >=1.9", - "sparse >=0.12; python_version<'3.12'", # make optional, b/c sparse needs numba + "sparse >=0.13; python_version<'3.12'", # make optional, b/c sparse needs numba "fast-matrix-market >=1.4.5", ] viz = [ @@ -176,9 +176,6 @@ filterwarnings = [ # See: https://docs.python.org/3/library/warnings.html#describing-warning-filters # and: https://docs.pytest.org/en/7.2.x/how-to/capture-warnings.html#controlling-warnings "error", - # MAINT: we can drop support for sparse <0.13 at any time - "ignore:`np.bool` is a deprecated alias:DeprecationWarning:sparse._umath", # sparse <0.13 - "ignore:In the future `np.bool` will be defined as the corresponding NumPy scalar:FutureWarning:sparse._umath", # sparse 0.14.0 (2022-02-24) began raising this warning; it has been reported and fixed upstream. "ignore:coords should be an ndarray. This will raise a ValueError:DeprecationWarning:sparse._coo.core", From 0f66e652f5232a762d6191abc59d9716d15dac13 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 7 Apr 2023 12:37:38 -0500 Subject: [PATCH 17/48] sre_constants also deprecated --- pyproject.toml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a168174c5..1eaa942e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,7 @@ dependencies = [ # These won't be installed by default after 2024.3.0 # Use e.g. "python-graphblas[suitesparse]" or "python-graphblas[default]" instead "suitesparse-graphblas >=7.4.0.0, <7.5", - "numba >=0.55; python_version<'3.12'", # make optional where numba is not supported + "numba >=0.55; python_version<'3.11'", # make optional where numba is not supported ] [project.urls] @@ -97,9 +97,9 @@ repr = [ ] io = [ "python-graphblas[networkx,scipy]", - "python-graphblas[numba]; python_version<'3.12'", + "python-graphblas[numba]; python_version<'3.11'", "awkward >=1.9", - "sparse >=0.13; python_version<'3.12'", # make optional, b/c sparse needs numba + "sparse >=0.13; python_version<'3.11'", # make optional, b/c sparse needs numba "fast-matrix-market >=1.4.5", ] viz = [ @@ -119,11 +119,11 @@ test = [ ] default = [ "python-graphblas[suitesparse,pandas,scipy]", - "python-graphblas[numba]; python_version<'3.12'", # make optional where numba is not supported + "python-graphblas[numba]; python_version<'3.11'", # make optional where numba is not supported ] complete = [ "python-graphblas[default,io,viz,test]", - "python-graphblas[datashade]; python_version<'3.12'", # make optional, b/c datashade needs numba + "python-graphblas[datashade]; python_version<'3.11'", # make optional, b/c datashade needs numba ] [tool.setuptools] @@ -189,6 +189,7 @@ filterwarnings = [ # sre_parse deprecated in 3.11; this is triggered by awkward 0.10 "ignore:module 'sre_parse' is deprecated:DeprecationWarning:", + "ignore:module 'sre_constants' is deprecated:DeprecationWarning:", # pypy gives this warning "ignore:can't resolve package from __spec__ or __package__:ImportWarning:", From fd82c1227d47f77e39063db5a3a04df60f15e4df Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 7 Apr 2023 14:14:35 -0500 Subject: [PATCH 18/48] clean up --- .github/workflows/test_and_build.yml | 2 +- graphblas/tests/test_io.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 22528ddb1..d47912005 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -81,7 +81,7 @@ jobs: shell: bash -l {0} strategy: # To "stress test" in CI, set `fail-fast` to `false` and perhaps add more items to `matrix.slowtask` - fail-fast: false + fail-fast: true # The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype]. # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. diff --git a/graphblas/tests/test_io.py b/graphblas/tests/test_io.py index f3527412b..ada092025 100644 --- a/graphblas/tests/test_io.py +++ b/graphblas/tests/test_io.py @@ -29,7 +29,6 @@ import awkward as ak except ImportError: # pragma: no cover (import) ak = None -ak = None # XXX try: import fast_matrix_market as fmm From ccb1b30ae6322712138826c4e150d99dc70ce964 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sat, 8 Apr 2023 20:15:39 -0500 Subject: [PATCH 19/48] `shouldhave` make tests a little more clear (I think) Also, bump version of `fast_matrix_market`, and randomly generate OS for import test. --- .github/workflows/imports.yml | 21 +++++++++- .github/workflows/test_and_build.yml | 10 ++--- graphblas/tests/conftest.py | 6 +++ graphblas/tests/test_matrix.py | 16 ++++---- graphblas/tests/test_numpyops.py | 12 +++--- graphblas/tests/test_op.py | 60 ++++++++++++++-------------- scripts/check_versions.sh | 2 +- 7 files changed, 77 insertions(+), 50 deletions(-) diff --git a/.github/workflows/imports.yml b/.github/workflows/imports.yml index 99a6d5e19..b88315dae 100644 --- a/.github/workflows/imports.yml +++ b/.github/workflows/imports.yml @@ -7,11 +7,30 @@ on: - main jobs: - test_imports: + rngs: runs-on: ubuntu-latest + outputs: + os: ${{ steps.os.outputs.selected }} + steps: + - name: RNG for os + uses: ddradar/choose-random-action@v2.0.2 + id: os + with: + contents: | + ubuntu-latest + macos-latest + windows-latest + weights: | + 1 + 1 + 1 + test_imports: + needs: rngs + runs-on: ${{ needs.rngs.outputs.os }} # strategy: # matrix: # python-version: ["3.8", "3.9", "3.10", "3.11"] + # os: ["ubuntu-latest", "macos-latest", "windows-latest"] steps: - uses: actions/checkout@v3 - name: RNG for Python version diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index d47912005..db9270487 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -166,7 +166,7 @@ jobs: nxver=$(python -c 'import random ; print(random.choice(["=2.7", "=2.8", "=3.0", "=3.1", ""]))') yamlver=$(python -c 'import random ; print(random.choice(["=5.4", "=6.0", ""]))') sparsever=$(python -c 'import random ; print(random.choice(["=0.13", "=0.14", ""]))') - fmmver=$(python -c 'import random ; print(random.choice(["=1.4", ""]))') + fmmver=$(python -c 'import random ; print(random.choice(["=1.4", "=1.5", ""]))') if [[ ${{ startsWith(steps.pyver.outputs.selected, '3.8') }} == true ]]; then npver=$(python -c 'import random ; print(random.choice(["=1.21", "=1.22", "=1.23", "=1.24", ""]))') spver=$(python -c 'import random ; print(random.choice(["=1.8", "=1.9", "=1.10", ""]))') @@ -211,15 +211,15 @@ jobs: psgver="" fi if [[ $npver == "=1.21" ]] ; then - numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", ""]))') + numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", "=0.57", ""]))') else - numbaver=$(python -c 'import random ; print(random.choice(["=0.56", ""]))') + numbaver=$(python -c 'import random ; print(random.choice(["=0.56", "=0.57", ""]))') fi numbaver="=0.57.0rc1" # XXX: testing numba fmm=fast_matrix_market${fmmver} awkward=awkward${akver} - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .20)') == True ]]; then - # Some packages aren't available for pypy or Python 3.12; 20% otherwise + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .25)') == True ]]; then + # Some packages aren't available for pypy or Python 3.12; 25% otherwise numba="" numbaver=NA sparse="" diff --git a/graphblas/tests/conftest.py b/graphblas/tests/conftest.py index 24aba085f..8bed4f0b4 100644 --- a/graphblas/tests/conftest.py +++ b/graphblas/tests/conftest.py @@ -7,6 +7,7 @@ import pytest import graphblas as gb +from graphblas.core import _supports_udfs as supports_udfs orig_binaryops = set() orig_semirings = set() @@ -116,3 +117,8 @@ def inner(*args, **kwargs): def compute(x): return x + + +def shouldhave(module, opname): + """Whether an "operator" module should have the given operator.""" + return supports_udfs or hasattr(module, opname) diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index a8571df39..1c211990b 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -25,7 +25,7 @@ OutputNotEmpty, ) -from .conftest import autocompute, compute +from .conftest import autocompute, compute, shouldhave from graphblas import Matrix, Scalar, Vector # isort:skip (for dask-graphblas) @@ -1357,7 +1357,7 @@ def test_reduce_agg(A): expected = unary.sqrt[float](squared).new() w5 = A.reduce_rowwise(agg.hypot).new() assert w5.isclose(expected) - if supports_udfs or hasattr(monoid.numpy, "hypot"): + if shouldhave(monoid.numpy, "hypot"): w6 = A.reduce_rowwise(monoid.numpy.hypot[float]).new() assert w6.isclose(expected) w7 = Vector(w5.dtype, size=w5.size) @@ -1365,7 +1365,7 @@ def test_reduce_agg(A): assert w7.isclose(expected) w8 = A.reduce_rowwise(agg.logaddexp).new() - if supports_udfs or hasattr(monoid.numpy, "logaddexp"): + if shouldhave(monoid.numpy, "logaddexp"): expected = A.reduce_rowwise(monoid.numpy.logaddexp[float]).new() assert w8.isclose(w8) @@ -3119,10 +3119,10 @@ def test_infix_sugar(A): assert binary.times(2, A).isequal(2 * A) assert binary.truediv(A, 2).isequal(A / 2) assert binary.truediv(5, A).isequal(5 / A) - if supports_udfs or hasattr(binary, "floordiv"): + if shouldhave(binary, "floordiv"): assert binary.floordiv(A, 2).isequal(A // 2) assert binary.floordiv(5, A).isequal(5 // A) - if supports_udfs or hasattr(binary.numpy, "mod"): + if shouldhave(binary.numpy, "mod"): assert binary.numpy.mod(A, 2).isequal(A % 2) assert binary.numpy.mod(5, A).isequal(5 % A) assert binary.pow(A, 2).isequal(A**2) @@ -3151,7 +3151,7 @@ def test_infix_sugar(A): assert binary.ge(A, 4).isequal(A >= 4) assert binary.eq(A, 4).isequal(A == 4) assert binary.ne(A, 4).isequal(A != 4) - if supports_udfs or hasattr(binary, "floordiv") and hasattr(binary.numpy, "mod"): + if shouldhave(binary, "floordiv") and shouldhave(binary.numpy, "mod"): x, y = divmod(A, 3) assert binary.floordiv(A, 3).isequal(x) assert binary.numpy.mod(A, 3).isequal(y) @@ -3194,12 +3194,12 @@ def test_infix_sugar(A): B /= 2 assert type(B) is Matrix assert binary.truediv(A, 2).isequal(B) - if supports_udfs or hasattr(binary, "floordiv"): + if shouldhave(binary, "floordiv"): B = A.dup() B //= 2 assert type(B) is Matrix assert binary.floordiv(A, 2).isequal(B) - if supports_udfs or hasattr(binary.numpy, "mod"): + if shouldhave(binary.numpy, "mod"): B = A.dup() B %= 2 assert type(B) is Matrix diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 685bbb064..9ba63960f 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -15,7 +15,7 @@ from graphblas.core import _supports_udfs as supports_udfs from graphblas.dtypes import _supports_complex -from .conftest import compute +from .conftest import compute, shouldhave is_win = sys.platform.startswith("win") suitesparse = backend == "suitesparse" @@ -73,7 +73,7 @@ def test_npunary(): # due to limitation of MSVC with complex blocklist["FC64"].update({"arcsin", "arcsinh"}) blocklist["FC32"] = {"arcsin", "arcsinh"} - if supports_udfs or hasattr(gb.binary, "isclose"): + if shouldhave(gb.binary, "isclose"): isclose = gb.binary.isclose(1e-6, 0) else: isclose = None @@ -157,19 +157,19 @@ def test_npbinary(): "FP64": {"floor_divide"}, # numba/numpy difference for 1.0 / 0.0 "BOOL": {"gcd", "lcm", "subtract"}, # not supported by numpy } - if supports_udfs or hasattr(gb.binary, "isclose"): + if shouldhave(gb.binary, "isclose"): isclose = gb.binary.isclose(1e-7, 0) else: isclose = None - if supports_udfs or hasattr(npbinary, "equal"): + if shouldhave(npbinary, "equal"): equal = npbinary.equal else: equal = gb.binary.eq - if supports_udfs or hasattr(npbinary, "isnan"): + if shouldhave(npbinary, "isnan"): isnan = npunary.isnan else: isnan = gb.unary.isnan - if supports_udfs or hasattr(npbinary, "isinf"): + if shouldhave(npbinary, "isinf"): isinf = npunary.isinf else: isinf = gb.unary.isinf diff --git a/graphblas/tests/test_op.py b/graphblas/tests/test_op.py index c4f6bbb74..7e6077904 100644 --- a/graphblas/tests/test_op.py +++ b/graphblas/tests/test_op.py @@ -35,6 +35,8 @@ ) from graphblas.exceptions import DomainMismatch, UdfParseError +from .conftest import shouldhave + if dtypes._supports_complex: from graphblas.dtypes import FC32, FC64 @@ -630,7 +632,7 @@ def test_binary_updates(): vec4 = Vector.from_coo([0], [-3], dtype=dtypes.INT64) result2 = vec4.ewise_mult(vec2, binary.cdiv).new() assert result2.isequal(Vector.from_coo([0], [-1], dtype=dtypes.INT64), check_dtype=True) - if supports_udfs or hasattr(binary, "floordiv"): + if shouldhave(binary, "floordiv"): result3 = vec4.ewise_mult(vec2, binary.floordiv).new() assert result3.isequal(Vector.from_coo([0], [-2], dtype=dtypes.INT64), check_dtype=True) @@ -695,13 +697,13 @@ def test_op_namespace(): assert op.plus is binary.plus assert op.plus_times is semiring.plus_times - if supports_udfs or hasattr(unary.numpy, "fabs"): + if shouldhave(unary.numpy, "fabs"): assert op.numpy.fabs is unary.numpy.fabs - if supports_udfs or hasattr(binary.numpy, "subtract"): + if shouldhave(binary.numpy, "subtract"): assert op.numpy.subtract is binary.numpy.subtract - if supports_udfs or hasattr(binary.numpy, "add"): + if shouldhave(binary.numpy, "add"): assert op.numpy.add is binary.numpy.add - if supports_udfs or hasattr(semiring.numpy, "add_add"): + if shouldhave(semiring.numpy, "add_add"): assert op.numpy.add_add is semiring.numpy.add_add assert len(dir(op)) > 300 if supports_udfs: @@ -769,10 +771,10 @@ def test_op_namespace(): @pytest.mark.slow def test_binaryop_attributes_numpy(): # Some coverage from this test depends on order of tests - if supports_udfs or hasattr(monoid.numpy, "add"): + if shouldhave(monoid.numpy, "add"): assert binary.numpy.add[int].monoid is monoid.numpy.add[int] assert binary.numpy.add.monoid is monoid.numpy.add - if supports_udfs or hasattr(binary.numpy, "subtract"): + if shouldhave(binary.numpy, "subtract"): assert binary.numpy.subtract[int].monoid is None assert binary.numpy.subtract.monoid is None @@ -794,12 +796,12 @@ def plus(x, y): assert op[int].parent is op assert binary.plus[int].parent is binary.plus - if supports_udfs or hasattr(binary.numpy, "add"): + if shouldhave(binary.numpy, "add"): assert binary.numpy.add[int].parent is binary.numpy.add # bad type assert binary.plus[bool].monoid is None - if supports_udfs or hasattr(binary.numpy, "equal"): + if shouldhave(binary.numpy, "equal"): assert binary.numpy.equal[int].monoid is None assert binary.numpy.equal[bool].monoid is monoid.numpy.equal[bool] # sanity @@ -824,7 +826,7 @@ def test_monoid_attributes(): assert monoid.plus.binaryop is binary.plus assert monoid.plus.identities == {typ: 0 for typ in monoid.plus.types} - if supports_udfs or hasattr(monoid.numpy, "add"): + if shouldhave(monoid.numpy, "add"): assert monoid.numpy.add[int].binaryop is binary.numpy.add[int] assert monoid.numpy.add[int].identity == 0 assert monoid.numpy.add.binaryop is binary.numpy.add @@ -841,7 +843,7 @@ def plus(x, y): # pragma: no cover (numba) assert op[int].parent is op assert monoid.plus[int].parent is monoid.plus - if supports_udfs or hasattr(monoid.numpy, "add"): + if shouldhave(monoid.numpy, "add"): assert monoid.numpy.add[int].parent is monoid.numpy.add for attr, val in vars(monoid).items(): @@ -863,7 +865,7 @@ def test_semiring_attributes(): assert semiring.min_plus.monoid is monoid.min assert semiring.min_plus.binaryop is binary.plus - if supports_udfs or hasattr(semiring.numpy, "add_subtract"): + if shouldhave(semiring.numpy, "add_subtract"): assert semiring.numpy.add_subtract[int].monoid is monoid.numpy.add[int] assert semiring.numpy.add_subtract[int].binaryop is binary.numpy.subtract[int] assert semiring.numpy.add_subtract.monoid is monoid.numpy.add @@ -920,7 +922,7 @@ def test_div_semirings(): assert result[0, 0].new() == -2 assert result.dtype == dtypes.FP64 - if supports_udfs or hasattr(semiring, "plus_floordiv"): + if shouldhave(semiring, "plus_floordiv"): result = A1.T.mxm(A2, semiring.plus_floordiv).new() assert result[0, 0].new() == -3 assert result.dtype == dtypes.INT64 @@ -959,7 +961,7 @@ def myplus(x, y): with pytest.raises(TypeError, match="Binary"): get_semiring(monoid.plus, None) - if supports_udfs or hasattr(binary.numpy, "copysign"): + if shouldhave(binary.numpy, "copysign"): sr = get_semiring(monoid.plus, binary.numpy.copysign) assert sr.monoid is monoid.plus assert sr.binaryop is binary.numpy.copysign @@ -1000,20 +1002,20 @@ def test_commutes(): assert semiring.plus_times.is_commutative if suitesparse: assert semiring.ss.min_secondi.commutes_to is semiring.ss.min_firstj - if supports_udfs or hasattr(semiring, "plus_pow") and hasattr(semiring, "plus_rpow"): + if shouldhave(semiring, "plus_pow") and shouldhave(semiring, "plus_rpow"): assert semiring.plus_pow.commutes_to is semiring.plus_rpow assert not semiring.plus_pow.is_commutative - if supports_udfs or hasattr(binary, "isclose"): + if shouldhave(binary, "isclose"): assert binary.isclose.commutes_to is binary.isclose assert binary.isclose.is_commutative assert binary.isclose(0.1).commutes_to is binary.isclose(0.1) - if supports_udfs or hasattr(binary, "floordiv") and hasattr(binary, "rfloordiv"): + if shouldhave(binary, "floordiv") and shouldhave(binary, "rfloordiv"): assert binary.floordiv.commutes_to is binary.rfloordiv assert not binary.floordiv.is_commutative - if supports_udfs or hasattr(binary.numpy, "add"): + if shouldhave(binary.numpy, "add"): assert binary.numpy.add.commutes_to is binary.numpy.add assert binary.numpy.add.is_commutative - if supports_udfs or hasattr(binary.numpy, "less") and hasattr(binary.numpy, "greater"): + if shouldhave(binary.numpy, "less") and shouldhave(binary.numpy, "greater"): assert binary.numpy.less.commutes_to is binary.numpy.greater assert not binary.numpy.less.is_commutative @@ -1032,18 +1034,18 @@ def test_commutes(): assert semiring.plus_times[int].is_commutative if suitesparse: assert semiring.ss.min_secondi[int].commutes_to is semiring.ss.min_firstj[int] - if supports_udfs or hasattr(semiring, "plus_rpow"): + if shouldhave(semiring, "plus_rpow"): assert semiring.plus_pow[int].commutes_to is semiring.plus_rpow[int] assert not semiring.plus_pow[int].is_commutative - if supports_udfs or hasattr(binary, "isclose"): + if shouldhave(binary, "isclose"): assert binary.isclose(0.1)[int].commutes_to is binary.isclose(0.1)[int] - if supports_udfs or hasattr(binary, "floordiv") and hasattr(binary, "rfloordiv"): + if shouldhave(binary, "floordiv") and shouldhave(binary, "rfloordiv"): assert binary.floordiv[int].commutes_to is binary.rfloordiv[int] assert not binary.floordiv[int].is_commutative - if supports_udfs or hasattr(binary.numpy, "add"): + if shouldhave(binary.numpy, "add"): assert binary.numpy.add[int].commutes_to is binary.numpy.add[int] assert binary.numpy.add[int].is_commutative - if supports_udfs or hasattr(binary.numpy, "less") and hasattr(binary.numpy, "greater"): + if shouldhave(binary.numpy, "less") and shouldhave(binary.numpy, "greater"): assert binary.numpy.less[int].commutes_to is binary.numpy.greater[int] assert not binary.numpy.less[int].is_commutative @@ -1066,11 +1068,11 @@ def test_from_string(): assert unary.from_string("abs[float]") is unary.abs[float] assert binary.from_string("+") is binary.plus assert binary.from_string("-[int]") is binary.minus[int] - if supports_udfs or config["mapnumpy"] or hasattr(binary.numpy, "true_divide"): + if config["mapnumpy"] or shouldhave(binary.numpy, "true_divide"): assert binary.from_string("true_divide") is binary.numpy.true_divide - if supports_udfs or hasattr(binary, "floordiv"): + if shouldhave(binary, "floordiv"): assert binary.from_string("//") is binary.floordiv - if supports_udfs or hasattr(binary.numpy, "mod"): + if shouldhave(binary.numpy, "mod"): assert binary.from_string("%") is binary.numpy.mod assert monoid.from_string("*[FP64]") is monoid.times["FP64"] assert semiring.from_string("min.plus") is semiring.min_plus @@ -1399,11 +1401,11 @@ def test_is_idempotent(): assert monoid.max[int].is_idempotent assert monoid.lor.is_idempotent assert monoid.band.is_idempotent - if supports_udfs or hasattr(monoid.numpy, "gcd"): + if shouldhave(monoid.numpy, "gcd"): assert monoid.numpy.gcd.is_idempotent assert not monoid.plus.is_idempotent assert not monoid.times[float].is_idempotent - if supports_udfs or config["mapnumpy"] or hasattr(monoid.numpy, "equal"): + if config["mapnumpy"] or shouldhave(monoid.numpy, "equal"): assert not monoid.numpy.equal.is_idempotent with pytest.raises(AttributeError): binary.min.is_idempotent diff --git a/scripts/check_versions.sh b/scripts/check_versions.sh index 2166c3eef..23b10eeca 100755 --- a/scripts/check_versions.sh +++ b/scripts/check_versions.sh @@ -9,7 +9,7 @@ conda search 'scipy[channel=conda-forge]>=1.10.1' conda search 'networkx[channel=conda-forge]>=3.1' conda search 'awkward[channel=conda-forge]>=2.1.1' conda search 'sparse[channel=conda-forge]>=0.14.0' -conda search 'fast_matrix_market[channel=conda-forge]>=1.4.5' +conda search 'fast_matrix_market[channel=conda-forge]>=1.5.0' conda search 'numba[channel=conda-forge]>=0.56.4' conda search 'pyyaml[channel=conda-forge]>=6.0' conda search 'flake8-bugbear[channel=conda-forge]>=23.3.23' From e1ed1f0ca4c7dd32de996199b69ddc05b0c33ad2 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sun, 9 Apr 2023 11:54:46 -0500 Subject: [PATCH 20/48] Recipes for L1norm and Linfnorm aggregators --- graphblas/core/operator/agg.py | 23 +++++++++++++++++++++-- graphblas/tests/test_io.py | 10 +++++++--- graphblas/tests/test_matrix.py | 2 +- graphblas/tests/test_vector.py | 8 +++----- 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/graphblas/core/operator/agg.py b/graphblas/core/operator/agg.py index 18d85b51c..09d644c32 100644 --- a/graphblas/core/operator/agg.py +++ b/graphblas/core/operator/agg.py @@ -39,6 +39,7 @@ def __init__( semiring=None, switch=False, semiring2=None, + applybegin=None, finalize=None, composite=None, custom=None, @@ -53,6 +54,7 @@ def __init__( self._semiring = semiring self._semiring2 = semiring2 self._switch = switch + self._applybegin = applybegin self._finalize = finalize self._composite = composite self._custom = custom @@ -153,8 +155,11 @@ def __repr__(self): def _new(self, updater, expr, *, in_composite=False): agg = self.parent + opts = updater.opts if agg._monoid is not None: x = expr.args[0] + if agg._applybegin is not None: # pragma: no cover (unused) + x = agg._applybegin(x).new(**opts) method = getattr(x, expr.method_name) if expr.output_type.__name__ == "Scalar": expr = method(agg._monoid[self.type], allow_empty=not expr._is_cscalar) @@ -168,7 +173,6 @@ def _new(self, updater, expr, *, in_composite=False): return parent._as_vector() return - opts = updater.opts if agg._composite is not None: # Masks are applied throughout the aggregation, including composite aggregations. # Aggregations done while `in_composite is True` should return the updater parent @@ -204,6 +208,8 @@ def _new(self, updater, expr, *, in_composite=False): if expr.cfunc_name == "GrB_Matrix_reduce_Aggregator": # Matrix -> Vector A = expr.args[0] + if agg._applybegin is not None: + A = agg._applybegin(A).new(**opts) orig_updater = updater if agg._finalize is not None: step1 = expr.construct_output(semiring.return_type) @@ -224,6 +230,8 @@ def _new(self, updater, expr, *, in_composite=False): elif expr.cfunc_name.startswith("GrB_Vector_reduce"): # Vector -> Scalar v = expr.args[0] + if agg._applybegin is not None: + v = agg._applybegin(v).new(**opts) step1 = expr._new_vector(semiring.return_type, size=1) init = expr._new_matrix(agg._initdtype, nrows=v._size, ncols=1) init(**opts)[...] = agg._initval # O(1) dense column vector in SuiteSparse 5 @@ -243,6 +251,8 @@ def _new(self, updater, expr, *, in_composite=False): elif expr.cfunc_name.startswith("GrB_Matrix_reduce"): # Matrix -> Scalar A = expr.args[0] + if agg._applybegin is not None: + A = agg._applybegin(A).new(**opts) # We need to compute in two steps: Matrix -> Vector -> Scalar. # This has not been benchmarked or optimized. # We may be able to intelligently choose the faster path. @@ -340,12 +350,21 @@ def __reduce__(self): # logaddexp2 = Aggregator('logaddexp2', monoid=semiring.numpy.logaddexp2) # hypot as monoid doesn't work if single negative element! # hypot = Aggregator('hypot', monoid=semiring.numpy.hypot) +# hypot = Aggregator('hypot', applybegin=unary.abs, monoid=semiring.numpy.hypot) agg.L0norm = agg.count_nonzero agg.L2norm = agg.hypot -if _supports_udfs: # XXX TODO +if _supports_udfs: agg.L1norm = Aggregator("L1norm", semiring="plus_absfirst", semiring2=semiring.plus_first) agg.Linfnorm = Aggregator("Linfnorm", semiring="max_absfirst", semiring2=semiring.max_first) +else: + # Are these always better? + agg.L1norm = Aggregator( + "L1norm", applybegin=unary.abs, semiring=semiring.plus_first, semiring2=semiring.plus_first + ) + agg.Linfnorm = Aggregator( + "Linfnorm", applybegin=unary.abs, semiring=semiring.max_first, semiring2=semiring.max_first + ) # Composite diff --git a/graphblas/tests/test_io.py b/graphblas/tests/test_io.py index ada092025..24df55e9d 100644 --- a/graphblas/tests/test_io.py +++ b/graphblas/tests/test_io.py @@ -267,9 +267,13 @@ def test_mmread_mmwrite(engine): # fast_matrix_market v1.4.5 raises ValueError instead of OverflowError M = gb.io.mmread(mm_in, engine) else: - if example == "_empty_lines_example" and engine in {"fmm", "auto"} and fmm is not None: - # TODO MAINT: is this a bug in fast_matrix_market, or does scipy.io.mmread - # read an invalid file? `fast_matrix_market` v1.4.5 does not handle this. + if ( + example == "_empty_lines_example" + and engine in {"fmm", "auto"} + and fmm is not None + and fmm.__version__ in {"1.4.5"} + ): + # `fast_matrix_market` __version__ v1.4.5 does not handle this, but v1.5.0 does continue M = gb.io.mmread(mm_in, engine) if not M.isequal(expected): # pragma: no cover (debug) diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index 1c211990b..78df8a077 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -4144,7 +4144,7 @@ def test_from_scalar(): if supports_udfs: assert A.isequal(B, check_dtype=True) else: - with pytest.raises(KeyError): # XXX: is this the best type of error? + with pytest.raises(KeyError, match="eq does not work with"): assert A.isequal(B, check_dtype=True) diff --git a/graphblas/tests/test_vector.py b/graphblas/tests/test_vector.py index 8cb31863d..2731bce1c 100644 --- a/graphblas/tests/test_vector.py +++ b/graphblas/tests/test_vector.py @@ -903,11 +903,9 @@ def test_reduce_agg(v): assert v.reduce(agg.stdp).new().isclose(0.5**0.5) assert v.reduce(agg.stds).new().isclose((2 / 3) ** 0.5) assert v.reduce(agg.L0norm).new() == 3 - if supports_udfs: # XXX TODO - assert v.reduce(agg.L1norm).new() == 4 + assert v.reduce(agg.L1norm).new() == 4 assert v.reduce(agg.L2norm).new().isclose(6**0.5) - if supports_udfs: # XXX TODO - assert v.reduce(agg.Linfnorm).new() == 2 + assert v.reduce(agg.Linfnorm).new() == 2 assert v.reduce(agg.exists).new() == 1 w = binary.plus(v, 1).new() assert w.reduce(agg.geometric_mean).new().isclose(12**0.25) @@ -2516,7 +2514,7 @@ def test_from_scalar(): v = Vector.from_scalar(1, dtype="INT64[2]", size=3) w = Vector("INT64[2]", size=3) w << [1, 1] - if supports_udfs: # XXX TODO + if supports_udfs: assert v.isequal(w, check_dtype=True) From a074aa0677bf1c81791c2a9321319788e64e2bbf Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sun, 9 Apr 2023 14:15:26 -0500 Subject: [PATCH 21/48] Better error message for default operators that are UDFs --- .github/workflows/imports.yml | 22 ++++++++++++---------- .github/workflows/test_and_build.yml | 4 ++-- graphblas/binary/__init__.py | 16 ++++++++++++++++ graphblas/binary/numpy.py | 5 ++++- graphblas/op/__init__.py | 10 +++++++++- graphblas/semiring/__init__.py | 27 +++++++++++++++++++++++++++ graphblas/tests/test_op.py | 12 ++++++++++++ graphblas/unary/numpy.py | 5 ++++- 8 files changed, 86 insertions(+), 15 deletions(-) diff --git a/.github/workflows/imports.yml b/.github/workflows/imports.yml index b88315dae..2b0b0ed9f 100644 --- a/.github/workflows/imports.yml +++ b/.github/workflows/imports.yml @@ -11,6 +11,7 @@ jobs: runs-on: ubuntu-latest outputs: os: ${{ steps.os.outputs.selected }} + pyver: ${{ steps.pyver.outputs.selected }} steps: - name: RNG for os uses: ddradar/choose-random-action@v2.0.2 @@ -24,15 +25,6 @@ jobs: 1 1 1 - test_imports: - needs: rngs - runs-on: ${{ needs.rngs.outputs.os }} - # strategy: - # matrix: - # python-version: ["3.8", "3.9", "3.10", "3.11"] - # os: ["ubuntu-latest", "macos-latest", "windows-latest"] - steps: - - uses: actions/checkout@v3 - name: RNG for Python version uses: ddradar/choose-random-action@v2.0.2 id: pyver @@ -47,9 +39,19 @@ jobs: 1 1 1 + test_imports: + needs: rngs + runs-on: ${{ needs.rngs.outputs.os }} + # runs-on: ${{ matrix.os }} + # strategy: + # matrix: + # python-version: ["3.8", "3.9", "3.10", "3.11"] + # os: ["ubuntu-latest", "macos-latest", "windows-latest"] + steps: + - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: ${{ steps.pyver.outputs.selected }} + python-version: ${{ needs.rngs.outputs.pyver }} # python-version: ${{ matrix.python-version }} - run: python -m pip install --upgrade pip - run: pip install -e .[default] diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index db9270487..feab84a22 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -218,8 +218,8 @@ jobs: numbaver="=0.57.0rc1" # XXX: testing numba fmm=fast_matrix_market${fmmver} awkward=awkward${akver} - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .25)') == True ]]; then - # Some packages aren't available for pypy or Python 3.12; 25% otherwise + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .40)') == True ]]; then + # Some packages aren't available for pypy or Python 3.12; 40% otherwise numba="" numbaver=NA sparse="" diff --git a/graphblas/binary/__init__.py b/graphblas/binary/__init__.py index e59c0405e..68bab4d55 100644 --- a/graphblas/binary/__init__.py +++ b/graphblas/binary/__init__.py @@ -1,5 +1,7 @@ # All items are dynamically added by classes in operator.py # This module acts as a container of BinaryOp instances +from ..core import _supports_udfs # isort:skip + _delayed = {} _delayed_commutes_to = { "absfirst": "abssecond", @@ -9,6 +11,15 @@ "rpow": "pow", } _deprecated = {} +_udfs = { + "absfirst", + "abssecond", + "binom", + "floordiv", + "isclose", + "rfloordiv", + "rpow", +} def __dir__(): @@ -50,6 +61,11 @@ def __getattr__(key): ss = import_module(".ss", __name__) globals()["ss"] = ss return ss + if not _supports_udfs and key in _udfs: + raise AttributeError( + f"module {__name__!r} unable to compile UDF for {key!r}; " + "install numba for UDF support" + ) raise AttributeError(f"module {__name__!r} has no attribute {key!r}") diff --git a/graphblas/binary/numpy.py b/graphblas/binary/numpy.py index d84fbb001..4ab582004 100644 --- a/graphblas/binary/numpy.py +++ b/graphblas/binary/numpy.py @@ -174,7 +174,10 @@ def __getattr__(name): else: globals()[name] = getattr(_binary, _numpy_to_graphblas[name]) elif not _supports_udfs: - raise AttributeError(f"module {__name__!r} unable to compile UDF for {name!r}") + raise AttributeError( + f"module {__name__!r} unable to compile UDF for {name!r}; " + "install numba for UDF support" + ) else: numpy_func = getattr(_np, name) diff --git a/graphblas/op/__init__.py b/graphblas/op/__init__.py index af05cbef4..1eb2b51d7 100644 --- a/graphblas/op/__init__.py +++ b/graphblas/op/__init__.py @@ -39,10 +39,18 @@ def __getattr__(key): ss = import_module(".ss", __name__) globals()["ss"] = ss return ss + if not _supports_udfs: + from .. import binary, semiring + + if key in binary._udfs or key in semiring._udfs: + raise AttributeError( + f"module {__name__!r} unable to compile UDF for {key!r}; " + "install numba for UDF support" + ) raise AttributeError(f"module {__name__!r} has no attribute {key!r}") -from ..core import operator # noqa: E402 isort:skip +from ..core import operator, _supports_udfs # noqa: E402 isort:skip from . import numpy # noqa: E402 isort:skip del operator diff --git a/graphblas/semiring/__init__.py b/graphblas/semiring/__init__.py index 904ae192f..538136406 100644 --- a/graphblas/semiring/__init__.py +++ b/graphblas/semiring/__init__.py @@ -1,7 +1,29 @@ # All items are dynamically added by classes in operator.py # This module acts as a container of Semiring instances +from ..core import _supports_udfs + _delayed = {} _deprecated = {} +_udfs = { + # Used by aggregators + "max_absfirst", + "max_abssecond", + "plus_absfirst", + "plus_abssecond", + "plus_rpow", + # floordiv + "any_floordiv", + "max_floordiv", + "min_floordiv", + "plus_floordiv", + "times_floordiv", + # rfloordiv + "any_rfloordiv", + "max_rfloordiv", + "min_rfloordiv", + "plus_rfloordiv", + "times_rfloordiv", +} def __dir__(): @@ -47,6 +69,11 @@ def __getattr__(key): ss = import_module(".ss", __name__) globals()["ss"] = ss return ss + if not _supports_udfs and key in _udfs: + raise AttributeError( + f"module {__name__!r} unable to compile UDF for {key!r}; " + "install numba for UDF support" + ) raise AttributeError(f"module {__name__!r} has no attribute {key!r}") diff --git a/graphblas/tests/test_op.py b/graphblas/tests/test_op.py index 7e6077904..1a6a25d2a 100644 --- a/graphblas/tests/test_op.py +++ b/graphblas/tests/test_op.py @@ -157,6 +157,18 @@ def test_get_typed_op(): operator.get_typed_op(binary.plus, dtypes.INT64, "bad dtype") +@pytest.mark.skipif("supports_udfs") +def test_udf_mentions_numba(): + with pytest.raises(AttributeError, match="install numba"): + binary.rfloordiv + with pytest.raises(AttributeError, match="install numba"): + semiring.any_rfloordiv + with pytest.raises(AttributeError, match="install numba"): + op.absfirst + with pytest.raises(AttributeError, match="install numba"): + op.plus_rpow + + @pytest.mark.skipif("not supports_udfs") def test_unaryop_udf(): def plus_one(x): diff --git a/graphblas/unary/numpy.py b/graphblas/unary/numpy.py index bae2c3779..606501f70 100644 --- a/graphblas/unary/numpy.py +++ b/graphblas/unary/numpy.py @@ -139,7 +139,10 @@ def __getattr__(name): if _config.get("mapnumpy") and name in _numpy_to_graphblas: globals()[name] = getattr(_unary, _numpy_to_graphblas[name]) elif not _supports_udfs: - raise AttributeError(f"module {__name__!r} unable to compile UDF for {name!r}") + raise AttributeError( + f"module {__name__!r} unable to compile UDF for {name!r}; " + "install numba for UDF support" + ) else: numpy_func = getattr(_np, name) From b9f221f6d30e67aca6622593d8ff51e8f5d6ba56 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sun, 9 Apr 2023 15:22:00 -0500 Subject: [PATCH 22/48] Update isclose recipe --- graphblas/core/vector.py | 25 ++++++++++++++++--------- graphblas/tests/conftest.py | 3 +++ graphblas/tests/test_matrix.py | 4 +--- graphblas/tests/test_scalar.py | 4 +--- graphblas/tests/test_vector.py | 4 +--- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/graphblas/core/vector.py b/graphblas/core/vector.py index 6f42a64c3..bec6a0aeb 100644 --- a/graphblas/core/vector.py +++ b/graphblas/core/vector.py @@ -104,23 +104,30 @@ def _isclose_recipe(self, other, rel_tol, abs_tol, **opts): val = isequal.reduce_scalar(monoid.land, allow_empty=False).new(**opts).value if val: return True - # x - y - abs_x_y = self.ewise_mult(other, binary.minus).new(FP64, mask=~isequal.V, **opts) - # abs(x - y) - abs_x_y(**opts) << abs_x_y.apply(unary.abs) + # So we can use structural mask below + isequal(**opts) << select.value(isequal == True) # noqa: E712 + # abs(x) - x = self.apply(unary.abs).new(FP64, mask=~isequal.V, **opts) + x = self.apply(unary.abs).new(FP64, mask=~isequal.S, **opts) # abs(y) - y = other.apply(unary.abs).new(FP64, mask=~isequal.V, **opts) + y = other.apply(unary.abs).new(FP64, mask=~isequal.S, **opts) # max(abs(x), abs(y)) - max_x_y = x.ewise_mult(y, binary.max).new(**opts) + x(**opts) << x.ewise_mult(y, binary.max) + max_x_y = x # rel_tol * max(abs(x), abs(y)) max_x_y(**opts) << max_x_y.apply(binary.times, rel_tol) # max(rel_tol * max(abs(x), abs(y)), abs_tol) max_x_y(**opts) << max_x_y.apply(binary.max, abs_tol) + + # x - y + y(~isequal.S, replace=True, **opts) << self.ewise_mult(other, binary.minus) + abs_x_y = y + # abs(x - y) + abs_x_y(**opts) << abs_x_y.apply(unary.abs) + # abs(x - y) <= max(rel_tol * max(abs(x), abs(y)), abs_tol) - isequal(**opts) << abs_x_y.ewise_mult(max_x_y, binary.lt) - if type(isequal) is Vector: + isequal(**opts) << abs_x_y.ewise_mult(max_x_y, binary.le) + if isequal.ndim == 1: return isequal.reduce(monoid.land, allow_empty=False).new(**opts).value return isequal.reduce_scalar(monoid.land, allow_empty=False).new(**opts).value diff --git a/graphblas/tests/conftest.py b/graphblas/tests/conftest.py index 8bed4f0b4..7f2561863 100644 --- a/graphblas/tests/conftest.py +++ b/graphblas/tests/conftest.py @@ -1,6 +1,7 @@ import atexit import functools import itertools +import platform from pathlib import Path import numpy as np @@ -12,6 +13,8 @@ orig_binaryops = set() orig_semirings = set() +pypy = platform.python_implementation() == "PyPy" + def pytest_configure(config): rng = np.random.default_rng() diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index 78df8a077..f0acd19f6 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -1,7 +1,6 @@ import inspect import itertools import pickle -import platform import sys import types import weakref @@ -25,12 +24,11 @@ OutputNotEmpty, ) -from .conftest import autocompute, compute, shouldhave +from .conftest import autocompute, compute, pypy, shouldhave from graphblas import Matrix, Scalar, Vector # isort:skip (for dask-graphblas) suitesparse = backend == "suitesparse" -pypy = platform.python_implementation() == "PyPy" @pytest.fixture diff --git a/graphblas/tests/test_scalar.py b/graphblas/tests/test_scalar.py index 12e210453..9d441341d 100644 --- a/graphblas/tests/test_scalar.py +++ b/graphblas/tests/test_scalar.py @@ -1,6 +1,5 @@ import inspect import pickle -import platform import random import sys import types @@ -13,12 +12,11 @@ from graphblas import backend, binary, dtypes, monoid, replace, select, unary from graphblas.exceptions import EmptyObject -from .conftest import autocompute, compute +from .conftest import autocompute, compute, pypy from graphblas import Matrix, Scalar, Vector # isort:skip (for dask-graphblas) suitesparse = backend == "suitesparse" -pypy = platform.python_implementation() == "PyPy" @pytest.fixture diff --git a/graphblas/tests/test_vector.py b/graphblas/tests/test_vector.py index 2731bce1c..48843c230 100644 --- a/graphblas/tests/test_vector.py +++ b/graphblas/tests/test_vector.py @@ -1,7 +1,6 @@ import inspect import itertools import pickle -import platform import sys import types import weakref @@ -23,13 +22,12 @@ OutputNotEmpty, ) -from .conftest import autocompute, compute +from .conftest import autocompute, compute, pypy from graphblas import Matrix, Scalar, Vector # isort:skip (for dask-graphblas) suitesparse = backend == "suitesparse" -pypy = platform.python_implementation() == "PyPy" @pytest.fixture From ad0d858f8857b74240cd4bf0cfb88d8d127e2fc8 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 08:51:30 -0500 Subject: [PATCH 23/48] Get ready to merge --- .github/workflows/test_and_build.yml | 17 +++++++++++------ scripts/check_versions.sh | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index feab84a22..746727b2f 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -210,16 +210,21 @@ jobs: else psgver="" fi + # TODO: drop 0.57.0rc1 and use 0.57 once numba 0.57 is properly released if [[ $npver == "=1.21" ]] ; then - numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", "=0.57", ""]))') + numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", "=0.57.0rc1", ""]))') + elif [[ $npver == "=1.24" ]] ; then + numbaver=$(python -c 'import random ; print(random.choice(["=0.57.0rc1", ""]))') else - numbaver=$(python -c 'import random ; print(random.choice(["=0.56", "=0.57", ""]))') + numbaver=$(python -c 'import random ; print(random.choice(["=0.56", "=0.57.0rc1", ""]))') fi - numbaver="=0.57.0rc1" # XXX: testing numba fmm=fast_matrix_market${fmmver} awkward=awkward${akver} - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || $(python -c 'import random ; print(random.random() < .40)') == True ]]; then - # Some packages aren't available for pypy or Python 3.12; 40% otherwise + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || \ + startsWith(steps.pyver.outputs.selected, '3.12') }} == true || \ + ( $(python -c 'import random ; print(random.random() < .50)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] + then + # Some packages aren't available for pypy or Python 3.12; 50% otherwise (if not running notebooks) numba="" numbaver=NA sparse="" @@ -241,7 +246,7 @@ jobs: fi echo "versions: np${npver} sp${spver} pd${pdver} ak${akver} nx${nxver} numba${numbaver} yaml${yamlver} sparse${sparsever} psgver${psgver}" - # XXX: added `-c numba` + # TODO: remove `-c numba` when numba 0.57 is properly released $(command -v mamba || command -v conda) install -c numba packaging pytest coverage coveralls=3.3.1 pytest-randomly cffi donfig tomli \ pyyaml${yamlver} ${sparse} pandas${pdver} scipy${spver} numpy${npver} ${awkward} \ networkx${nxver} ${numba} ${fmm} ${psg} \ diff --git a/scripts/check_versions.sh b/scripts/check_versions.sh index 23b10eeca..026f3a656 100755 --- a/scripts/check_versions.sh +++ b/scripts/check_versions.sh @@ -7,9 +7,9 @@ conda search 'numpy[channel=conda-forge]>=1.24.2' conda search 'pandas[channel=conda-forge]>=2.0.0' conda search 'scipy[channel=conda-forge]>=1.10.1' conda search 'networkx[channel=conda-forge]>=3.1' -conda search 'awkward[channel=conda-forge]>=2.1.1' +conda search 'awkward[channel=conda-forge]>=2.1.2' conda search 'sparse[channel=conda-forge]>=0.14.0' -conda search 'fast_matrix_market[channel=conda-forge]>=1.5.0' +conda search 'fast_matrix_market[channel=conda-forge]>=1.5.1' conda search 'numba[channel=conda-forge]>=0.56.4' conda search 'pyyaml[channel=conda-forge]>=6.0' conda search 'flake8-bugbear[channel=conda-forge]>=23.3.23' From de2c81f0f3a6713ff77134022b4ca56405c9c7ce Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 08:58:14 -0500 Subject: [PATCH 24/48] Try this --- .github/workflows/test_and_build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 746727b2f..52505b3e4 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -220,11 +220,11 @@ jobs: fi fmm=fast_matrix_market${fmmver} awkward=awkward${akver} - if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || \ - startsWith(steps.pyver.outputs.selected, '3.12') }} == true || \ - ( $(python -c 'import random ; print(random.random() < .50)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] - then + if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || + startsWith(steps.pyver.outputs.selected, '3.12') }} == true || + ( $(python -c 'import random ; print(random.random() < .50)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] ; then # Some packages aren't available for pypy or Python 3.12; 50% otherwise (if not running notebooks) + echo "skipping numba" numba="" numbaver=NA sparse="" From 837796c97c7e075d974c483c7a45e1b6341b28e7 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 17:45:29 -0500 Subject: [PATCH 25/48] Stress test numba 0.57.0rc1 on Windows --- .github/workflows/test_and_build.yml | 11 +++++++---- graphblas/tests/test_numpyops.py | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 52505b3e4..53566cc27 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -86,7 +86,8 @@ jobs: # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. matrix: - os: ["ubuntu-latest", "macos-latest", "windows-latest"] + # os: ["ubuntu-latest", "macos-latest", "windows-latest"] + os: ["windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest"] # XXX slowtask: ["pytest_normal", "pytest_bizarro", "notebooks"] env: # Wheels on OS X come with an OpenMP that conflicts with OpenMP from conda-forge. @@ -218,11 +219,13 @@ jobs: else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", "=0.57.0rc1", ""]))') fi + numbaver="=0.57.0rc1" # XXX fmm=fast_matrix_market${fmmver} awkward=awkward${akver} if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || - ( $(python -c 'import random ; print(random.random() < .50)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] ; then + ( $(python -c 'import random ; print(random.random() < .01)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] ; then + # XXX: change percentage above from .01 to .50 # Some packages aren't available for pypy or Python 3.12; 50% otherwise (if not running notebooks) echo "skipping numba" numba="" @@ -338,7 +341,7 @@ jobs: if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \ if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi) echo $args - coverage run -a -m pytest --color=yes --randomly -v $args \ + coverage run -a -m pytest -s --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_bizarro' && '--runslow' || '' }} git checkout . # Undo changes to scalar default - name: Miscellaneous tests @@ -359,7 +362,7 @@ jobs: rm script.py # Tests whose coverage depend on order of tests :/ # TODO: understand why these are order-dependent and try to fix - coverage run -a -m pytest --color=yes -x --no-mapnumpy --runslow -k test_binaryop_attributes_numpy graphblas/tests/test_op.py + coverage run -a -m pytest -s --color=yes -x --no-mapnumpy --runslow -k test_binaryop_attributes_numpy graphblas/tests/test_op.py # coverage run -a -m pytest --color=yes -x --no-mapnumpy -k test_npmonoid graphblas/tests/test_numpyops.py --runslow - name: Auto-generated code check if: matrix.slowtask == 'pytest_bizarro' diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 9ba63960f..1a14db008 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -79,6 +79,7 @@ def test_npunary(): isclose = None for gb_input, np_input in data: for unary_name in sorted(npunary._unary_names & npunary.__dir__()): + print(unary_name) # XXX op = getattr(npunary, unary_name) if gb_input.dtype not in op.types or unary_name in blocklist.get( gb_input.dtype.name, () From 571b27aa5a3905cfa0bb5a62078c3ca4ad14d316 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 18:13:38 -0500 Subject: [PATCH 26/48] But which unaryop is causing this?! --- graphblas/tests/test_numpyops.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 1a14db008..81ea5b488 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -79,7 +79,8 @@ def test_npunary(): isclose = None for gb_input, np_input in data: for unary_name in sorted(npunary._unary_names & npunary.__dir__()): - print(unary_name) # XXX + print(unary_name, file=sys.stderr) # XXX + sys.stderr.flush() op = getattr(npunary, unary_name) if gb_input.dtype not in op.types or unary_name in blocklist.get( gb_input.dtype.name, () From 30f5532b75e434829383506314b6b40fa60882aa Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 19:32:22 -0500 Subject: [PATCH 27/48] more debug print --- .github/workflows/test_and_build.yml | 2 +- graphblas/core/operator/unary.py | 3 +++ pyproject.toml | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 53566cc27..29c80cd25 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -87,7 +87,7 @@ jobs: # since we need to run all slow tests on Windows and non-Windoes OSes. matrix: # os: ["ubuntu-latest", "macos-latest", "windows-latest"] - os: ["windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest"] # XXX + os: ["windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest"] # XXX slowtask: ["pytest_normal", "pytest_bizarro", "notebooks"] env: # Wheels on OS X come with an OpenMP that conflicts with OpenMP from conda-forge. diff --git a/graphblas/core/operator/unary.py b/graphblas/core/operator/unary.py index 1432a9387..58c77db6d 100644 --- a/graphblas/core/operator/unary.py +++ b/graphblas/core/operator/unary.py @@ -1,5 +1,6 @@ import inspect import re +import sys from types import FunctionType from ... import _STANDARD_OPERATOR_NAMES, op, unary @@ -181,6 +182,7 @@ def _build(cls, name, func, *, anonymous=False, is_udt=False): if not is_udt: for type_ in _sample_values: sig = (type_.numba_type,) + print("compiling", name, type_, file=sys.stderr) try: unary_udf.compile(sig) except numba.TypingError: @@ -232,6 +234,7 @@ def unary_wrapper(z, x): def unary_wrapper(z, x): z[0] = unary_udf(x[0]) # pragma: no cover (numba) + print("wrapping", name, type_, input_type, return_type, file=sys.stderr) unary_wrapper = numba.cfunc(wrapper_sig, nopython=True)(unary_wrapper) new_unary = ffi_new("GrB_UnaryOp*") check_status_carg( diff --git a/pyproject.toml b/pyproject.toml index 1eaa942e1..4983fabad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -344,6 +344,7 @@ ignore = [ ] [tool.ruff.per-file-ignores] +"graphblas/core/operator/unary.py" = ["T201"] # XXX "graphblas/core/agg.py" = ["F401", "F403"] # Deprecated "graphblas/core/operator/base.py" = ["S102"] # exec is used for UDF "graphblas/core/ss/matrix.py" = ["NPY002"] # numba doesn't support rng generator yet From 3f4a3ee007823c607525277ea368d16080497a71 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 19:37:26 -0500 Subject: [PATCH 28/48] Always test with numpy 1.24 --- .github/workflows/test_and_build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 29c80cd25..917bc3a6d 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -189,6 +189,7 @@ jobs: pdver=$(python -c 'import random ; print(random.choice(["=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.10", "=2.0", "=2.1", ""]))') fi + npver="=1.24" # XXX if [[ ${{ steps.sourcetype.outputs.selected }} == "source" || ${{ steps.sourcetype.outputs.selected }} == "upstream" ]]; then # TODO: there are currently issues with some numpy versions when # installing python-suitesparse-grphblas from source or upstream. From 050d709536a6f93ccdd336a60110fbd51330e979 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 19:54:49 -0500 Subject: [PATCH 29/48] Don't map numpy --- .github/workflows/test_and_build.yml | 2 ++ graphblas/tests/conftest.py | 1 + 2 files changed, 3 insertions(+) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 917bc3a6d..620b3d58e 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -307,6 +307,7 @@ jobs: if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi) echo $args pytest -v --pyargs suitesparse_graphblas + python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' coverage run -m pytest --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_normal' && '--runslow' || '' }} - name: Unit tests (bizarro scalars) @@ -342,6 +343,7 @@ jobs: if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \ if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi) echo $args + python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' coverage run -a -m pytest -s --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_bizarro' && '--runslow' || '' }} git checkout . # Undo changes to scalar default diff --git a/graphblas/tests/conftest.py b/graphblas/tests/conftest.py index 7f2561863..63856ac66 100644 --- a/graphblas/tests/conftest.py +++ b/graphblas/tests/conftest.py @@ -34,6 +34,7 @@ def pytest_configure(config): mapnumpy = config.getoption("--mapnumpy", False) if mapnumpy is None: mapnumpy = rng.random() < 0.5 if randomly else False + mapnumpy = False # XXX runslow = config.getoption("--runslow", False) if runslow is None: # Add a small amount of randomization to be safer From 73205e8e19c9fc27bacb0f94fe28e1a18460524d Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 19:58:21 -0500 Subject: [PATCH 30/48] more brutal testing --- .github/workflows/test_and_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 620b3d58e..b496e4224 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -81,7 +81,7 @@ jobs: shell: bash -l {0} strategy: # To "stress test" in CI, set `fail-fast` to `false` and perhaps add more items to `matrix.slowtask` - fail-fast: true + fail-fast: false # The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype]. # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. From cc08a34a10541878f2518b5f97bc46db603f641c Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 20:06:44 -0500 Subject: [PATCH 31/48] forgot a `-s` --- .github/workflows/test_and_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index b496e4224..e5688bd86 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -308,7 +308,7 @@ jobs: echo $args pytest -v --pyargs suitesparse_graphblas python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' - coverage run -m pytest --color=yes --randomly -v $args \ + coverage run -m pytest -s --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_normal' && '--runslow' || '' }} - name: Unit tests (bizarro scalars) run: | From 4c7441b7251783bf87bec90986fffc143ad8ca62 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 20:10:30 -0500 Subject: [PATCH 32/48] shuffle attrs --- graphblas/tests/test_numpyops.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 81ea5b488..1e227b26b 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -1,6 +1,7 @@ # These tests are very slow, since they force creation of all # numpy unary, binary, monoid, and semiring objects. import itertools +import random import sys import numpy as np @@ -78,7 +79,9 @@ def test_npunary(): else: isclose = None for gb_input, np_input in data: - for unary_name in sorted(npunary._unary_names & npunary.__dir__()): + names = sorted(npunary._unary_names & npunary.__dir__()) + random.shuffle(names) + for unary_name in names: print(unary_name, file=sys.stderr) # XXX sys.stderr.flush() op = getattr(npunary, unary_name) From 4b0c3cbbc30ae9794820c4b9119052c591fcfa6b Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 20:28:01 -0500 Subject: [PATCH 33/48] where exactly does it happen? also, only wheels for psg --- .github/workflows/test_and_build.yml | 2 +- graphblas/core/operator/unary.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index e5688bd86..5825e1dd0 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -129,7 +129,7 @@ jobs: upstream weights: | 1 - 1 + 10000 1 1 - name: Setup mamba diff --git a/graphblas/core/operator/unary.py b/graphblas/core/operator/unary.py index 58c77db6d..b89e724c7 100644 --- a/graphblas/core/operator/unary.py +++ b/graphblas/core/operator/unary.py @@ -235,8 +235,12 @@ def unary_wrapper(z, x): z[0] = unary_udf(x[0]) # pragma: no cover (numba) print("wrapping", name, type_, input_type, return_type, file=sys.stderr) - unary_wrapper = numba.cfunc(wrapper_sig, nopython=True)(unary_wrapper) + cfunc = numba.cfunc(wrapper_sig, nopython=True) + print("AAA", file=sys.stderr) + unary_wrapper = cfunc(unary_wrapper) + print("BBB", file=sys.stderr) new_unary = ffi_new("GrB_UnaryOp*") + print("CCC", file=sys.stderr) check_status_carg( lib.GrB_UnaryOp_new( new_unary, unary_wrapper.cffi, ret_type.gb_obj, type_.gb_obj @@ -244,7 +248,9 @@ def unary_wrapper(z, x): "UnaryOp", new_unary, ) + print("DDD", file=sys.stderr) op = TypedUserUnaryOp(new_type_obj, name, type_, ret_type, new_unary[0]) + print("EEE", file=sys.stderr) new_type_obj._add(op) success = True return_types[type_] = ret_type From bb35f98178238b4a2e5b7c5f2130d1dec327e5e6 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 20:49:14 -0500 Subject: [PATCH 34/48] relax numpy version --- .github/workflows/test_and_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 5825e1dd0..119100ba3 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -189,7 +189,7 @@ jobs: pdver=$(python -c 'import random ; print(random.choice(["=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.10", "=2.0", "=2.1", ""]))') fi - npver="=1.24" # XXX + # npver="=1.24" # XXX if [[ ${{ steps.sourcetype.outputs.selected }} == "source" || ${{ steps.sourcetype.outputs.selected }} == "upstream" ]]; then # TODO: there are currently issues with some numpy versions when # installing python-suitesparse-grphblas from source or upstream. From f4645cea815cfd9a67592eadbc0bcbadc26cf14c Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 20:52:01 -0500 Subject: [PATCH 35/48] exp2 reliably fails; what else? --- .github/workflows/test_and_build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 119100ba3..ee6cd5b4e 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -87,7 +87,7 @@ jobs: # since we need to run all slow tests on Windows and non-Windoes OSes. matrix: # os: ["ubuntu-latest", "macos-latest", "windows-latest"] - os: ["windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest"] # XXX + os: ["windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest"] # XXX slowtask: ["pytest_normal", "pytest_bizarro", "notebooks"] env: # Wheels on OS X come with an OpenMP that conflicts with OpenMP from conda-forge. @@ -307,7 +307,7 @@ jobs: if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi) echo $args pytest -v --pyargs suitesparse_graphblas - python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' + # python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' coverage run -m pytest -s --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_normal' && '--runslow' || '' }} - name: Unit tests (bizarro scalars) @@ -343,7 +343,7 @@ jobs: if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \ if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi) echo $args - python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' + # python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' coverage run -a -m pytest -s --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_bizarro' && '--runslow' || '' }} git checkout . # Undo changes to scalar default From e7422a5e428a2d98aaebdefbc2c728ca6d1ca4cc Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 21:13:01 -0500 Subject: [PATCH 36/48] test --- .github/workflows/test_and_build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index ee6cd5b4e..fe8fc3d14 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -307,7 +307,7 @@ jobs: if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi) echo $args pytest -v --pyargs suitesparse_graphblas - # python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' + python -c 'import numba ; import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' coverage run -m pytest -s --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_normal' && '--runslow' || '' }} - name: Unit tests (bizarro scalars) @@ -343,7 +343,7 @@ jobs: if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \ if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi) echo $args - # python -c 'import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' + python -c 'import numba ; import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' coverage run -a -m pytest -s --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_bizarro' && '--runslow' || '' }} git checkout . # Undo changes to scalar default From 92c8df5d59c0de2bdb1fcee12dd3a7bcff84e39d Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Wed, 12 Apr 2023 21:14:25 -0500 Subject: [PATCH 37/48] Try other sources of psg --- .github/workflows/test_and_build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index fe8fc3d14..2562576da 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -128,10 +128,10 @@ jobs: source upstream weights: | + 1000 1 - 10000 - 1 - 1 + 1000 + 1000 - name: Setup mamba uses: conda-incubator/setup-miniconda@v2 id: setup_mamba From 757ea240167f112e112c55c3c489e311657ad269 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Thu, 13 Apr 2023 08:15:18 -0500 Subject: [PATCH 38/48] undo testing numba on windows --- .github/workflows/test_and_build.yml | 24 +++++++++--------------- graphblas/core/operator/unary.py | 11 +---------- graphblas/tests/conftest.py | 1 - graphblas/tests/test_numpyops.py | 7 +------ pyproject.toml | 1 - 5 files changed, 11 insertions(+), 33 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 2562576da..52505b3e4 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -81,13 +81,12 @@ jobs: shell: bash -l {0} strategy: # To "stress test" in CI, set `fail-fast` to `false` and perhaps add more items to `matrix.slowtask` - fail-fast: false + fail-fast: true # The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype]. # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. matrix: - # os: ["ubuntu-latest", "macos-latest", "windows-latest"] - os: ["windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest", "windows-latest"] # XXX + os: ["ubuntu-latest", "macos-latest", "windows-latest"] slowtask: ["pytest_normal", "pytest_bizarro", "notebooks"] env: # Wheels on OS X come with an OpenMP that conflicts with OpenMP from conda-forge. @@ -128,10 +127,10 @@ jobs: source upstream weights: | - 1000 1 - 1000 - 1000 + 1 + 1 + 1 - name: Setup mamba uses: conda-incubator/setup-miniconda@v2 id: setup_mamba @@ -189,7 +188,6 @@ jobs: pdver=$(python -c 'import random ; print(random.choice(["=1.5", "=2.0", ""]))') akver=$(python -c 'import random ; print(random.choice(["=1.10", "=2.0", "=2.1", ""]))') fi - # npver="=1.24" # XXX if [[ ${{ steps.sourcetype.outputs.selected }} == "source" || ${{ steps.sourcetype.outputs.selected }} == "upstream" ]]; then # TODO: there are currently issues with some numpy versions when # installing python-suitesparse-grphblas from source or upstream. @@ -220,13 +218,11 @@ jobs: else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", "=0.57.0rc1", ""]))') fi - numbaver="=0.57.0rc1" # XXX fmm=fast_matrix_market${fmmver} awkward=awkward${akver} if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || - ( $(python -c 'import random ; print(random.random() < .01)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] ; then - # XXX: change percentage above from .01 to .50 + ( $(python -c 'import random ; print(random.random() < .50)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] ; then # Some packages aren't available for pypy or Python 3.12; 50% otherwise (if not running notebooks) echo "skipping numba" numba="" @@ -307,8 +303,7 @@ jobs: if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi) echo $args pytest -v --pyargs suitesparse_graphblas - python -c 'import numba ; import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' - coverage run -m pytest -s --color=yes --randomly -v $args \ + coverage run -m pytest --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_normal' && '--runslow' || '' }} - name: Unit tests (bizarro scalars) run: | @@ -343,8 +338,7 @@ jobs: if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \ if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi) echo $args - python -c 'import numba ; import graphblas as gb ; gb.config.set(mapnumpy=False) ; gb.unary.numpy.exp2' - coverage run -a -m pytest -s --color=yes --randomly -v $args \ + coverage run -a -m pytest --color=yes --randomly -v $args \ ${{ matrix.slowtask == 'pytest_bizarro' && '--runslow' || '' }} git checkout . # Undo changes to scalar default - name: Miscellaneous tests @@ -365,7 +359,7 @@ jobs: rm script.py # Tests whose coverage depend on order of tests :/ # TODO: understand why these are order-dependent and try to fix - coverage run -a -m pytest -s --color=yes -x --no-mapnumpy --runslow -k test_binaryop_attributes_numpy graphblas/tests/test_op.py + coverage run -a -m pytest --color=yes -x --no-mapnumpy --runslow -k test_binaryop_attributes_numpy graphblas/tests/test_op.py # coverage run -a -m pytest --color=yes -x --no-mapnumpy -k test_npmonoid graphblas/tests/test_numpyops.py --runslow - name: Auto-generated code check if: matrix.slowtask == 'pytest_bizarro' diff --git a/graphblas/core/operator/unary.py b/graphblas/core/operator/unary.py index b89e724c7..1432a9387 100644 --- a/graphblas/core/operator/unary.py +++ b/graphblas/core/operator/unary.py @@ -1,6 +1,5 @@ import inspect import re -import sys from types import FunctionType from ... import _STANDARD_OPERATOR_NAMES, op, unary @@ -182,7 +181,6 @@ def _build(cls, name, func, *, anonymous=False, is_udt=False): if not is_udt: for type_ in _sample_values: sig = (type_.numba_type,) - print("compiling", name, type_, file=sys.stderr) try: unary_udf.compile(sig) except numba.TypingError: @@ -234,13 +232,8 @@ def unary_wrapper(z, x): def unary_wrapper(z, x): z[0] = unary_udf(x[0]) # pragma: no cover (numba) - print("wrapping", name, type_, input_type, return_type, file=sys.stderr) - cfunc = numba.cfunc(wrapper_sig, nopython=True) - print("AAA", file=sys.stderr) - unary_wrapper = cfunc(unary_wrapper) - print("BBB", file=sys.stderr) + unary_wrapper = numba.cfunc(wrapper_sig, nopython=True)(unary_wrapper) new_unary = ffi_new("GrB_UnaryOp*") - print("CCC", file=sys.stderr) check_status_carg( lib.GrB_UnaryOp_new( new_unary, unary_wrapper.cffi, ret_type.gb_obj, type_.gb_obj @@ -248,9 +241,7 @@ def unary_wrapper(z, x): "UnaryOp", new_unary, ) - print("DDD", file=sys.stderr) op = TypedUserUnaryOp(new_type_obj, name, type_, ret_type, new_unary[0]) - print("EEE", file=sys.stderr) new_type_obj._add(op) success = True return_types[type_] = ret_type diff --git a/graphblas/tests/conftest.py b/graphblas/tests/conftest.py index 63856ac66..7f2561863 100644 --- a/graphblas/tests/conftest.py +++ b/graphblas/tests/conftest.py @@ -34,7 +34,6 @@ def pytest_configure(config): mapnumpy = config.getoption("--mapnumpy", False) if mapnumpy is None: mapnumpy = rng.random() < 0.5 if randomly else False - mapnumpy = False # XXX runslow = config.getoption("--runslow", False) if runslow is None: # Add a small amount of randomization to be safer diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 1e227b26b..9ba63960f 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -1,7 +1,6 @@ # These tests are very slow, since they force creation of all # numpy unary, binary, monoid, and semiring objects. import itertools -import random import sys import numpy as np @@ -79,11 +78,7 @@ def test_npunary(): else: isclose = None for gb_input, np_input in data: - names = sorted(npunary._unary_names & npunary.__dir__()) - random.shuffle(names) - for unary_name in names: - print(unary_name, file=sys.stderr) # XXX - sys.stderr.flush() + for unary_name in sorted(npunary._unary_names & npunary.__dir__()): op = getattr(npunary, unary_name) if gb_input.dtype not in op.types or unary_name in blocklist.get( gb_input.dtype.name, () diff --git a/pyproject.toml b/pyproject.toml index 4983fabad..1eaa942e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -344,7 +344,6 @@ ignore = [ ] [tool.ruff.per-file-ignores] -"graphblas/core/operator/unary.py" = ["T201"] # XXX "graphblas/core/agg.py" = ["F401", "F403"] # Deprecated "graphblas/core/operator/base.py" = ["S102"] # exec is used for UDF "graphblas/core/ss/matrix.py" = ["NPY002"] # numba doesn't support rng generator yet From 3db0f4eb2309e6d9b79a60f95f36f9d8ed89812c Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Thu, 13 Apr 2023 08:33:05 -0500 Subject: [PATCH 39/48] numba version depends on python and numpy versions --- .github/workflows/test_and_build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 52505b3e4..4abbefad7 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -211,10 +211,10 @@ jobs: psgver="" fi # TODO: drop 0.57.0rc1 and use 0.57 once numba 0.57 is properly released - if [[ $npver == "=1.21" ]] ; then - numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", "=0.57.0rc1", ""]))') - elif [[ $npver == "=1.24" ]] ; then + if [[ $npver == "=1.24" || ${{ startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]] ; then numbaver=$(python -c 'import random ; print(random.choice(["=0.57.0rc1", ""]))') + elif [[ $npver == "=1.21" ]] ; then + numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", "=0.57.0rc1", ""]))') else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", "=0.57.0rc1", ""]))') fi From 2e9d8cd800dfbdd146bc18397003ef81b289d8ee Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Fri, 14 Apr 2023 10:29:17 -0500 Subject: [PATCH 40/48] coverage --- .github/workflows/test_and_build.yml | 4 ++-- .pre-commit-config.yaml | 5 +++++ graphblas/__init__.py | 2 +- graphblas/core/operator/base.py | 6 ++++-- graphblas/core/operator/indexunary.py | 2 +- graphblas/core/ss/matrix.py | 1 + graphblas/core/utils.py | 4 ++-- graphblas/tests/test_matrix.py | 6 ++++++ graphblas/tests/test_numpyops.py | 2 +- graphblas/tests/test_op.py | 17 +++++++++++++++++ graphblas/tests/test_vector.py | 7 ++++++- 11 files changed, 46 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 4abbefad7..1ff14b9aa 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -222,8 +222,8 @@ jobs: awkward=awkward${akver} if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || - ( $(python -c 'import random ; print(random.random() < .50)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] ; then - # Some packages aren't available for pypy or Python 3.12; 50% otherwise (if not running notebooks) + ( $(python -c 'import random ; print(random.random() < .318)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] ; then + # Some packages aren't available for pypy or Python 3.12; 31.8% otherwise (if not running notebooks) echo "skipping numba" numba="" numbaver=NA diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b092cdf0d..60c3a0e9f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,6 +4,11 @@ # To run: `pre-commit run --all-files` # To update: `pre-commit autoupdate` # - &flake8_dependencies below needs updated manually +ci: + # See: https://pre-commit.ci/#configuration + autofix_prs: false + autoupdate_schedule: monthly + skip: [pylint] fail_fast: true default_language_version: python: python3 diff --git a/graphblas/__init__.py b/graphblas/__init__.py index 0aa7dff11..a9895cb6a 100644 --- a/graphblas/__init__.py +++ b/graphblas/__init__.py @@ -139,7 +139,7 @@ def _init(backend_arg, blocking, automatic=False): if backend in {"suitesparse", "suitesparse-vanilla"}: try: from suitesparse_graphblas import ffi, initialize, is_initialized, lib - except ImportError: + except ImportError: # pragma: no cover (import) raise ImportError( f"suitesparse_graphblas is required for {backend!r} backend. " "It may be installed with pip or conda:\n\n" diff --git a/graphblas/core/operator/base.py b/graphblas/core/operator/base.py index 394540241..a40438f14 100644 --- a/graphblas/core/operator/base.py +++ b/graphblas/core/operator/base.py @@ -465,7 +465,7 @@ def _initialize(cls, include_in_ops=True): if type_ is None: type_ = BOOL else: - if type_ is None: # pragma: no cover + if type_ is None: # pragma: no cover (safety) raise TypeError(f"Unable to determine return type for {varname}") if return_prefix is None: return_type = type_ @@ -494,7 +494,9 @@ def _deserialize(cls, name, *args): @classmethod def _check_supports_udf(cls, method_name): if not _supports_udfs: - raise RuntimeError(f"{cls.__name__}.{method_name} requires numba") + raise RuntimeError( + f"{cls.__name__}.{method_name}(...) unavailable; install numba for UDF support" + ) _builtin_to_op = {} # Populated in .utils diff --git a/graphblas/core/operator/indexunary.py b/graphblas/core/operator/indexunary.py index 23a9fdeb3..00333effc 100644 --- a/graphblas/core/operator/indexunary.py +++ b/graphblas/core/operator/indexunary.py @@ -280,7 +280,7 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal setattr(select, funcname, SelectOp._from_indexunary(indexunary_op)) - if not cls._initialized: + if not cls._initialized: # pragma: no cover (safety) _STANDARD_OPERATOR_NAMES.add(f"{cls._modname}.{name}") if not lazy: return indexunary_op diff --git a/graphblas/core/ss/matrix.py b/graphblas/core/ss/matrix.py index ec0c74c08..93743d2ce 100644 --- a/graphblas/core/ss/matrix.py +++ b/graphblas/core/ss/matrix.py @@ -1794,6 +1794,7 @@ def import_hypercsc( ---------- nrows : int ncols : int + cols : array-like indptr : array-like values : array-like row_indices : array-like diff --git a/graphblas/core/utils.py b/graphblas/core/utils.py index 0beeb4a2a..214b5ebae 100644 --- a/graphblas/core/utils.py +++ b/graphblas/core/utils.py @@ -359,7 +359,7 @@ def _autogenerate_code( end="# End auto-generated code", ): """Super low-tech auto-code generation used by automethods.py and infixmethods.py.""" - with filepath.open() as f: # pragma: no branch (flaky) + with filepath.open() as f: # flaky coverage orig_text = f.read() if specializer: begin = f"{begin}: {specializer}" @@ -379,7 +379,7 @@ def _autogenerate_code( new_text = orig_text for start, stop in reversed(boundaries): new_text = f"{new_text[:start]}{begin}{text}{new_text[stop:]}" - with filepath.open("w") as f: # pragma: no branch (flaky) + with filepath.open("w") as f: # flaky coverage f.write(new_text) import subprocess diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index f0acd19f6..7a32d6f15 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -2012,6 +2012,12 @@ def test_ss_import_export(A, do_iso, methods): B4 = Matrix.ss.import_any(**d) assert B4.isequal(A) assert B4.ss.is_iso is do_iso + if do_iso: + d["values"] = 1 + d["is_iso"] = False + B4b = Matrix.ss.import_any(**d) + assert B4b.isequal(A) + assert B4b.ss.is_iso is True else: A4.ss.pack_any(**d) assert A4.isequal(A) diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 9ba63960f..2b5d6da3b 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -271,7 +271,7 @@ def test_npmonoid(): assert len(op.types) > 0, op.name if gb_left.dtype not in op.types or binary_name in blocklist.get( gb_left.dtype.name, () - ): # pragma: no cover (flaky) + ): # flaky coverage continue with np.errstate(divide="ignore", over="ignore", under="ignore", invalid="ignore"): gb_result = gb_left.ewise_mult(gb_right, op).new() diff --git a/graphblas/tests/test_op.py b/graphblas/tests/test_op.py index 1a6a25d2a..d51e32b0f 100644 --- a/graphblas/tests/test_op.py +++ b/graphblas/tests/test_op.py @@ -161,12 +161,29 @@ def test_get_typed_op(): def test_udf_mentions_numba(): with pytest.raises(AttributeError, match="install numba"): binary.rfloordiv + assert "rfloordiv" not in dir(binary) with pytest.raises(AttributeError, match="install numba"): semiring.any_rfloordiv + assert "any_rfloordiv" not in dir(semiring) with pytest.raises(AttributeError, match="install numba"): op.absfirst + assert "absfirst" not in dir(op) with pytest.raises(AttributeError, match="install numba"): op.plus_rpow + assert "plus_rpow" not in dir(op) + with pytest.raises(AttributeError, match="install numba"): + binary.numpy.gcd + assert "gcd" not in dir(binary.numpy) + assert "gcd" not in dir(op.numpy) + + +@pytest.mark.skipif("supports_udfs") +def test_unaryop_udf_no_support(): + def plus_one(x): # pragma: no cover (numba) + return x + 1 + + with pytest.raises(RuntimeError, match="UnaryOp.register_new.* unavailable"): + unary.register_new("plus_one", plus_one) @pytest.mark.skipif("not supports_udfs") diff --git a/graphblas/tests/test_vector.py b/graphblas/tests/test_vector.py index 48843c230..8baa30082 100644 --- a/graphblas/tests/test_vector.py +++ b/graphblas/tests/test_vector.py @@ -20,6 +20,7 @@ InvalidObject, InvalidValue, OutputNotEmpty, + UdfParseError, ) from .conftest import autocompute, compute, pypy @@ -805,7 +806,7 @@ def test_indexunary_udf(v): def twox_minusthunk(x, row, col, thunk): # pragma: no cover (numba) return 2 * x - thunk - indexunary.register_new("twox_minusthunk", twox_minusthunk) + indexunary.register_new("twox_minusthunk", twox_minusthunk, lazy=True) assert hasattr(indexunary, "twox_minusthunk") assert not hasattr(select, "twox_minusthunk") with pytest.raises(ValueError, match="SelectOp must have BOOL return type"): @@ -815,6 +816,8 @@ def twox_minusthunk(x, row, col, thunk): # pragma: no cover (numba) expected = Vector.from_coo([1, 3, 4, 6], [-2, -2, 0, -4], size=7) result = indexunary.twox_minusthunk(v, 4).new() assert result.isequal(expected) + assert pickle.loads(pickle.dumps(indexunary.triu)) is indexunary.triu + assert indexunary.twox_minusthunk[int]._numba_func(1, 2, 3, 4) == twox_minusthunk(1, 2, 3, 4) delattr(indexunary, "twox_minusthunk") def ii(x, idx, _, thunk): # pragma: no cover (numba) @@ -833,6 +836,8 @@ def ii(x, idx, _, thunk): # pragma: no cover (numba) assert result.isequal(expected) delattr(indexunary, "ii") delattr(select, "ii") + with pytest.raises(UdfParseError, match="Unable to parse function using Numba"): + indexunary.register_new("bad", lambda x, row, col, thunk: result) def test_reduce(v): From e6f94ecab34b8fb44ac18ab2b661f5111ca3a066 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sat, 15 Apr 2023 18:58:49 -0500 Subject: [PATCH 41/48] lazy indexunary handling and a bit more coverage --- .pre-commit-config.yaml | 2 +- graphblas/core/operator/indexunary.py | 3 ++- graphblas/core/operator/select.py | 22 ++++++++++++++++++++-- graphblas/io.py | 4 ++-- graphblas/tests/test_core.py | 2 +- graphblas/tests/test_matrix.py | 12 +++++++++++- graphblas/tests/test_numpyops.py | 4 ++-- graphblas/tests/test_scalar.py | 2 +- graphblas/tests/test_vector.py | 6 ++++-- 9 files changed, 44 insertions(+), 13 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 60c3a0e9f..426153fee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ ci: # See: https://pre-commit.ci/#configuration autofix_prs: false autoupdate_schedule: monthly - skip: [pylint] + skip: [pylint, no-commit-to-branch] fail_fast: true default_language_version: python: python3 diff --git a/graphblas/core/operator/indexunary.py b/graphblas/core/operator/indexunary.py index 00333effc..9e69fa6d4 100644 --- a/graphblas/core/operator/indexunary.py +++ b/graphblas/core/operator/indexunary.py @@ -278,7 +278,8 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal if all(x == BOOL for x in indexunary_op.types.values()): from .select import SelectOp - setattr(select, funcname, SelectOp._from_indexunary(indexunary_op)) + select_module, funcname = SelectOp._remove_nesting(name, strict=False) + setattr(select_module, funcname, SelectOp._from_indexunary(indexunary_op)) if not cls._initialized: # pragma: no cover (safety) _STANDARD_OPERATOR_NAMES.add(f"{cls._modname}.{name}") diff --git a/graphblas/core/operator/select.py b/graphblas/core/operator/select.py index bf3e1cad8..0a26fda50 100644 --- a/graphblas/core/operator/select.py +++ b/graphblas/core/operator/select.py @@ -145,10 +145,28 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal iop = IndexUnaryOp.register_new( name, func, parameterized=parameterized, is_udt=is_udt, lazy=lazy ) + module, funcname = cls._remove_nesting(name, strict=False) + if lazy: + module._delayed[funcname] = ( + cls._get_delayed, + {"name": name}, + ) + elif not all(x == BOOL for x in iop.types.values()): + # Undo registration of indexunaryop + imodule, funcname = IndexUnaryOp._remove_nesting(name, strict=False) + delattr(imodule, funcname) + raise ValueError("SelectOp must have BOOL return type") + else: + return getattr(module, funcname) + + @classmethod + def _get_delayed(cls, name): + imodule, funcname = IndexUnaryOp._remove_nesting(name, strict=False) + iop = getattr(imodule, name) if not all(x == BOOL for x in iop.types.values()): raise ValueError("SelectOp must have BOOL return type") - if lazy: - return getattr(select, iop.name) + module, funcname = cls._remove_nesting(name, strict=False) + return getattr(module, funcname) @classmethod def _initialize(cls): diff --git a/graphblas/io.py b/graphblas/io.py index 2b8e71b33..0e06df4c5 100644 --- a/graphblas/io.py +++ b/graphblas/io.py @@ -502,11 +502,11 @@ def to_awkward(A, format=None): @ak.behaviors.mixins.mixin_class(ak.behavior) class _AwkwardDoublyCompressedMatrix: @property - def values(self): + def values(self): # flaky coverage (why?!) return self.data.values @property - def indices(self): + def indices(self): # flaky coverage (why?!) return self.data.indices form = RecordForm( diff --git a/graphblas/tests/test_core.py b/graphblas/tests/test_core.py index 71d0bd8a3..ae2051145 100644 --- a/graphblas/tests/test_core.py +++ b/graphblas/tests/test_core.py @@ -80,7 +80,7 @@ def test_packages(): pkgs.append("graphblas") pkgs.sort() pyproject = path.parent / "pyproject.toml" - if not pyproject.exists(): + if not pyproject.exists(): # pragma: no cover (safety) pytest.skip("Did not find pyproject.toml") with pyproject.open("rb") as f: pkgs2 = sorted(tomli.load(f)["tool"]["setuptools"]["packages"]) diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index 7a32d6f15..68fecdeaf 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -1290,11 +1290,21 @@ def test_indexunary_udf(A): def threex_minusthunk(x, row, col, thunk): # pragma: no cover (numba) return 3 * x - thunk - indexunary.register_new("threex_minusthunk", threex_minusthunk) + assert indexunary.register_new("threex_minusthunk", threex_minusthunk) is not None assert hasattr(indexunary, "threex_minusthunk") assert not hasattr(select, "threex_minusthunk") with pytest.raises(ValueError, match="SelectOp must have BOOL return type"): select.register_anonymous(threex_minusthunk) + with pytest.raises(ValueError, match="SelectOp must have BOOL return type"): + select.register_new("bad_select", threex_minusthunk) + assert not hasattr(indexunary, "bad_select") + assert not hasattr(select, "bad_select") + assert select.register_new("bad_select", threex_minusthunk, lazy=True) is None + with pytest.raises(ValueError, match="SelectOp must have BOOL return type"): + select.bad_select + assert not hasattr(select, "bad_select") + assert hasattr(indexunary, "bad_select") # Keep it + expected = Matrix.from_coo( [3, 0, 3, 5, 6, 0, 6, 1, 6, 2, 4, 1], [0, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6], diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 2b5d6da3b..3a892f31a 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -68,7 +68,7 @@ def test_npunary(): "INT64": {"reciprocal"}, "FC64": {"ceil", "floor", "trunc"}, } - if suitesparse and is_win and gb.config["mapnumpy"]: + if suitesparse and is_win and gb.config["mapnumpy"]: # flaky coverage # asin and asinh are known to be wrong in SuiteSparse:GraphBLAS # due to limitation of MSVC with complex blocklist["FC64"].update({"arcsin", "arcsinh"}) @@ -180,7 +180,7 @@ def test_npbinary(): gb_left.dtype.name, () ): continue - if is_win and binary_name == "ldexp": + if is_win and binary_name == "ldexp": # flaky coverage # On Windows, the second argument must be int32 or less (I'm not sure why) np_right = np_right.astype(np.int32) with np.errstate(divide="ignore", over="ignore", under="ignore", invalid="ignore"): diff --git a/graphblas/tests/test_scalar.py b/graphblas/tests/test_scalar.py index 9d441341d..7b7c77177 100644 --- a/graphblas/tests/test_scalar.py +++ b/graphblas/tests/test_scalar.py @@ -510,7 +510,7 @@ def test_sizeof(s): if (suitesparse or s._is_cscalar) and not pypy: assert 1 < sys.getsizeof(s) < 1000 else: - with pytest.raises(TypeError): + with pytest.raises(TypeError): # flakey coverage (why?!) sys.getsizeof(s) diff --git a/graphblas/tests/test_vector.py b/graphblas/tests/test_vector.py index 8baa30082..499ecae7c 100644 --- a/graphblas/tests/test_vector.py +++ b/graphblas/tests/test_vector.py @@ -823,9 +823,11 @@ def twox_minusthunk(x, row, col, thunk): # pragma: no cover (numba) def ii(x, idx, _, thunk): # pragma: no cover (numba) return idx // 2 >= thunk - select.register_new("ii", ii) - assert hasattr(indexunary, "ii") + select.register_new("ii", ii, lazy=True) + assert "ii" in dir(select) + assert "ii" in dir(indexunary) assert hasattr(select, "ii") + assert hasattr(indexunary, "ii") ii_apply = indexunary.register_anonymous(ii) expected = Vector.from_coo([1, 3, 4, 6], [False, False, True, True], size=7) result = ii_apply(v, 2).new() From eb1560ea4f365cb0b0664bd739c47198280bf602 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sat, 15 Apr 2023 19:23:10 -0500 Subject: [PATCH 42/48] skip numba 0.57.0rc1 on Windows for now --- .github/workflows/test_and_build.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 1ff14b9aa..e301b7a60 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -211,13 +211,18 @@ jobs: psgver="" fi # TODO: drop 0.57.0rc1 and use 0.57 once numba 0.57 is properly released - if [[ $npver == "=1.24" || ${{ startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]] ; then + if [[ ${npver} == "=1.24" || ${{ startsWith(steps.pyver.outputs.selected, '3.11') }} == true ]] ; then numbaver=$(python -c 'import random ; print(random.choice(["=0.57.0rc1", ""]))') - elif [[ $npver == "=1.21" ]] ; then + elif [[ ${npver} == "=1.21" ]] ; then numbaver=$(python -c 'import random ; print(random.choice(["=0.55", "=0.56", "=0.57.0rc1", ""]))') else numbaver=$(python -c 'import random ; print(random.choice(["=0.56", "=0.57.0rc1", ""]))') fi + if [[ ${{ matrix.os == 'windows-latest' }} == true && ( ${npver} == "=1.24" || ${numbaver} == "=0.57.0rc1" ) ]] ; then + # TODO: numba 0.57.0rc1 currently crashes sometimes on windows, so skip it for now + npver="" + numbaver="" + fi fmm=fast_matrix_market${fmmver} awkward=awkward${akver} if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || @@ -301,9 +306,9 @@ jobs: if [[ $G && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \ if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \ if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi) - echo $args + echo ${args} pytest -v --pyargs suitesparse_graphblas - coverage run -m pytest --color=yes --randomly -v $args \ + coverage run -m pytest --color=yes --randomly -v ${args} \ ${{ matrix.slowtask == 'pytest_normal' && '--runslow' || '' }} - name: Unit tests (bizarro scalars) run: | @@ -337,8 +342,8 @@ jobs: if [[ $G && $bizarro ]] ; then if [[ $ubuntu ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi)$( \ if [[ $H && $normal ]] ; then if [[ $macos ]] ; then echo " $suitesparse" ; elif [[ $windows ]] ; then echo " $vanilla" ; fi ; fi)$( \ if [[ $H && $bizarro ]] ; then if [[ $macos ]] ; then echo " $vanilla" ; elif [[ $windows ]] ; then echo " $suitesparse" ; fi ; fi) - echo $args - coverage run -a -m pytest --color=yes --randomly -v $args \ + echo ${args} + coverage run -a -m pytest --color=yes --randomly -v ${args} \ ${{ matrix.slowtask == 'pytest_bizarro' && '--runslow' || '' }} git checkout . # Undo changes to scalar default - name: Miscellaneous tests From f6f35d21682aebe466ba5d7ad4852e3cab419a26 Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sat, 15 Apr 2023 22:56:12 -0500 Subject: [PATCH 43/48] quick experiment with coverage --- .github/workflows/test_and_build.yml | 16 +++++++++++++--- graphblas/core/formatting.py | 2 ++ graphblas/core/matrix.py | 4 ++++ graphblas/core/operator/indexunary.py | 19 +++++++++++++++++++ graphblas/core/operator/select.py | 16 ++++++++++++++++ graphblas/core/ss/matrix.py | 8 +++++++- graphblas/core/ss/vector.py | 2 +- graphblas/core/utils.py | 2 ++ graphblas/core/vector.py | 4 ++++ graphblas/tests/test_dtype.py | 5 +---- graphblas/tests/test_infix.py | 7 +++++++ graphblas/tests/test_matrix.py | 18 ++++++++++++++++-- graphblas/tests/test_op.py | 8 ++++++++ graphblas/tests/test_vector.py | 1 + pyproject.toml | 4 ++++ 15 files changed, 105 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index e301b7a60..fc7665d19 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -81,7 +81,7 @@ jobs: shell: bash -l {0} strategy: # To "stress test" in CI, set `fail-fast` to `false` and perhaps add more items to `matrix.slowtask` - fail-fast: true + fail-fast: false # XXX TODO # The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype]. # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. @@ -227,8 +227,11 @@ jobs: awkward=awkward${akver} if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || - ( $(python -c 'import random ; print(random.random() < .318)') == True && ${{ matrix.slowtask != 'notebooks'}} == true ) ]] ; then - # Some packages aren't available for pypy or Python 3.12; 31.8% otherwise (if not running notebooks) + ( ${{ matrix.slowtask != 'notebooks'}} == true && ( + ( ${{ matrix.os == 'windows-latest' }} == true && $(python -c 'import random ; print(random.random() < .17)') == True ) || + ( ${{ matrix.os == 'windows-latest' }} == false && $(python -c 'import random ; print(random.random() < .34)') == True ))) ]] + then + # Some packages aren't available for pypy or Python 3.12; randomly otherwise (if not running notebooks) echo "skipping numba" numba="" numbaver=NA @@ -366,6 +369,13 @@ jobs: # TODO: understand why these are order-dependent and try to fix coverage run -a -m pytest --color=yes -x --no-mapnumpy --runslow -k test_binaryop_attributes_numpy graphblas/tests/test_op.py # coverage run -a -m pytest --color=yes -x --no-mapnumpy -k test_npmonoid graphblas/tests/test_numpyops.py --runslow + - name: More tests for coverage + if: matrix.slowtask == 'notebooks' && matrix.os == 'windows-latest' + run: | + # We use 'notebooks' slow task b/c it should have numba installed + coverage run -a -m pytest --color=yes --runslow --no-mapnumpy -p no:randomly -v -k 'test_commutes or test_bool_doesnt_get_too_large or test_npbinary or test_npmonoid or test_npsemiring' + coverage run -a -m pytest --color=yes --runslow --mapnumpy -p no:randomly -k 'test_bool_doesnt_get_too_large or test_npunary or test_binaryop_monoid_numpy' + coverage run -a -m pytest --color=yes -x --no-mapnumpy --runslow -k test_binaryop_attributes_numpy graphblas/tests/test_op.py - name: Auto-generated code check if: matrix.slowtask == 'pytest_bizarro' run: | diff --git a/graphblas/core/formatting.py b/graphblas/core/formatting.py index 52b7ed4d0..42c3e8ae4 100644 --- a/graphblas/core/formatting.py +++ b/graphblas/core/formatting.py @@ -880,6 +880,8 @@ def format_index_expression_html(expr): computed = get_expr_result(expr, html=True) if "__EXPR__" in computed: return computed.replace("__EXPR__", topline) + # BRANCH NOT COVERED + raise Exception("XXX") keys = [] values = [] diff --git a/graphblas/core/matrix.py b/graphblas/core/matrix.py index ccab2082e..fc119db4b 100644 --- a/graphblas/core/matrix.py +++ b/graphblas/core/matrix.py @@ -180,6 +180,8 @@ def __repr__(self, mask=None, expr=None): def _repr_html_(self, mask=None, collapse=False, expr=None): if self._parent is not None: + # NOT COVERED + raise Exception("XXX") return self._parent._repr_html_(mask=mask, collapse=collapse) from .formatting import format_matrix_html from .recorder import skip_record @@ -2469,8 +2471,10 @@ def select(self, op, thunk=None): self._expect_op(op, ("SelectOp", "IndexUnaryOp"), within=method_name, argname="op") if thunk._is_cscalar: if thunk.dtype._is_udt: + # NOT COVERED dtype_name = "UDT" thunk = _Pointer(thunk) + raise Exception("XXX") else: dtype_name = thunk.dtype.name cfunc_name = f"GrB_Matrix_select_{dtype_name}" diff --git a/graphblas/core/operator/indexunary.py b/graphblas/core/operator/indexunary.py index 9e69fa6d4..3190850c5 100644 --- a/graphblas/core/operator/indexunary.py +++ b/graphblas/core/operator/indexunary.py @@ -47,6 +47,8 @@ class ParameterizedIndexUnaryOp(ParameterizedUdf): __slots__ = "func", "__signature__", "_is_udt" def __init__(self, name, func, *, anonymous=False, is_udt=False): + # NOT COVERED + raise Exception("XXX") self.func = func self.__signature__ = inspect.signature(func) self._is_udt = is_udt @@ -55,11 +57,15 @@ def __init__(self, name, func, *, anonymous=False, is_udt=False): super().__init__(name, anonymous) def _call(self, *args, **kwargs): + # NOT COVERED + raise Exception("XXX") indexunary = self.func(*args, **kwargs) indexunary._parameterized_info = (self, args, kwargs) return IndexUnaryOp.register_anonymous(indexunary, self.name, is_udt=self._is_udt) def __reduce__(self): + # NOT COVERED + raise Exception("XXX") name = f"indexunary.{self.name}" if not self._anonymous and name in _STANDARD_OPERATOR_NAMES: return name @@ -67,6 +73,8 @@ def __reduce__(self): @staticmethod def _deserialize(name, func, anonymous): + # NOT COVERED + raise Exception("XXX") if anonymous: return IndexUnaryOp.register_anonymous(func, name, parameterized=True) if (rv := IndexUnaryOp._find(name)) is not None: @@ -246,6 +254,8 @@ def register_anonymous(cls, func, name=None, *, parameterized=False, is_udt=Fals """ cls._check_supports_udf("register_anonymous") if parameterized: + # NOT COVERED + raise Exception("XXX") return ParameterizedIndexUnaryOp(name, func, anonymous=True, is_udt=is_udt) return cls._build(name, func, anonymous=True, is_udt=is_udt) @@ -269,6 +279,8 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal {"name": name, "func": func, "parameterized": parameterized}, ) elif parameterized: + # NOT COVERED + raise Exception("XXX") indexunary_op = ParameterizedIndexUnaryOp(name, func, is_udt=is_udt) setattr(module, funcname, indexunary_op) else: @@ -280,6 +292,8 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal select_module, funcname = SelectOp._remove_nesting(name, strict=False) setattr(select_module, funcname, SelectOp._from_indexunary(indexunary_op)) + if not cls._initialized: # pragma: no cover (safety) + _STANDARD_OPERATOR_NAMES.add(f"{SelectOp._modname}.{name}") if not cls._initialized: # pragma: no cover (safety) _STANDARD_OPERATOR_NAMES.add(f"{cls._modname}.{name}") @@ -321,6 +335,7 @@ def _initialize(cls): "valueeq", "valuene", "valuegt", "valuege", "valuelt", "valuele"]: iop = getattr(indexunary, name) setattr(select, name, SelectOp._from_indexunary(iop)) + _STANDARD_OPERATOR_NAMES.add(f"{SelectOp._modname}.{name}") # fmt: on cls._initialized = True @@ -346,10 +361,14 @@ def __init__( def __reduce__(self): if self._anonymous: if hasattr(self.orig_func, "_parameterized_info"): + # NOT COVERED + raise Exception("XXX") return (_deserialize_parameterized, self.orig_func._parameterized_info) return (self.register_anonymous, (self.orig_func, self.name)) if (name := f"indexunary.{self.name}") in _STANDARD_OPERATOR_NAMES: return name + # NOT COVERED + raise Exception("XXX") return (self._deserialize, (self.name, self.orig_func)) __call__ = TypedBuiltinIndexUnaryOp.__call__ diff --git a/graphblas/core/operator/select.py b/graphblas/core/operator/select.py index 0a26fda50..e4ae26049 100644 --- a/graphblas/core/operator/select.py +++ b/graphblas/core/operator/select.py @@ -38,6 +38,8 @@ class ParameterizedSelectOp(ParameterizedUdf): __slots__ = "func", "__signature__", "_is_udt" def __init__(self, name, func, *, anonymous=False, is_udt=False): + # NOT COVERED + raise Exception("XXX") self.func = func self.__signature__ = inspect.signature(func) self._is_udt = is_udt @@ -46,11 +48,15 @@ def __init__(self, name, func, *, anonymous=False, is_udt=False): super().__init__(name, anonymous) def _call(self, *args, **kwargs): + # NOT COVERED + raise Exception("XXX") sel = self.func(*args, **kwargs) sel._parameterized_info = (self, args, kwargs) return SelectOp.register_anonymous(sel, self.name, is_udt=self._is_udt) def __reduce__(self): + # NOT COVERED + raise Exception("XXX") name = f"select.{self.name}" if not self._anonymous and name in _STANDARD_OPERATOR_NAMES: return name @@ -58,6 +64,8 @@ def __reduce__(self): @staticmethod def _deserialize(name, func, anonymous): + # NOT COVERED + raise Exception("XXX") if anonymous: return SelectOp.register_anonymous(func, name, parameterized=True) if (rv := SelectOp._find(name)) is not None: @@ -126,6 +134,8 @@ def register_anonymous(cls, func, name=None, *, parameterized=False, is_udt=Fals """ cls._check_supports_udf("register_anonymous") if parameterized: + # NOT COVERED + raise Exception("XXX") return ParameterizedSelectOp(name, func, anonymous=True, is_udt=is_udt) iop = IndexUnaryOp._build(name, func, anonymous=True, is_udt=is_udt) return SelectOp._from_indexunary(iop) @@ -192,16 +202,22 @@ def __init__( self.is_positional = is_positional self._is_udt = is_udt if is_udt: + # NOT COVERED + raise Exception("XXX") self._udt_types = {} # {dtype: DataType} self._udt_ops = {} # {dtype: TypedUserIndexUnaryOp} def __reduce__(self): if self._anonymous: if hasattr(self.orig_func, "_parameterized_info"): + # NOT COVERED + raise Exception("XXX") return (_deserialize_parameterized, self.orig_func._parameterized_info) return (self.register_anonymous, (self.orig_func, self.name)) if (name := f"select.{self.name}") in _STANDARD_OPERATOR_NAMES: return name + # NOT COVERED + raise Exception("XXX") return (self._deserialize, (self.name, self.orig_func)) __call__ = TypedBuiltinSelectOp.__call__ diff --git a/graphblas/core/ss/matrix.py b/graphblas/core/ss/matrix.py index 93743d2ce..aa365e5a9 100644 --- a/graphblas/core/ss/matrix.py +++ b/graphblas/core/ss/matrix.py @@ -937,7 +937,7 @@ def _export(self, format=None, *, sort=False, give_ownership=False, raw=False, m row_indices = claim_buffer(ffi, Ai[0], Ai_size[0] // index_dtype.itemsize, index_dtype) values = claim_buffer(ffi, Ax[0], Ax_size[0] // dtype.itemsize, dtype) if not raw: - if indptr.size > ncols + 1: + if indptr.size > ncols + 1: # pragma: no cover (suitesparse) indptr = indptr[: ncols + 1] if row_indices.size > nvals: row_indices = row_indices[:nvals] @@ -3464,12 +3464,18 @@ def _import_any( format = "bitmapc" elif values.flags.c_contiguous: format = "bitmapr" + else: + raise Exception("XXX") + # BRANCH NOT COVERED # Then consider bitmap contiguousness if necessary if format is None and isinstance(bitmap, np.ndarray) and bitmap.ndim == 2: if bitmap.flags.f_contiguous: format = "bitmapc" elif bitmap.flags.c_contiguous: format = "bitmapr" + else: + raise Exception("XXX") + # BRANCH NOT COVERED # Then default to row-oriented if format is None: format = "bitmapr" diff --git a/graphblas/core/ss/vector.py b/graphblas/core/ss/vector.py index e9b6edaa6..2b1e8bf05 100644 --- a/graphblas/core/ss/vector.py +++ b/graphblas/core/ss/vector.py @@ -587,7 +587,7 @@ def _export(self, format=None, *, sort=False, give_ownership=False, raw=False, m if is_iso: if values.size > 1: # pragma: no cover (suitesparse) values = values[:1] - elif values.size > size: # pragma: no branch (suitesparse) + elif values.size > size: # pragma: no cover (suitesparse) values = values[:size] rv = { "bitmap": bitmap, diff --git a/graphblas/core/utils.py b/graphblas/core/utils.py index 214b5ebae..c5e70bd4d 100644 --- a/graphblas/core/utils.py +++ b/graphblas/core/utils.py @@ -131,6 +131,8 @@ def get_shape(nrows, ncols, dtype=None, **arrays): # We could be smarter and determine the shape of the dtype sub-arrays if arr.ndim >= 3: break + # BRANCH NOT COVERED + raise Exception("XXX") elif arr.ndim == 2: break else: diff --git a/graphblas/core/vector.py b/graphblas/core/vector.py index bec6a0aeb..8cd8ff7eb 100644 --- a/graphblas/core/vector.py +++ b/graphblas/core/vector.py @@ -1542,6 +1542,8 @@ def select(self, op, thunk=None): if thunk.dtype._is_udt: dtype_name = "UDT" thunk = _Pointer(thunk) + # NOT COVERED + raise Exception("XXX") else: dtype_name = thunk.dtype.name cfunc_name = f"GrB_Vector_select_{dtype_name}" @@ -1866,6 +1868,8 @@ def _prep_for_assign(self, resolved_indexes, value, mask, is_submask, replace, o shape = vals.shape if vals is None or shape != (size,): if dtype.np_type.subdtype is not None: + # NOT COVERED + raise Exception("XXX") extra = ( " (this is assigning to a vector with sub-array dtype " f"({dtype}), so array shape should include dtype shape)" diff --git a/graphblas/tests/test_dtype.py b/graphblas/tests/test_dtype.py index 64e6d69ab..66c19cce5 100644 --- a/graphblas/tests/test_dtype.py +++ b/graphblas/tests/test_dtype.py @@ -252,7 +252,4 @@ def test_has_complex(): import suitesparse_graphblas as ssgb from packaging.version import parse - if parse(ssgb.__version__) < parse("7.4.3.1"): - assert not dtypes._supports_complex - else: - assert dtypes._supports_complex + assert dtypes._supports_complex == (parse(ssgb.__version__) >= parse("7.4.3.1")) diff --git a/graphblas/tests/test_infix.py b/graphblas/tests/test_infix.py index 14af6108c..72e1c8a42 100644 --- a/graphblas/tests/test_infix.py +++ b/graphblas/tests/test_infix.py @@ -360,3 +360,10 @@ def test_infix_expr_value_types(): assert expr._expr is not None assert expr._value is None assert type(expr.new()) is Matrix + assert type(expr._get_value()) is Matrix + assert expr._expr is not None + assert expr._value is not None + assert expr._expr._value is not None + expr._value = None + assert expr._value is None + assert expr._expr._value is None diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index 68fecdeaf..0f9eac602 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -1231,6 +1231,8 @@ def test_apply_indexunary(A): assert w4.isequal(A3) with pytest.raises(TypeError, match="left"): A.apply(select.valueeq, left=s3) + assert pickle.loads(pickle.dumps(indexunary.tril)) is indexunary.tril + assert pickle.loads(pickle.dumps(indexunary.tril[int])) is indexunary.tril[int] def test_select(A): @@ -1260,6 +1262,16 @@ def test_select(A): with pytest.raises(TypeError, match="thunk"): A.select(select.valueeq, object()) + A3rows = Matrix.from_coo([0, 0, 1, 1, 2], [1, 3, 4, 6, 5], [2, 3, 8, 4, 1], nrows=7, ncols=7) + w8 = select.rowle(A, 2).new() + w9 = A.select("row<=", 2).new() + w10 = select.row(A < 3).new() + assert w8.isequal(A3rows) + assert w9.isequal(A3rows) + assert w10.isequal(A3rows) + assert pickle.loads(pickle.dumps(select.tril)) is select.tril + assert pickle.loads(pickle.dumps(select.tril[bool])) is select.tril[bool] + @autocompute def test_select_bools_and_masks(A): @@ -1320,6 +1332,8 @@ def iii(x, row, col, thunk): # pragma: no cover (numba) select.register_new("iii", iii) assert hasattr(indexunary, "iii") assert hasattr(select, "iii") + assert indexunary.iii[int].orig_func is select.iii[int].orig_func is select.iii.orig_func + assert indexunary.iii[int]._numba_func is select.iii[int]._numba_func is select.iii._numba_func iii_apply = indexunary.register_anonymous(iii) expected = Matrix.from_coo( [3, 0, 3, 5, 6, 0, 6, 1, 6, 2, 4, 1], @@ -3946,7 +3960,7 @@ def test_ss_config(A): def test_to_csr_from_csc(A): - assert Matrix.from_csr(*A.to_csr(dtype=int)).isequal(A, check_dtype=True) + assert Matrix.from_csr(*A.to_csr(sort=False, dtype=int)).isequal(A, check_dtype=True) assert Matrix.from_csr(*A.T.to_csc()).isequal(A, check_dtype=True) assert Matrix.from_csc(*A.to_csc()).isequal(A) assert Matrix.from_csc(*A.T.to_csr()).isequal(A) @@ -4285,7 +4299,7 @@ def test_ss_descriptors(A): (A @ A).new(nthreads=4, Nthreads=5) with pytest.raises(ValueError, match="escriptor"): A[0, 0].new(bad_opt=True) - A[0, 0].new(nthreads=4) # ignored, but okay + A[0, 0].new(nthreads=4, sort=None) # ignored, but okay with pytest.raises(ValueError, match="escriptor"): A.__setitem__((0, 0), 1, bad_opt=True) A.__setitem__((0, 0), 1, nthreads=4) # ignored, but okay diff --git a/graphblas/tests/test_op.py b/graphblas/tests/test_op.py index d51e32b0f..c9a176afd 100644 --- a/graphblas/tests/test_op.py +++ b/graphblas/tests/test_op.py @@ -195,6 +195,7 @@ def plus_one(x): assert hasattr(unary, "plus_one") assert unary.plus_one.orig_func is plus_one assert unary.plus_one[int].orig_func is plus_one + assert unary.plus_one[int]._numba_func(1) == 2 comp_set = { INT8, INT16, @@ -573,6 +574,7 @@ def times_minus_sum(x, y): BinaryOp.register_new("bin_test_func", times_minus_sum) assert hasattr(binary, "bin_test_func") + assert binary.bin_test_func[int].orig_func is times_minus_sum comp_set = { BOOL, # goes to INT64 INT8, @@ -808,6 +810,12 @@ def test_binaryop_attributes_numpy(): assert binary.numpy.subtract.monoid is None +@pytest.mark.skipif("not supports_udfs") +@pytest.mark.slow +def test_binaryop_monoid_numpy(): + assert gb.binary.numpy.minimum[int].monoid is gb.monoid.numpy.minimum[int] + + @pytest.mark.slow def test_binaryop_attributes(): assert binary.plus[int].monoid is monoid.plus[int] diff --git a/graphblas/tests/test_vector.py b/graphblas/tests/test_vector.py index 499ecae7c..faac42639 100644 --- a/graphblas/tests/test_vector.py +++ b/graphblas/tests/test_vector.py @@ -818,6 +818,7 @@ def twox_minusthunk(x, row, col, thunk): # pragma: no cover (numba) assert result.isequal(expected) assert pickle.loads(pickle.dumps(indexunary.triu)) is indexunary.triu assert indexunary.twox_minusthunk[int]._numba_func(1, 2, 3, 4) == twox_minusthunk(1, 2, 3, 4) + assert indexunary.twox_minusthunk[int].orig_func is twox_minusthunk delattr(indexunary, "twox_minusthunk") def ii(x, idx, _, thunk): # pragma: no cover (numba) diff --git a/pyproject.toml b/pyproject.toml index 1eaa942e1..4b1606db7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -279,6 +279,10 @@ external = [ # noqa codes that ruff doesn't know about: https://github.com/charliermarsh/ruff#external ] ignore = [ + # TODO: temporary! + "TRY002", + "RET506", + # Would be nice to fix these "D100", # Missing docstring in public module "D101", # Missing docstring in public class From 49e29f8181478ebd6f779ba0e6ba1777dfe2babc Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sat, 15 Apr 2023 23:19:10 -0500 Subject: [PATCH 44/48] try "no branch" here --- graphblas/core/matrix.py | 2 +- graphblas/core/vector.py | 2 +- graphblas/io.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/graphblas/core/matrix.py b/graphblas/core/matrix.py index fc119db4b..a5b5f3ee7 100644 --- a/graphblas/core/matrix.py +++ b/graphblas/core/matrix.py @@ -1589,7 +1589,7 @@ def from_dicts( # If we know the dtype, then using `np.fromiter` is much faster dtype = lookup_dtype(dtype) if dtype.np_type.subdtype is not None and np.__version__[:5] in {"1.21.", "1.22."}: - values, dtype = values_to_numpy_buffer(list(iter_values), dtype) + values, dtype = values_to_numpy_buffer(list(iter_values), dtype) # flaky coverage else: values = np.fromiter(iter_values, dtype.np_type) return getattr(cls, methodname)( diff --git a/graphblas/core/vector.py b/graphblas/core/vector.py index 8cd8ff7eb..15c3c2e2d 100644 --- a/graphblas/core/vector.py +++ b/graphblas/core/vector.py @@ -1989,7 +1989,7 @@ def from_dict(cls, d, dtype=None, *, size=None, name=None): # If we know the dtype, then using `np.fromiter` is much faster dtype = lookup_dtype(dtype) if dtype.np_type.subdtype is not None and np.__version__[:5] in {"1.21.", "1.22."}: - values, dtype = values_to_numpy_buffer(list(d.values()), dtype) + values, dtype = values_to_numpy_buffer(list(d.values()), dtype) # flaky coverage else: values = np.fromiter(d.values(), dtype.np_type) if size is None and indices.size == 0: diff --git a/graphblas/io.py b/graphblas/io.py index 0e06df4c5..8ece47a57 100644 --- a/graphblas/io.py +++ b/graphblas/io.py @@ -502,11 +502,11 @@ def to_awkward(A, format=None): @ak.behaviors.mixins.mixin_class(ak.behavior) class _AwkwardDoublyCompressedMatrix: @property - def values(self): # flaky coverage (why?!) + def values(self): # pragma: no branch (???) return self.data.values @property - def indices(self): # flaky coverage (why?!) + def indices(self): # pragma: no branch (???) return self.data.indices form = RecordForm( From 759405fdf9a2a0e9f89023ed593d378a561bd50f Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sun, 16 Apr 2023 09:18:08 -0500 Subject: [PATCH 45/48] coverage cleanup --- .github/workflows/test_and_build.yml | 4 +- graphblas/core/formatting.py | 1 - graphblas/core/matrix.py | 5 +- graphblas/core/operator/indexunary.py | 12 ----- graphblas/core/operator/select.py | 15 ++---- graphblas/core/ss/matrix.py | 8 +--- graphblas/core/utils.py | 5 +- graphblas/core/vector.py | 4 +- graphblas/tests/test_formatting.py | 68 +++++++++++++++++++++++++++ graphblas/tests/test_matrix.py | 5 ++ graphblas/tests/test_numpyops.py | 8 ++-- graphblas/tests/test_vector.py | 18 +++++++ pyproject.toml | 4 -- 13 files changed, 106 insertions(+), 51 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index fc7665d19..811080ec7 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -228,8 +228,8 @@ jobs: if [[ ${{ contains(steps.pyver.outputs.selected, 'pypy') || startsWith(steps.pyver.outputs.selected, '3.12') }} == true || ( ${{ matrix.slowtask != 'notebooks'}} == true && ( - ( ${{ matrix.os == 'windows-latest' }} == true && $(python -c 'import random ; print(random.random() < .17)') == True ) || - ( ${{ matrix.os == 'windows-latest' }} == false && $(python -c 'import random ; print(random.random() < .34)') == True ))) ]] + ( ${{ matrix.os == 'windows-latest' }} == true && $(python -c 'import random ; print(random.random() < .2)') == True ) || + ( ${{ matrix.os == 'windows-latest' }} == false && $(python -c 'import random ; print(random.random() < .4)') == True ))) ]] then # Some packages aren't available for pypy or Python 3.12; randomly otherwise (if not running notebooks) echo "skipping numba" diff --git a/graphblas/core/formatting.py b/graphblas/core/formatting.py index 42c3e8ae4..aefb87f94 100644 --- a/graphblas/core/formatting.py +++ b/graphblas/core/formatting.py @@ -881,7 +881,6 @@ def format_index_expression_html(expr): if "__EXPR__" in computed: return computed.replace("__EXPR__", topline) # BRANCH NOT COVERED - raise Exception("XXX") keys = [] values = [] diff --git a/graphblas/core/matrix.py b/graphblas/core/matrix.py index a5b5f3ee7..0183893fd 100644 --- a/graphblas/core/matrix.py +++ b/graphblas/core/matrix.py @@ -180,8 +180,6 @@ def __repr__(self, mask=None, expr=None): def _repr_html_(self, mask=None, collapse=False, expr=None): if self._parent is not None: - # NOT COVERED - raise Exception("XXX") return self._parent._repr_html_(mask=mask, collapse=collapse) from .formatting import format_matrix_html from .recorder import skip_record @@ -1589,7 +1587,7 @@ def from_dicts( # If we know the dtype, then using `np.fromiter` is much faster dtype = lookup_dtype(dtype) if dtype.np_type.subdtype is not None and np.__version__[:5] in {"1.21.", "1.22."}: - values, dtype = values_to_numpy_buffer(list(iter_values), dtype) # flaky coverage + values, dtype = values_to_numpy_buffer(list(iter_values), dtype) # FLAKY COVERAGE else: values = np.fromiter(iter_values, dtype.np_type) return getattr(cls, methodname)( @@ -2474,7 +2472,6 @@ def select(self, op, thunk=None): # NOT COVERED dtype_name = "UDT" thunk = _Pointer(thunk) - raise Exception("XXX") else: dtype_name = thunk.dtype.name cfunc_name = f"GrB_Matrix_select_{dtype_name}" diff --git a/graphblas/core/operator/indexunary.py b/graphblas/core/operator/indexunary.py index 3190850c5..ad5d841d0 100644 --- a/graphblas/core/operator/indexunary.py +++ b/graphblas/core/operator/indexunary.py @@ -47,8 +47,6 @@ class ParameterizedIndexUnaryOp(ParameterizedUdf): __slots__ = "func", "__signature__", "_is_udt" def __init__(self, name, func, *, anonymous=False, is_udt=False): - # NOT COVERED - raise Exception("XXX") self.func = func self.__signature__ = inspect.signature(func) self._is_udt = is_udt @@ -57,15 +55,12 @@ def __init__(self, name, func, *, anonymous=False, is_udt=False): super().__init__(name, anonymous) def _call(self, *args, **kwargs): - # NOT COVERED - raise Exception("XXX") indexunary = self.func(*args, **kwargs) indexunary._parameterized_info = (self, args, kwargs) return IndexUnaryOp.register_anonymous(indexunary, self.name, is_udt=self._is_udt) def __reduce__(self): # NOT COVERED - raise Exception("XXX") name = f"indexunary.{self.name}" if not self._anonymous and name in _STANDARD_OPERATOR_NAMES: return name @@ -74,7 +69,6 @@ def __reduce__(self): @staticmethod def _deserialize(name, func, anonymous): # NOT COVERED - raise Exception("XXX") if anonymous: return IndexUnaryOp.register_anonymous(func, name, parameterized=True) if (rv := IndexUnaryOp._find(name)) is not None: @@ -254,8 +248,6 @@ def register_anonymous(cls, func, name=None, *, parameterized=False, is_udt=Fals """ cls._check_supports_udf("register_anonymous") if parameterized: - # NOT COVERED - raise Exception("XXX") return ParameterizedIndexUnaryOp(name, func, anonymous=True, is_udt=is_udt) return cls._build(name, func, anonymous=True, is_udt=is_udt) @@ -279,8 +271,6 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal {"name": name, "func": func, "parameterized": parameterized}, ) elif parameterized: - # NOT COVERED - raise Exception("XXX") indexunary_op = ParameterizedIndexUnaryOp(name, func, is_udt=is_udt) setattr(module, funcname, indexunary_op) else: @@ -362,13 +352,11 @@ def __reduce__(self): if self._anonymous: if hasattr(self.orig_func, "_parameterized_info"): # NOT COVERED - raise Exception("XXX") return (_deserialize_parameterized, self.orig_func._parameterized_info) return (self.register_anonymous, (self.orig_func, self.name)) if (name := f"indexunary.{self.name}") in _STANDARD_OPERATOR_NAMES: return name # NOT COVERED - raise Exception("XXX") return (self._deserialize, (self.name, self.orig_func)) __call__ = TypedBuiltinIndexUnaryOp.__call__ diff --git a/graphblas/core/operator/select.py b/graphblas/core/operator/select.py index e4ae26049..27567eb2f 100644 --- a/graphblas/core/operator/select.py +++ b/graphblas/core/operator/select.py @@ -38,8 +38,6 @@ class ParameterizedSelectOp(ParameterizedUdf): __slots__ = "func", "__signature__", "_is_udt" def __init__(self, name, func, *, anonymous=False, is_udt=False): - # NOT COVERED - raise Exception("XXX") self.func = func self.__signature__ = inspect.signature(func) self._is_udt = is_udt @@ -48,15 +46,12 @@ def __init__(self, name, func, *, anonymous=False, is_udt=False): super().__init__(name, anonymous) def _call(self, *args, **kwargs): - # NOT COVERED - raise Exception("XXX") sel = self.func(*args, **kwargs) sel._parameterized_info = (self, args, kwargs) return SelectOp.register_anonymous(sel, self.name, is_udt=self._is_udt) def __reduce__(self): # NOT COVERED - raise Exception("XXX") name = f"select.{self.name}" if not self._anonymous and name in _STANDARD_OPERATOR_NAMES: return name @@ -65,7 +60,6 @@ def __reduce__(self): @staticmethod def _deserialize(name, func, anonymous): # NOT COVERED - raise Exception("XXX") if anonymous: return SelectOp.register_anonymous(func, name, parameterized=True) if (rv := SelectOp._find(name)) is not None: @@ -134,8 +128,6 @@ def register_anonymous(cls, func, name=None, *, parameterized=False, is_udt=Fals """ cls._check_supports_udf("register_anonymous") if parameterized: - # NOT COVERED - raise Exception("XXX") return ParameterizedSelectOp(name, func, anonymous=True, is_udt=is_udt) iop = IndexUnaryOp._build(name, func, anonymous=True, is_udt=is_udt) return SelectOp._from_indexunary(iop) @@ -161,6 +153,10 @@ def register_new(cls, name, func, *, parameterized=False, is_udt=False, lazy=Fal cls._get_delayed, {"name": name}, ) + elif parameterized: + op = ParameterizedSelectOp(funcname, func, is_udt=is_udt) + setattr(module, funcname, op) + return op elif not all(x == BOOL for x in iop.types.values()): # Undo registration of indexunaryop imodule, funcname = IndexUnaryOp._remove_nesting(name, strict=False) @@ -203,7 +199,6 @@ def __init__( self._is_udt = is_udt if is_udt: # NOT COVERED - raise Exception("XXX") self._udt_types = {} # {dtype: DataType} self._udt_ops = {} # {dtype: TypedUserIndexUnaryOp} @@ -211,13 +206,11 @@ def __reduce__(self): if self._anonymous: if hasattr(self.orig_func, "_parameterized_info"): # NOT COVERED - raise Exception("XXX") return (_deserialize_parameterized, self.orig_func._parameterized_info) return (self.register_anonymous, (self.orig_func, self.name)) if (name := f"select.{self.name}") in _STANDARD_OPERATOR_NAMES: return name # NOT COVERED - raise Exception("XXX") return (self._deserialize, (self.name, self.orig_func)) __call__ = TypedBuiltinSelectOp.__call__ diff --git a/graphblas/core/ss/matrix.py b/graphblas/core/ss/matrix.py index aa365e5a9..649cb5f3b 100644 --- a/graphblas/core/ss/matrix.py +++ b/graphblas/core/ss/matrix.py @@ -896,7 +896,7 @@ def _export(self, format=None, *, sort=False, give_ownership=False, raw=False, m col_indices = claim_buffer(ffi, Aj[0], Aj_size[0] // index_dtype.itemsize, index_dtype) values = claim_buffer(ffi, Ax[0], Ax_size[0] // dtype.itemsize, dtype) if not raw: - if indptr.size > nrows + 1: + if indptr.size > nrows + 1: # pragma: no branch (suitesparse) indptr = indptr[: nrows + 1] if col_indices.size > nvals: col_indices = col_indices[:nvals] @@ -3464,18 +3464,12 @@ def _import_any( format = "bitmapc" elif values.flags.c_contiguous: format = "bitmapr" - else: - raise Exception("XXX") - # BRANCH NOT COVERED # Then consider bitmap contiguousness if necessary if format is None and isinstance(bitmap, np.ndarray) and bitmap.ndim == 2: if bitmap.flags.f_contiguous: format = "bitmapc" elif bitmap.flags.c_contiguous: format = "bitmapr" - else: - raise Exception("XXX") - # BRANCH NOT COVERED # Then default to row-oriented if format is None: format = "bitmapr" diff --git a/graphblas/core/utils.py b/graphblas/core/utils.py index c5e70bd4d..77c64a7ac 100644 --- a/graphblas/core/utils.py +++ b/graphblas/core/utils.py @@ -132,7 +132,6 @@ def get_shape(nrows, ncols, dtype=None, **arrays): if arr.ndim >= 3: break # BRANCH NOT COVERED - raise Exception("XXX") elif arr.ndim == 2: break else: @@ -361,7 +360,7 @@ def _autogenerate_code( end="# End auto-generated code", ): """Super low-tech auto-code generation used by automethods.py and infixmethods.py.""" - with filepath.open() as f: # flaky coverage + with filepath.open() as f: # pragma: no branch (flaky) orig_text = f.read() if specializer: begin = f"{begin}: {specializer}" @@ -381,7 +380,7 @@ def _autogenerate_code( new_text = orig_text for start, stop in reversed(boundaries): new_text = f"{new_text[:start]}{begin}{text}{new_text[stop:]}" - with filepath.open("w") as f: # flaky coverage + with filepath.open("w") as f: # pragma: no branch (flaky) f.write(new_text) import subprocess diff --git a/graphblas/core/vector.py b/graphblas/core/vector.py index 15c3c2e2d..542bd440a 100644 --- a/graphblas/core/vector.py +++ b/graphblas/core/vector.py @@ -1543,7 +1543,6 @@ def select(self, op, thunk=None): dtype_name = "UDT" thunk = _Pointer(thunk) # NOT COVERED - raise Exception("XXX") else: dtype_name = thunk.dtype.name cfunc_name = f"GrB_Vector_select_{dtype_name}" @@ -1869,7 +1868,6 @@ def _prep_for_assign(self, resolved_indexes, value, mask, is_submask, replace, o if vals is None or shape != (size,): if dtype.np_type.subdtype is not None: # NOT COVERED - raise Exception("XXX") extra = ( " (this is assigning to a vector with sub-array dtype " f"({dtype}), so array shape should include dtype shape)" @@ -1989,7 +1987,7 @@ def from_dict(cls, d, dtype=None, *, size=None, name=None): # If we know the dtype, then using `np.fromiter` is much faster dtype = lookup_dtype(dtype) if dtype.np_type.subdtype is not None and np.__version__[:5] in {"1.21.", "1.22."}: - values, dtype = values_to_numpy_buffer(list(d.values()), dtype) # flaky coverage + values, dtype = values_to_numpy_buffer(list(d.values()), dtype) # FLAKY COVERAGE else: values = np.fromiter(d.values(), dtype.np_type) if size is None and indices.size == 0: diff --git a/graphblas/tests/test_formatting.py b/graphblas/tests/test_formatting.py index 3094aea91..44ca82de2 100644 --- a/graphblas/tests/test_formatting.py +++ b/graphblas/tests/test_formatting.py @@ -5019,3 +5019,71 @@ def test_empty(): "gb.Matrix 0 0 5 INT64 csr\n" "---------------------------------------------" ) + + +@pytest.mark.skipif("not pd") +def test_vector_as_matrix(): + v = Vector.from_coo([1], [2], name="v_A") + A = v._as_matrix() + repr_printer(A, "A") + assert repr(A) == ( + '"(GrB_Matrix)v_A" nvals nrows ncols dtype format\n' + "gb.Matrix 1 2 1 INT64 bitmapc (iso)\n" + "------------------------------------------------------------\n" + " 0\n" + "0 \n" + "1 2" + ) + html_printer(A, "A") + assert repr_html(A) == ( + "
" + f"{CSS_STYLE}" + '
vA
\n' + '\n' + " \n" + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
gb.Vector
nvals
size
dtype
format
12INT64bitmap (iso)
\n" + "
\n" + "
\n" + "\n" + '\n' + " \n" + ' \n' + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + "
01
2
\n" + "
" + ) diff --git a/graphblas/tests/test_matrix.py b/graphblas/tests/test_matrix.py index 0f9eac602..26017f364 100644 --- a/graphblas/tests/test_matrix.py +++ b/graphblas/tests/test_matrix.py @@ -2297,6 +2297,11 @@ def test_ss_import_on_view(): A = Matrix.from_coo([0, 0, 1, 1], [0, 1, 0, 1], [1, 2, 3, 4]) B = Matrix.ss.import_any(nrows=2, ncols=2, values=np.array([1, 2, 3, 4, 99, 99, 99])[:4]) assert A.isequal(B) + values = np.arange(16).reshape(4, 4)[::2, ::2] + bitmap = np.ones((4, 4), dtype=bool)[::2, ::2] + C = Matrix.ss.import_any(values=values, bitmap=bitmap) + D = Matrix.ss.import_any(values=values.copy(), bitmap=bitmap.copy()) + assert C.isequal(D) @pytest.mark.skipif("not suitesparse") diff --git a/graphblas/tests/test_numpyops.py b/graphblas/tests/test_numpyops.py index 3a892f31a..74a264330 100644 --- a/graphblas/tests/test_numpyops.py +++ b/graphblas/tests/test_numpyops.py @@ -68,7 +68,7 @@ def test_npunary(): "INT64": {"reciprocal"}, "FC64": {"ceil", "floor", "trunc"}, } - if suitesparse and is_win and gb.config["mapnumpy"]: # flaky coverage + if suitesparse and is_win and gb.config["mapnumpy"]: # asin and asinh are known to be wrong in SuiteSparse:GraphBLAS # due to limitation of MSVC with complex blocklist["FC64"].update({"arcsin", "arcsinh"}) @@ -180,7 +180,7 @@ def test_npbinary(): gb_left.dtype.name, () ): continue - if is_win and binary_name == "ldexp": # flaky coverage + if is_win and binary_name == "ldexp": # On Windows, the second argument must be int32 or less (I'm not sure why) np_right = np_right.astype(np.int32) with np.errstate(divide="ignore", over="ignore", under="ignore", invalid="ignore"): @@ -271,8 +271,8 @@ def test_npmonoid(): assert len(op.types) > 0, op.name if gb_left.dtype not in op.types or binary_name in blocklist.get( gb_left.dtype.name, () - ): # flaky coverage - continue + ): + continue # FLAKY COVERAGE with np.errstate(divide="ignore", over="ignore", under="ignore", invalid="ignore"): gb_result = gb_left.ewise_mult(gb_right, op).new() np_result = getattr(np, binary_name)(np_left, np_right) diff --git a/graphblas/tests/test_vector.py b/graphblas/tests/test_vector.py index faac42639..ab019b734 100644 --- a/graphblas/tests/test_vector.py +++ b/graphblas/tests/test_vector.py @@ -824,7 +824,14 @@ def twox_minusthunk(x, row, col, thunk): # pragma: no cover (numba) def ii(x, idx, _, thunk): # pragma: no cover (numba) return idx // 2 >= thunk + def iin(n): + def inner(x, idx, _, thunk): # pragma: no cover (numba) + return idx // n >= thunk + + return inner + select.register_new("ii", ii, lazy=True) + select.register_new("iin", iin, parameterized=True) assert "ii" in dir(select) assert "ii" in dir(indexunary) assert hasattr(select, "ii") @@ -833,12 +840,23 @@ def ii(x, idx, _, thunk): # pragma: no cover (numba) expected = Vector.from_coo([1, 3, 4, 6], [False, False, True, True], size=7) result = ii_apply(v, 2).new() assert result.isequal(expected) + result = v.apply(indexunary.iin(2), 2).new() + assert result.isequal(expected) + result = v.apply(indexunary.register_anonymous(iin, parameterized=True)(2), 2).new() + assert result.isequal(expected) + ii_select = select.register_anonymous(ii) expected = Vector.from_coo([4, 6], [2, 0], size=7) result = ii_select(v, 2).new() assert result.isequal(expected) + result = v.select(select.iin(2), 2).new() + assert result.isequal(expected) + result = v.select(select.register_anonymous(iin, parameterized=True)(2), 2).new() + assert result.isequal(expected) delattr(indexunary, "ii") delattr(select, "ii") + delattr(indexunary, "iin") + delattr(select, "iin") with pytest.raises(UdfParseError, match="Unable to parse function using Numba"): indexunary.register_new("bad", lambda x, row, col, thunk: result) diff --git a/pyproject.toml b/pyproject.toml index 4b1606db7..1eaa942e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -279,10 +279,6 @@ external = [ # noqa codes that ruff doesn't know about: https://github.com/charliermarsh/ruff#external ] ignore = [ - # TODO: temporary! - "TRY002", - "RET506", - # Would be nice to fix these "D100", # Missing docstring in public module "D101", # Missing docstring in public class From f6c6d2785c09e62f907a3bd0ad3a177ee9306ade Mon Sep 17 00:00:00 2001 From: Erik Welch Date: Sun, 16 Apr 2023 10:24:52 -0500 Subject: [PATCH 46/48] Make PNGs smaller via https://tinypng.com --- .github/workflows/test_and_build.yml | 2 +- docs/_static/img/GraphBLAS-API-example.png | Bin 324997 -> 77589 bytes docs/_static/img/GraphBLAS-mapping.png | Bin 122647 -> 31687 bytes docs/_static/img/Matrix-A-strictly-upper.png | Bin 11022 -> 3259 bytes docs/_static/img/Matrix-A-upper.png | Bin 11276 -> 3335 bytes docs/_static/img/Recorder-output.png | Bin 34324 -> 9883 bytes docs/_static/img/adj-graph.png | Bin 29071 -> 7710 bytes docs/_static/img/draw-example.png | Bin 15744 -> 5317 bytes docs/_static/img/logo-name-dark.svg | 8 -------- docs/_static/img/logo-name-light.svg | 8 -------- docs/_static/img/logo-name-medium.svg | 8 -------- docs/_static/img/min-plus-semiring.png | Bin 6500 -> 2348 bytes docs/_static/img/plus-times-semiring.png | Bin 7306 -> 2472 bytes docs/_static/img/repr-matrix.png | Bin 13694 -> 3858 bytes docs/_static/img/repr-scalar.png | Bin 4573 -> 1339 bytes docs/_static/img/repr-vector.png | Bin 9254 -> 2921 bytes docs/_static/img/sssp-result.png | Bin 14490 -> 4558 bytes 17 files changed, 1 insertion(+), 25 deletions(-) diff --git a/.github/workflows/test_and_build.yml b/.github/workflows/test_and_build.yml index 811080ec7..6aa692155 100644 --- a/.github/workflows/test_and_build.yml +++ b/.github/workflows/test_and_build.yml @@ -81,7 +81,7 @@ jobs: shell: bash -l {0} strategy: # To "stress test" in CI, set `fail-fast` to `false` and perhaps add more items to `matrix.slowtask` - fail-fast: false # XXX TODO + fail-fast: true # The build matrix is [os]x[slowtask] and then randomly chooses [pyver] and [sourcetype]. # This should ensure we'll have full code coverage (i.e., no chance of getting unlucky), # since we need to run all slow tests on Windows and non-Windoes OSes. diff --git a/docs/_static/img/GraphBLAS-API-example.png b/docs/_static/img/GraphBLAS-API-example.png index c6dd4818280a1ca9e425cd1d76e1efda7cc8407a..1edc9198890db10ce401055812291d9dd263ac2f 100644 GIT binary patch literal 77589 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

hcKp#aH% zf;=JAAji;a0rxywF~#B-w*Plu7i{B!jS@{D1Gi0=~|u0J=khUGTHo+(BQV5Vsra0fB}D#y$%{LXl+jzx7|J zS|1SwUA15BLV1OGvtkp4J%x%Mn-XhzmK1QjP{vL*YYyrJN>F@);KhARgMA-VZ%TZO zDa}_|?bdhrAv+>7VaA^;n|VENAUN##Y`fdY?vJ~E54-IV^p8<0Qcehq7!-vu2}CSI zd~UiWu%)h4WJb7-ab&4c$WaVW0~hGmg;F7bFp0w6YmSVi0>6Qp_vl8lL!(~J*jC=+ z9kv!SRc~%zx~pt%NYaP?)i9C-;)t*S+9lzIG>VW4Jq&`EYEYK~X(Oe|8NiLIPp^ z8-@S?Lr|y{)7%Q*Zg0Z6?UnpajiSTmCZQi`heQ1IWWCNx(f}QlB#8)Uj20bD4>hw# zq!`BGV}i5OX=JVWa#tzIxJ|5|fE2Es`BBz88$IenfBP3V*Z?IUVzX#?!Y1nmRyjVGPT)vgOGhY^&;ZOE%%9WWp*$LM0ty#b36QK zbv1jB1mbiZ_TH5Qk|+vuOhBpheM*aTyUM}I-j10Tz^pGIHjc_Qgt5w;@dll{ND2CA z3#qS$ZxoF@mL!2h|4Eq{dti|r1UyU~b4r96*)mLCAcQ_scc*iSJ-O@}{%Xs2`m^^2 z$0#Wt^5Y-O8m|?UG-y-potxk9y}lNwP^KY&fcNcY4ynOsmsmJRwuEeOcT<`&_>L%y zq#w=p91vnR`r$P^{47W8K?e^{!nvrJG=-$}jiZmVM;?TfVa|8&MOtypV`E>tg?F&y zM>6k6&_6WY3%8mpx;pz{Vl$$%H^gPh@qrXi zg9K2v|Bz}NeVmlAt_#)JZekgtJqSixpj+47qdl6Or-k*2tz%8VJw5@>@y1EOfG}y{ zy)fT8#PFw|bHtk~DJQ4n@Gmf?2p!Y~c1U3Ef_&XjyP-$JHez2Y0?eWC6qNV)k=)O( z?Qe6xZMx1qvEaF@qt?Nb!9bSEM3Q6yDDW^nl-2?9jygJ;#1~78|JtxZRG^t!AiQb{ zrEPMXyn07r+a~QKm6{)ANWY~qRU8%c^Nw?bo_+hnq1@;<#@jD(MLF_xs>3{GDV2*@ zwVFi`Q-}AH;Bstt#lHnW;*UB8;fK-1lF@c2RW?GUh7+^r{R{SpcR)us?>=-5K{V$J zK;{oa)5*`GqsQ>n)`olnYCeSyR#!z6P72705!%_(PFT3UQC}0$z(YiSSZT)YWzJaF z!@e|LnZ?!D3L6LnM^~?Sf9QGoePF5mNP;5P0UDl9Z?5Z#D&i@nHsC1oi^t<*oV1W2 zZ{`b9Q6qniCZK@q>#aw@t(D`?$v-B-vL(>;nl^&Mewo%8VMm!cAX8XP8|wIyS0 zcIg%}vL!54^;FeuO}gP-mHM`Q746RS7`wanl%vcmUfo=)pI>vC?vycwcB5;6R*k=W z&qEwMeB5_deERQtG~7Gi`J>$zD!|&er;PNNbx28VVm(~mi)CHP=jDMOWwFk*=yiz+ z7|o`rn}C~&?ehKl?hVP5(VeJP44?E_6*L;#4Y29#B@UmD*F+byG~`##+j8fkKZ*Td z)T+EC*kZs#Tk>e(8&fpg2|*5c8x#d8354k32ZK8gk-9SutD%9+u*!u*4$p&WOE+P~ z-VAM_qB@4L^O81p1%Gh)U^DO2uNg0Sy694A#zYRhOfVmR$SYnI!DiA3bQ%zg^rzJOH%XMJMx?^g0oQVd!;q zbY1|0NUQ&$ca~Sg8x9x9R%q_?B7e)(EAoE7K*N4c^RJp!Sb(NyhS|J)_tLF!s-jNQ zTbLzPsD7Xg?cN4*QLDRtU!>;E)79j&I8@;u!e!^%St(?ii?hf+_)^gO782(mb|+!= z7UiIGFg&CjKV`rs_lYfC@2f}GKJpZJf6n1adKFfC)IE92ar)9=<#N8?s@_>4{N6QCK$+mkj%W>tQ?%&Fe5eHnYN#-X1LXdx=vhmOWX~1G=*C$Z^x96qY;S zO}g6(r0W*D!^y;Y4t)8}A2NNLOuh9TwogcsE{yEum0(=O#g&b>oVzUP4@L)2XaamZ ze02ukDwiI(Rz?>@xJQ`@l)4n?UNAs~S_tya7@=TLT<;r#(n4cFB-Ui23;5N?8v(^l z!tVrNw!J0FHYx~BrnFmG+A9G%B{^&Mh#0Ks=%Po!JvB*EiX*~6xh=LqU+Z~vVAm)* z<*q2VQy5Nh%Fshm{pbQd zC*U#@xbvllQj;f+Eopk(D=cyB!0V?z5(Or@$tKiLyAbLTj-Bb>nJaz84y)`h+|s@G zK@WnbF$RcgkRG@X2dWxcsmvjT7z+w196bAC=&-P5J;al!UGO$6Z?-9_T1-=GFKHVpK-`l@LjG}7Ekq3Gu+FoIzh2kbsSm^NCj}+r%HNXtlR6*+T1QFEJPTq#(M_KWuwy338w@ z6}+5FEFZ+qj?Qu<;L}7m? zn=!z)Mmg6p&tYPyWtTy0VQmPJMgPuEyDt_43~-I%iG2M=p?ZjtvV(?>5aa!n`8o45 z+;XO|zIW?HX_Yx577D)U`l0c+yzI|~a2*vyLuvaXztDTvhU>-pVqnqHD3y0;Hav|W zzzPh`-3mh6xxXh>Ez$eXJbPyFYKgk~7`ra0I}~)oeCYhW?J5p_$VuW(AfrXRsr*`l zC()jQj_UOri?_*u4j_awoT1CCFLuv0 z2p~~lHlRH7ED^2T`MueEWSCRq_D75Fu_dJDFO7p#ZyI~y*Smk>z^9pa(JR2MI=yO> zz4grBtE4~Gqjbewefl;_T@0CLw%(%o$Ebnn&3g$8?HwhQ

>O&$l)WpA+)et>-;& zHZS^2zVXoYmyzw95OP-<0*kDhG}1kLF7nUymkB>e)&o7(6s?)(?tVttj#qxaelh

7tf5x2wmd;X>KW5;9BQy$E?ne<=Sf2 zNipehmoIy5b5dt0eb_I-)>n{RNZH zZZ-X=K={e{Q@cIZxz60>z~T;swTKh$bk-fXQN#rY38uz5*c^BY7{{FAq9n0NEadh06g-*8bX2+*(c=5Pw=`zP9w zjw+Zq6xlz?weudA=`j3IMvz0#dcv5;fErLXlI`U=#;|DGU$x=S5TMh)E5L;@pk1Ie z{8uTtO*a-$5&OGfyd?$3)N9g}mU%p8RLFfHdMg9>u|55m>9KBc@7IFXY zqVxZ*iT_#T>2*eG8G-m8!L~B&zanU-uQOPrz*cqx2Tj!&X?Ku;krQ=TbB{s_814#s2)NbeCrzs zSPZ&`8ihrbt9wI2gptt8&}!G>PIuwCqmh-iPZ3QtX9e9GzxX=aGY-^O!2d{-LlF!p z40%+K5y0Eqec@gFzB{fRa4v}yooaX6AVHxiCNsOT$%V~

@>tZ?^?s;Tm5WEoIWa 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 literal 324997 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� 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Ξjs|#*=8PhLS~VCn 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 ZPpL{M=HaR*+?`02<<;f#FZ^=*e*rVJgO>mR diff --git a/docs/_static/img/GraphBLAS-mapping.png b/docs/_static/img/GraphBLAS-mapping.png index 7ef73c88deaa7fe13a8eddab4762a9d7f13b5b02..c5d1a1d4ededb9da6dac9ab9904e206c308681b4 100644 GIT binary patch literal 31687 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

f-7NGXWBMHfhV(kWorMV%SchdAQVr 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≺qpGYF+(L|OSQQh=9KXp-~V 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�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

TVpTg&=l(i3=>k60qhTDOTZx~Gb{ zFtlAk2whU<)ZPbNpXO&OpXJJ77wtYsAG3tU)$jcv7rLs@DK-*mTnxdpGn-fidsf+9 z_xCbdv55r5Kcx~ZxtF{)aSGARH_;LT4#qV;9!&2w8eglAjbSn$5L1U=GF>yqK7`1- zQ{7u^Sh$+c-3vX2O3U^|n9KV7k_=7dYp&&47Cd-^z1_cJ^r*ycM9;BOhzM<1KMj<* ziNhtJ5tr?AvKBma7_6t!yd}Tq{RkUqFx@k-HBgT;FzuKL+m@TC^V|K(`W@(19UI7$ z2V5fP{yXjJ!DFtm@xr~;voN*Pa-2q+p`kI{;c$+17unfjo|19pzP3cSuG8apu>Uec zLdd*Jnbk&A8fd}ElBx$~PtBB%@|9AW&DPk+NbyE%w>_>~ zpe(*nek9WJ!2iC4;(eFoz`OkctPQzJH>GP2>yf?kJi0hW9bIMW4n&H&r3(dZ`5LB@ zt3x8HBLE-}1N7>?F$)zn;ryCmvNlT_ZH!6wJViA`AKs^NWCDnCkY>G;l`7?jje(WP30R<>LCeZzMxKn z=l7C3$6(COSJx@Ua$-L(K&ukCF6uX}_@}9z&C_}E=~j*u*cK$dSHG8m-W=DhSk;oW zVE{PY{dg;0w+@d0nCUg`{GD0)@|ulMQV2hv!*u=mI-WTh!BJBs$HA)@R~8)9Cv7-& z=ZU^uF7jzjADJ}yZx0PfEVp!8R31W>uKoa zjKpmE%6FdRGk&={g(b|voXM2EHh|ArYVSE)@g*(TKk4aaBYZ2({Wua9iJ%Ue#eHTK zfv`|efO0;#(dhxlED0!LPw~8(i?W=j0|D3JDk7#wLXUIC>9r3Yp~8CCI(Vy@zHfnp z-sbFs#3lZLvU>m+ZL9VEIGS21?}mUp)52@Sm2ggoN1+;@ z+-Pf5*fJAPs9uPbA;Pb_@LfL!Gw$jyoB= zb7JNFp>^E$$ZuEuQ8x8_uB@GUau0ypRQl>*hNfOTdQmWkpDg!&7~BysReu7{H5Vv$ z%F52(?PUheh11xgBr5LD2J_QJEQxb=Dwgj#Wx3A=I#C2HVnxK&sBLC5oieVKs)3qJ zb;73oT@0WH@pVm5_NANbX-k@UU^QM&mJnKH61?(>Vl{VE`|)QagPE%I&DFZvPd0kt zn1?I$w{z~fC+%L;{0j~ zvyB(8?B5K=`D@PfcN`tOH@>HE?%aKE&om9;zu6Q@-l(HgjC1#093>_u#=E^>T&W&mqs?DH|Pe+KI@aPv(+ZOK?%6_b`$~9~7dRoiJ=qV0lx-liK

cAU%pXn+s$#+j6X)*dCrTa&d zr|t3g`u-ZGrG+c$VPB}?#lAwxX?P~fX4aTt%9@DmyPAmi6Y$MNpVAOA)R?@Z=@P3IRi5j# zuM*Le-W(1%ayZCIghWp!O_75XWzU^UGHaNG^i#vlNvD)<_*#nge_RK>hD83Yb#iHT zt3Sp**JKoK!RG7Z23F0Mt8#q9VIED&cUN2G$4ATKLdGoW5$^{kXx0Auh1wAxsdo4N zZGq+r12C9NyJ-@US)(!RkUKAfQ{rFC(q+og2*$nF*CBZ5|jD$?)sg|K|wKWW&|Bx_GFp$TEMQ=bPv9dst155T*vdrA2A> zR0Iu01~QmUkAjPfdExw{#_a`OHPDp8;^$Ikh;5oKLO3V#yjL5rlfAt2J*rb%0|p9>s=X24H&!_E4=SJvlI+7YG!|lo zE32r904uJ^u?y>SV&OtT5d&f{1n^Q+XejQiZ((lhQakD1tw3>pHyeI+ISfsg#gv`i zU(XOM^m(J0pG{+;+(s*##45?qe8@awG1#_$@^i)GT()t;<7&>>aI!#gE3W#*Vu<+I zb1?7wetI!mFAQ)%vXRGHx)k3-d*RieOa0*h*=jH9h8&>7zt8T_EU^;R6ncS|CAt=4Ah%(`ixTb~@bE!7j!CmS#3&r}fXJ;rhNJauGak+#$LicRHHy zt1=uYA-z~c(svMsW@Tn(&dJCy=(U^qQfIlK633uTBPl6a_OXS`M-T?V=2%R@PyzF= z1!({xlvTG+#rYR6fYmFK0uoYCkQad{x%9mY8w+2tUQtmN6a8fuB;R4ec#b)5ft4%`o(Q|6}vO4;T2&%}uq)24HrnGh-?+CFV6T{~{l8F$S^M zP3CJt?wZ9l(BsttGjM8bH=qu@HIfwID(`OmRu5ZLssN}*^aLo`ptfEd5&(I*Re>EQhr#8R^zArnR2iW_P`4T?T+j$ z{(6)ku5Y-&liD!n#_Q{GB!&jTW!D|TYmXASMVF1xvq>d+SHk5napD&%72D9jS-v$0 zaC8$MAfBAI0{UOX(|I9Y{V^5SzYuSX1R$PCLGEb3#M1X|Y-CNv`Y{FR7_>i#rvmdk zjF1+%DG#}~d5L)%&-!VX&MWx=;+4#N=n4Fbcrj>iS&Twt5wpnfO%u0ce~?V!GZX+vAIk~`==(2J{D*e` zH~!ZCg+wsp*B6C80|G#m00wl&fBdrK{LvXZ zKH+^IZfK6thEr6^az$3NzB>$R0U2Z&?Pr*wh5!Ca|JaP+AQEZ;>iK5^%~xs(>F?Se z?~Ug8!3#eGDjL4In7WOtkMBjjde6YXus$FSiN>h~+fYVO#x`R62fP0J?-DdbKrK*E zuR5&%1mop>0IB{`mQe-npEvE1K8}ccWGF3Jss`9okO46hiwITqAF3s&28)P-)prIu zATOs9D7i1)9mdNukN^$~Xq)is!u25e-O;qTFp*yrt-VrEagB8DLOgDBM{N4Xpy{Q# z1c;)RfEWc|G#(8T2c@O@CVzfg?XT7P_F~_79gw-M_w>B0i|FgyI~!g# zCad$nq;miWnYmE;ho%Z{BGBEM`t#bK8%L^EJjYU%>J;%ZKW6=)Cx$If00{Z>w$c$$ z8mlg=B|AWKRyBPDVOJRFKK|3=aX!GnD|0^V^A?4>9B;(;mXV)l@4rpD!--&{&6Q%7tpCrik!h0Te~>SGzVe!DG}acyV&!KLT3^T5nsmw^D0nv#Tu`N$ zZ~}iahZO$KUFhXqKVJK`qzJp7HSJY--46FsjXq07M!aPV+SYwWYVO5VB_>of%>J;3 zv3icfFMWln39!EMb2jh?(4%F1fNMEC7f^f~BXQ#&AF`AdLM=b+|bxuSHHQJDf{WF#W+g8HKL zps*z>>D!GN>ki_xUy_SA9KI>gx1SPpF_{8OeG!3-0zDm-n8`4UB$l#$r~J%f&K?LJ ztVEq372W>DQ2nvO6hzd5RppQe@1}MjxinlFRNZQiV~c7t4#Xt>nL><*Nm(goDJfG( z&X!yoKM1KRb;*7CXK2e@ntY-NxVQ@V7ertqy;y!(VB@3nl)x3IC4}!T0$U1jO?* zZAO;jUvR>QsjoaRyK#DS@em>e;UR^QLC!EjKUsx-`jNmte1sJG39CR&HV%`EfZg;H z6Mq~n=X%*43<`vx&N)l3x8-nmc8>=QkgJ~I3%E2_vs72F(9fm1wq5h41&d0MKtTN) zK6Z_D+cDe_->&%fQ` z|HNJXEnI&K*S`d}|F6YdtnlxD_l#FpEMO8k1*h>fiRdgR_Hu~B-v)Un+HcPk_|pBE zc~HCr>Cpcv3rR-kqUahsGw0d8Jr~Ul)o7$u5PDwh=f-~VG3^>qE_G_sueXFCVA6P9 zg~h`NGVwXA6buYn&$fF#FN-c(mrE_oJYHlO>Hqma{ZF zM{g(Mi=eBCK#X9Un`F|#`?Qy+10!)VgfNMStS~}=siaE4s0fRqV5vW!OpPHSA(0`< zR0-bLNLm3=6O&54m|Y)!DCe^86F=S{AtSck+RBU zVW8Oa)EV*e@BsBqOo+%U#@N1tst~u&jt&xGB0+V$MkGv~OHb3{Hjl8j{m2W2#Ni$& zRdXA|3u1cnH4=-x={;n~dE=(3y-Pl+vds;(MEaWtpp9a()?C$;Sr5QHnFPv-F6Nl7 zprD-Iqh7T(d`AJ3Ny&^_OcjqE#OOb~AF}L~Nfb;`cq9Vgo`EtDc>sMr8<-C^zR?p- z4b0SvGVU84RoJUH8Ow?h5D<>bmBA!`kqVN;c3m8f(RHO@YW6EryF4>$>1~p`>RXf| zf*JL1OqB;Iv=^8#T0szL^koipqpGMjbdX_LC%=#wQBlGcl7Or;mSF!SUlHtwaXMa< zw4ATW+}$-vVm3qs0Zqcxs=^2_LTaM~^?^ceDG0W0@>Im~n%u{|({rRWJN&StG@n&} z)UC;OE%Ufc&?g^1b^-GnU(!N~6u}QP-{j`F@x8`us*VsA?d)}mVo2EFQ6y;ZY#B%{ znL1Kv7_C@{-?v(qgIujEs5G2U1UarKK-r}zFalip*K*tKc5;nPW@ddDD;UNJ0;=#m zs`C*IpI3Hdw+in8Yi0&GU!BfBG!LfEYDo&fnaI05m{C$zjxmJ{O#!ARytH!dUC!v@ z5TWs!0ytX0&}WLXlamYp1R71iIO5N+EefHf+KPnF%Z-++)1+^P1OIVpobCC0N5br` z!B;Fm=@?*6EGm)2SfQYB{o1>NFihKhAPc!w;ITdhpv0zrYX?AjO#why3eZ|5-bPMr zk73Q(<#yr0xu<%80_n!mS3ZCAo0Coy)BVZ9@iBW*Sf{8@g`aX?OF;)BLy<&`A+#rO zI;uk4F#iw!lY)B=j#%m6u?&2_c-g^udz zW`(Qadzjqqw_Vr$tH^8%tfHqm-m{YnDQ%I0BNZ5}+vRS~bWQD_du|_4Y2X*d!-;Z% zDaA>!D-~Zv&aSUHnwOH0flldsV4`qxDLOj3@aH1sN^|&4pzB!@uIo&$Cj?hS^#y9;17tOh0wjBz(CPP9fmi`9N!(nbk~m-x!vkzrX1Ue<$P% z7T9{bL~8T9##6LBqmWbV*G~p0bc`9( zdtRqwUzq?HX&J!Wm5KA6yKvM~=qhSlG~?SicXixX_RhYI>LB5sNF-$;1datMu>hShn=h&uITie4VI0I|W>g zf{26!30|sU(slY=02f+Xr;|Q*thw}au}aO?Zp7ejpzGWI4w!^PA2-%)3jmo+)>&%i zx(EvTyzlRgg#HqMNu_3k3pLU$y;==@Pkm}zrAF%J_dyK4jgb)g8{(b(7ErWS=>7ck zsn_wb_9EWE+MVuOdrpm)5fuUy$?6l#ut2L22N{_9RnzUZ4!4_Se$AUqKR;Nc7tW9X z$2*WXP=JxtfeOZ^&jQLG_vp*i-w4CX()BtpL6z}#Y<(>l)22n}>gqz};c0ZFS<@wZm9r*M@H9;nw#6>>m{BR-(Mp{9GdyVv#~L3IR$e^Wp!)2w;%58wiN++ zhDCz4GtNYZtyWBi3!owi4qv)ndyU+51`4+2H*WCLszw30QUQ$NE&`bF)7T1dDXdP1 zvzP<9%B$eE=e+u5H`?5<7eF;8dYeZsdpAP%F|%R+Xm>D9Y~CTYp8{Sta1b5Q-dVpe zaXt~4LnK&`0T#7Uj?EMa+^0?X`Kj7?Bo8Rc&C7yShJA@tt|?Atx{)t-BDuzegbP-e zcksktL6PY30f$8;#^3QsA`}t2dU}-n;gC%LYOucpj@*oZc`%|dTCRQrK_9YcO+{CM z!9w|7k9X9iJAKjON%g%+Y{gN50T-00L_~7FzP@{H`l;>?S5JGquQ8z^p#fXX-u~qh z@kTxLH5M~GU{-K9MR`uYgzZ*D+;DHgWcp#GQ}H;_mmZGI*IUaY;V{%R<|nck=PlG* zD_tGVSz2|*(tM@seKI~c{AKH4IHfi8-P0aMG0|B}A&n+fw$2_Vq8NW?ETD~2QMknP z{dcI)`A?0*x`~taQy~HP<)aT%@e?)ob5(8=%|pS88+fiksas7-c9-rr8y?3FY|%2MU#IfT{e-sj(FmA0%0Az&cep+8c0>4-Y>&zXGM- zp#V6sLCf6!B~UD>08C1Xb>rRj-s;CfeDg--tO5e6Ob$2~JQ&V6weM(}pN=KsvU`t= z&py~BMFkjJ2q@eiKF#o03<98!kJHGkoc5NqK&T=0e+xArTCHP(hPWbwf7MEUxQsfEy8CF2_WXNMw4c$MQRY<=YgNL6Df&grnP?~^u8jW&+Ai;NPK6J8%oL7d2(16d4MQ8|C z@Ez&cJE4s^;Z?uUWF;XsJiW5tn(%K0qFYW#NM6m9)%O`lB&%XDK>02#x64V!HkwdD zMi6WwgV-P3dCk#e4(*G8K{49y+ehYnWz!cHn=+T(h8(yz`I++$bp+#Rp?)MI9q2c# z4L+yy7qe8ey?UCnktl$IN`fg%cPAm(CD%Ov_6;t|+Gt@XgUxyUcjD^KZ%UlNI2x!1 zju-c@BncrLpbX_uxgS<1u37mNw$^M)D)Z`k#aju$DB0T{O8%rXl*DEVgmV2(&N}UC z5uPK*eYd*fp`pRDc$e5t*^Hq&LO@!;F_#x>Yjfs)v0AXlrnc8t>o0M5|RPabzpBkwDD-yQOw{PEO?Kw=4U@nXbUBpdP zF)b}kxk68N5*4A z3V8p9(LP~SOS08B7+UOvoHUKEeS3Q)5Rs8{fw-5()2RFjh(HvlDr7w7$&JD3*$sMaf2II0KUZmhs}!497Q=Ke?s=k8z?}5g%PJ^D z7z{9f?Sj7pz=mU>H-Eg&m5x`LUUG!g7rNr94mz!@$+fopiJ_14yU?IVzCdE)`1hRA z46!bkkh@q7$DB@*O`%z6@3#B*44&_qHl`j3lu(`jyk(g`|YFs8h zYqZ>QcO#(rrzEw-guB&Jlb1JLl=Cb$zumFllO82a4OCbYID84RfdxpJGq&E4$)$>R1gsT6#$=`}=4R%0dr{IQpKHeOZfaUj#y)#mna zu3Acy*z*GI5r{Bfvcz_6;MO1mEOT~Fl8eH`$jAspofv=x4Ec$}Xf^&J&`Ja3#^!lB zrRuQRixz$K8yA)4Ek+0TixYo~4!E6&SJQun#eZZL^az3l5pfPWHt=b#%5dxRgP)JEPXGci?fmofTqU~r zXT2Roi7QG}Y;3V?vCu4__fk}DLl?$Qn6C(dfO&mfW5KjdHVh8TP2A;SzY_@^Xe9I84#FajFXR4Usvf z*qO|owI>T^AO1A{q*2)Fime78hS@5 zniLQA|$q4vE$m=+U4z!jzT(TbsR+yk)p%DF#X0KjH)3JUZ<8$4c@itZ>> z8nrI}&=(mO1g@;e{^QEZ_u?Iph2K^FP9qR$ABUOAPxq1nTBIfq6Wp{G8`^=)vjB*6 ze$S03xB{5ovS(Yb;js+RZ`df>?MV*@sYyv)qi%ukWF0SEx>K-PVI1Va%$fvtixTwR zk7bKfz-rW4NCIhSJb_N4g-qaUW3VnaNjt-TFsi*2*uknw{=|9*=R8s9$5~>J6W{S3 zU;;EM&%15qd^y7TM*IAl6h>Ws0Dl;-vRckr?k!T)${ZheHSy9MXgH^XjK29(AIGbN z&HR{3OFfaFtr)s@gVx zaHq@-mOBr~A>ofXtQIqX@Rr6{@9E+80_b*70{oEa!F1^-ev~wzjYXR}+xQER8Y&m7 z(0|R=k$Z@^1rqf_pa+iC^Ui^~Tp?4~;d1}8>7359(slBJLFWb_$8*K5HPBFU9|6PX znZHpxqmvDc^EbmDjv`00Tx=L484orR%9gpRyX?l%eY-_bE?f{X2qpc(s*IQK(9`rn z|HJa_P_~b4PnT&+H#>vlC|YKtRo8w66xwa|j|-#`oL^kj9QYClcxmBfuU8fVVm=0R z^^(6E0dP5_hZ$!f#ef8%P%&GqYsDo@;_%BO02Kb|n|#=Q&+{xbJP%aleV?NEoQS)i zpkR~p7;XTf2R{lCFO_YR`*oRv)$N0rsHnsa8!Kzf*zoe07htiBqAb`BEq(ytgu-V?(29hP#uaPkgZ-bnIQzdA-h+1eE2BMfjW!! zVr~BXG@t$*3(^fP&%sPgBkjVFNW0Lt=lAV@E8J>Twc;$bk@ ztR!(yAF=euSG-7FpctCQYy43aph3*$0Oqh(yqVj8JA#cZ7MprC$kA(`A6tV;^C2Dl z%q@$L@;->a>i&N80nJg1D4A#J#TwrZFfF|Sc;o8^oDEFo$>PIu2Y#bb%z{D2W&YNB zyNyqtJ{4ys)UevO|2w8DKscD5|j2So`m8Y!)hgKXDzGktM~H9pHcFaUrn2=`5wKV4spAK5cY5I zXQ+f^3Mly-EIY0AU4K8FcMm4*#Yz5M^fm8}BRBADAQ9Pxnse+p>Ga?n)aKKf1f@a{;(cO!O$H5jIfZ zz;{@W)P6W_i<53Kl?M)1PR@kcf*@o)g4h(0ci8&Z7Tv3#y~{K%dOt=;1t?$e#6dW? z@t?~D(7f&EX2Z)TZf;zt(UrS@Vx_LnD_>8f4NSvht)p-3nssS65ne`EedNoaWRj;Q zi57spH_VTq<0`b!`*L}D&+@2Rmc zqU|v&d5>?p;KtbDcF(d2pHS>Ni+F5e79Me!KmxXUJ5%8qwLg|Ca5*m}iy-hGL>smt zsrAj_bt1?!HA{C_6dkhl)thAjX;m_-2@KoP)636vnvgW<*##d((QFkRZq{6z$jYX^ zb-~cYfgoasb$YkT+sjm-;+44=*mONd)WO z{y}n`xB2bDX*0MrI)w;;asBb%2fz)~1m!&h2H;v$E7CcyDmR5ckr%EkV9|M%rm&3YAMTsi=RMX~94 zYlqr>2j3P^O`sI&Z)jTBXC@jds(!eOvt7pW7Kw-S(fZ^m^dE=$)p6IL=n=TPd>A ze*ZXN;kh-EYqJNJsNJ|VIc@topa^)qm1R<_jG;HiMjVX&yx2BJF!th;EKTSvhq-b@gkuZCCVqR;HTK$JamIWxoTt=j_Hh{E z5lTGM9(Nao2G1nn3-b#^^2_Bck4@uh5iGVW$I@Dp81s|)dA97gTm7<(^0Qx~tf}8U zsl)KKdW3|H;7KrrzuqAQj)O&qALC)VWXyMmqx|4{Frr@aD-nJ!8VXX*3c_W$J27!;eIlK91+nX!Au+#@Qx{BNL-_4r4 zdcyZkZ_25^bRuTCOa!^gqlHo5*9%0bDhzMdS!n&l`8jCZ?DT1|l`qET0%Gh@Q*fBrun%X0*gw#3<_nQJB^RNB09);I0*71&L$ zeq5Q609%o+U$7TiHbe837_PAMBPYXnnNY!kS<|JNHxuiyVy`naq==rLHZ|KwZ$B4V z6ebK<=%a*KL}bU#`fLN}64UcBUx|VVyzY-UhV0-M%7Vz3nCDglC>!VWQl1I<+?1Kg zm}el_^@_Bc*==)PW6$TRe%*KmAeCZWgp;!0o;KxnrJ>D2(~48lsFtOCib3`Sn(!%c ze<>F!OZLeh`DNeLTQ0EgJyfb{ly-?34+_hF^=G+y+mWU|M9yya)t}OSS^f6W5ExW2 z?)YB(XVk(vBq{p`{mx>bomhzZ_vlaI&mcF)ucrn}O^#bd<6!;M`Y%9l_5~0xVFY7^ zC;>B4Ot%LU_x59_8cl=P?4*+2+K0dsoRyFTK!Z+a8Iv;;TKw3kD}xfvUfRNbTR;!<&Pw9 zHJXkyJzAOkike+zL;Ix7Y6}%^0a^G!v3Rrzb2pitC`~=YX0^kV`|5-s)!ioTSDF@1 z`Md3v+m;q)#itDP$?9L4)OgVg!q;8d(lz2KGbW@7AL7s8(PZwkLI*ALX1{T2xZ5*6 zx|?DwVa=Ec3zsNQ`}2PLV(|e)m(Z$N1$+Bbe=HguHhfF9eyp_jKE`BCo4%crc4|md z{q6kD%tXoRLyFT15A|$%F6S2uYlho!q8il=f1^bUFGy-BL%Wn7Zsoow_-&7+l zZVL=Ex!2QVGj4aLNAYZlMFrdq#-H^_?e;&PdMop(o~`oZxZ&YQvdGbA@~PJSynZ!d zo@20F#G0ew+`ndi57W%Tr>S+>_|;B0@=IJh(9kcclqbW~tZfe6W?x0hPZ_4u4yLsT z8S%3O6#_%QK8eZ_nO9MqHuD6xs+Opc@^zLJ7BdWdU4ev#lUN&7LZ>_7H=iz{4%IAN z_)tHXwF8{3NrW-YlFUpiw|cm)Gt~gF@^kawj@`o0X-+u0M>9o&df>L0#FtXpm4Mi} z(a`qe_TW`&%$l|26T_ypoBhf=qb9?sp^d2D>sag&hHDYz@2sQ0KMmM)fijPgyz@`r zA_g;ZmeihB77pZfGb2TE?lbBRJUssXh2m(Ji@;#)&Y+36@`)ub-t{51hr9+|oPC>W zVEO^H>cmNg%oANf&UFX4p%Dw#U*}i^d}4AB8~}tE>=}($DM|YVKX1<^;9im^*Lyiy zN`ZrMr)T#s06sMC@Uj5QlHB#-tnq1$_ap3l(`JpqrbQvN&N9(25+)y-HUcSG9#wQQ z-@zEvc!~SzR2;YsTjgq3+kToZ=qoAba)CU;0lA4jK90Rg3lmb0*-MvSNpGkA%K@tL0z5%Gss}l3EqE9SHLmGqzu9a19rcX_UDWmLD1@ zVoRcC^ziW~%OAE-kM4Hp_=1^J@AdPnQOcyBeCyhDD@l*{JURBxg4~5qti2Y+mn!Yp zkfatTT}>-JE-yT}LC+N3qRB+fEo~XRPs;VRYj1s9LcKTi1Kxd;jqhT!6>Cz_{~Fch zLVy|A&B|CyB^1i@nT*($el{v4Xa$5Xzk4%m9%b8hS~+Q^*e~c{bAR@3{(V{BJI!)< z((pabpIQRml_W(|Svd{z(h+T_B)OlzLL#iZ6R+3Kbzdi9kH1MPRc2JaD8!5{OVj<) z8=Z~6)QBhNK9e$2vcK`}*wNM-cSS!bAoV@Q2=;v%ylSh!p|r5BIUOr!-3ARG>R0H} z7l^Y^;h6b8noUD0@W&YS5MS*!ZX- ztJFCpkMijR-qq9F`UkvmAB!CXZ3HL^Wuk-GnmumKj_+!Qn7GfrDG=TiR%I^7rcf0qOP`Va zmQJD_{gK@&2gbdfm0_Zht5Gtu;y)XSs{MrMHE0xL?r4nk%X+CQNn_*W;kpn8{ozG+ z!sKRHBdAUe12V>Ev*56~+9Fwrg};OPc33L0(F2a=bY+GN{o26|l}tezWdfp$KJk1> zEK#Z?ue3D^$c~_PeAf-%qKzaZgfQs#R+=(qO0D(Y7X=^E85ly~~%^8f! zQMETCQAwJ78&ulcwy(37*7e_jJRVijz10om{-asIzNflPqj)Lu`vP>hL9wlBb&Cv1 zE3|IQ#I_PW+l!fLG0)d*2Q?0N0Osv}lF#|A$4NelX-Em9Ze07q3gEKww#6c35* z9>A-R&8O_u&d)v)_qO{p$$Ls$+B>_=h4oF7qpI%`(&nf;p_hgtI=Xj;u3>h$*5nvC zx0Y7PaSUq?rQTDGt80=`k)Ug#jJ2Rgmn?y?z|<7G931^SZtMa}7m4&R7#HH8nWI3~ z>p#8yW*xKGT}d)l*72IwuCVXyTsfY@C7O(ZWm6p3jHI-@ zd#c?wpQO=g$nc!Iu9K*M{jo;2fwH7gz3|r0m9`Ia`&%pEIL2%%?JRz(Z%a6{=5e0X z=of}jonBTPg%h%maz}F*NqcK#d%I+);{nmLn118qDVZolS95B<%-7o6NeA36)?>YS z;{xM?k`m6h)z=|5wBLmde%4JN&Yn1x=!f6w_9vAh#oHfAqLyFCHqi3XWkyuIk$moU zhUUK+#4E-X#6+&#ei0MjXjYYjzcDYVz3Xs2bE594Kl^N_FymyFAM=fMVcPklxf3e-i{_+NctSx{?P5m`+*k__!h}Y zb816uH5Hm8-N%E~>UPP)Kf6$|74H8BwGBlX>1U zuJrc%ZLxt|)evP809E(r@?VxP^8#4c@mi6lONn`1lw&07a-%{1U`zv?^TkT_zP>(+ z+AV;lv>=T%l0fJ8yd#cwA5-cii2K(D8|F7EjQo5*6lw5U&ZDyhh zf_uMP>d#Wv;&AppP1y60j6l#_e!K#!Xj4Q!uPAbp^h6d#fu2A4`_BKi#wdRf$GO1_ z_Vt`Q;SRBUlHHz{A;Vxy$!LwSk`(l7iL1)2d!0Br-<9GQ=R_4>1{Eb&Wpyaj2iu^k zI2K1U&9{v*@;QNX7L}Xx3R)SN>i_Pg7)d!z4z7(?cFmT3ZhR{(Zkcc$@pEPh=ycy@ z+J2b0X@SSgZjoR*Hmp;qYSx2Re@}DyMM^l7YNKIZvz#|}^~`}&%L^wcu*tOfm_WD@ zp-Plqx2}dygx6p9b9c)CX=ZgRT1mKl-+`m3PV?{S?~FgmGHUgp8f!-X7UfMu2k-^O7206>?0V=1`d=^x-?fzp5?eO~ z5^XP(M^$nUW{A<~ETw-Tpg-y!T`v#$`90dlBtLkzB-ls}D8bHeqwU+4y_rtE1Neo~ySi25 z5ahX5-4BxN`Ms{n15~fXAGHV{9SLY&3V;1!brK3*hGr=A{oY(6HkRmA4UuwQvkSn= z7F9+v!Vuv0hYh#l!O?Zh=1Zph>ESOTC*VfD(wmljw*mmMMTMg+$j_fwBS(QX$Ifx% z=-qjsvzyb4=g#Y0#q&BY5vd3H=YvI4OF~lI`L8glp=Nrgbzj~M`*t77?_>GOOOlt? zojzvccl|UMWVK=b2ZdE)Tt>h+o{xB8(#}IO$^^Pbmq?JN2dD#DCG^3gvki?l1QLj% z80&kr$fm~C>4c$~Z^1UWRWj5)FL$Vy)!Nyo`#v5KP6Aaul5Nn6lLDRMUpV38GB{o; zC{+It+$*y9cA>fU*zoTn*t~wsL=Y7X&!<~QrM;~>hBL;z(^c7(7$91}Wk$V>o+cRJ z*wBA2NyPL{VgI7p}UVkp!wnjv^gG31>rvmnLYLJLg#x zVTkDB?l?7%-}IHJUUr8To@GA36~Lnoy@-TA|7#5~Xb9~NdYr(=e)upd2j+F-TsBNh zj{ZFbO`?_cVf+~woCsH^@qW()=XR+b4yv|&H{(os^iXd4?OMnQG#|Ij zH(bf=Bk_v<1w@YX2-XRW!Vu;yoWJ?yTiPAitS1kzr3jgX>tufoL;~uel!Mwwo^SGJ z_{Oh~*Rx)c*G+etZs7MKs4pEae;nRF$r1e_5hLU7q8C8N!ec6~Y#90#`JhqgZHIfO zLbq#EvA9C_nyIA2R)AQFXUzP)J@mkkrWVEN^152lumQ`1Z+2jdX zKHH<>pQ}>K%w@FpS`>kY%dxGkLMo$~JCiLx8g*=kQz-z=f(fopC`l>F-hnjbc=gD{ zd^220ix7gSjVBZa;b9TZ9!<(by4luMQK&+P`P~2YEc_k zWjb`$UqxVTwgNf#RV&uPAlRbvg90K!EfG#8D+%1~BP#tJTo$*DYxXs38@d)=vLTU6VR3}nM0|R@jwdP{-Z?j~oNBkEUV(>pyO6F=&vl+mF z=ixxTkKSxb?mTWC-|3)%!^kHyvFz#BYZ#JcL)+vPG+=#tnr2m6%#4kdlTCLk6J}`D zU=2+)*15c2khae2ow3!hcqTrt{n--Y34+D%DDm5EK_?^CE=oKDq?iY8or%!~9UDNE z$K$a1_Otf}5M?L>UBJ9vVzP&Ci)a{XctX3?LOBZWvh)9|^v}tH$Mczc%p5IUOz_WX zj>*gz{zF5eGoYe`qmxxZxijefR_!iiS_>s9Zu^V!hz9pt_M*SPr>vDFC&x!y=@|d4 z{SzB$w8PGIP2uR5b|+Bs;m}cWAOh%DQM)uSmAHu8=|J-I3=|B4NTxJ$j~A{S+>;W} zO6`uSNjVXGmt?ss*R0Lgqxv&%R8@!=@sY*jLMs<3yASrbaReY2W%O_YUf1aYiIL!M z7__Rf`taQF9TaAcI*adv`mLfUyW%Q41NHgk*ttIRkozl!`gFDCAB!JkAB6lPyj)oP zyxyUtkPj5hpEGq=72x9s;R4xR_I{0j+FRQ-8C^Y)yFm_4Qo`d@yweC2``xi8q?j|= zLF3h>kgz6YbbQ>-jeh%PF{j-7cdOus*iG5mFYh3u_GajVLmelqrw9&th zV=2_0?>3&k((YL*co$}H`MIX2BXjbEcRQEs#aB($@sGXiXC;4+7LM3&Y;R~i4w)o3 zN!Qz{6r^Ei#M+TP`XdAeVf;nLbDYK{!l7wIdn#m;CW3iqyUd~#Ne;#>!(UzLDYAKt zJ#E@$KDx>MBQ)=>CS>*Rah3n(GTpfihRM_kjRJw?^x)WzAOL1-R`+7u9kKLvz4<|k zXHcUVkrVhjE-Eef8IWu(q8HaH!F!<_UY5P;ntk!*5dM4H7fb@ke^LbIpR^_kKjsIw z`C2A7-_B|HO!^QxdJm6~PWmC?ZLp_*Yq6H)tlP^oGczj_0itAD9Qo@lEv@gRRn_`U zu8szJOE}L%XstOuV4UkMH347lGK8T!Sd2f6UetT1f&6IYXw~)9BJ#;Wu=v-8k5}8X zUT_9v?UPF}>c%MWcs<@%Jy3~s8jK?lLxuPLScqSJu`eh)(o#uFr z-3HId3z64a;@lsHT??Sex+y&blS zPg=Lrcj5)q-4a`So#o{tJM#%}$J1FR=qa(UncKoB#vd>r`#5kIP3r=(DqsaPQry0u z!}Rae27krM<0N!*e7TPjul{x&tP4W!FaPwFzrCaf^PjDtJ#Y6LIPcGhdA{C7`wx?O zeb=AiW$q)5&j~G7to|xp zULH+L5B?!|T@ZX@cY!C#n6TM}pCwOF88~G8NVp^oaHI$bg!F@K?C}i35O%>`Z;_xw z$6I1az#kB^?%IAJJI<(*8E8s{x;4HT|49Ikq+a6{@37BeEMLVesz3|7TYu74j?RxqlFmG% zGo=pdF`Yq1xs#Ney6|T%y2E!=1n8LC=IY?NEV}L9*f&Iib@vg&=kOPlR93kA>}AoE z!+Wn@odZEZ0^}i@1H6Ixt-!SykfMkeUwBkGo(sLgy%>7fFMI$cKYn4eA9rnap^@c& zJ?s5Np^i;jPNu#$oCMNt*N7@-XQYJ}=s23sKD}GxTss~q*t?!w?5LQlxKveNooPcx zA(R^{J}(&~-T8tSlp)hxO*vIk9HQv|(ldiBf7U5fI}>aIW#pDaJD5Hw4BF+bnyn^l zR#X-J-IG^?;@cQ3R%TNfK+5wSbL2m_jn@KTeN+36&qgOwbT8#r6=9g~G+Xa$t#;ht ziv>|dWtB~>R9vbTcT`Mei0V?SQ7|odR+1-`>Hn$=vyK6^cz11~JPgM%XjrVx&Orv? zVv-_2`b@e1zbt^~BKCcZ2URQ7<`0pr1$5V?X@7(0b*(b>Th#c}-0#Kye?`18V?1#dmIi-AUx9NK8F zm&kQ)prDsh>|Q_Dm*W(J_FKrtM|Oc8-6ZXldzxJTu0^0EW*G)8*DY_3_qeAYfl*BH zg$^*U>==+pCDbjyM;^vZh}8f@PQzZIX4TX#vJKUC^oZJEKxWokks9mKYcG*(tCsm0 z?I^BtKXFb@*UOMgzJ&R2H;d1C0iUGx=oEs!UB20a73b^8y{3Qt-ej|PC%8e)H_(v( zzpZ3a_2Av97tl)9jMnKi+rc{QO4a4~K8J1kefXHZ0QcK*dEJ^?KxI2RgR^{l35b$| zq`8j^a`0&M+yCUR@6~|UJ3CO}i01VtJV-MU{=0XlsxLzNCp-(n0=k_h&8(O-1o9Pk zEqh}!x#;Qc;BZfs$6+QK-+`Rs0ajDWk20s>YAg0Y+pyk1C(Q~C$;eggy)imM2pPp_ z54ho5K@%-*!S_WuSU-{Z1PBD-zsT(>A8?`MpWRQ{^Gm7r;+nsCEc}+~M8J(RxW|pB z7TSy{+De@(p*A)&@bo>cQywp{Q5)s{us7vrhog*x3Q~$!2zeOp(m}dG&91*MJhIiH zvAW^%^ktwS4O1TS7lybHIRnAn6-rQ{GCC(RhGhhK^MG^DakXi$OGWA<>r+HG|*@S8u`qvY@kgq&4oe_$SCMAeY+g@7~!m$X#7 zKSO$vx7gd%5L0o;69GZ8&Kt*1UITu3?z2v3%e7`5M4GHEOb>y6Ssi{h{bYDsI%KMf zL?*0rl$(r)`=8r%?F9ye~v6TG;sHzG9il%V6uvRh8cBScVXxjkc zWPeO6UZDIHF$sa*CbqhR0@TUefRG9K}uksFSCCJDh*_bV(Cu%vG@EDSB9N4Q2x zy;&Lv`K>7uH9zc|arG^RQ%ZrhaHb-SIgC_dZb_vRp!f(16r|H_k*|#%Wh(=ldzP=M znoX{#HQb5L@-}LhUfrhcHz;EdR1~<^gdPm!Ba}rThwe?p&l&pBH(@t<)d~H8vnIum z<>JY4)zz$Mcv70^oagd$G39TBD?oe~g{rnuOUHS?Nl|70lUR2V4wn$~A*C}}$#U#j zEc=N~R+kkc03N}#VArH{shEjImx4uEW0J0FA*>M!;4p$q=dwz_JsZ9ei%oYwtOQ`L zipQOJHZk(N&+1jxZugnt_H4y`6h1jdCXO^$jtqI$cJjzGFhf(h6-%r(Y5in zx;W+t*hwNe*P9+w6*5&#-VbO73~}&DzmN5L*=P1+U8!)h+|A;~as5CnpRSb2(D$+g zKUV`>z83`8NvzySc?XY?`HqH*<{wbhj-X%P1)u+}6|4TSvE!C`jzSTC+}+d>Z)T)| z`!o*`t^pr+Qj5~WQw#k=wL~mD*B=6LSG}{6(RgX!fj@a}A5Cho^q4~Ro7;bPdiW`c1fgFb<>iLEFe_9wC-O|>V?`FZ6*IL( z2!_Pfsm_N+eH`?o=P}FgPf2BQTRSs)f)C$Aja{+b)tS_pkq}a!S_eFnIm87##7(wz z~@?_i@`xuBUgHb%24k#ODfpARdqFQXb8olc2H)T8t2jn`p<7jjL{2jU;E zC1lgYKhH5 ze0@jATN`%F6YMzBU1Hlo6L~yoXzZn9sXD=mJ@`21ugj03fM*7U$LFb5IoBkicfM8% z#dJdrYyJA4eXK%1>UilAo=Mfv{^Lw69Zi7?M?n`)LiZ7HD}_bf0=%rT;Vz#%-}PAb z)%*-@QdroaA zn*1w8Z|63XFE%Sfrf`4=I5mi+L9OkcS}LW)q@+JGnp0UY7|I#T=_M|g<>P$XXiskf zB;r^SMX=wzVC^lnk4GXc(O*<L){mG|*A)Q}V$U zNZ6*s1ipkw*LJhF4fCdK=l-r!Iuy>oiY8K5a1V>W7LY73d~coPiXN5WKwhmb?0;OdWRcS^Hco;Sk!y_#%fp&=}k; zST$*g_Qlg_2pt7W?9%=*lT=Lf6E{K`Z;<}Dp1OYHvxX;Qf;*$v^7|wf;ccS8I!iz{ zY@Z+Z1g7{lH^{+Vo7^O?x4jt6vfn?=`SsZ@aN{XL68Ve%kw{XY4EA1y#xk;RVX4>k zyJdN7H7!ELqDaTe&Q0La&y(8XF856;99KwFCebdA_f=zp4m@rvu^jdsY7{)!P-<8e zgQm??*~|CYip*r7UXn(7J;A}=Bh8!*c6yaqjJv8-jqk1Td>Nh^)2QEky|uQOsU^P@ z)BRg=AgFAI5=Y7qPnOLv`Kl`gH;9ub=L@wDt#IO|6Ne~ z`bW`bv!||fmc3n?7}jg&z@L_?H2ff8(>=Lwit(;-qh#V%!E%8>j9SrR zY4*#&=15BnpZdV1y+)O89I5Rzo%`L+D6h7t|FZXN zB?{p|>ve3f6~7~PpdVi;8sR%Ym2nx)M6icd=gbz#oOZe{$oHRhSH2{d7CoOgsd>fA1O zmL9xt0kC0`eUegNQ=zuZ@ht%yCK}Fl$IFeY9FtB#c^wW!doI9Y9ELczyf|WLu-A(h zL2c2kdR-}93w>5C^d{sU+e-nF-VWO2IYHU06t(8vfnz->P0!-Cp?weFYej^=9PeJH zODQSd;p0iLVsCiB@VDQp(ro%k!_lfS{BRk3>3c4a+`_fW3%Jg%hi2A$sK!-VNr#B!)Y3hC z5W{4ydS>@vOr~qNG>E`$YCanuG4A8x0Qe=?5v{E!S+8_QdC#>1oCk}^Om4tsUZ=Oz z>T-INq(Kk&(>+qQDP^~ogD|9SpeMw^Ak%gu3FtYZvRVbTg&`D(>^=9XM0)NL=%_5G zGzgAbuw|B{^?PxgqLtOCYuqtfUoUN>-7!rR;e{c-;A3iBgdPP7zWM~q>%wb{nm#<_ zS$?rr{GKc;on68BXZL?NX9w{pq2zteH-QubySYT)Pf^A@aX>(3 z5)}p2@%OT%K6hZkZDjIJ|K8>@s|$SLbV!C+*MKY@%(qD@W@ z_Dqn4lYdz{4L2JX?eTHy@5H*=U{3~rZ7K#NwbI#~D}OViBA#%<_k6!1;&Ty;na0N0 z0AksHVsnp$VgvAVF<7;`7mK6NsEV9x0>`wlo;^Fk{ZMT!BUeUi}qYl}h z%w1FZ#N@A|P3XX-2tGuQZmaWgy#J&BR^Ovfk1pVTBWBR53j%0E`zp!w{oDI-LY~L0 z*qjs^3X{BmR_~YatYbfl^zwRVrXi}qx!4YsqqE8{(gX%uXKd9galSo6XVL^;0`sl0?*^H4i~I#JxH7ojY8rMa&*J8IBiaz>X=H>>+urA}RC zPz{K)!Fv0+bDVcHNUhv}kPGJ}LBwK~!#!|=z!D{i#bLboB4dnt;n?Qq2^%;lS@eKU zV&qw1Pd&_(5pUk!jlwFR{ZbZhTkTZ9R;vB8zn+4OPeV17b)2+|w+=g{z@nBbWof1F zaWsj}*0_61ginApW}t>FWV6F-j>zxTXf~TWP~G?P;DHKrTU+`yx+m^(IdpNI6Wi~w z_FGm|pxfE9Q5m--p4ZDeF#be#wAKhP`X5p_^aLZ|Ig5qG;~B+ppGmy}PLMhDyt@B9 zfl(Q30Q-o(wcx%JJ9Ija_J(ukzyoXwjpiK0AKinaPwg zPphUwgm|2|xJcz%S6t*V650vNWP&*fiONdb|Lp;e-;}{m<1mp=Z(cxtM7#s|U*d(8 zayl^wmQoMSB|>(hxe$v)RHJxo94Ry&?A2G^t*#U5Zb#Nv-CgrI{Ogpl8xPCX`PXI; zQ1&rjZ=Iyx)=fk{U3@V(q@nmnbJeGc>At${%#fiF$Yt8Qh)UjHr+QUYj9u~fOsPcA zcQ3(DF$Y{$4hhoziUl4b}oG-)h4WtyjQW8pCtF1=sl@ z5s965s;{!txKszYx%7w9)X&#j(Zvhin>8)p?+F*krw*lqli+6JYS~H$?9uTO*q}@z z6t|BHEN~a?{88n8wJGMglAQ2&hK1r@8kxq#M{J=F@m#-QK%R4)C}ywTS0?FFgZ{1R zlx8X)j*cQR6AwG(bECASmEE`LCtC*3qJz-?#)ag42D^kYPBD`;&Yw@AMZBD#axrOt zOdQBSghS1&h%_UFYm{S2>vjHC7>uKahb`I-CwsKSF|L=~p0i}2A*QZZlkih=m-}dX zkiKR}B^Rz(EQP+u-dHZ@_;Z!berP#4%plE=i4OnT!oJUF=qoEh^Sid@Hiwn%n4#p!LKi{8ECXW5Qar_CalCf;GkC5D+tD>rtM7`hPQNmRd497bMx7kA93BxHjvwE1_AD$dA*(PE5h{F!*?Y7!%D9|2%Tyi&Wd zPIbVvxdqU7*9$MwsV?)^vGcch%in&xX!^IXSjMWYaT%E6aT8C)tdgK9H1MXT(0$Xd3Ls`hVf2+v)(hog zXDg%1EWlso`JpnpIQP02v%c83SUr1tiWRR8;_Rp2dQWr&blY1{?9y~fP~K3H`M(ge z_9*8rQ(k(6BmR(M6fafS(hQ|Kl&$*RRb`<+&9q75rFCTsYh`qn|6Z#@UcC29bhoKi zT_`Yg7;UkMVwkX4^mugj^7MUnGkKBTuZGdd~uU zI@o({FQb6|S_~lH8rF>JNTfp$2|_Qe!M&k-gkK-i#>F9CAEMAcZ1=k2nkd0nqxuB< zVQRkb^*@6@^ouzh3|1@-fQlro;z{|C)N9;}9G$-_L zM%W=crgnu&;nN}*LJ2+{mR=_cIr(Hb4y#GLKSd%&1qPU->8$xbps-bnp?h+_(VNHI z+UQP_eyQv?ApqoIGpmJrwTGUBTic}wo@iYe*Szg~n?-6dLq&}G?UEihylZJH~5n(?Bl)zgLFr*~faIUVD7dzZ?5=ODNUe z$;OT8JiFXEX>BwE7pK%HvwVrtT)T)At=DeExN!=86P!tJ`&3>=nWul2!hFy2u`7I7 zK@k?Kovsafo*yUyd|QQPJ;vSFyF0n!VAM*{XscK6 zculT&c0h@1i zzUc(iL9oRZS=U)p4Jpr#%bhX=Grz2hK>X?I_REmJY(G8nN6mHnf1x;J);3-6uu17w zGBqvf{~z?xMyWvv=NRk+{6oke^zj_vD*4{EEGgPGQ)-Og_7<$rd7pu%Tu7BTX8%$E zlZ?+3m+r02fhn9ce@E`|IU>~i%O<0QnyA-B^7`>V1g1?d3oMuo&!GB^W7?#T8;oj~ zxlFclwcVFwlYL|~1!#j6K5W>A!pIEu26^qYdp4w0Yp+ z?{bzt2{E4tMrU(LZectfjcM};B<#{RpgDaLH;2Vf_kN?p`>h%JD&anka~-DI_u_&= z>-NW}0fjD|g~m#%w0j1h@cyhk)1al!ypbnyHw0&I`;f}qwA28|Z_vlwkKy*h=Tk^^ zI`RPD4WJ!LRw?}IARZMLy6k*my#6n!G7Q1YY&k!(jaLs7zsb7Hg41 zIc4GcITN0@*T}DAYEQlGMvoWiVJ*>}Bb2kI>Pz=f8_=BX!CB=A=OV9+FVNH-H=FS3 zb!M22y^3sHHvxtQk#@Cs@u^9fb{BtM?hfzK7|6iQlKj?i!T%( zW#|4r!sYOlD*K}h5Mf>yJL~+@Q{h4Lo*m6>KtH#;+-#j`Y*orudcg#ys229=FwTun zC49}6pxl>hpA95FSgc2n`K6Whdv~Qg>oURur(7l2r`A3yR_F78=o; z&;8DXYBagpif|Y=7$ZV`@6+bv{6!yDJhg|x^QaPEj`*v>%GGWo-f$=K%$1~^{BZP2 z|DK-8UBcFiF9eHCd~uq_lz_un{^|GY$~~J3gHUfly#MUnd$h?;Jxb`pz|Y?or%8+Z z%l#&`NET%JDmOKRGh_b{<#Y|$PbJk|ePm<<1nb^3Y`zLMXjJUMxjAzRK6*iA#-@GmYfmQVN1A5#UvQkL3GKHiUMC$f4CHe9j>AB;aR4n9RrVJ=3&0C_#16$VF8(3jg- zCAg+K&wVbcT$Ub$);KfQ5%|SQDzD0+EV^OP)Kh zk%13N?;munLjY%yOU}Y2$|SmykitCK6BlqhiZ1*yIV{b{^kGJx*K6JgrMM9*eUn%6 z4D?%D7B3)nY2GsS8+F`S&7Y8Yy&vVyMPM;J%R70$#ZhbCe+!G{+5V97~J)jw{RgtZBAK*Wsn48w9C-iL`lBkvbzXz1AY z{o%O4M^D2`2mA>WfVN2I`i(*RQ&lwj)rj$*{r-`sk-at$(+RSXk9!|0@wa(FIg zaKKI-!-1e&xEtS{{s#5@-4y2yCxl_M$Y565Nyu~ikoGR^zhvd;E+sNQ-~27+Zz zM=t<`?I-0>dBUj0{}`~JvlZytlqrmM$9lsv!k`a?auF9DxDeMez+0x5yV92cf}C@8 z#oGF`x@D%__GG$Dx!U!f-!QT&NuhmScI*1?6nx;L_#OI6KCpGK5oCFiAD$YsjyB523?&)iF zB@%)y4m<~x%vPFyp~3yBtkv3OW_xc+nJbh^CBUmG1;6 zo8_?h?g{a9NN4AWjZB+LT+3ac`N_{}sr1_dEzwy`ElLKj{bBf|_di|xB-I*1#@Mtl zM0U5ylyl~?#XE3ONiRw5n5q?`z+-hh+3aXzV;<(ze7e~$`ni=kwOt9EHrVxHF z;f?niIu5pLAfCgV0COtzytKti4`aq9bkL7Pa+r4ZB2w`w^i^|YyQ zh?s+%Jm_CU5b)lbPW`o6e(e*~<`t_q$XoNq&9+_l1VWWrshyi!NehF3s6ezBEF7=C zrs5dD@KiUvh^u5H{o(=%*p^w}A9s-~U(W!4CymQW`8g2O@Gpx1hG_i!SJ$BjONtmz z6D6UK7{^01kWM33vaYXv$h+N%Gkst2^Z{rK^MjIB<$?W=HQ$UfLqq$^#{~&d|NxE z)J;H1r4sBgYioXgC}?mW6$m`XH_er=P)_X9ln;Du&`(=8r^w>>)>%cslk%%?M>EAz z!Z^!PpW>DsGpFPgdAWILO6)3qI?QkP`;9gFY@#iv9yqHm|tXT;eAp13aM8si5LAp!IQ- zb>{N{pXi1I5nd|6iX>@>qKYH*^D+RCUvP=!(v|74qFJi=F;O?at@0Ahe|?SQd+rA7 zcjX7J`tsc>AI@*-g}_bXvO|iAR4$!3oRs7H*RSXhqTfH^g%gJY-hv!PvGh>VSucC# zqKCl@mxusV{5oWJ28bv){SXb| z7<8~-(mH)!i~&qTIm>h`IS;sg&vx<&<(+N0?;_Bg?hHgwYd4fOTw3KzB~UImSSHNF zgUl7=<<(!A6Jfbymurl^P?!6sBTM;{Doh8!jBNLXK+prr^tZa0lkZqE14Z>_6RoLf zzVOYyjQcodsR|;2=xPhAWQ-U2D@mLfyW!F-9Tz$@LWqV1cKgj9$Ue>Sia~?${p`|r z%B~gI!3whd8%<24Z&ri1M!{ZHd{>MrC<28dD>qkkDwv&T`e4LGzn#^yc3R$Kz*^^t zaQ!$$@?E>UOk5FKcxX!0u<@jrFFPJtQci9lo!$ED)B%vttjb0j3u`SK%Z!Ah7aJna zm@V>4*g8(*Q!C~kO#)x;3=zsXbv!b|Pt@9=Cg%wt50CiG=>V7Jh+(2APLW1;BoALaCn(4c_p$=?M70t0J z-lQ>J+Tt;U2+H$R_(wJ9kdqq)|56&Fd(qHC0 z8)bW9{GrYr(ZMlmx^7JBoDI z^9fx$FqtT~lr0;%;PeniR+roSW>@uf-V0}vsKs(Y_T9KevCxJMHhCEINh0s8^UN45qtIhO+FTeVc$8wx1bFMd)X>F=r=b?umT->{& z5NJG^rG~x2**l^T+_a{N5|+BqaVz2To~wJieBz%{@M; zRc_EW&@Yw!QwAEwuWkPFd}&K-o8R9PP5DCQdS`Bte(s&|pYb|iE!nZQNu`N`UQ8q( z%Bl6c>#dhqlGfANp6kaBpVmEjf3zg*Yv%U?@i4KR_WH*GaybG7K(0grm;tTB^Bxrw zohC>44A{!}Ozl?z=%)UX&<(>Sl;{HCn0`{j*mtXq@R#IP`venI0YQA^EI3&wEq~>n zhFjC0SbgdO5f+L6FFOC&}sUGX?!N7PDWeEtRPj}H6e17 z1D6Q%3C#2Rr*3s9?7TB>1i53i6K|mbPti|G5dFt@_kG6ys*NeORq{|@t>;AzD_5^Z z_dsaeNvhvTD9dp)*5u+4IlZH6JeaPYpdD2~Lln2oD(qmu*E z=e>O!fSgU`cA^{}`$f0|t0W}g|9z8dB#=6eJd#v=Ng*1Iik3@UmDuE)0(2BwV>pG9 zk!Au(DXN;bwadglC6PfS#?U+R=nIR;qo96zc}o=;1n?_xD*NY$9$$7ies|PBaNo^Yf^o7^2e~gl(Gq&p?*R3 zS8~E=2*2}G~u5uo?%gqHgtdiAkKPU@E|AYI`)Eet0Mv`a9i7p_+Tf5du-JJvY z0GrO4*P?8GAdSvj#hkDy0XP=KfgDXGAOSk6@eGS~_H#@H*uGX+)J&sO(WWBr1DhH12KYEUGo9Q-PW#$W%o@;lmlH@D|2Ymr^2p8i zjM628+BTgo1=#GSy3|Y1CIT+!4Fn@LUThQ$N4%-<`eJR(SO(rGY#PUqHxEd>g0DLBq%-qaF4yw17K( z(C=$sICMA^ig%{wnua3tT=+f`z#a43@XkDC>Q<_mMuD0*)+7v;bmn`15b1xhO6}>f z5Bl1ws;D<+BKp2I%$%o7)l4{%v&QT36f%kFjy%;sNe?ipUH*?jccxoT;drJXL~S01 zg{P?JFMy9%xR*;FVQ&;; z#o#)CK6*%x^|%)k_kD;hgg$kF=7~nTIp@G$B2CSalD;9vjXbu3(K* z33MixFz-h*<13e2UKljwg&;P#Cp^pYWZ~7yj|*&;3r%#nDc_p%oG&k+k?mW?C#;(j zDpp#tR$rQnSL(S{I+?_oaQ}$I+My8)pgs1i{=|FkM3gzN(8h{rjp)fQd}8(CnjICO z;ur`;d~eF5(is@UZG^MPvg6M!EI`Q5il^7J?IdA~7okD5vtOrHXn}N={3-cZ286zeA76p3VLBO@ayq<9?n>A(mMa);CF5&FV)&*Pz zHhzI2nbmTfZ02H=D0}a%czcYTtu2G7sOXk9Q$eVaY`8>?`3Q!n^@K6X@!U_%G4mF+ z)92f@WKrh@hNm@=3q9%QoL-f(ICTgjs-$=Hmb>b7%k~gl5BkK}pysPp*zjNU9LW3U zPSUOVS-q_|hYvo(2ggGm6M;`0o#}sq9w+69igfzV7o+I`pwTxH4q-ntbrA z_adkl@8P0cFRPi8R?mf^q$cC(##7jX3%^6-eCC2t^8#z<%+GMIJ$?W=Wf(f8B#p;S zT*E!sp1~toU+`y+62aIq?o8pkY!AM3tH}RG{ycGt@vMlpANbP0x3T8?SHjDyHPOEu z4SNd{Hwtf5i#ApUAC$#aJ4LlhB{i}*b4yE_kE*KM<4pnzm=;Jl-$fUG(teUryE{xY z4C>dn-p&|lprVua^dY){S%}uy-n$1c6Hyf{LtO90UkdH-qyzJLdpJg&6A)t+q>D;B zh#|{{Dh7HM5%ZIPv=@XAmAUGXXQ9LcoKQ6QBo%ByV-;)yD@X~;%igJ$XO}qE>9d+4 z2eaA|;#_Iwe`=%1|JFtuqpwiHnQ{PF z`c4$9QYWjk{m+3UBly1u($X$?^)h$7#RK?%Z`enzP4fQ+Ui=KD-7%^(O=v2i6y8%r zj3d|Xq7mg;)GSWh>9_Vh{t?k*FP_j`%tAe7-$NRG!^=>t;0a{mqONrkyAPiax`f6x zYY65>*Sg2whI1s()qDzC3>tSWeU_dF7ZUZspq*2$KO0k0lO$V@V4V=0P@6+F5?=M6 zFI&t>Lm$nOZ;};OLd-f$V?Kj}3G)t=w#t~oh%2xDYc}V_h@wB6LFc+_qY2kJ0yblx z9{xmPUeu?f z^ZDKe{&{6(q(|<1Yt*M124=ovDt<+Y7LoVP%V#9&Dg{6vqEA)bl^l<{F>E%q+`p?& zw_Ysk{@F_CCx`KW3ZGdb-vGPE4(M84#ssJtn?Kku;}LSD!tGio`_HFvIjnN;|^-2ku!32$k({bvz6oW?a)%6Q?k1Ig*o-j<)g2lC_b8VjXP zJdHBaq)87@fSg|)_ObPq6SK3y)&9JmfyFe?tvWr>~s<{r=tDsDf}Y|^JL0v z^T`2BY2HfG=)x#i5;M2O0r_12y2*&Vvpd$f6zcx`&EGN38+en7BvJ$@wRrJrRyWH( zrLDwA9~4wc6GsaZEF{#t%!s>#CJnxwR){*6Q}oer*%&kaIv@qRJ);~8DlDqo1i@VFr7Ns?n+x~y7dL`e*FHO!9> z#O6>2v4I)Ce=Hc| ztIlOyT%2%h&URdixX8VGwNC16LI3?M5D%55v%|o_Fs%kEo0edYd{`89MF*T~wN zpt~ITYbfj9FC)w-{=>$O?Q{^QZh z&D2}lr{^L^L`5~USU7OW{y!BMYX8358E2nN))(rv!0#*mc(f{~r=($W@iPb_RFC4{ z_yrTeLhQ$i+?L~s{!U|1f6Lmv^^QZd{sJ*ngEI^R$q=nBq~aIzKtVe8@?oS z)tk=bg_Ka|)1%i@D}#OA zM%jHmyj4n1fIUP!V^gm9s~0R zSQqo2Tm9%QtJaq5(KxSU`qBP^dB)$urixgg9;?bP;&I#g?2m|AnT~qq_W2d?V-A8K zZ=Hu%<|ShpeXO-qnJ(AYWvMOGC`(oKAjl|+sq`k?c=-B(>rZrlq@Sw?Wv!j3+r9Oz zGv%ATQNjwc=V@~Cp%ro1CX$QK7l}iVG(JMwq3@b~cgWoz&l@#6F(5CVC<4gFNpiaE zxlrM$Xlxz?{s;W;YE%07yVpD~KY&Tqj8{sSrOV>^^8q@}V?8&0^v>9D(-^H_R-!r478{Rw0L;6=;asOk<>s8GXTg z$Il^TKzmDJz_9qL{fK~@(z`yYr#CGmsDvl6NI0V*qGY^d^%cLq@bjY)24zI4X%D)J z2mifbCjCdvEWt z=$`%)ImZ|2U}z~tH5T$g&_Xk8(NYSKI=4lngSoTy_L#kBwK4F7PKmVjwdZUm_TmUO zal~m-Tk#`L5$JdNv9xmLzK^LNFWW^+zFmK~J!LL_1|o)U=_!pArnh8^j}v;!AlRs^ zT}mI6&Y2IBdNJsgEwxT>fvc=hfo$GH8rt`v<@NDmA*uDJHT=U94Qvk6yBeOp_a-%k zDC*{z*zl{QJ4C&+0r)1jU^=Kh^XAlvk7y`x2NM`&}}44x#iI(y9_|nVrjUl%h-u=NT_HV}vI_6AE zjb@c`7S=&=WCD=IUP!@&?nS-`LoA_{h`fTOUPAMp7gI-IoEG z0e1<#yW#snY%Fv&g@2B2-bzJ@6RD?)x&BEsh9V*&T@4(Jtr#+$nP~1tAXqKi!SS6_ zU=a&2;%^1vbFw4w?pRjQ@Mi#t6(j^X7FSyN2z7_TNY_{r6Y8v>L#AFEO5z3`vT!s0 z^+ILONUXQBsalh>Sq|EY zF&j5?G|`_?P>?YhyQqM8CQ#MtHW{F|3Y8R;@1hZc2@^eZc;SF`$3=qObtx}aY!%ou zAkZCd_w-ym#y^NFM!J;zcSQZu_ws?8yFM$C?po?8a@@aQ1r-9$3VW(Xsaet%foGtlZcd?F0|QQ_&!!yWn(3yZa4~=JseM+$O^zUPU=e*fLVY zQ!`Ug?URGBp&$X&IDr2{qYOKT9W6IuPFtuP%$9|JIh-Ze3ULhw@8HnmCSckIH%o$n zvbDZ;TRiAUNv%k`6&-Hwh^gbKIiIieD5UW&0v_|-rF!oe3f#eDxfx}8(W|2lZwxUm z)cEWHLTyBotQR7Y_SYXXYXD@=LVmjfU{v?7WeKd=FTxzdhU$yBm{W=jos)U*9ZFYh zZhs*$lt_HV{#T<0&B4e_%FO43sucyh&4{MrMF6}=-d-kF+j5k+)xIh%|=?xNdRUJ|8w_w>C83 z!i{;N+=p*Z&f@bGXpHjvy^B|f8vS>i@c#ef^oR6MKm~5SSa~aXbFsW>pJB%eUES>t zHOhEp9rk%*UpAehK2R$=)!O=Le@w=k;T@f2$ckX`k_x#>h;U%3 zifXeHHpL=%ZbUE;Y`+OJZ`wQ|qa)&W$2C;=z+;CebS8r}Qn=<&I3dDy@oxhX;dAR| z&_N`lwzt$!QHdvghRdL(44;>&o$N1KpbAfyn()ra99=BjeyfTf(ibg2?j`H)kGEBnUso3=@^>b{q zy^N%0TPs@K{;Sq6ko=sWB4KKUHeb}+Mb_#ryMz6MI7BAa3C6QadmK-+tdYZQx`*k{Cq5LP6~i>^HO_tp~k3l0>np zg^CF1c=Zlz|!uK*>HJtYh9d_4oOf ztimnHc*`On*H4)Pk&TA>H`-^R7CD+O#5Uai@r)BQiuk+x`+a8*N=8Tbi#A(?ABZEpZq)=nEGywGPq$0d5Zh140G8AN+Pgw?tLM=ru}d#x|_@ z;L*Mvgpm56y=-i349iYAC;;6;APx4F?(x52@}zI;>o6q)K}-DoXW8FFZPt08WWGSf z=QXRS1u6KNax3ID=gql_e5!n23-fKz`_-c)53_=kQL>R}pv3F(AWuIAx=^^XX|VE@ zR-Tu~8$o;A8y&*CouHH1J%|k7Y;#DHdmMegLGpehToZ?koJrf-9}}C3=GT9l(LB(M zu0*7QW;7<#LsH!>Jtm^F;&1R9R}2_pW*W6PB*#gOLm=V za$MP(NQ$Q5NA>gdf=zD0U3z|QS3P#49NR}!m0UB|8P1xE*RE*ToJVcJ6G)2EEF*-o zuX03gIy?&ywfT*<{_RA}&eMia4tBv@>7M@M^&136A|?Y{w)c~Sm!M6_{-=?t+47dN zucRd&Cs)Z9er*&hZ~M2A!DK?mCv)cDMQ+X|D4!+H(NBcH2 zgR)oP{}ltg)6?A9@C5{v0GXAnhvKWKpyMeCy+J<&GBx+2`ZM z8S{IPC*_aB?(JPedZ|^m2{K@R*IMC^(c)K4QGLtnW3slJs-rxGrxJh3w)qp0Us#9) z$6{=X681^FPts%UaCA@d3&1B^4V}TWEA`&ZaNPpwggi7$&gy(K-%mZGuYP>QBl@Ogcj+kF`$4LpOaXvBT694G~T%QH3 z(By&xIigL5l+!5+ChEMwh9KiGyA+3KoXnpGziYB7RIS{Uis>g5sOiQ6VdCeDHWdiy zu>Io+6maAI8|Rz06T#21u?-*(ur#l};GS0(?yvRr^u>yV+IJQse+B3IJePniKfjY1 zp_e-`=fK=)Dey^ZS$&%>JHsm0vi(T#@V`Ku(s-kj$qbv$+woR$03=sAtO?d^eD?i^ zwRU+yo`k^;cI&}Bq&60(k^kPHzBTFM1I&;K7Wz&_$4m8a{i2eL47#+C_{VGqdtCsC z#Smwqu)*iJ=F)Izig$$bSlKHbwUFpil*ft1gMmlu*#NB`B-lWY?4s=tU>bjZUJe?l zwtB3zeehZTtW-}EWG|L>@YPzbtJ9*RR-_8?X4fwcL-kDiu<2iiyeCSM@kY@qlETd8 z@JAXw3IL<&_pE*nfhOFMEtmWTQXcNKA7~XZVdh9_zNe?58-gV};W5w?J@;q4Ud~(! zJR3JRuFUJ*w{aNpDVMQoTl7RxU1rYR(QV0BI4|}SxGI!_qz^aBe`gaQh@WvZvrMc5 zGR?wjKY!YUUBu3x7{Wg5`;F40ztSK{Mz@E~+7$?*HNy;%QB_VE-jQNI$^=PX20TG;aNm-jzbM?n1yS&v2zo*L|NVIg`?r!N5Vs=Y zEcby2x&G((G^ECWqO;@D?s<1^lP5x=y#Uzmtl75Yr-d(XKMIcR64~<2EARdp@EODN%=A{0EvF@D`WXBI^yW*`I-wvR$8rl02_{kguqtM*pS+EGSIJI zxe;13>qm)4?k9x;SkgM#f%mtUIXgYZjzgz(CZ zd19>xMMMw8w;AMuK4mxeb_y`Z=vn%Q5@<~>uPnwgd%+|hG`_JRm97Je$ow)Pb%1PA z=aF=8>S)9)It(JvzOeqO;%|t(-41@Y6+1b3)~&rVfO!BkIt3C6V7Z$Qy#noA@eK>X z7$p6UmK5qlGW(B;1WW6H4mQ-A21I``JxK}YSHVUarDLgVyJ6uteko8`+CbJ#0glXPuG zVtlbRkhB0rtCOx&$4fJGHeExmN-p;f?*}L2{ z(kt+NdmV&0`qfQxhwQbAlpUm5o+mt|T2)=<0zTt{P#nALpMJd>7cir}dYW9uZ}UBV zeycq@W3#sRus@?z_thME0kZOQ3_c`4?D@QVQ1R^iT7&){y{yiH#rw?nkgxQI1~>(# zD^J}FlVZUET#M18q`_n6^&*ym?NNzEc2Yrvn0#U1H@5+;htOP-qet*%Og&=X=HdA2 z@>X)Ks!X}r+Q%-Vn&$fV-HI09ZHxqy?o=fFujrq=y4#0|v2p2P@8WNb1w3&J3Q~Nh zB*fq3Y!;%ZG>NdbDN@&VuQ4`vA^h+4HVxijpH(+sH955+{r>&~ zVp@?x&@S@LlEWh{!tvAB@26U1F$>~BhYYgH(WhTUh?q2JGmyGH_Znsgv-HD}4t_CZ z?Yg`wCDP;gjgAedEjBn4p8#vj93Azl9k+j}aZf+=yO=T6o3=5rV~`d9>Yrb@_7s+V z`xl!X5y3Z*SU{MRj26A9z+^A?k7mwwC2|UV6*G!Ve}b}S6E=Cac0H3=^lK3r{~5`j z;GkQub?KQg|9FjQB{bH?wVPTtZP&gyPP8i)ROIV~!#TEo#ORYSZDBVKXU0#aL0+Q@ zt0@H48F3*cs&q1vL?AwUjrJ}VnGx+@F+JeA1F`l!Qe1yYPoTI z%$PvEX{{NEOkjx~DVRGQNHNndP+6QfWPcCV;sS!eW-~|EluRO6s+@r>ZbAcC%I4Fc zP#BbBVE5noofOW`M}$%|k6Gn@YbD!z2PmfEfXxlFNo5`XUJlZlD*^he`8Q3mFcR;9 zU1qUce-2}$#2$W!>uIL80KhQ3lk6Iv>zfTC7x$4Vb>qSx*C#_YA}k^cTymDA_l{I(d{k$-Kglw1KPdCs)d0~)DK^$D7L<6j}#f8=KA9h zGYp~01S0z#yL^i^h@7z_zXcfZW}B2&pYE3;9KL9Qn^lcOVvGiZKIA2AF2t{fEHd zU_=;K=V4LbD?5n^%KgXmoll#an~AA$7X%!ZWPje7Jtea|)EE_4Ox)7a5xZ+sf9x<2 zbwS12k2+zc_{|M4Z|0##kxNQU>KCpodZ9BzohxM}an!DW+&<+5v&aZz+j#sY92v)v_>%8Bvy zh2(~>7Ly6fRMJSJ9DeH^Qng-j)c_e@0S z;34DgK~PH z?}sFdW=azhESO_c(}Q`|>^euW3$eq^IaSshvc7)WJe}>(%w@YGA>h83NGM8B8g_Oc zT4Q7qvz+x)$wFm+hf<#h7+4>?!SLtN;bHk?EfG@dlOE%*-OXk67jDYUk6@3p79rDC zWih9oi1COvw=3}VPbW9eVAU|$FX7p@N~2{0Spr_rn1VV%ck{?fkH&wA@s&cqSlUdp zX6Z>uO@W3jKAzliHFSs9F7}@I7&@`=`pdoRc&qzm>CsWTm8QY(6;6>0mvF1R5!g@< ze0NWuZLIW%5#B+sf|G9LqL-hN8Y?W#X75$VY2Tq_MXW{FXv(jZlDd{a;MA`PNiQts z?sY@QE_tH$6-!b!A&6VOdw{irTh7Y36BnBal$M(I@a~QIsDgLGTBeQ#0=i!YUL{1h zV`3^G8(w%wuBJKr7$KSBjtZM* zCUUiCW-F6rzCj}LTT9lpq!6hRePAx|tu%Wz?uK#{4ZF6%z9ruv=c2!;8R$7VmFkVU z;W(@|44}o+5S#YN@OOt$a`pn^kzv!(*|he$T759kdq3*Eqf_=Y9lo5=G?Y=05*PRD z|6H4WTA~aC0of_@5yE*pDXPbMl5^2l@1LZVFfQihkVZ^twjslr0=i^*J-xl!>Hr0& zmu3?Xiv*Ar6P`W}<>9SVW7cLz=Wl!&qy8Jxh3{wW(;>X?($+5z^b4Mc|MgszhkfW? zEysKatM+xPy>h*_gmkh&j2N1m_C|M^p^zpMft^k9AmmDhJi4uLy2x`SRMA3pQrTNy zM`f(=A7_}95qCOd>FzDKCKY*O2d}>>#c)+){b2hTXV4Xj=s}KP`r+RQ_tWqZn6}Sf z#Z?$gHBpiuEu|o<$t6zOqgDGnd&Io4a>ZZNz4_-I0JEM?l}SbyGjRY=Aarc(g8Vq` z%w-|f1;2->&L0)}H2iz< z+3fx}S%46U$r$GCprdauSY*}l;cl0{i2D~>X#6w{x~-na4bzjC#K=VZfPuOnr=N*J zF{aERuVPsioV&S|us3ep!R{%i68S?Zi%I-0QECQjYza(%okpRQCb(7QBmkW&lp7tSmV-5$+Mn|K8Vuj0{kt*N> zn)Zc=XAdEbOzt^?6W6pjOXZeSpC^>qP|H_rn@$t|i{Rr(ku{-g#V`e3&wHxPLigX5 zw~Yf$cA5RJlTwZMzAi;qV4n-1-a0EU)1z*7k7gO~Pe?L~ONcr{eDB_`78*dOV z%MLB71IdB?GmJGPp@XO{!7%0L=Qqq>M!v|&ra~U+p4hTf`+mOU6PyM^iRk=MFFaVc zv47pS6@K|NtR$_?fjLZ|S(Uj8nt)Kv^^fqRLfAeMVRV^O20PvOQ?VT1@Q*^hEwG{B zkR|2`ANY|*F|egix59DH{wQ#c%f~SGOKpo$g_r)pw0jI#Gw4W+qOTfG9Gtk6CG{wG z>%(1orxg6brrL9CM3mI^4JwKF=g+l67C#)f#6n64&nNsJ0ScifsH9=*$FC9h8kO-N zHpU3cy*$4NPbWz5W&nBvc=pG{#AItJpyopD&zGpvmm0L`@V;5u6ldF8Y2oU($<7mn z<1z&a$a33pLcTtop473hbzu|Nc|K@Wc?yJ*l@ChrN@4Oj5~Eo{(If&M^XZmgbYhe~ z(Cv#WLc>TWbUJS+hz|_f=^k$;%~5N-@pKrB?0Q$Th=<-hv{+3l{(t5uwaY zYDfM`8QoW%#AzsA#RdzIZ;3?orO0mB0~DBFRgL4Jyo!3OIIF(} zOQi>M5|9S1d{p+It|BE&ttsIpmdSp)B?;dMC zBhNQ%_P1oLs~lrFGkf0&G1K&;o?OMuHDPm*f2;`gexAeYa#L zbV!5VkNN;xa^V0Ljf8j@KB^sHRe^l0(T=va*hGt8Wgr@++Ew>y>Su$GO1yP&HVa8@ z-r&x8Ys(uwkd-p~2C_WyxVw8)Oi$GD<(hoQy8#6lHOMLaTcA8j5?mHv&l&ibFXkzv zav%tJ-Xy5ax4PG?Kngw@y}<+oB;5AMB7)c*X1&Jjhv(x@Q)ht+F$GbQX-L)6WBreW zkF#Qv(D9VQDsu;LS7pxuQBcye~Xo38!8J1JYa-6kELUd5la?4`@`y zm%Q@Bn#~uU7Cr=Y=MaO-2ThNs*|8qnuicJ+e!WJs^2;~u@R@|+RtTPgs@9{i#lpX~ zK3{%6OWC(Qn!y*ehipt@2Mk82-35Pm>*O=&)-yo(g>zN{0s?4tHB~&E;%*B8F-d*y z60d-jjYBDSy!VKgdNecmid~9L4GB?V+@d?EmidyCSh)$YrcsmAzin#$Lw?rqCv8eY zbeOg^!=l~a(l9Tatz@g^-O_Nh`0*vHC|MH1E;pUs5%$mv&ztc}9{?f zQ2l-9ZqaA2?c5f$V5Hl<5YBy{L$@SczF(*H`a#f1zIzf*ZTA~uiL?pE-L$2=b^$sc z&ZT6;nw}MdmDqY+BewpfH-e0dWVN13ci7BK6}jIPl@uk9x?tV-T`+8}g0=B0E@sdL zZe45m%lP&gbfh;jeT92aRWN)W;2M49=CAF?p;Sy>s7b1u6f7jCqEU~2Z|d{K@S6aE z=rSz&Rj2TN=D9if5wy*$KW%>00{paYixAn=kQ7f}uc|A!7#d6Lqg&Ohz2SKqcXSr9TGZ#rmDUfm<2TGyzCT zRK6p#@L5*59L_Sv;J)(6OgKTJuu|^t1L6*y>DmsP&(D^vDus%~>zTNoQ|;cK^1$oi z%d%(>HihNrcUEZA;di(mzhgu~X-r#1=aMKCCcXgg1T0hp-PC*@Fu{EKC4L(z%}Z{K zu`eu|X|nH8g05uXwhlY6WDcO2^Ilv-`0KsqL?(S5Y5Hd|NoMh3@*KdkdyB4LgrX~{ zDQo9W7u}anO`<0*pFYrUW-=_q?M2(Yq%SPY-R{7F2hD|I1jkwxmug_JS~QeP-m2P; zk_$Z}RIeo17>E$Ev$-+S{ZU^w5Jt+xb~C4+cyWsMUqwoc0H*Z%rTL*B>P5 zL4iG~==gp@;`NsE&6pP$krV zq|Fw+cEu#!kZnZ}D<)66JA9HnYN^!jzc@$u^;qXQh`J;{Rio6CYMgU#mo#bF=XoVd)f{K0y+z+`X9y z9>1Ty*fTP%n6636Lus$AmE9!8Frmc}VpD__x2HYYJ(BD?5Md00FPFZeYZv&r_^gYD zGiM)k|)#g8FPyxDH+E^ z)>twxUgVpVP5CaY%ioI!`T$i*m5EfJmQqcU7}^*xZWU`FrAuMrf!ru8mwoMFV@eyf$%@L*Q;{TIhQ?%F^dI7_(4WuQ=fQ6mx< z2y7oyzu19d<8(;~7ZTlMNnUX}9;+8A+gw zT`><%)=Y7AZC2p=>m<*%IGo6bcl>4=R}o*I3@d0z{AU#DZ{J1?sjvFzgE)*?gk!D) z-dI24wGHx{ZqcWGPOJ zC@A5UjmO046puTCQIP)X&Y5qo5l_gwQNIa!Q+abyed`}BOFy_U5UtAUf|oX@>ub>D z7rb2Lm9xjzh(0(=11a+*c12P#diJNh^Bz`2S$r*2wjc3_<7@vl`YCf4zU4)-`J5~|M0A-aiVu4Mxhq~t4fKy+-nJ%%?@XIWG)k3;|H63C<&}Yr0v*S z2bKPEeuNho4Sx%Bphy2i{_euyg-bmV_8R3RHR-At4)AB zfbu*&ICyF2UK*e5!jUnI+%v$fN@cG6oNVBMzyTSuzp%WK=O>pPP6{!uE5#+n zEw3HYW{Eg#72{&CL}wxARD&CWo0LR19|i8D$-=LID>IM6_>;o#v8Kl9tw}LAbZQu} zE;yZO_?^6T`$z8WQ;j&`KA+fDYi+v$bvR>ASJx0}2yXk)9f|UGP~n0oWD1Kds`c*@ zCZdyKtnwAw1rt6#J}v&;!NiX;PC#5kVsjiH`n2_rcaC12nk*moQEbB6xf+f0v!Tl8 z*G=ONueXzFRG>z4NL6+MF z0uhgKsyG*)rAY`sdi%|y4H+|hlIX29P?HJYq6@sqb>a>BQMjgCA{NV=aCLKjE&@Pi zm{Uh_-p?8lIw$zCS6JDbTj83sAs)c%}- zOpxpQ(<3*VvlzwK*EfeQ7O&q?KK%1P_3w&`44`ZbZJMTYf<4NRt&w3XE(2;DIU&C9 z0^4e3>1OdWIm2M*w{Tr`B_;8oAm%4jsgsQEN@5|(bD;p=Du3Ko6&6=~wJ}}%d%SzU zh_h4n&4;0?Ij291ule1uC~*?&O@{@m4SWk_5HmEq{7iAke-X$1!)`c~hXCQsbOmqjViPphETW{)&|bqrz1rC#NKq1?T`5 zWt--O`4D{UOLfU_fB4C|op_hZ?mQb4-Ea%>$hY3N+{j{Jt6&8jUiFQ=@vWoC?H`f~ z#O^u5SsSXsn!=2FiTXgDL_;z~U!zcPv!`3h6lJCcTP3lIiNi z8l0KKTFi9;5BccT5`Gs%bH+uNSrT2Q(-K^1X9iV0n(br1hnzV|r#K`joXh#lfc2j! z6}`o%%mit_s*t{>t2BuC3aV1Gv@F`#w?)UM!D^BAApwrue@exw&LYo4b9F@;>Z&by<;>yN>GXPFoT%$Ve9xk~exVY8BB5e0>I zp4aI-isE_M9wr4~x9C+bJk;RUi;{h^s27=J(t z{^=8T5jCtOZ7w)3vEEAcE(XP<*@>mxUVbvilZu5uSqn4qJ@2|%UMF;Oq!uwykdAk{ zd@~%*fX8RP%I!`p+p+wUGxJyt5TWOj zF|iqtkkcm#3bbI5<;W=?#|%^H-5ToolkgvP@>C$Z2E1m>Ni`6h6xyw-7Kz^_iWyyy zyAcZ&SmkW-j*zNg+okQ+^0L%nTFdfRJi@t=3g6d*$0uL~b%T z_h3ITI2Kaekf}tAjxAosMAGq2oV(d$w(6eTBgsZU6@$55m(YEIyGuKVhB2!l1yzpH z$6~2Qb1aqyUe-=u@C)Hu+cWOvsg=%V4h{B))I{<1$%!-6tIoDGr$$f4Bnc&mN`#=u zeBFTtw3!V~k5XF_Z3dk2780X)bt&79>QPaoyuk4Ugyv8Ga!e5p4_0;)ETgE+tZB;z zq_O!wm22n)A1n<&3Q?X?3p9t6k#dR2ismM!x|hsJCEiMQbFuUseE%r9eC@)`|7^m~ z?~5^^#2*^Rd?RkUuOll_W4hW=c)Bq(aFTI5ioFx^%|Y$)>*H7pamdFcYO@cD&;nv{FxbTUUDp0F2!0G~esEW(W*%6O zIq|-G{js5RdbR+v+}~!DY^<#-4trYi1^qhw;+HyDBaUvYJyQnWR&v6~Hn~IJu6gy+ z4f^F8Tc^ByJF}U?UT+ih!(}IHyX>Q{4@ErsNoT$3<7T6k(EfLZET7>~fxAZY+wI~`;a+nEM_Nw@*9s`@bWp3@DOYrw!Y<%!eR1ivihz_XfK3ZIJU04 zx|dTzTN^LLllv&*vTXr!WYeGHRc!{#^E4kmnhP|e$EVA&ZXA_P^Z;DBjQ%1B^5lRn zi95j;^*ydcpT~as4idoTX$O8Og}5=a7;r`snMk3Pli4EB>ivpYf{YS8z>e_Ed!@`$ z9Sxssu(RX#(Q`-tjia)DJ!kkE&^EReWUK(Pj!pLU5wM}j5a)D+fd7 z^iOau<%sTz<+q~lt&@*3J2U!Or=Kp81VYf^n21zK=6Fh6V8SKG&$baQCvOls*{gKC zd3QM_HO48#Q^`#1-&IMd6|LrTuM$q^6%&B6XK<>CJF=)=UE&HD4#=mi^K?QrY=CXb z>LbV1a%s77-*MU=DB;;idtyFVFBy-)K=F%RvCdBXN%FIPgdDX!-*ncPMZL&`v%A{i zk&Zhed&g?2$MVH5RC-pa)V;|ey zMoSb@D`m0;{4}zPW3ff1o`4nv^WBE!92y*AAsfq-GWVy@~fEYwHo#==0x zT>qlZAQP@C&l&uqHAltRY?>tcE(&CU&fL~%dlkeWS;^1^MF*vm@XoQeWIp}1iLe~> z*LP0p7E(V`690N$kd%IRA7@ZHRAj{|-kTBp0)w%=?^|J_7F|%HZnbPg&la!6N*{SI zo>6CiT`ff!5^jojRK$%jk~CYInEtT9S4eL&mRXGucRK*)3g?w-(TC}*JjWLYGisxp zpzs`zwPN^DRjoRD+R!TQ23rcIvXp>ns`$%+?AH5n$1S)K6So;mysclShs=NG5_eZ} zBS{}$tUgkb@(OA~HR(ah&E&LSjuu6wp7FAFReuMQR!NfSVq#lXw*WIR|MefUy~1I? zgmWAQv=qa^)g;u_b+AxlQHO;qDiQ1S2av>Iqx)0oc(nF_E0|~_{bJb0ps=iMx8+h# zn*L{Omo@JO_&9{CH z!%OQc<;1aHrBebs_twv>Rza>|G>eU_9rgJypB|qx&R_f)a40XY$;TQ*m)GQCxIGCb znJYt$3i{t#N2&<2Yu#GS5*RVi1rdo|iMR*isG?3hC5TYTe z8U8=*eP>*gN%uB{fPe@Iy%PvZH#8NH5=!VrP>NCo6c7-^0-+{=f>J`0CIW&hNJo0F zQbdZPG^Hq2rFTT+Kd@_gcK3bU_xZeh;+JG*&YZcnU67C_M{JvC z%FTsk=QUP0pQXENVh65*a1jv|Y5kSYCJ&TI8^#nv%9L|69&K<%X7ST=VfoUpMw};N zne9^zCF!ZV8En`eD~3R^t2_bJhq;fGXNNRv&Ru*h zD_)x@?^6kTv^b?R7eY;XkP&)bqve#FUe@YK^^IFmu*dkkL&L^-)^1n)`){0_+=kZ5D zSnOY3N$+@n@Ls{r66$uJt5574@}ReEDtHCClt&?QZE z-mUbGgUtG1-W4hA4nksHlIC&d<0m9H+p@i*qqY;f0GE0q4QA}URt@`RtU-{ed{@#>k9(@g|8(Itjlf?oD@eG#NW#IvDu*L>+1 z#eAZpINNCkwWIMqD+VHqsvj6HMk3@#wj_}Gv!`>k9^T5hBNqms|0bFt&fTgja+KxP zXJ%HDWE4}#Y){c8JK4MWQIij}hj(qKnUjJCk@v^%KI33+AICb34pZF8TI}sgiPz6s zmSf;NM?`ne*E!C_T5G{?P;OfyB-53EAuT-Ips4Rr(%9jV8@TKqcKC+1DgAE&c^Ay@ zIu70#+%~eMLaoci5Nd*I^Lm3Ye)<;l5<^vog=&nO9g(BUOHbGjO-e>efRsy9ZdPWN zz7FJRfqqxvIQ2KH<|^Uh!PPqB+;V|R5xsBWVRvt9jXYPmsx-}oty8y&|*HYk`_i*)ZD*9j(5ogg>0G3@vpK1-KyFPLA_ zMZF&sS4<2)!$dA@J2N{25ymK|S9F5xG)kLm=cr1j*AfdJ*%z8uUW2zRTE|GL(T|j0 zNyiCc?86BCqAu3yS3FgNi=GuJ);UU^Ku``Vs6?f?3p0hIbtMs?bYs$2*G@8VOspcCsA6&5K zBFvw4C(}AI-!#YETUl7GW86!sC918E6|!6sBlh}b?Tf{2yETU|atY^K(gFvfacIj1 zbot3D1*fp<<6Lqr6MB8`sX~II64P|8AMp$7i7%tKzpl;QKi7MON91hHfsl;v^y>o>3UiySmQJg2|^?p|3= zdl0=?#<}$O-~_SoOrH^tQ23V9nwqaR%BvV$g;MGg7t>PAoQR#0bT}H(S5rbhs2gGa z9MF;#(=*L(t(thPgB!RD2g3I6{3AD_$GNOO;U1|QCD5(etb1;Kk|zYy8V*`AKvgCb zzjSKNF34KvCpX*;tK-(Vm@lyKDcZ6NV=LgeO@&R!iK^}5`LZLmz}#i#+1A&;_F4u9 zUs@>|Ew9$cXPWRZoqN?zD6pDt#h)t~@6I!Ns6DwUn?i9g`3V7CdPHzw!FOF`X{nWK zJcvu1>`k$UN^&HJxzw{-a%`=ggOk^M#rh>k+VehSc~~& znpb=14;UndjK|Zb59i z$A{nI0^PNz%;ZM0PQs*a>_WcQ7O*f4tSf%u;N=~$>sDj+x>2JT$qf9JKGKgtQsfL9 zNL8y;KI}_<02Zth-kNrm?aI3s3}%EHyw{Zz5%HU7dwd(cqOgoIRDw4@DuaiWJ~N!p z?e5~H*C2kLCC#4Ii&G|_Ggytvl$NLNx$ouTUN~m;pLg;DhcqxanjIA# zhS$L-hk|(fn&h-=~btJ0>$#!)g7JDORIb`tnj)r z2X;L_fcusXRNbup`0&7h$ve|9s<$6Z=fG1|>Ne`=QQgYj=1=GiZl92d`PDg9zha#B zXmY~R+*G@r@~p(@lq|GOqZ!;MiaPcQb4MW}8E1U7$7MfLXKaY<=&$ODUq(cQCr7H4 zATF=k1&ka#K+PUesicwvYU>ydO;dn9RCTQ7w*yk8+n_3K1wMptUNqo6l(+dv;Z`kG zHjOw>*fXw{uS(GF=@+Dpr?Ss#1WJ%7xVMFM&_He8k88JrSVhXuPvxE=>abp3VgVY* z8QT~FT`y`I#W!*k`TD^v>7#XY8*2614%I)5})dn80Fw1;6E zq0ekNDZtJhfwq`23aHacstT=+#lu}=GOfn)m^Dj++{X)V%yX~nRs^vzagBAYsX2Z1 z&t)lCQkOzrSCL4wxheA;j!CC&1D80+N;aS88Km@=2^YBzrw>5~`;+1j(4#JiK{gUW zpQu%vB86Z{`Q`I-%VcZHIEAY4^X=1H>`g)$aZ@Tcojeajv{oAYrYS}fcZ8;VLTu;0 z`$+pExh~FOO+9TD842;Viz8D{0t@mhB}?t+p2{BdEF^U}%1#Ve|GVcVat$;;UgjxslDkram9Z`Kns1}b3vT6*~T35w|J{dQlg?(gu zerTv@<~QG@XHWdxl5;t4{G1MU2-ZvaKSe= z$Datp!7UDvYgGkRQP?KLia;het+vV{;-wNu*!)d4d5qi@`W%k17Q~)fUs=KD*Acc9 zNoFHkCtE4n$!#sVZs*kBMApOG;n zeqwKFCIuN}CziM9nqnFt0wGVNBxcY&$bP#vRdU&_iD;$3vxQn99ZQB^MV9G%m#)yz zp!#?kqp{7AY=7&mJ1SN)jioK8qa2&zZH?rvX-bT>9%k2xi7yjcTmqAD^;@rdSFs!fo?VL_nnOuJFd7!!M52`j1w$*kiWN>%v8iYCKwEcTUvTh zy9g9(9UmyP5q?!t*d&oC(CNOXq(4@vjULLMsMLQw<=se=kkYoVZ$o^0nn2)Z(hJYF zJkr^Tk=!8uOSO`9(3lBOuhjO(ZiMcSP|k+;T>E$)lm~n1uy+uzohYfXr?qcz0&5>o z|9D4i^TW<$6qrqJ@H)vyt!>#o6_$qs6_kf_yELqjyLw4>Tax7Ay&6?i zEF(NVJ(`R5BtCyrE45AH{;7h?Y@3@a4N)q~t%9>Hw1b1U@h(*UdkLC}&@7V<>+G_Z<9CMjt=(VX> z;V30NMt%H2H3T05%vt)KpjR#7(gurz5lEM9Zf^Fl(8weHqcJll{*ScUsAM=CF6HxC z61+knCzqf<_1=OWyP_lxSXb%FY&bP3eZ)(SX`Xq;H@C9)qcIssQs$Vsjo*$8JMs@1SZsQ#dzAiII=aUMpz#k%TC73RCZF3Kygp7-URHx5jRM2-+R#y8NS5v4Q3VO;L@da z_Jj@KF7w!)E4z9WQ9b<~g`)hB$L$XB^0p-FE>b85lLA|MvhK-nMP4*8s#H3ls#Lm& zY8Jx2s(dNRf5&fqF8Lx>zO3>y;Ls?bl*WTVfGgOkj$PpVGI~4^1`83TrXNy1{A4%NMySviA3x@DQ?44s&Z_igL z+3~-Wz<5tJ?r$CYhKDPJ1$)H@3#8;VwUhMoJ_Uz-qONX^^!f3|&&KyG2+ak2gCZ9@ zR;UGy12uKWWn4vmZ+Q|1HvM_Dv{!NfU@(}zUh>h<(^IA|&-~!fahDNxK$Ku~!Gmmn zx}ua26$8Y$kbYYSE7o-Ur}2S_!e(mEi(Vc%$%lLQi4A9&%oaetdy1M`4bi#}{V9X0 z-1Lc8@3Zr3U(R`xQqmJ)>_C~6o?M*~*dGA5)q&dUSc53zU;;r6#DZ-Nsq|HcnmK-3 z?_1;#c{ASk-3=P3UF9v^^?^`aX*WRC)YSAi^z>$Kd!H2`@a@fM2L^~%cM2v%u$;gT zOl>*VAKTkwr6BW4V9T#K_+i$a6Kp)b{V^NC`&hNbLIDM5A*c~1Y+gwZYD}ntd*X7u zR%~5XHOY5C6@=A~zv2y*5+#|QPg1><=y3kk6Gk0eGvC`|9n=)zvFkN8-ukjxyz+S? zr0;yW4dj8Jd_o8Du1>n2_ekus(hHhB@`P-0kc+MeIDxM@N1tfnPyRO8pZa&sK}u20G4{s{zV}{ zW#-L86+u^~J#)@%yc?F{r#ej&9o|m&mAIDQw1{YkCX-LLYS~7%^Us5~3GO*i zqY48vy`T2neU$7;7ZC9_^zg-Y4Fhw{FL5GRqRKx9AgTq^xX zFAo$D>m)926y&8Yw|wtl&x`CoIuM8B4ngNfLz^;CokjYM>kq0iJd5)ubo9%$FTWw( z(%-|Y1Z1?jggH)cxX;YuvDK~yDoy+K7tJ6K&OgBNM@K|z^@~7i|92?3al}s>&-V$~ z`auC*BBA?)_hVBv1;<5!bnZ(>PQoiLcsME?T2b<6HBtGEd96+Tv|>83c<-ikN8xQ9XMfG zY^=Rj4tQT~?Y`gy@%M%ui$5UsO&>@k$RJRyl`%WiBM)SrMOZLv8*hJ< zR1W+b5Y6j0Y6#vr-sI53CPKy*i6(?-yO8_?DtEXh$jfh`AxLVD(W|8H`K{7#Bm7cP zAoK|L<*A#rS)B2IbhiJ5KuQc^SDxJ+^ZXBm{pEMAP}#ux&U+`s&No8Y*B&n zs4oQ!fyNOLL!jjU?|*dZrOdu^TFU#fg#ol!O38bVQTsC z+kpN4wULN3@hyV_|4qB!^Z_MLimd-SVlB)RWVc${TQ_By>5BdI(qz;`VW*=SUr!3u zYt}>a$qv3JD;@zVJc_pbvyOjg6EsDm5NBpOo&Mvqf23Pth$1=@W)=ERAoF8V`{Up( z(3w5=2LFkY|NI+&+$rvQX1YIr{HFo_4stcPQx8rQDgFxGf726`_<<5m?8q+-=VX7Uf?vP`1`VVnZi)YgtN(LnGo*o(H3^4) z82`^-{@1la00V)9iv17L_8cT<@RVTt$0PkvB^m}3gfiRw57MSG!30+?9{=k?|MHW6 z4fMalU~h5$HPBxn@?Qh}m9_tCpuhA||9a40Ik&ShC@YDA@^ZVmF^PczX`FPE1Uay(g%zNhferkx(Wn&g#27y3q`g+>NAP|l7 zsqSE+JH6=`RsR9S@Rlj+aNy$NQeR&m5D=iHrFC?4)Y;i-XJ-e8!-a%| z`uh5Eb943d^n!wdw6(QAe*9QeR74;UC=^OhPfu!UYC=K+4u=a34P9SfUsza}o0}UR z9)9@nAr^}@Ha5m!FzxN_ZEbDM&CNt2QB_s7s;Vj}DM?yddSGB6J3BiiC8e~qw5+TQ zjYeO)b}cVgQM=j&tx}Mvg9e_|aee{LQ-9AeoVhL*4LMmH7Xh zRity_^vFzuRN_2nZ%B#SaF?3e1*4g~eenn-BIsWq7kH*N%M+8y^#{`3JE8ta!#168 zP;PP)&W)pF6F`$;%FrC$@x?@06V4}ntTvXvX0VLb-CyeIR!#L?TjI4R1`2fsS8D_s z$%-?nyAOXBVrMWr&iXU4w@7^9nEP*qvI-bJJ5;=8M?W5PWGU>D2kH4@uSc_uK1I=F zui!6th3IuLJ{jtV*GL(fWEfzjyDQ>~kPeOd54CF4*yKTBii@ISgbSPl&-KR>)7oPw zhBSfpMgYU}MOy7a%Axn@) zga_yUZHZ)h!I1e@Ah3}PW&_cmEUhC2T`0i5v@g9c7c)4#aw=Fa{~h<)keMmYTMMDW zj5yWAV!@zIp#z)Y)^S>QC$jlp^7HiM*0*>1h!MyVJyj6S(gCI;DG!?EB8oinG<8lx zOL?@N8TH%DQTdAK3Ceb%YfE$FrKz@8Gb_TRstAJ|Uem%qZR1_pdn(GvvntYc(lsQ7!}pG*R%Qpo5l|;hsyCSlY?N zS7%n?KSLu;5a$D~i5$p@9OV84IA#G2>HmT9+af{vE_T;HV;2P9C_$??v=ibGwk^3A zj*O8kA7_*@DetykB@)K%19M7R3dc#g$*t3(YF92!e0yF{?b7LgCYDczmF)KmR|_7` zxqH35BWKdqWraPrruUnDYZIdV1HZ=9ETW)xWP4AyuVeqW4zJfety#@*xPppr zh_6WvkF1qTJ|rs#?B@lBJjzPVDQVm&(6Sz@Tpan^*)-P5e|Uaj&x};ap9b;Ox7Y8j z1q?`BFG+I_3aK)l$Tbc=nNVuI=D0rF&YwxPjD~bF?Q+ND6I1!1L$a%88)in2N)uv) zUlF+I{;r}s@hCDbsa$gZwC97NT&$Kh1mVoxmu$)-S#)om zdCaT!Iwg4y-^9ZZlDPi~famEGT?z6EoE2zD4lTZOMC;Y-QZtU<2Hs!EY*_IrYlMVYBq+XK8o-$L4R zz2~AD0n>H3*1>O!4%8jV_S)~RV$+g4xA$LC@|{y|qQM&jN2nP+fkJ?Gpw0j$;O&n6T=A z=srHq1skfIy(*6Ig$>FWtK{P}8_p|wA2@vQZBqY_R&dE{pUBU|w%^m!M73f^(L!|+lt<3F%w3zhZ0f7D zL?+BGiUGFJ_x%tkO7`0C?jYY%6TZaz&TQoiHEgViH4Ct9^1uozaVPSR4P^F%h} zUi(3$n;PMAkE8dsU=k(;N1XpVRz-jLIcb zDVnkx3*7^G`|fx_HAusBjE%emH?+_MlDr*A0ix!(DGqygbGFxek8V^RU-BKJ4=3I- zjfnzSymDfsi7(~e?%b$Ulu(eetr;ZEKcWEB95~ym6rn$fhfy&q%3Oxfo##HY)_?Z~ zvNYAVxkB&l(-WmRj@Yw~jTU)+0%74X$Jv2Y(bH!K`*|Y#{e=F%X5-jtZPkkBOpaW9 z)|LZNpft{&k6t%x0ph!9%##~f*1l}~z1@QWfNMBZzF|igf+rbz25P+9Rjr-=(ZDa2|={?D!t#zH@ph_TY!L7a|Zmm^>Ol7^Yv zL|VeQhWEl`zrL1shezPHTANy={GFK8xqKEYM^{l)&H4Bxk8hHQ4*43R!(fZkxOZ#` zA0v{z+{>+8`$dI2kJ;n;o{}Sa)rYTR*AS`8m7S_rS?REA(145EOeuCDOm}stR$TQ& nauw9~9N>ncDj@#-LO`JHCYYrT&-hiU!9UVRVYJH-_agrf)H^|c literal 11022 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 diff --git a/docs/_static/img/Matrix-A-upper.png b/docs/_static/img/Matrix-A-upper.png index 1b930a9a3f552080ff902415ace5e7a5420190cc..e3703710ae20db0dc5569cb3869df7fa0a08e7e0 100644 GIT binary patch literal 3335 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 R2QmNv002ovPDHLkV1kJq*(d-2 literal 11276 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 diff --git a/docs/_static/img/Recorder-output.png b/docs/_static/img/Recorder-output.png index 355cc13764898bf9638e5ce9bbfc38fdfeb75475..525221c557056ba5515a197c5e2a74274ddd73cd 100644 GIT binary patch literal 9883 zcmZ8{Wl&sA*X`gg!3hu?f&>o|Jh*Fu1_|yOY;c0Rh2SAL1P?NUy95{{_#nXs%OC>` z&gFUD_q%n!`=_f<_o+T>?X`OEuC5cSt*JzS`y3Yl01&7s%j*IFsK}@OPi(ZOmi-Lz z5dc8()mGP6xVpN!L|#5VK0b|KTwFjP5I7ueVqyXa1t885KY#wj$H$+Wo1>thSX*0z z!CwJalw)Y-wrH(9p28 zwav}VH83zJD=T~T>XovxG9x2nWo4zFo?dr%_sYu3$jFF`iwi$L|M&0T|NQw=TU)!n zzCJTEBPl8Q`Sa)K=x8A!p@4vZH*ekq1_mxHEPVa?H7F=(Y;4TU&8@MqvA@4RH8mBo z4H+LFx3I7Pfk5%`@nA66#>PfOL?k04LrqOBB_-wT>?|`gGbt%aI7j&S_*h0p=I`IX zR#sNstKALr4ZXd+gM)+btKR$g_>BG;b^7Tv51U5`NAYa+?C9u->WvBs329quBZwy0 zJKdX{oMcO9ubipm&Eh4GBj1E?N)<>IOccl$$-hW`ku;bT(ix&rrh)kxGix+!V12-% z&LW^AVEJIVudi?YXq`HNnvahUmm|s(0AN{Hk(br?TRws|sG{=&(5DjrWJF+xk8mt3 zVlz=Zgw{kpKFT(x41OTuK4w6yk>QzWMd@ePG9<61D<7+rAX##5%KtJb9S4b1j7$T& zxrn!0k?G2sN0MPjo$^C#q$6u;*8l54^D@}n!aH}Zd%e3Q>!zNUQaX_dwsH%R>kN7T zH(VvS0wLEG$u_$!yb*RQx9w&DRLd&Ie>+*MS8rR7%jc6W3;xsqLq6DH0eQFV_Jd%- zTH)`G%XhLmv;H7_kJ*8ct9hXG@S2+Z|N3eNsWQWHUz+{Cr2I6HWM4A&yg)uci>Z@+ zTDr5&?xKHk^`e9z%96HwB8bD12*a6!;UKhjmCAW@MLR0}Rj$|OZ)d^jqmjA>Yx>|C zWA+5~M(e1>L*E|K8Jd}h$KLdoO5)W&1>j-HkH~Y8qk@=K(gq-tkJbP@c2Sa*roEg6 zyc&dD9)4WA4`eZWdsG0QwnqloI3vx-TNnTO?9jmH|NdwM=18@+L#PuaGCfucP1;J2 zxzRPXdp~fRC9lq&Q!lSCyl#}9x%aQq8!Hs5xz=ZvP z#9@(glnVEYst&G$8Rl8)q!?Cnx5?Akale-1?T)%`?$6$|mvitz@4Kof6v1@{VRkF_ zjwp*f>)vkMtLTJK*M(UHUW`R?rNrm%)^jLM^fD$*p|kOJd``_ENYOqYw6o+V7xQXe zn~c~&7b>j}%J_2DZC-H?+7F`P;o%+cEexh!U%({4yOEz-R%oJ`M1)cFEii|Kd6n`G zYL8Ug^`4bqUBKlEK*_7{U6RDT!8V&}fwUYIfRvHq=9)jgd{|gIgs1Y>WHwVm>VY{g zm{-*_72Ais>Kd97(FpXl02$3>L3@M&;H(;ID;LJj>VtC&-s&8IxaU=93dLF>Px&JI z13^s_Fb6YzwQd!k*jVE2HlAy)iJCdj-)grdq2Q(_5y6fmm09a>_<~6A0cX!`^SQhF zRA*=F0_LKmBtsxiVp`0q9!UdG^+|V?0XWA$%0F8tRaO~5_UZnA4Eb~)^U=llGc8Zga__ky7OQtNXOuONBJk&%U-U3*fn*=eb!B^(dI{d5AKGW? z^Fh0%QJf^=bK1qM4d5!?+$y?jwDV@@ezbIo2QC|Xk!i#0mPev|eaG9%7>U_e>zOJg zdbZ{C_e+r;zoxS%41sTB1$B^K^Rg`@_PcNBQu`K$wtC;1eH2>=;r(l{97i}DYgXeB z#Jgb2f=T@+>39u~#aq96?!8Sye3|mT!Z{-6rw}u#-*-EbY!5=lEHhec)=Bx*?)aQB zW2eSLA%QS(ioQxoZMRZ9_~i_Nd|!WnA#rat#zi&z*;c+Q0VZ`SlwGa0F#d;VFe2T^ zUe$S*5{P`rY@r@PxywZ;D66B6+!Hc|V}FlfSUYYt{^V%zq5ac`1=mAxO}qE%-$L_n zwjs>w#*00+Li%~HmX1-xN$`U1*sL$x;tzUgKiVS`=6%p2V&NC_K7swmqi9>6EgB@? zS$Bx;^4YCkJ@I!AnN8Ghms=l}=Rlz?+yr`pF<;2yMRlxkzykwmp|#?hsv!EY!Uq;f z%Ca0IUlsR>+khFJuYsQEZ@W;FjqxHCJ2b~VU#8iRT%ZYu_Y#*x853a`g^TwEx^q(Z96q`A~|o zd5{uE_3hr~y-q?&%fXNs#}?h%W|`^-%6Q}Z?V>hTp%>|(@zF=}q^b->tMy=#mrzB& z^TQ791MpEreVD)yva|F|hhXjmG4xv$nnt_w5v(%Jaf0D7Tsu-3DlIuafU0PPR}i?WE?>RD*W)EA)0F-q}`^x1u=8l;n6W*N_-0wlq2kA%OH4bg49XMOljGQaK32zHphfuqf+^UIstaEJ`m;I(Q)e9hf)r=2@Cxm3&h92spFJuaQ;n}21eLClS z$aDW}wP1v+Jm<8KEg>IYe%rn*zD>U)H4Sv6T_ETCk`z2rdikau>LVe{Pl9p7+(xs)g8N8bywAPI!vQVdciXGGiTsw| zw529fqIZ5oRMUt14FQ3akg z`pM5Y65iu&%IqI%*3#xoM_!?W1jv>R5j73^9^%)tI!djA$sGv21%|Eak%V&e?CBDy zQ_h#y2ywqGMC=tsVf?1Ao5CpqB7ZvCSaCf7KEA1+s`)DJpd`SiWou2p?B100#abvz zIM6%>QabEr-W~ArVGnp3*><;?>lPAxh1xS*7{7iO=QDFgKgn@vZdlGY$f7#V{;g!} zT3;uI6%<#zQTAD{07$D=I_8kkfcSY5)>$b_qnHPD9bss%*Pev zJU>X){NMReT*%F?hwgTbdpK(v9{&+PiY*D-X4AIZaDL0mhWt5kpTY^Kr2Smh-8HpA zMi#(Okv@MN$?Z5TAasB#-s_1m;SdRqQ0AXcGzCbvI?V(B`3Y-4SDb_SwnM?NfZFBMP73UrTJn z4-@g$dVLhkOXR7ThbDW$1L3V5a#Ji3MN9TKPYTKSu0VmJfPpO!9PD3SQ!jsW@L_N< zFU_fBu_6Tps}QE}ohdUtjYY4z-y=1|ljn+~MPfY@&q8WGD6#J9V+JWcQF!&~`JT(j zm-1W_#%sJO&-GE-aDO|SHG}eu zzh%DOC=+bK+6kUY9S953tR&AWfvO|@C)xDN&Mu_DN4;5X@l2ye40)e5Enj;`e2uOY zv=bRZ`w_5=d{9nT%dlT_&lT8t%|0 zKyzOi9|*Z?;2IaWx+=t7fZr^x^!`gtWm&lC%|v7i=uthe81}#}L!1bGJSlBBZm}$) z$rGox(+b86tzW`+W&Hs%-<0w;GEiuypjJn#-cN6JoMoqJmI8T7A^Q$tyo|By_Nxz` zIk%LXh3xm;_XEPVjXeZMEST&(wSp47=LYc-S+|_UFt6k<+ic#upT|0Fn|f>7Iwutg zl*u>@J&#eC&U>b?{e4Qie!fOhrSBk)y@bj^T6~uoIQQgoZ$F`tF!TL*jbV|BB8il- z8Clbb4KJQ|rvizX2p#_1UAsANsu6V*&K;)|&)qsz*BC-EIc8IO|1f6CvoNtRn*;0! z;z2d<#&{9`s~i+^-}x`a+&pod-EBFB(-^pX7X_l?S(sDt(R4pmXsz-wI`@rHUOHDO z*{63f1ZpU!(O|Y)0r%~TINs(5^T&s)!()b5-NEf0cMVtN54ra{JB88>iP_i_dwRq6 z#le>OU32e zrKZDzO(S7OO?BEwjD+88;4P56l}WYB5Do0@;&kNh+gQ@eE2G24JVo|3Y>@PR_9od3HTkJ%wf^#B zF7P`wb-w;BWlKWC#KCK72*U@(5qP3I96-HT&~Taw`7t0Jx##Rs>oe9-WzOSmEk#f#H8AYMaLBo+xsl95sXvDWYY)=!}zzT zDid180tvHoXcL|?5dn&$>OX{;WIbz|#0prj0Kj8DzsgFKhUeMc3%2Xsv(hz>8t7&n zWP|MMTY{$pa#sK5*Ehb6jS-hKa`v$p?q=^iWY{nKzH#aGwg>V8M89NVEdHbu^hj!_ zYpWelC^cc%SHFA{X~`PqguwPozOSpA%D5!QpqTmYW<$1DGWhFIsP*l_K5eoz?}z3x z57V~eJ}&#yUwIqF;=4Z>jt1%)WZkBg-A2i>E@1y-~|75r)E#NC) z$Gz11&uVB1z26YP+KYmheN(5I^wzUHyfB|*AQCw8;lnD_ch&!&M&a=ksR5yYna-Sn`!uG~Q&A z^b68r)=QohK!E}UBjcd!Z`{{~H_(lc!y(9ZuV}K)j=}B>fl*Ej?#@}}CrZW7rYT?@cv*!AtKAm}mQEA|h1P`~ZX+wQT0(iZqXoKR zA{4Fkjp7oRP1p|-k`!CBAfg1P~4YI zzyk=+k(>x(wr(%?^7ItQHVU`QnX@p+Z^V>upsTAW$ZXuv3hmzg^4Dsn-~KKD_D0QzU0W`n-Tn4(b1UbBna=4Vy$`Ui!H;dn_)>TfB7Jb& zH%RW}Ly%?`54*S5dg(8WiTmy)wk70N#^hR)nwsg}no6}xTBf@wO4$4zqm|{)7&l#) z&Yzv-H)4-U-d>&}G4HW+-jI=rrE^Mp`d~FY8=($z8~)C;E3HSX1RU^@PF)+7Wb%9$ zGcxQ#VrQeyEk-E{62skBy^xf?%HxbKh*0W9ONP-^C%o|Eeu0u~ z=rXGxj+ogJqu9*N>PT~YH*Fg;@-jR&W$>Jj#l+g`tqIe2CySEvk)JRzn4MU9#tX52 zID-SaC!4%$YwnngmTPeKi&l}APTuCp<9zf%@NYwmWn<2w*G}mbV^kIl0NDu{=EO3( zoosLbPKpaj>BSkpP~zd|oPOL>v3C!C8~zb?!*1U1sU>eF5jWYG^~+@-bl6~xo53l3 zMMTzYw6*F;n@v>4^?K}KC)L^?%-Eb6D3z`L9K*CYCL~?)wCG&9&L0a4t{uLkt{bq8 z-yTu&Y$SVwZ=+nrB9AS_^9h@Zs*lexx@4|S92`YUZ*km0e6~ZQZ;Z+{eMBOWVt**H zvu*jAta->INhlD+FXDnkT^!fpLDl!XZ$60Ox4FL;!o0mrZqx8=>Ne&sbp*7Uk;y(g zj>Tw|Ev;`$VJ_Yy3Cq#Y*s<*%0rAfj#-oh-pH1#hcqK1j71W*X*4MU7N%}Hc%*lG; zOh(Y7-1&`gUBA!#W*`q!ZIHTF$Kj*#O4YQQAb+)YIp&U2b^cNtvsTGyvP3nR><=l` zzj`mxvBWr|wCSS?tO*ZONUffnTDaL=YTDY{nzk*DfnMM;7&xu5S=!*Ys#q5^vf@S~ z%AOcGFPc$yYgQ_&+|A{yHH&%nz9y!_fp$odd(BcB3c}mkG)QvF_bjAcLQQz%zQrKr zrQFuIc0xUj>;6)^?umg5m^g{Z)lM=iQIE(B1kSIlK#%+L$u-+%nHxU~fYW$QQwQmg zZJ!{up8%CNucgGz@ZJv$XtQ>6N|Jzh1D+TtC+q(|42TKQSQ=##&o7635a+M)aeb|i zKcKf%=OAoI`JCg>ks7u1qc_LJDW?mqD9S9-Lr4PKv)$1(mw=p)+3|Agm)94r~G8U{90QzQ!L}rrku-dr(3ENcM@yq zOH31%w}^hO2zv&$wwEboM9PUVe_GAG zvWK5;7}9>L5!giQ0IF5F@&p40)*@X&& z?5WQxXNr49?hF;5HYKN|?q{th=PzP!9}$wsf3K&aMY~aUa&uu5Kd3PzB)WC^|fI?W@A*DYBK6hlPBAk7pF8Fee6-Ivd-vFNe$;r z!O%1wb?!lUxWzr^c68bJ2{&|Y+R(+H=H;|&Uf;wDi|!M2lB)?P=CXZ~ejWn~1Y;?4 zcuKZ%c3CZC{HEb;R>OX0;rOiPlnth94jyq^CHC(X79&q0mWr`|oH77ps{ea9s*N4* z{r7Axduh?8Sid%4G#ba4yTl$1>F|?J*;P73Qz5)K$jga*-H)(zY;SO(Agj7st1HWq z2HyCRgqBgLB{<_$vo@m@6~|Z+%_{@+S9N=5+t&_t_dX#Num!Qzm=(hHb96>m+K*zA zoS{&x+I20?i!D{UQ~V!S8GB&$YN;4rRY*|h%L1+1m5_{vWu-|+`FU;rWd;CW+!6Mi zR+SO~#TFG^7DIHtm+ztP-!PF{&$h~DT#{lC=dych>Dfl1^Iy+h1>~|EPNw^+z~)M?6SRrcu ztK3FsO-JfeQW7^{6#B-SI;bahE!oJ|cxz!hS{D9-e@H_k^+mQdziF1B%Ko$NRL;PU zi*y5u3|PLz(jp^1%MO&w&uOa2q8XGLH2>zeQJ7A;kYFh#y_lUMNpJP|(r}(Fta3?$ z4h={RXCe>Lf@0A~Zf8-dnBo;gal)fZD$!w)YjI=BnHzT}a14F<+IeZ(BoMLlG`KJ) z9x6|2IJteI=+qu39+N2Z3LN1&+%s6j?+)IJ>zeU+b`c{IIBJ z%v+P=!=}5kVnjCq`q5e=;Fymi`mG~1J-vKKL^pZU6e>HJ;3>H5YZ<@}YcFqF-u?bG z8s)5XRg%j;|mK8=02R^j) z%)%$`sKULQV<3vW<>+edgUETe9S)AXXyrhD;XAwr|DZGEeSE<5Usr6Ws{{~?0NWB?BnZT zl;Gx^#=Yy5LdM}%hkNi#UVm;|HP1{Y3>^nQ#;%O*Ti&y}ZI07f^2v84)`=&juhk%j z$QO`5%uWT>(8Nvu7F#*6b^$%;eU=(z*9>M7ks?GEJ>)ReZ3#^+t@LYrycr^PrXaX2 z$o2-0CEsj}mV=UkO*j=lx*Am_*E{dC@icE%XxyGqu*v1GX%#68u=TVhd~C zYne(nNFiSLhse5Mzw^6ZqRn3ljWmM@=jkYK9SLbqE&pmKS1xH8rQRh|_wOt}q%!%a z;lY$5O)QO~8PBIfIj`G6lggIkH+imuDAX5Q*qQnK5f6D=E8v*o{xts z?5c1RPEn6awfXMfP~Osjj$FXYw@P_H{1nWn+U;`PQqRFPuk^bPT{F>iAQ|E*c-yK4 zy6MnXR^3fOPYRCJpxeWhZ*p*xdd3g55TauaN$Cvq%ROvHkBZs&3SDLOHQrn!e9CCk zjD{xf2sJ$d5IwO7+H$G)v9@kH9nWiIEPBrN!)SWzQ+E=B-RL0gg7-C&`PujmKzlGh z4a7Ue!uz{I#wxXDT!q{*Z{Dx8!(A9Dg7%M!JCqWowjej9k^#GtxQyRWtio=eksv(b zlK8FbKa$t;G$m+VQP8@Tt)ohjCMq66hw~}I1-`5@P0#h&V^r4}7xDOg(5CyxEOApu zc=Su1{DRfH6(}VAJ10X3(S3;T{zM@9VZt;6iXLRGY@F=_$K$ZD_8>G&DnYTMI6+MZw#d692TqR z>_YY@pYb`Fo`{ec2XEeJrz=L*AHg&(f7Lth((Jh??3gE;2;;v z^z6@@6l3>I-K-xW{BoT_jydu74}0TMrV(pj3vV`qnHaVRR!z#De>LN@KYNN8`_o83ltz5X9@j3X&|`fS3D1TJr>yBh*B- zn(&m(jdZOVi&(`?ag!Pg=!Hr*O1zV3aW#|dgKy`{5H;wK+HJgqUBBwQwB>O}gMYS4 za8Z#mn-q&Z(MfAv#AEwYI6|b$Wk~4^u@3OtvOn=Km0ok_oIS3jNcDEjNq4-~^}5<{ zq0GxWl$n$)yEJ&yT9KFS9vE=TRO*Ll7w?HW$GNOIXbt{&Sd6~717g)8H;mAt)&Hy_KGJt`JVqcytLv7X8?=9cM15od+693EyYJv7}RTD9PXbui&U8F@v zKU4}f7`}%Uy3-VbK_y7Y%M^t&nyhoVVasK_kn8=3Tl`& z3I=e63VdjQ4+;u;d?*Sw@J$MQlrqu&a~JJ26a7EeC{=e4%Ihhrs{`M9=FS!t_AXWq zu6aZCl0a9#te+UT8fZc!%^mFcp|2dwEciX`9PgT-JoJfRGR$@C2XB8+%u%C!f6w>;HA~pMI1qT+E%V z9bK&*?3wQRg_=3Ixk|IJ+zs^KKmYfh7M|9Bjb!ig?`Z)O6u7%1Ajl6E_;24p(}#Dz zO6pj9TG$#YS=#~P0mhIK6bC>2*Yp2#=dTg}*3#gwmSPVi{@(I$cm8bo)WyPC(ZLQF z(pBcKmHBt$zu)|K!-oQQGyj_;{!h&R`W29~4DLgL|E`$~?(42zYZMeY6m=!}C!VO= z={SvJdKcZ=>TI|X@m5I{uc8twa&x0~$a3U^%JE?=Te8oolnE?&5lFQU%oVB;PvSw` zg0K2MJb)A?o?Q=KiVTj`&0St!H_gqt@9q6MoF3crt*P`KIC(huW4XsLtTy42f8cof55dThd=K^)Izf(uO-^s0aQ zbZ>6Xbz`^_k}mnvb#Hb?~Ww{O^Pwq8SRFezh4B<0k7r z;$BGm=FiXlsSZunwfFzrl#y~9tiUn7{oT!|A$y#n@W-Obk${NRY(9|H4$=P4okCLJ z{Jmt4R3|I?W7~DG0>|v3%BI2}hw1-Qi_yaGPkw!R`k5tXq!u^01-Qb!7mtGEySf6 z^XG*>7mz$!?$_n??cDA4%PzKGB}QY$-oHDkXV$wHSsgpc^%J9B?a#OFn&dmIJlw$h z#|j1950d+Zl$M~Ce(O4kPe?B*vQuL$o95VtbEmOIfU{=$OupEp;g|R2PR)S!*VjKG zJCk2ExzpqEDzA@5v{NpJM%Ms*EWH0l3T?of;h(LQQ%$IOY>pG(>nYS+4AXepI# z{BF+IQbX`4Rk{!xD|*_}7KE}_jxO^7*eN&Hm#MMzQYox)4~M<4kH-*=PseLyZ_fww z)e|^YqXe1?%fuhB{Br`wlmW$v%eTjy2xi4lB^KwU7%`P5?TdqzqH8Qv8eLs>y} z^MQCs2Cr>sY4gq7kxY4XN{m%D?;v@9k4B=ZxrU3bggEDV=*QW(KYO&U^sPG`oz zv?w#KBbuR1zpxg7c43E9$s{@U-u&U;>#i&pb;*)R^*6CAi+3QgpnlpN^slQ>J zbDq~=Gh_oHWD$vXI&L2KAWr6@usy($#5C~_1%rC0;k!quEz_VUQx3BB=#txI?T{M# znZPw$hYtcT?PFywtVSv1)CGa9@ldZJF~9+lHO$Rlw*7&v_rlXe>GST^b47Pm6O> z5%0geIiOU0!QZegR0)`e`ZJT@lb88N{(BF`jF;eVg6Xb^7-gont46dIO}_l|EYOOh zNlZ)!O=QXkLB72BhIZB!O-(kv<{TtSAAp)q-X?kzN^9@veqbg>lz=ZBbwa}@D|*KH z(bLSM9^~3o&uB0P32~aNwuwrICS~W943By6;zZV>Gp|? zw0h3hE1BrW*`c)F+i;I=dJosOb~5dU3#DhefBGR90cj$qo+=td2?SZK_Op$34THyX z`Kk7=pOri(_dM-?y3CGWO5AYJcsL++uwLrW_*=zPbji=Od~?d7*-p}J^VQ8^#w|vM z%;mPQ<-tf9RIxp7Pi)S+(){4ZVvZr@C*7P-X!*Vht=;ml`jtZC61A+%4q)VNaz?ff z+fKK>y!@WXfCFkq5_0{iR-hQpuw5L`;X6Qc&{9mSY9P^gpI3cHEEv1}e9G~A zdD{EvhwAD_uU$c57}Bx&h*Uu8tjb|-cA~OR>J}GW#(mr1@H=aqIDypM$(*0x;ZOaS z5(L+bw`Zy&)pkaQzl(%~L%G$ofk1g+K|LLuAp;;4ukE&BO8VuCB zdv#kq38zJ+n!+b=Z=A!kr8tioM(_Oqd0O9#jRGmG^UNSZQciiASHJlfO+QY+;(4O{ z1(WM`>$e~oGCtE3i8(4U&iVY{neFF62+iZop9Ig}+Fq9@?@d$|6zLVj3R9Yu3#^K+ zrMbjz%zkTN_7&L+j_Jy%f>yMn8ABXf!Y-%m8~D^X(MYO~rS=*t>n=7wYo?0YrELse z?ln6Ix{qOt!&j{&|OaUtyMF!!7NFWb|Pt=eL5fF|1ac-^ zhLm&iZeK%(a>5<1vcpfevlI9Ph2O=Na~4B3dPMo%zWl>DmMt*pJVyFNQSjk6OvsHl zt6KMorDgv}`_ooUFzZynBql5rO(^kDAM|nmX){Aqnd-7U7nXhz|F1Xae`ibOzz?|o z5M8Da31CZwevH-r(IxSCFi;Ca55Mv2iVzn1})cK0mDPMX+t7qTZ zRQ~RwT_e}3{`k`Sw=$rp(}ZSUkCoaDh%ZG8?J@Wq=?Yu)-m3)c7Q$sfqC4>*CB7$t zGquiTE#=N|=D7jU26sYooQu6$3?^Ueyi2=HK za`4UXI6n;E2*&z@UY;Ni;5_=po08TUHn^9V7taFrPiZ%52L!up!xIqc`@ko>*L>@% zo9zWyf5=@3<}v4^&+m-3(rd>a%wS8Y$EEsKI>)x#xF# zDKw{7l(;cklz@rC2mo9#39QrVDSMX; zE$QPYl|NKyB{(w5yh%BpES@&^e9Mq|(@nmL8#x*9-Dm&i`k+rB|Lw6S0zV*2C1yH` z5(XIXw=a+(->#c)FJ*&GV+2E+W+VaMoC`+vcbs-~qw|%IyIAO-5+CXi6+7AW!@4RZqMU zM1(^Kgc-~SVQRy|KWoKiv{iDsT}^e6ln<^wKi-}g$xNbP;cE{g^4M6A!sm+~ox3>^ zTYGh~J+azF>)?8NI_vd?Opcfiqz}>*4a77sm2tlFh^d8P-z{AL&qACRL>qurBeh)? z6qRtr!Hf}IZr&|<1-kw8xl~9Na8~EZ7jR?tT?VDsW|_TzKXhH!IrZN8I#$0%!m1)( zNenajzE)*D5(r)ntx%4d{;V(XhTNEv@A)#77g*x<>aY)7e0#MfYeLuI)x(}l6`Y4o zD9+@0+Cip`vGA&XV>nMkCx4lC74A&NVvKa}ptEkiK5=m)TBsmiE=U#1X*zp@UX$wz zz&Ljf{D;<_Q@oKlQ?FJ`N+qF_#cJ&g8CYu|CTzCx&A}%mc^1v89}+GYF#ohGK;~~N zqRylfkCet2IB701sv(qHq~<7eTI$+0xxKljXN}YpiG~3Nn(i*LbKU3~j>*qL;W)!XrA2k{ASh7;F35 z1*}TI(Mm1I@SPMi4i>ce#oN8^Omqku=_8u53O{OpwTPYSxY#lc3Q&eb6N}yeqLGrv z;4RAtJr8NUbB^&icjo}0gHAYRA46E<`AZ-~Xqme6cQ_qe;ff#)zUNioC`tkML3j{T zqiLTeB2)QJY15-Kik_OPU>s1tK5e^cKf(>{u^q{enSiC*O$*i50As57Lg zx&nW(`qkr5eROp=C?$2QNGQR!fB%gV_?|-9qt~PyzQZPn8C30I&BoE0yZB?qV{QhD zgeZ_IIC`%n=^IlgcmxZ<-(%pQY7-3mq6nxSPn`Kaa`JsO%DJ*seI;T+P;`0Yks z>3~Yz50Ah60-bYEBAZKG^@Nz9zwQm7Vz%It6qwGNs9@o9jJ4?0gCD zCFzq3a54BhSXbsSF4eUPP;rtf^q02bm{H&XGe4g(6AuX(e*eR2q}3r5sU}NfL**he z$(iODNQPS$)%79O5Q_v1W+dGa#iz1f4&xwidvWn~?1gZSYMdy%;%H}TEHf*#hkQpi zFfJEo+H@ZapK9K=)9CB#mA0NEB5&0gniVQ{47}~ZjJKObLN6p;*XLmb%j|8Pr476H z5|$2dkOFnPcT~@N zI2ZF1Vvp+JGL<(>U>u*@>(kw5un5ojhDJ({b7O6Zm3#V@#8icrAR>?=vYx4!otdIX zLEzg_d>?wHB%H3qpqyo&Us#OyQGu59(U79nC4>0c903}3B?v^P+aU&uCfWR3SeGe6 zQm7l*(?)1S@jUy@iO2hZBFYisVZwIooWxku52nV@?4kIaIwdZUz!wp_Y@^I3J zu3w1{v8+{i;cmpcVVm{w!Bpc3Az@020(;Am6WGEi$WYVB5NqOd5@D_~`-zG?VdXXq zP(b*Bs(;@HF7)l8A1aq@m6)JJg;CWv0(%GF9#g7cj=l8Tf#nUgv5vB_8z%c}N>?g^ ztgFb~2i{Mx7g>&)h#U?9VX-Cg{q_!i$ql6Q&~{}@J*+=P{yg-0tMV_TAQQ^g`GcOm_nqMRvg}Rs$iPMD4+E2$6-iid=FD z1m~-K58HzyHn0c5twX&@JTpIUIq}`a@v9~_C@3y(5~lmIpV^j%j6Z&Fh?_C=;c_E( zQeCxbdoj+ky5UG2?srRn3Q}V9yDAq}H2c=xu-CMO!3KTeg#HZ9*^0q>25#RkkiCx3 zHY9UDUKX}xz+gz+`uwG7vyIKfbSZU1?G>+8C&nX4%(72BPl~I^0usM`7IlP!dynnL zP#;zOTyRT1{a%dB9Gsq6KnPF%ERnhL5tJ0leD&gEYtUDQkhIo!WyhcXa=Jp~GuaSc z^5W^*OKftkc-QT@DAr<9-0$a*w5kd94o18fe z!4B^JMX%{A8tg}rsPPR7eQ-?6EFWI4L2p5TX$P8mgM62b!P|?$EFM{ijZD#5Yki^q z7nb;lEa0{Kr0^L32jyF zgeR;hRQ(voZ=5ZRX#e+&(oB0|dzpDWdcrapl0Uk}stP*%<9kIVh~_DL4w#mdK_Xtx z0E;n<$&m-cCF~svD;AU`XaWb%@drFRouXgzhQH~|tfrIMo&=>WOsI9gEtoT}X3lpi z&2uqgpoviy>~9)(@{t;EI7s4N!#(DQ?}*^8v&^<-4TRBbMj>V}v>?J+5EC5t9LcuD z1j3%WRA-5bYz^$phDR_Nm^zb*rbACDPd=-LzcaDx#YmhFpicrvL3QonT-p?z z3HqQegyafYvw2*TX1C*z=cyWg9L1=kHmH(aMCWbF|~N^mG9+T7D+K<1jh_zECy zi7tV}Z4_CyCcV32b)Z!{^*z zPq$yV0(coM+yxT(NvPb1$D(_|M7M(<0>WA_4B)D{(E6K<0H=GJuVCEK6h`*dD4bCM zCVp;ZeqDC|kYUQNdK;+(zxrOCjhME$=n8x(GRWJjgcp4xP3AJ#bcG}}y=g0kFc)SY z+_$y}MH5a^5I#xLl@+XvFL}!Dcay{?VwhH%`wUd>a<|Z!rE8Cx9Tn?#m<0Tsq7_K$o_ zW5tF`Cv*ZTzT&d;J)9XLK!Eh|&ZDeD&u@W$yS(#4t7l&6rvfO~Jyz~5Ww`BD&w`F^ za?eSwEyD1r$1QgV8ua~xwfkjJqQu zD*)$c4TKSVP|e(T5GMnuUSs!6Glr}hudzb ztN@@6NcWN!vGQ*KAnLvc)6*%`Dxcy}4%7=@t(+aYVD6*3REmaMSee|Wyr1KaL14_Z5^sS-Hkh0dG}$M{k} zmPlgIWosvHKJD~*3yh*)c2x>^Utb)XNaxwNMLQQhBkis6ef;ck&BhQjmd_;a-byj* zW@GK)m$NXZReDR|GAioOa4)AYCMs3BUH08}eTfyS(EeK$I@{EG$AvbbR=}H|A^5ai z-N8NVj8?e^;&?ZcE-p=#)jXs$&71E4__IbjL^Qi9Vi_5FWF|ikCsI9P{vt zD!0`z%Q1^@)4etWi6QZ~>GhZ+YmQD&MuS6Z=*;0?ruxDhj%bKd(_CcJP2DlurZuccOIyFX_Inr z=Cu!1=1{LKxULUnP3JRL3A+#EFgT;IT|dv#qP?|0_Q)R?lC(rN5+cGjXI!_~VWj@3`EK#On5FX(Ld0&S0k|+Fu>!WGu9) zH4QaQH#a|j(VEz~d3@sku|-qVx_7L^0xQV#+Vx^#vX#l=K`^&eA-4VX-uZM8>)8aK z+(@XM_MRJ+A;I(KVs-fose4W8CMU}l+%8$_c5V~TidJ|&6nyl$t$UKuaFJWx?0h*I z|K&sOu8HH9OW&0v9=+Pz=)Ki5YDkp6ay5N(uv4_*pe^9}BK(WZSZQf-zGmv`Wb0juVgDQ8%ZzlbC3`g; zyR7skaYu{@{oo%ktc2Bx7_{6Howa~!a{F)-xEu6+UoUniTygyjdQoM4%gQd&G*jv*WmQg z&3DW-R>8V3>p-|?9k<$QK3+Jtp8cA9A&^GA=hsBD?jZpxl zSS-tLE-QG@;ME!=RItZ}Kdk6yW+`R-0!VZuaM3?oN~yp`O2{S_kW=WL_)Ai9xQz+z z@k4r}>koin65B1dQKvMK+`0_;J}LpcVGimR3fr9tp?tBvnJ2v=X%X^3pXj%_WjkqJ zLhbt64)+ZAfkVg>N*Sm9{(-CfVy5+BD0NDv?{nC|Ik%Ej1==IxFlp#iCsbS5!|8EB zu5E_zh4pF7(Q{Pfj8SWckM=NyOGyT)>~X?d^rn-JJrumpM^1Z=l={1*&*IAieM6ng zuqm+I46l-VliYC_j=XfOA597YnZc{}lm3aA+h}mk<2}D~-`6Xjl8PemIO_Kl zGiXwtmpg|np%T)0nZ6Ed-hF3w<$FCc79^5TZQJE>pe+m6{`je44uHR=s$_ymFkql*dVl|N=E!|_D6_dM~6B6G6biBJ2W-IZek@iG`6!XRZ~srF1|VmLHN5{ zKR;R4i|j4Vew`^TDSFw^v@wUC?JWTgNM~sV{03~(f{!`R<)1|TxA<vn(vLn*jT5!)GzJJ)SFf>Ul&Uy*p~F*n)MoYB|Ug3FhTo@_yhnjmM_Gv z%t$*S_o2@0kk3jun{@Vt8M#3sYS&BxMzs2K)}ZW7er92@`~9}M z1x9+*>VWZgvNvZ-vFGY$1vU>J+h>L@wBVzdZ4!otiC>)TY%N-twi9dwQOgaPIs#Ob zj;jCBE?B1$vrjt} zJvHL4wB6Frr`i}HegQts$_V-$#+*M0Q2_TI*?_I_7mtoXWW{|TvK2fsamRVN?(s+0 zY_cI%s=nTjEjy+=Z$E6v=ov+S&Oo#g__ebUB8x2NEiEnEv;x;0>o}=-S~8A_j#NW9 zFk}hgucnm^%(n|>vRg7sbeq&c>`Y56KE#ni7%l*k7=NVEbZNYc_j8ur{+Is*qN+ti zbJitr4I2D%geMUBV4jS?dD%UdUu4l3P z(B*ZJAHQ0sIoWMqFHvD)=^e;e4Ka;n;S6NUD~q>Mkf%NmPI0tM7HNX)^6z=q)!FUZ zt!}Or=er)ZSrZC%8h&>$#SBvS@i*lDgbC7U zVYf{nF*fkaW}aceUs7{Q&ZT3JbCRc08%*I^3%Y0J!Cd4w{zG`b<(-ff9(q>_$|U}A zCDp5fZj(vnJ`K7mVdhCe2qvWZL8mhWwHK{dBC-uazr)Y1TgpW+8%D*y+2aVS$fOJ zudF1$?MD(SnBMzMkgeUPa!yMAjJt_PtFKSE0CKFS&MavTf6fN+1!Kr$xv6!JFU59g z0mz>Uamx`#*8`j^X$5pVbAkoR(Dc@4;kX@Mi;6lO;R<)NYB z9#$aha4@+@*YBln>`EMO?ML|T@U<2;!_SCstF%$}%3Zhbg; zhJhy~jNy6@KNHM=TxF8eQ&ErbZ57ZD77Ko>>&Qlc?ST{>o*Vk;!n`Tr$-3MQHbvve zx71yDuL8rm7M*XX6y3eanE(!@i7YD`W4;kwpn^$^TXzpCvW7$~U5GXivOR{&r$W*d z9J3jdno8d7gui7`z)~QOw!GUkl_eQYPO%Kqll|{9cVe?4EBtm3W(=TX6yl+{9Mmo( zlc+l%I{QP|5@Fjnfd?_=lzb1(Egr`!@BVr*v(wnQjd^}D!u>{bOn^OxC!s;%tA{5$ zh69HDFpn_5?=%+<7am|=gA2H@Oy&;X9&Qfn_X}%$QF!Ajl-kooEu#pybQyJOibRw4Ub;(Q7~Jx76vljStep=3dZ~oh_eMPXZQdM zZJTTo9S5FDy0tOlwFc<`fK%>B640PeDnabLOJrjhOGr}C@8dmJ&G@ZBifu16!QM97 zLI;j{Mad?Kr6ppb-d=DJxdZm~JfUV4bR!l!ptBem#K(w!Dk>g2^5$2QC1R&~d|>+F zg8|aAZ~3A1(Y-A&g9k0pK}FnCpR^Fsc|<(A4oc01$qyWz!cT4 z63bnqtsILotfGgWu?t?tpB)rsv?aDczy>)h?2X2oj2o>g?yE?|F6TzyNiQU!StERp zkpn*g4+#cmwPPrTUx3K&S7(mOVmz<%Cr%epkjcjoN)3LdSrtc0IA*-bi4=hpf$l+0 z_3|sE@TcryieR^8Y%-Fnp{fT6)M&i0hY1X@fo&EEG2wP$eCz69St>0gic1k?BDxVq zMb|Qrro@Nwj^v@Q(rZ#TEQJ&EM$%jjSu&w0<`w|CVXbo1gg9c>O0B>K7x)5W8&)OD zQHE9jk7q2=??MaZ(-ADcTz{ODkA&e)#I6?zPGr-A-IrP3z0Y?v;&r`dBW%kx&f(Il z>l=S(Uo5v3Gp{kB6I*2to6WxHG`=()MjB|Cm_d}B!dm#Oqk8qu=mXi5q(jsguL3|m zjZs_4j_5zC5qxG3NibXM1%BV+{g^GX+;$E253)dg)B(YeRl2=b-Pf(ne{CsVDtbHx zm$AEqL-oRv&O6@L#Uj=_=kkvg zq5}CC0#TvE{=uH1S!QzC2?__QLE6~bVJg!ilEd6dkl=f5ayiUwBWE{K=UwD{m?Mi2 z`J9*>^MTM7QvAa2t|;Jq-ZL_mI9FRRYHsqkhz+jxN%bb2N|eeZ0-vTu7tTC^E3+(l zDcMhJT$SGaUugCMg>tn?V;@j%Q}&-E(@WsEg@&zxUhT@LmK z3Q*KCF5oazHJb;-x}j-qTp;Lci}(anMBMhA_-2G=M@lT{Y=rADUW&?2zZ`s zUqn=g0U18F7r|O0$j8k}T;@{Bo3ex8uxY#z#q?J?EckF{ETPF4qR;gvGax2YGgN_I zj0#jni3HmW|nE|QxFsf zD^MoB7J8&J*>a|^93=^vVc!8u2&J;(C9oH}>K~~4sZ6}*Sj^fT^3ct|(c9#-VA)uv zpTqqT8?L{Y*))V*R+vnEzv@&dN`8jTw>RFs`&-plHao#m-~4v9*^xo@se%|1S&Ml+ zdO7^oV^<2d*Xq?KM<#$g_ zPn=?KnTWK2t)wKio(-IRgYDGIh^GEdKU;5K_sRjKm9@zg$;sBwzPH6Y`@z%;6kwCtkeH#Q;ja#E(*|9FC8=eMZ>obVdl{aSg&TAQF(*Grqkl7`+C)*ldyf!qB=&T+uZHR_8i*n z!A!I7$&RJP)x})xo}b?>6NA+EI&YnV@m=2g{fJpzEZ_4WoN- zB=7XA;Y|&`_nmr!x$7w)D+R9;Gw#wXJ=R-n^%MX00pa8{9#9UMjwh7r-)Wk{jC(&f& z-*M8|T8mVzTd%W^Z-b5cijz0=wzogfik-m_)6P(X{OP=xixCaOmLxTE4gq3zsLjJ3 zVI$qbZ+MlY;w3qqzJCaMoH5axXvcLe5@|$@UbuA-Yg1nhFY@hzT70dtSY%?@jNcO| zo$j;)pr7iEwVsrr#0Z`_8F-a}%Fj-y^b3eq&ty?DghMM7PIcWneS3of;9He%^dmOJP`)@z?Nk3<OPTFE%$_|_McLc;ItG6GNNy=-8^>oruIR$*Is%3nJl7iBn^ zD;rba`$Po8!XaaxLkjTQ-%5FA*IDMrQfF`hx&@x6aM@SSg0PFmEvT3iv{5n&N{+}@ zILh#?9UnCpq7`j;vp02$6#LvHSW;tcC;FwXZZFUD6!{8#*!EU~=PD5|*<`>VNNu8k z=hXS*r=h5L%iYh!AKq{#$>UybxF!kifpCdY^eV;=p=$<7IG1V^6oTL?F%3mMfp2Oyb-odP2)yF=E`D}M|2DK zg*u-i9jvb4B)B%DQPh^hWg2uHIk!*S9iM z<@!B@qQLc+yLTK-q*F>P4L2=A@bkNwy>y0;LV`0hCpRFVq+d0_!hrFSEEX*8T!tA) zCZUxFa}IfdoKZKX#ls}4N!wRXCZ0SUHk=SA@hdu_&hy8#Hh8%i8@reHIOo#~Nl~@c zrcLsMe1pFdj{nNQg{x+=)wD%xSJ(f&Wbgkf;O>f6!bpBt{zZrU*E5-sceGS;K5WY81ECp48i>l0G;g|EBS}tQ|l;@Z5jj~JI)@EAUSbdBosk!11Pv}vpH&*gIrJk zQ%NRAhsNGF-9EGj&@NyF>Fz>aJ71Hh-j)M|y>h8`wa^LNC`HGs3~3*M9l85A%e@O& zi^*rqUc;vQ_5d@7vf#~23A8lDd*bUBip=oO)pk?$CJb$FREFwqZ!S#?$rFBa_zUu^rk)SWiITVhOfHv#1&{B&C0 zUsd_;N@D8u)JM)w=U72yeqx*)&MZ8x07fer8tA1ZdK^)EeRl2OoUz+rMVzB`P2TK$ zjG%r)>85P@J!x@KEq<)FR-y$Xi`yHQe-bGlgjH9996!7TN;0DG?yv3LB^c`#LTQCA zwDn<&MZ^Yb28hy);U54v>9YJ@HD&Uvjpf0|!y1JuWiMn+kx@2o@*mak)kW z6b9+mn~vtCSw+#wbVcNDLy_Fc#Mfw?4_)k0Ig^?IqWkJvhM)U5$h{*f6KvjvKUQ#8 zOL(+9GxbezeqO2FJXWI1agxmk>$uFIgZl?ij^`3qsMM)j^87(NGjDq+LDWU@-hY_P z0abStG$Oq)929hkApS7LO!c)Y!PxN70qIj?F;IIjD+--c2T7>;B9YWK7~OoT@r_H( zt!T7-9D{V4`yoKcbq#t;%8^30rX_prN?A>3g7lp|QywDjmyX5=1UVgU0gV3C1IiBd zzWs%ElecGtihY>`=4jAI0dGJUIe|khagHHFuUHNIF(Gsc*!Yn{^d8d-WlY<5#fNpu zQaD&36{ik{o@MM?u*h=4B{rjXS@f9e8+O9!_IvNem;vr0z3ecT(nOmYKyuZ1fjOoe zMIm9w3va=9j!Yxw>{0hjHg=96%O@0{_n%L$ublD*Q& zE_`QWY@|e-D-(b6xwO9bAwa)IwFfy40SV2u0YiUgRpM59h)A0|DNr+_;;8fN4pX=L zc%kIC4*(8zOyVKLSbo#BPP@e7!3SGknrBOj{B>2O2!Db5K-Wjy&d$ucpY*@%LQ>ZS zK*=&WaMgHOfanGrls*-ivaQs74!StnFsI-(n1``t(=itsJGNq$@+td_{fA*l%Ynw; zGu^%~R90<2BgsYn5$e9I^aCjUl2Y;QP2`T1w;3&bPg_e3S0;w@ueP!h0OT|Iyz)nb6Jotd5nh6X}68U0w~T8g0q?Q(=c-A>&AS=`k$ zP#8G9rj8#aT=E;je)|B`Va9a1jG-V|I1VxPDms|a>~mDvZ=m#N0*3`00saDR2A2UX zoEBbPU@wh-c`3Wbh;<&xQwqK#bgrd)yzsZkZ**>>JrB%cr#JoqX@h&L549E>l(*q1 z#fJiMaGeoG78rUTwLevC5b@#+NtE)emy#p)$eD(z4U|s_9$FT|A?fa za=$l}pX$?I2l(9X_&g)CPD&5Kn*j6Obzv}FYD{pzik?|y1WW~f!QzS!u)OOmdg+_T zUU-#AECiFGRc*6u*V#>$&4qMRZ9zUedcNs0zwg1iV{Gf6`vQP83xnF9q zDH7WFf#2lykhu9+lqdmdi9kv(SkQ=xL$K)_2gx<*=jYD6J?8h}j#wHbvx=jO_Z!Yl z9I8KU=@K##0LKYXV&&RUOVUIVo|NEQW5O0( z&^#>@-8|-9;Ec!}&va3BDasIQfrVK2MxEL#f^+04#pGlC;6h8YTgI>u?}AcLYw)9Q z?*aB|FgpNlV!~7m{3BQES-4ZHJ%MsGsVpgzi>^4vJ&YF=x6ayi%*#wwZ0x~|!2+-+ z;Br)RnAAF}cdJ@kkf6%hyj0*BK)o}{FWvV6((n{(@AY93aBKPT-efCnxJ7G~UNurh zC`UenIIm|8s1h7bSz&54pG~s+)+u+!^5)NUd`9875V7LXTLW_zn)7-Mp*(2$r zzKFfL#fX;}1e+3XICqeQJ&=2IKD|}7=_d-Z{wO8?<*b43l)w2TnxJP+QV{dIkl^ej zmCGnmdQA=pgRCE;Hx+l)E&fRxh8bFriec3VnnFGgz-~30dt{uQ)kQ?}W>G%q@_kYXUah7@)U0fb(qIyKMuB(WUV5&@j$dE*j>p2Ly?Ei9->MN5dNF zDs-Bx)$_&{C#YRPmf<|-n5njECz#2fL3$P6%#2?|;0fa$;3fiSrstWJwwA+|TPFkLiDm@A-ReRyZ;a$Ga**pe|#>MtrJr%s> zWKaet%ZG>LY!71)TKTmrO%@R$TjoQ*(vLzn`6jJ5F^*A3xHgGa#gVUCs1(4yAcEx( zZ~vlY9y-cZd0skANprTFrAd}m=iK-1STY@hgD~(UPRT=22yb7j;g}0bqF*0R9jRIwWnG~@r;Stpw;Ib z=kt+64Ee^tbBz&B*)QJ7R3CL*#T+S${pns}La) zbW?c8Gl?siWXr1OR#p~JZYcPBtD~UlB_1EUH&n9x9#CXZBJ|UjDitip{Ks3!iE#VA5ciT&j}D@1uBCa9KM1S%eekVlo80)ODC7%zxT zRB2l{^V%}9?PiOVK{B5&qyueC7;HdBu*y6BzAGNpnQggr9rWEK=hbmT0es10l*+1~ z{AcX*Fk5cjG82KE*C}$k(efe)D2KG<<{OBI!X)Q6PThK$6R8ScXIzcMZLo^WpkCj8=9WjXF$~VQp>={blS%m9+AHXU-oL zBf~|(1KgN=CXrWg^05{r|38;VOsG5M5g=H&E;IjPxgtIDtaAv5|y^2?=+QuZI zs~d%z!}xAezNX8c74SH4=tZE}>U73#K~^|dqb9h?_V-^hGzm1Lw9zt54$3*x{Wqc{ zW<)rtEuRW&DKMMLcecOH5WGfH9>$$L;{G%h?$mi7-nHkH?(=oWY3lDk&ki%zv)s0? zcVYQ0Et;K8hxT8cKd4&~Ru2l@kB2iZnyz#4XF7j|B8el?GDFzrp zk<|acMo@G>W{g(-v;DWnzux^%UQEEZ=w}W|!-X8z;SAl7Tkxxl?nF5P0jh!2@K-67 z%o#*I)sX~Q^t%82Rigq;GRiPYVFW*{&!&P&J!(bD`t{#MLd%`Rs)Z<<49l=xfUvny zBC@h1c5b5j=XpOtkdpzt*HHDk40L8Iv0S=vR1MTLa-H5XYb?WOTbGO)5OZcTQ)z54 z@Udwc@LV=px)y$0NyqA@yX4F^^fA1|5#{R?vjz-xj`K9tZ|xfqADB7oqWf$FhKNa0 zX2+bd`T&{UE@Xe=OO!EU5X5nG_+Ykrah4=RFphytS$J$^;D!m1PdKf^3k<5Fc&{Dg z0PfJnF5WS|Z8CRA?o$iLacLbHOaC8+QIykZwoX_K5SzB2JM@Aw)5aOQS?{|h7s(e4_J3-b+d;Dx} zcg(m>$u^xy(p5?y5okw1Xy$(^KL=|_<^;i8xYup8Kw=N1Ik#1 z?;7O`*v6m*r}FQ~gqMgN6Gw1&5Bj?p-RfqGP?p)^5^%Yi5&$8~&5?aA4Jx?~xd;G*!-3R^n zBj2Q{Y`8a`w4}tn<$#m)qf^ATH5- zkdX`5tj4Th-cA06V+UTH1v@L>85A-H(FO>e!syEYnQegDumDxymp$GYFMKfKSXu^L zxmN2&x|+Sd5o$j!av$^Uap5r_0xjbeWS@8PkCI((=rwy^y9EcGN~&r_cK?+Xo*_p! z$n$%8G$ZmNGFSR&p%+5Lb_Fmp5(m*djjjc-#*!&7kyhnF2HVfsl}Hx1n>9E|EO!=s z**mtBR$D;MX?M5()v-;*Q;ASXmgAc19W&e<90`9(1O*_PWySva#YjEWJ0hW+b-vF2 zxYHA`TrOM%0cJ6mup7x6%r*&dUX|nEt8DszK%g+Mh>#oydm@%~-@MK!HA4IZ(CPn50 zDVcs-PNvOQkDU6mpOciNf@>M;zH3&vp;$@zM0uegvfPv$RrU#%lukHSZ~H)rJa~I} z@p@7$$Z~vV9F1@6tn9Of6>d1{oplZX2lIi_i&1(d)Fh#`j_jbhNGV5;iO{t~sils9twn_|rIktryb7l*+2)0`BjycQgY;7BB_ddu&jTV(V>sh`_bxrtc~+1ybr~ycZQ_4?yD~MV_N0zxH|?!Y3g=5F z+3W$B5WBbBsvjkL*6Ylan9T3Yp%T4q-Tmbf5 zORvhQrnWRYEvnEx@#qh zN2G5*Z72qGLwLj zLg=1-$It3FbX}z|I>CDy%Ww_CP?TrW@wj8Y6qx1>m)=B|I}s^Vok%ErFqRlya$6>3 zn?VP6iPJ}_4}}0&X}V!9Prolj6^mrBDVB8{dYtZ-^-TirlJPkeop-UI`i6*o!J7q) z#pFK@#zut?F%Y^@oI8223dEhHzsu{i(?#xBc3`pmMowZ7VM{-e{Ax62k6ZzG)rVh< zr8sryMY(X8O56kKp{zS4eh&(M7fW>~nq_KR5g;#RXOwc57fs}m2xfRGzdf8x=bFq> z@Yo8N^ToglRf*ibk9i@8=JM@?ZI(9uJg(^Qe;Ba3JF_R>3`*@>P8+%}gZ$=dtbR}g z^0@|CeG>5<2RVMKEV2Tu#y{3WIw%4C9A}KgjG0488F6w&%azWyZ+AFOsFlfJ?yaJ? zae*SIB`4&@Wh>nR*^$G8S~Q+vLd+uzH!Jx5KKQg-gp*leR?W~-I`|M^mn>m z$+WNEUeCvrb3L1QD`m`peKFIWN5JM+kX5ZKXSHmMB3Y2~Z4z!^6@*FgLF?R7X+7nt5F+j~(E(>}Bon2G~i;?=z zmbCotb2i}?2R-2WAUhV6AI?;nLW+BOf^q?r6t6}1c&Qo#Ap_@U@B{B*BCqFkoxPzm z0Fr8|y#v@$0zCIg%~IJ;tg$=Jc8$CAC6{ULA&s{W$Ntuf7A=v0;^g}bm4(%!|BnVeCdiRZhn>tv!KkDOpFU5!-ZO3 zp2L_ZT%mZ-t2f3OoEEXwJtZ_rBE?3#-e&ApxPs$fX)uFuZuFWxs$L_e+ltCdLGP*f zeJ5g@iX=U0Z6)4QfN+F^Qn^?r!W8}EmAK>=7*vWEHysgOeuh-tpY}DmBrFx} zQ*f-xdQZNnF|FaWaiK2tS~!2KYkMe%_ZlRRp|YaK1luMEqihDv#0L_ZwcEfy8tD}M z7=L7~UqQIehSvkZr#`|_C!UG-1+!LHN`XxOm&L7Ta1jJ#pe5_2tovJ+Q8a}u- z&m>Iyv5)uq6^^H*oS#gSso-gZuXZvEV@l%1`Ec3z@o%giy1rxg`xDqAYd_UoX*dEVs0M0dbYc4^l8pAB_41 zas7plR(^ypS}&%8~;a}QrFI3T;}0Ou1`f0z7R?m1AhcHv>>pQOkOKDo-J}TrcO974Fw5F z5M;GF{zWM6A(~{LY|qC}s=-)jpgK#|(Hq#GgwnXtU^7XMZ_ zj)yXb8~%5l?NcbMK(NT^(UM$#zC3}|=~ z42Y)U#N+9OA5zjW`B9;?T+#|dA+l%DkYEBb#TPdr5g}_QbWa#Mmbu1q=@Iz=RAT&F zmtOuUPJwg&!jjLmzUND?FU?lbMPt+WJ)ff;R@^^&hkCvYO#fn+XKc~i!(gu5{vrUM zWq|g^WN?aM4?`SJWc-Akkruob*4V3nZWiQ^Yo1Je|GUxwjwlFum^I_`{YvibsQ((C zaenDK>5VBw^rX=DB<40)mdyBW7){|#=dYTVs7Xxj(2s+;0Cq!|Q5ouLT-IY-Y)vnC zDoskOH^(9e7tC8@FAkZld4+Tq!#&rJx@LK2ytNB0#oNH4Mt+Ab?hppQPAmoYkO*1~ z?kPjJ9bg!Y_h4d}LpTBlcVZ+RmuOw{Ts4lnkjxJV-mO;mL>7p5nuWsS<(<>#TJ&BM z8&W$GaNyz`eKF`bph`v`uT8o-pH$sNKfzv)T6;wrm~UZY68-88BNkN-^>}j=%3a(Q z)_9zmsgtyBVVhV&ABK=ft_+GTjv2b?*9uGqR=~!f-s_BHcFVj?kCXdx#hLpi~WD4dNa!et@cq4k~}hLe&c#U;}RLa=PL z5|l;VLN6!5#CSuY^B&nzh98qiVff`=S)Jc>@`aZpV57zaO91?k!ib6+#s=RdIzIc3 zz04)GI|0*}M-~M=i2=xPX(Q`U$#984T9e^VgJ>UjK#B1zHD-IbTVVR^Q8{Gx0c(E2 z2t>UBkxhTMmo~=8Qh((WV1I3U66Oiqxk=ZJx_YvGo&S-6= z7aXNd&^fP~rJKh50~_!a_%0LA0#rjSy;LtT-o#N-Tn0D=5Lx2bNCh1l%=uyT?m{t$ zjG%VGCPYim;^R5UY3}jmggl$8m602Ie&TJPC=*gB1RWGRfn{`Hb-WVm&?yv!A0qiX zZM*)pS#0T9r(?|ueR8_}us^5PfnZ!LGIygDhP~qX zU_0|cFSP>U&C8?Poas!>wAN2K+Gh$44pWcKwZlz-NG0;aN%t2{S%V?Tj8(C@#2R}j z4e@z>s6_|I<@uz(`BzJONcx4yaH_dPjp6Vs6)dobDKR~?29t527AKJUHp&L{V&X8h z6#s?l3>(5*41PH}^Qf*t%wVfz?Rv5H_A+HqF=;@!Bibv{?r3h?W|d&vP;KRO>VP)U z!ZD)MN==vvXSaYF*zh7QXJD4DG=UTffG*7%OoQACoDnmlqj1)8VGAeG^%eeP*PLWl&qa-A+5{>Fs4@(cqQpyPL9C0gs}{Hh!PU-3uNpPTuiKkq)SPvq}n?P}5>W4eM>qOR0LxEQ?-o5cfH^s3tD(*o9wONd7*@_f zi6>lBy4-tVHQ$Gk$zK+YZSyGdWT#I&6vor$0ppr!E=$#F9eB%}eHLS_ZeSeVk78~7 zliE1LOqE&3xmWP^qxs}Lab>;3ZqttY&NNOVaaR##+&Ssvs1EHgXL#;a5Jy1Oq#;8H zWzMcwXSLJnNkL9}L(*Hz)#FL~V2oZgBE>drYSy;6)me*$0g>Si0KbT1*@5#Os(r<@ z?AC1#N*3UTU33h)3_*|jl8y{|JqDr#hjeJCWW)+CrDi1zUy=BTEO^i11d{oXJ+Q3{ za^55oh{V!e4@dsQ;!t2r@}76v!|zlfs_-6?TzeDJsu;{EtM*rpkJEQ+?p@dFfHRO* z=+tY+$fq{ilPyM+dL5$?I2e# z`Ax7y$sn)v%udmw3C6&hXQY2lV4K9D!J*NqiJ^)fmMY^{a=upH9B>_9JByOs4c8HB zyA@GLKd?f?R{}~=t+AovArZ7>j9AJws+PRQwe6`rv6cr+7J~+z#tMC_bm88xiN!m;fZp+QBFPF<25!WH@z}O<*-YH z%Amy_oGTtY+`Ta`gw_-c#$#Q;VMTc3nkq)*OrPTuD3&Vt_jr?H1c!uj>ZMWB9`?o> zJ?t%B&R<%+3CViPbjM3YV%QfW=4!WL7Zo;$0GhQfG@;-D!b>CL zPfBM-KT}|oCsA??wR-zEIWyTg@m3aEqdGBo;lnMy$X04N{PX3|u>1E`PJ8dmP^-o- zAG{Bymst$Y_shUhpECbbPCexNe{yQWI>yU3k;m!gt4(XVuI7i!dGiiJ^acBYI{AgB zWZ4E=?g)!#J+1pfxwft^Ik-55h4E#6|BJ+xWkQiMwOba0+8OU(Yp*$f&i8ZNP=N^U zeVgx1&+E3I%v%jEe-U##L+6>k!j!UYnAc&%X__MGmQe#J)%mkv1x8nRV?0H!2L@B@ z%g|H!$o=h8iMyf}*pVs-hv1TK7aC?Hr(e{T{22cFcqfS}*e)1sj<;h$Q~_2u?(R~^ z0IZDC{AL=YQUME5oO^HxTt3wox_?peOi|bQ178fky}^flSoqnC+~I%x(=I?5%eG0m zp_Udk=roHRWs{oMcr+bzHH|&za~G6uD_~eo^g?q({x2edMi9EG8`Q~G8W;OP1c7{0 z-Y*M1LN@jU%a>>)s0QZ8K>(46Qo$+K8!E!T<0d}$HW(OVL$mhC^~NXl_2_7^l}Y$W zYRe28BQRpVAKDO}x35(#X5k$0{%}&gQuM4Y#`5hDcxoz-7Rx9fapdDkrIwxT;C4vj zQcP`-U!CS4+q~Bq$-JZAtqigm852~4Ym-Vw)fN6*&8FfhG4Bz(^ z*>_@PZPe+8Dh0>EQFEka2aDH|E6W`C9XzMlZnEcL0!FUraxFYBpW-24?u!;C&zAZC%C(H|%3 zt)Bpn^TRs!y->5!AP<(L+@EU8V!|DWW#!rSk@msHDA{>$&PLD{M_bJN10BkK;{~tQ z`B zi!82F5^Y!cfcV-3c0{HI0eQ-MV zhq*_OjAQC%IdMUEQz5-IqIKfBk7)N?A{zD4{pj3E8kfKn(WBG8zsaUTqiVIYaxkwS za{qbI;{_#gEbTN06OfVc*6yk7>Oy3Nv+ETrUA(JR@ILN>@u;(l>n%|4n2r78O1wdNBt_(@IlSb{eeP{HHPl85f(S zTVYLV!K#!g>B}%m!ynfhc(Qn$S>kC7B(_r`fH$cp0Qr@mlw4!dN;;k2B)N@tl4a6F zNM8mv*VJT-cc(0&FZEI(Dm=`aKr>&}SchoDl;5N_`ZHn9H#74gHx)C2CaDmyMU$(r z^b(i(>HO@E1hmayKIUed<#FHkh?AR;bL!Rn{Eu59FAO+_XqG!QJ3r2m9TqRw+A5t&5}65NHUQtX3;4Rh3EB--utC- z%4wvS^DWvgNnj0Y<9LVY}aFZP$lhp+bN6r+?(yb8X(k>^THN=yA_~ z>P6i4vEXmL9cE=eN+x0Fj7&{SHya*=l#5!wsXls{ZcwvWV=)yX6*J~&#iTA^!X5iK zVhAB2tb59?3QfnjP5SB^=9rM~Q~Nt+uLEcC50OaCwX!0G&ov{`$RI49*cR5sBT zKrEdS5v;H6Lwd@29%ZFFIfE7_u00qXQB((>2E@?l39^_HK$UHfw%uqLfs21O-;J6Z zy>=#shV&gyZ(=O!Y8d%vt*?=ow)~w3{z_PCCGTIRPJCJP!{+QT8hqJgX;U^^Tv-s_ zfv1KwjIo9#`u!`{CJFWySs8IaX@3g);M*hd+b%9FYGP*=&UW zhlO)f zY-GI!ChY^KxF5esD(@$H`s}-+V;-5UoRAcjtRcy=z0{yj91X88?Lizih#3)Ddi{YE zUp$cT$2_9Z4iOHK5jFWcy)h2MpBtVON$1hb;Y9t$ndHEkm(+QgdTh;%8Cdq+;ejf6b zDqOPv+Nb?C7S7sgqrL4?s3Jo|Dvt(-(Q_-ur(#wDfXL61e)f5FC7_=hUOvv-lbV~w zs`uxtZulSQIKpgxSB|S9jV=OLGWC>LyVe_XQ)RH*uIx5_+V!EGoy8~2 zA7(lR^Air16B~65O%_Xkh;{lFuD-qD^cu52CcSo3<)Rqp_2BUta9I~wx4Zj3c=R|4 zKzIVYQ1{Et>^Bn^qJ3vb&Y#tv&!uXw$7*->Fx}atD$d)aI8f4ii;Y2Qv8!YW+IhRk zd6#LKpYqkN)L=LkOXvegi7iQg{<_48TO)<>_(s*+Z7 z{NQZqW5dK#M%HYkv{FO4_eTbaa%-uNe{${(zSKFJWv#0SyY*EuzzFfDr3pnyE_9!= z+K&7?eC*~JJa|6#f?@XW+g3c=li|%zr=x-_Zk4g}lZ2IjT!abtT;{H&2Gs!BXr*lC ziVK~BXA!n?iDKB;V;KuT$ z?gx4zfB(v8>jK$IC;Ur*fLkrl9pQ4lGu|Z#fR&FfS^(xx#|^`hiwmIlYZMEBQFMKb z+jG0?2fBYeYylE7Y(K0VSjvYLsxC|v%lI&bVE=d749g+Kx?anlNTzLVgtZ?d8jP1P zi{)Xg=AEYi5*=Vjq`9^XU(9_;oBcj+P`o>(I703-jVg=hCo(SNZu{qti_OCLf=}n- zRvFelv}!&MfNbzvy-)v$bRiW5@vF1N^Qra@3tXTTAj-fJQCQN8w0l znOL4EDRGpZfjDk$f*5dbGr6bb|kdLkW3par}Ai-gciRmH-b&E#yMz_op zvl!RLmyPF8GtwCs@I9OYB`J5~p?tdFFhhRV@rAAh>TocR2(qG~{5zdcY|5hv+BrcI zlrSGrg?09~sO(f-qNlWa)Cz83mi9m_qpCW_YxVMOV`rCaR_J1NYpn;g)Ao+ zCrz`mVIxs~7#@Xe1rk90QXCP}yePqIBBD0a#d#(Syd|h$ANUfZ``GtdVEf%5hM=*> z0BJR!UdV1dghQWiDwDQzd{B)|N%-cYX5ERz0vLs+Y@S9*gFJGu`9%fU0!)?C4N1BD+wAk^)p=Ag>LH$=>jZtCSVu1AtyLRmWY#g zKo^sS)&Qr%78>x>S5;bGl^?owc0c?IeScrK0A=Ec37K5!hae-toeI!2!-RzP`#9O^ zF{5=QtY3vo1;0w(xB(`V7h<1@H-Oy^Z)qnYrl74DVo3CFQO7GJYJNSJsV~d_!S8*I zQX0TeEd`X@n)!B%k}zzq0a+&xWEO;{0$}2TJ973n0v`SEfF4>6UK1|@;19DTrX3KS zl?~YIXnbTD?F8i#N9%o=WE&V{t?7BlbfgzIr46yWqV0e=`=^S+ulat!)giT z@Xoe$rVq)H>D*g8i#2kZ=F}KVUu?pRSI-YDhOcy2OQgLHGWA%QPteoK7%b z1G)S(&3O?A6p0P!OM$!Q7_h$sHFCS&AwRb3Vd05)liq6J(kyErmF1G^YFl7;Ps6!r3>N|h)P%qz3%S2x& z^F72LfbVo;aG02MuZ&E-701&0?Kp8d;Yt5XHKq$#-5GVU4?@r^JBhN4vqEIfnM$(O zCc=IA5CzEL$RW|fNNx~t5oI~C2+@aOeaZ8PJg$%ZU_x#)Wo?H!CX&B4AVq;7PV!$_ zEAs_C{EDow3kW6zA`V#wht>ECTqbm=hr?qfawJ?kY7P*TR zSzO=x#!iq%5dZTq7W)#+ZKsV$cK{JBr~Wh?vU3Lx21p77F|9X^$(Es2j-DCK% z!@@e@S{c8!Q5it`x|6E3|K^z#OLxV-%lmw>Kj;%xOMDm&ei^*0`~$KFCZQRhYd^?W z%{vW^^WPRCnS8jKA7k&g4CxB`+Kt!Rsn@X*CA7ED;7q<4i30y1^zfKIHpY6>y zIxI%(Wx)?gWGQe_J)pt2X=ec*wQ|2W^sN;0F_F}xvBuY;3rji4t($LrMo*e@+?QL9 z7X;3ihP^nKa|MsRuJ0SRy~p_4mXGg!+nmE@#1}@j5WIr|no^s=Xv}hglt?HpfW0a2 z-nd6JVZPPJtJ0;*Xz?~K@02@$^mMixe!{NIMv*bZ;#)-xaj1gGE=n}m+FrqN26e_H zK_Xs&T?2%feD!d5jk2ZS1I|S3#gr$`1aV_|sLz~KIu_WFis!Z0R5hC7bY%byOJm28 zx8xO~*^sK;zpG`%UXm6|>yVzcQ5@vtIccAW<$;mgI}9pMZ}y$TM_%ol0+J_qKNFfe z*=}CWwn_uc#2la7S(~x3>yO8|J|ay#UiR^EBr=Ofubj=2FURUnP9k!TV(P#|0veHotui(Wr%x!NXNz8la^8IMSZi<(67Cb;}w+S z?W7db-W8Bc%H* zIxuLhhruA;1=YL@t2q{=nx2(4tWp3tln7XsK?%jdza`+};^M-1)q}B{H2U9Q*$}DV z-gxNF1lL!_t(O}IGnSe4)cp{8#9+BpVqsnA*YX++E@@A<%t z5d_kN#?#s$G^56lARW&BWYB#G`ZMcgvAqB7an(J0TgLoR1h%Tb%WTAhl_LZ_e2{PH zTV43&Jo~-P>(@8SeJ|lFBV^-4=hmKI-XP4OmbB8(M9$Hk1IW3GUh|jgKavz_BDsQJ z5``pkI~frcf~=eO4qmX~uH+re%xEw$ioo2`wlZ=H1CK+9R-R{zKOw?W_QN!y#liSyFW;l5ry^}tz02ltX~P>@df z{^P_al=NALj#LdD6(4q!?(GNt>bFo~PaAO0W8YkscV1MB2DD`$ooDKR8{A6E!JpboUCxU@RsFG?^_`)q|o;beYiv2?T3-y z(_T}Pg3;cQ76@t>CToZ*8}$;h8QAE(NPRJA^hcbj&*`Y!2l|3l-0kW#Oc7ojou-wI zK3RZ;QmGZLxTNGk!?A}MJ7u5hzEF;u1?}oa{#ymBrBK$_ZzDExR40LzHof+Q?Q*i= zXsM%6?<6FN00+cAt@9Q+rigt;Kf_<2K7>1#C~?aHkT3{=7Fi`-??xLAKjTgfCl)%@ zV-owT@>n9nVCOP#SS&vP*A@SY4LlGC#gheDp&ZTG0T31E$)%t@1Cv zby@0Ydf_(<7;7t?3Zk3N7SgL{*|t!fkxj~Gz-y>oulu(WFxljM(@&@>18huMEY>lf zLXV64Q@pltGkXB9UvRzKV8H^6qJKJPI?M)+5PSUM?!%#tZrF56V`mfS)hCkBwaY&P zh3Wzch)k^;V}Rhw@tVs6{rnEFqvjoGtI$etuyMu`l#X-uKAiKOaUeYn`K= zq~CT2jni-DD_I98El2%WYR!mQCa-wDgckQTK7hOEZwG*`INuUo?GwO6a+?%9Z-eKt ztXZej>l_+Cki0^)=0^zB=g-vwSBFG%ZC38R*IS&e-O@Hnwzdc%C`~Y##i%8VK;GZB+&U&s>wTcWCgb{Cw ze+%(=oB;{$EQV^is)(b_LBKf`Q7VY&LCZgZO)47xFi6Wn>tmKDOu2XM{^s0RkI$?9 zT{yU!1Baq79UYsLxn%l*KGfy5!-d<|Ua*PZ^{toldgd&;wIL{#fvt;LD|mXms&KY@ zSki5!0!6%$lDo-?$noI5xnbdmI1Y=%)!T-+y=x_Lq+coMTRXfpOvfz z|IVnp>_?tgf-ENpoy}0S;kSQLR%t0Z+j}X>(*0taD)e&@k0=T{e7LiMsoFImDu3x4 zH8WSdhDpO?s>XyW()eV_gqGmAv24Jq7puAq$~hS4vpheNEn>U;EbSFGI!JrGjbkgZ zsID4axS(OEwBdbjH*8^6gG44?e7J}cOeU%kZ^JaQ`V&Yawcng_)Lh!vldkE`XjEY5 z(&lD2^z9|9?o8RY6`%LpeNjnT$9?Qr$#o~od5hv4~ zo)+Fk{Go!8Uhk$e=vhjpxW26bBhs6{tCr zDSO|wV+AVna+fIjx`;j|^sU`H_a+O{S4wy(TCq(u*jI3l*e0o6^xy|BBp(zQoI&5` zWd5q@hkai*r#@hm_dMacwzcbQ{Mwa#6YDJqLwcWJmzuQ@ERoO`ENgdk9B-Eyww!jq4`6|Jr09QB>;EPZ17LmleeLa=H=-~P9z4DsLW z$Ia#D zx-I&;A0yJLxx!!wC` zeBo8AdaPwy+#e!XToWc}WK1m~uRk+W@ zK;@6pT>Q7728!w9tIfMr-E7{=Ytu?xKp@ma2)4_nRqt&< zccc(!ujIJoPnHqV3aA=w7=rvj+<$xOt3~!L2WOjn@><=n>Z4IY*S!DBhRDh*CMt_bt6J7Zdw;mFW1u|EplS?-jA&tj=dBbYCpmpQKDu( zDN|I^A5A04wg+-Msn{@utKdJXU{hc%MJ!?8Zq3{Obp1XZqS@f-Q}^igy2*Rn>1ra* zV9@uh%Z&h1LF?M17W@{+UhfaTLJGs;HkPqwa9q2B z&6&;GSYttIauloV;wajnxNYp(RiSpgZE7umjH}0I&vmzGbG5)Z=87N2qco}z>ONoL z+c>KWFTiYh62ybGYPO!0ZJXLC_t%^1{wqs$BgcMkJDBM6rmvBZW{r+hs6tt#BhZ0`79n)>Ub$}qXueG4+cL<pjsvK1`_7*X! z#TD^1@L+{(ZVp>VDfn z2xwsEhJ!<3k(Crvx8Ig)`ysQL6C_Orw=c!0L*`BHDn4*Ntv+>W22fR~ql;O6)Q>8P zT8n!>z8X2jCm3SNo+kMju_t8%PMh=MU_LwuF@^Q^bei1<}zRhM?($7 zl2H}`B#k1cwu5)7oWU>Dk8`v0)jPU+Q+B9oY?!SkLmlPfJ z!KE?#j}e}SD-7^Yz8fcE`1St3hoQrXcghWxA^yjd|NWWmmQ+-mzFfVs<@o>aM4pF{ zMJifgpni}1-=F#aKlK0xr^1h{|2r9RqaB?1P2Zg`8O;9~e*_%ww2Z;9`9H@}A`X~+ zJ|)dtmH(bSmjv)-IkS@G|NCVOA>i1A`G!x5{`Wk8V*rP8#Nj>bf4>a50C{6)T3VTU TQzjR{0e`YmN|HasjROB4=fH4r diff --git a/docs/_static/img/adj-graph.png b/docs/_static/img/adj-graph.png index da9f36447792cd70f17650879c480c45c008d8f0..13a05fcc2e4fd5d545903e30780e7bdfc83453c8 100644 GIT binary patch literal 7710 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 X4K)u?rRbxS00000NkvXXu0mjfvC&h; literal 15744 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 f|MyPu6~RaTY_q##7tL@R8Vw<A5_p diff --git a/docs/_static/img/logo-name-dark.svg b/docs/_static/img/logo-name-dark.svg index 039eb7e25..cdf5227c7 100644 --- a/docs/_static/img/logo-name-dark.svg +++ b/docs/_static/img/logo-name-dark.svg @@ -1,6 +1,4 @@ - - - - - - - - - - - - 4M#>U172ne>ew)*<|V`F16F)`54(Ek4Z_V)JY=jVQY zes6DY5)u*(4Gp8CqyLqaZEbB?Sy@q0QQ_g?xw*OZ_4V@d^8fAa;^N}f)z!(#$%%=H zfq{WFH8m?MD<&o;9UUF$=;+(q+yBna|Cg8ld3pbKc5-rZR8&;|PEH~sA|N0j@bK`> z&CO|PXA{-rnB3ySq6#IRym;`T6;;udk-2reDk%YZ*N#cMEU3E|F^fumX`f=bX`kJ%RfIuFferh0F|ptJpcd)f=NU{ zRA}Dp)rnUUK^zD0@0ZXToo&u!*B-7H%G>j#tcM!9OX;4F0gB1vuw|rlm61BX@wmivxtCs0~)Ipy&T~3 zbb%tf&Xqo+D~jFBno%)%S^?+jsFpP}Pg^vzeQUo87U{``W~$0N;tBv8l{*;8W_ALoGp*lN0Wu<8lNA7l1E=MV zyb4W$emGJ&2~zF~G;xmw*D1E6+haltj_tZp*pe{Ca{x~1`72_tr}vXvp&71PC18tT z{UJ3lQc|DM<2(R`HNfJD0qF4IPkynxya!FTbrTERgBCXez)mlKDtQ{ZbuW1z0r9SG zD0!InQOV^x(BPVg@c^TR#WdVt7l4s%pec6jG;8z3bG01!?<)gX5P1s>0bcIvk*m=~EYsvLM}L;QGCDbH0B*6fwQ5UZBq^qUtJdTh0IPBuu!;qiM0_+E!H?2%3BbmK zdH_;CAwlv`9HEq3!V<84dk}R=tX)Btx5NU=Kt@kqph3?c9GvXgugQ(ylczZiD1}nD z9g;AbQ4Ga0vj9w-7oAxPXQK&7MmfCiWhNd%nXUzZ9kEc4Y#Z+77!9I7i`~{Hbg_r% z@h(DSKG;;-K#by(HTw1AYXXW41Af+_8B}*E_Pr_ML>RHV6emVWN6Gjpmn}y*uhhv@ z%||fWyefrckQ<+wD!{Yr56Cs{&rKMFEQ&Jdhgsd zoV~Vzv+E7R8~uKQp%RcYjMXebyHcJV1 za9qd`jw*d)6T{}&#&Ox3^5LiqoWig#?b>Tk+E5$@@aLf?wxyQa1_3Wbfg$)tQf`K! zGA=T~Ihjm1jYi$R|7X}ZRc2i#7^{<{zZZw(pC{y@93Y(3;v#0jU(Ne0;#sUjHsbyL z?)<5W{BAW8wkLUez8I-y!gpF_s+E@iNO@FqKP$#krJIM_)D80dbB(NO(YIvLkQ1L= zJEBIe8MraWV)}^8;!({bJY5jv9$cpg>Kgo{7$87?lM|mkZz4sWz!soY0!+pq*L;s= z;W$7h;kqbe0EWx}=rJZIzVX~-3sQ28bpRjjZ;I6b?h9%oF)ql*Fl>i{2L@2%Cph#| zDxT^sS7pPxeV8RDzVUp4bCABUF{)SNJ^)2G0e{bo;SYm%ox@h9e3~LPXFfvBh33BT zAN8HP&E=Z7ZT^#K08Q5Ln_7w8p1X`Gb0ZlxzR4f>#eVKVv{1dUYN7 zA2nw1WV+ml?{4<_rJMxDYe8N!85lsd1ecQSAhI<8d2S#aeYf&Z^A&O*Sm#y9nQya> zr&=UiKuKpBFtR+7li2NgXfX~cLTfv>Q)T?15i&#qfS;|D6%XN|<^yu;YswPW_wsRm zz!M$oB|m4Rc5*cF+bbF*yBJw7vY1u|6!RgJ+vTv1Hk(+^@}r8WIPwLS;Ibut!4$%Wuqk;= z$C3Z4Z^CUEu49e7#Er7!|phJe+LP zpI{y{XotxGPcegXCQ72$?7hA_%_hk64bWvy!))r$=siy!kH_Qjcsw4@>-P&J2n~xz S5!^@s0000J*Z$Dmjeszu)C@y+4JF+jLxaQ+!hodI&|T80gfs$DN`o|rC?yDjNJy8! zH=g(W&U>!k_uuzi*M9ced);fTz3*MmvtxC%REY5D@c{q;k(w%050!VIl0Ggr>fP^M z*$x1psktaB>ZmCyGV6GII=Z+y003O6b~ZNTYP?({FqnkiJt0hBzHZ_lsjUw3|5-N7b|bpHcHvs%H7ccX z#udiH-YQ0?dXKh|u=%`{92oz=7dG4VX;?Hu`_=W z?=5cP5|l23z9*x7T!mj4Fd8UyLsB#q_jto>Z3&qhZ11)zfr`BRf>h}=BTL&;6}-~0JInv047R8 zLnV4t0st`5q5(LloE(*)#pwTNJBl&>k@f!o<@FWS)KIy;owtL7hmW(T@3^WXFUr+N z7XuSt6HN^XJ5P6hn7ya113$tY{>KC$g^)mr?hd{%W`w(&hmQn88u%AN0ww>c1_7D> zg7`j>2AXKP6vd`ej0-5;`sj2RBowi#v)QR16t0 zL8-ss|4Z@Tfd4Wy`LCgXnDDAAeX%Xccny$0N8=FHu>as8_8Gs)X@>E9Fc5`eYrtl|UBp zDG!}!c=NF5rtaCze%nvYY=gUu?bA7Jf1diTro52rA1iC2_XUC0Gyfiy>XD5YRI|BM)I($`PpIj#j@a( z)EwNQMi}dS(T+rPn8ByLBFl{1c=qGahfKB1aLF0*>V&0|(h2E{<%4)o54*wm)P^@@T~)9$9?+wP5af6@0PsX-Z_tEo38>^ISnEbP*PF zmFxIIjRsU8>3`m~>>Z!2a6_RjrQ5FtJ6&P)UoN@ox!$d@+Jwul_|84DqP09~Tk*?V z^PSVYEl=0lB@y2w4ZXj;xM^K5`w;)Cc>T?a-%|D1?WE-4<%G!6xc~0_D5zyx;VxB$ zX~vf`*PdL{KV4Jgs8m|5LK@Zl8<)!5A$894DVdvEYo7_>+m<=4nzNR$n1>OyMBGd7QsFAdi zDDFKTY^YO>`2fv@d!JKrbi zWs=~eSefko?~`C7DVTllwPmwN&Te?9)}pyOrl*@F3P<1ka+*Mqk| z>)3w0EDU^nCSUvbQHr))#b2=?_IS}@?p@v04K`5Mz7@s_n01s#t{Ynb9s*Lkk> z#AW5mNv1}nexA}6-^v&(j+ar~-z z{pN-2#j=m|CC$Yta)_qw-D8J ze19>Hn3BH8C*~*@{%D|oMP+0nFDbg;c7J#Cgvo-acp~3t@`tgR3%g_&ap8DW-6pd9*-vhywfb9aj!e@OW-unoij0@g4WSMeAeK={DQGVbO0%5N#eT`aNakAeM1j(h!9yr)>2s98&d2gyJ z{>YrkZ$MGiDI=))9@RmiCE|yc{FK3jQAJ`sb(mq7B-8 z``u3s;D_t9N{Tj^SfDQ@qy=CQM&kQo`3Rv}0dWLb3FR;^cWDf^1C&VRqxaEH{^o~0 z%4mlM^r=_w%)pY3om!UDgB5cpSqY8^d*Nxv+~1XX9^R-`l1o7*HztjJ&~xL#SvG9K zExPHE+f<;@t!6U|P{=i=H{CL(TVbeH!f+vtu>k4!mUvsH#y-m1=`KikT-Dy^e9b#v zY0UDf^JwUS<;B5@WsyuU<#5vWbctdC65ZoRMYd7?Et!!rA7|oAE;`0DZq_bI6j^6h z%1Q)IBc}-l*UVt(Jbq#Fm6FlXInIW zDn5&3j!@X`?ry$rMtx?wEczg*8V5%StGSL_g5)#eoy5rY^BKAa-;;cW-^AlL><|V04tghyHQBM%zf&Ec}sFH<`GlA2Ed#tH>PPu`90I z+mv(ELZB@*{Ep*U=CJF4MPh6n+*-*anPV4a)y>7>AyddDtbkpq(hvA8D}I3^-=#mtbm_rYj9s^P;~Gn)0jX${u{kx( zG|i-fPUgkCUj(8o{8yezMAdemf2o3uJcsfyzX+qWGCGgTR?>g|(pHYEdZce^)RrrX zHNn~5K$lHUY;`yE$k9$1Su2W zp+`@!g}r|;7Y#G()As~4&K56sFdVxOjSV)75h7ToiGOKxg^cjlSF7)En+fgjVBiq@ z?&*RTTk)#t?qd6as*v+0`LxIAPe~9)b1cP{Xdp(Q{0G$veM)Xo3?UNKncN$#q;Cgy zo#(RroUYui({zz(@!IWGuLhxQi3+0$0}DNEzVED>Su{LOnUFO!Bm#$I0gK6&WETp5 z#WuqY;Kh}_+N9`K*+=>@TXgNle z<08{1M&ElX73VVK`~YLVW**Bu3vJf|UV?xf?wRp3nQ?EFq~gghFvO`ax`xe$H&~Dr znY5I`NxR=-Rb9v7rVvaA%;k(|Q{uO-$>T7V*LWCcEPUP3L!J5vzE`|245&G!UZfft znGP;h)7=Up3RAOZz`w>x3if~2_a10V?zgbX_OZ6fzv>DrEV#@FKb=|Dq0UWBD|ezXp%iU&ID2OlvB(~Zl&bjDMqxxGZ~*WVo~b+4od zL4r!9dhDSK;5Yp8-{d7tI_yghw8hpj?}r|Emd{sw6?fyv^Np=e5o>B#AdbMFnw4uK z?w)R2VnP=x(W=y{2x`&pKUAVqGR@33-$-a z&!wQ9#BdVBDgyNTq-e zvSu61fyGZtdaQBrl#=)DBb19mv!8w5nLbmQ;P6hd-FAXk%P zPY)S8BlqTk)Oh;YJs#IiKfqd!1}m}3zhUmt(fEn^J2!?Il$lTO0*#g#dB0AVtdcNX z9#RBuSd~(_Y;S{ZE-o~>J?{=f@8;_CuZ*EJ)3Yb_rOi&|wEU%mZFAb64z@IBI2Q@P zX+t#^&LKI%TdMM=-bhzNr@x%~Hsqd!zi!&5$H`*>R^8E|O5HR+T|Cbc|?gt%Vo zmMyD!OElEy_sbQT9R$c7t{y1kozzC&I&P}AA!}DVN$BV6Q0`-Vz>o;2s(zSKFVZ-0 zOn-r?Dm!5Zc(5bj_8G3;U9(e?sg-gY_znP4n9aE$`aM4RjR}asPeX4v-`QoyMROR5 zUh5PIJ98seA#;nN%q0$MJ%L?&*qPTE<#skh2iN%Py`5W6T%(YeUtX6&I z#IdI64MYjElz_lb2wZahl3v1qv(7+BWnPx_dc}J21|sWHG9HbqPL2w{+5gOxtV4%2P^+UYYvn!4uC=GY6F(nWg5SSsGB;AC zIv7w*IfSz6G94i1PF>aoE4k>}b6ZBSWVh6d#HYZ)@Myv2zo!f;Y9U znvqW&^}J{Xv?3#vh_TTX*l%NR%b1!D7hap&HiZ4et&IUYZfRh|?BONfU=tRH&-#v= zv{5GK;V~Si$PkC9;$S2`Ccd>1lUt=VX9(C#ja{RfefO@EDQpSvco@-P_HHps2=4P9 z?Gd46f(V}}nqi)G_r}Mwu&j~kF$5|76EZ>nemw>T+1j^*0J9(cxp2GF=}@(tBmr?U zg)Ulg1n)kYlu7QEc2!jlHtrpGaKq-4+Xg#ti-rJ2_v6}~h)q{Na{`W-)DnTG@0-y> zGzW^!y{1jw1fCeJ267mPdMP1mu;1GPE20NzU&lS7ca8}q8K4wmM^ZX&Cdk+4SXZTA z{`#6JglzT|3ctTo=t|ghecHz(Andadr|~h-R+~;)ZRHycrus9&NUy$R_EfZ8Q7EmT zw}_N+f@kiX;u>WAM(U!E!L@Zt7}Kk&GWn8@($i#}r#qW&DE8{B2||$>7`I;~V>=TW zE)t>#|IFK5a2+-94DHUQ8V#y7h9rZ;yxzq>+k6W$-WWak*7x zBERTzG;;UC3`k1SeBp0NGOBl=1G?5*h-h+xE3oMqOGLbrlocIVuyMprgsgFRn#!_D zHr@jkX@F3M!|WLY28)@`l486CHE2hu3nB%z&AOZxY$+?HbA-cP$EHdRmlr|@UG&~QLvKGuc>17UE(=MB^r|rqy72e^Il0qO;U|_*E>IYqq2ulou@MV?$ zDoBh}B|ps!GD;;n4HnN67lV!w3~hqpxJWLf*+wh(77e@hRqR^5wd~pUb6QhRuJNSp zcINUcc@h=t{NKn2_!D*WG{Ey1M5k>eje530>VWvGIt(32Z*8aIviBNi06TB8LA}p; z&74VUkvc9{N2gJ}&;^5yG&YS=kBg^H-qdn{&P*2CLS2@~g8Yk@Fx{dWsW`_}(Fz;OkeN zQd-BlGRnVZ$qIEz!$!$)20C;44Vf+jFSQ$W^C1G>f&iqC{%e{iG(kqul}-U4JOyp6 zW)hAQC}=D6o`xHUkMRV%k<{(!JQq|6U0W*612GizSUHZYEpliE&w;LN{N%h`2geF) zv0s%w)f3uPixPaOB+y`QPWRi>lTD@OpQ6&nY-*naX>P`<@CO{k8fN&R!&&Gs1U{`U$6MdraEgP z`qRu&C4&*7z30HCjkYd>+f2zudX=vPw9dxU_00%7V`_JdCxG-hFQ>#MEaKAjPueoq zhTrt&MLN2+hNmQT;#XE*d@R=uG%xgq7eaBtS=*naToU3N&L^0m6i3>1roV_7#$49` z8>|N3ZF5Nsy;5pZSv;?X9qX`VMa2*AYR7N$SxpBKvnA%RZhCqwi{<8Gc{q}-L$0>8CL?QJB-sH_*N079(-|6*=oDU9y(~@m z+FDqShL8cuUU@6je7z{v7zc~>3fTsD_&353^XR+2lLvx zU8LBR9;?Ayua;e27M#WpziIZ1L!+qs?3tM^PnzE;5B2YE`MRfay-U z92*3RC~%a^m`N%xK9pmsRAYc98U-ep%V-3eqP{H(m2#0FLKK*$@{yfV6BlW&R6K;t snid5HY3L8d+3TWWP&)v7z?7G=UilM}F1iE5e{R{;l(e9A3O3LG2U8L5PXGV_ diff --git a/docs/_static/img/plus-times-semiring.png b/docs/_static/img/plus-times-semiring.png index 5cea4301f65772be4ee95e0bedf40b63f4d7e8f7..bb2f527e8375dcefe5dc186c805195101d4d4d45 100644 GIT binary patch literal 2472 zcmV;Z30L-sP)U2+9>HqN3Z|+r7QL zsi~=^rlwn4TR1p4F)=X;3JTxf-~Z3getv#xYHCbOOh7kS_!H0*3RaI60 zP*DF!NJvOXJUl!a8XC;Z%(=O_m6er@jEr=2bZu>I78Vx!`}^(f?f=);($dm>D}Gk$;ru*l9G3KcW`iUSy@?7P*9JLk1Q-KB_$>D^72GPL^d`y z*c=?Pva<2x2TVbd$g}dnR4VI(Kef;8M z9RJUv-0>=rl8)two`q-b-?riZ*;vOd!npTd(S(~h_HZxhK^qWOU#GLUtA6s6*21N0`e~?b|7BdDUmB7XoH-XruQi@g-dT?4+D3@q|&*csj zXY&TR9CrchLBbVC7&z@Hnba$V$Nhp!q1%8ZeM~cIPZU>BsXB`zdH{c%JFyG0go$9) zRn8A00|#!RZ;`o(*(0Y>rU5&t0onyqu;*Jyk1@kRkHgX0?TVQNlkC=w6NTBj;SDGN zUYu(vFfo(2!xIesK)S2K&U3xyV*ZKma>&G%Ps^}`P{czsPRmSOXBswNT2xW5^5US` zs!{`-bO0`jl5XVX6II+U323|m435MKD{-K#gyA**vitXxOCS_D*8x>=izD}d65CE^ zkkqDmVsQ;SPMCE%oec(IVn-HN2H=zDL7IUu6$4f)(DMK|7o^&4O6l~CgO?(umr>nk9rpX)atPnR}Dz>dEqNoQ0G3R-`1jhQxylIue3_f z+0K`6iwzd#^vr;h5x_6|Bq;j1Caz@0j4j$>!3jIE=f(i`xd9+5j#b%hh3IUaHwE28 zi-QSW6z7FWR-wr%wq;{F#aoS^RWznmwAm7$dZn1TfZMp)R$)Fi16oxiAF|RacF15e zG6XtVb$(mKb~mkA`T>iZK0rUG13*RGaKyNyHZGfH^K2a;lLNAhM_ctu6E)5T6}_;~UEB#@s<@etJtdjQ^npy0`K%YV1e0kyyJ?e)XNRwv znB^z8{5|G9F~7UZYkP2#Q|SlKC+9JEd-?8#--_8h2S=H>XpBu#aamAO$ZMmmka2yG zBy;`?lAA#>Fa**H+1NiPlXW9O9;e}=l!)RcZ8~%V!e`*o%Sk-&s*hfpCg-Wb+XrH7 zHd1}@x*+toPchAVgbB-z*9*z0h43#jopC9hNs1*}$a-8=0qN_5N6()B5$`^}{`4ch zh`;Y153vN+vrP#5bYQVlp5cdwj~_q%Bc8wh@c#9W_$J2g9$1DV{SYFJODvY98NbSS zu+&%zACoZ+N0Dj`3&r-xZXNeoq@pmM8*5msX_~n2Pd$3rinX=1wY7U~ys^j$R)?F5 zM6o*FaH43MXRohV6?j4NI)vW@SF8#>PVxnQ6Uwhv6-XsXn(>>?id7-EM&5*Z2dh?v z+!{F*b98Ohe*6nvlia|nJ4uo(V%6D5Htzcq;q8Vbvn&7D81j%DU@3OKw`*s+X#-&t zfX}fkh%7L!Lop7RG!)Dt!je>ikg`Qh12j+)l2m>F7il}fX<00Cfw5fi-T2DVSo6<6 z<6~E*y%YH2n?+SJ z!}fVDnvmhDo5MenESDc+I{cxNoU2%sp>dfY=WuZYl%_BvSTJc^NRofsXm3+ZrNp8y zvWLwEb6c4|-Wwe(T+kSOjLcYpKTeBe8q1!a7!}F8sP#tM#0s-3U0DX7a#-k);tOJH zwJ_V*j~RywmgQLkp!F%zgmY%0)RH#-_3n<#vVs~DoWEf#w7>!L|r!0&Wq|1l%H^2{gsk2RJx5I5;>s@WU@q!3cIbjYZP{0000y literal 7306 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 BaxMS> diff --git a/docs/_static/img/repr-matrix.png b/docs/_static/img/repr-matrix.png index 39c9a42d53082a02446e8b6cac7d93e518d31b2d..34f766c9ed07e3ca073f95ffb9a696c81c25f7e1 100644 GIT binary patch literal 3858 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 literal 4573 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 T%<`VX00000NkvXXu0mjf&+omz literal 9254 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 Q01i$;Mpe2>(lq4%0B{d&+W-In diff --git a/docs/_static/img/sssp-result.png b/docs/_static/img/sssp-result.png index 18a5e1345b9cc11b106bf56252c83518097b8996..6b9bd1604507968253fd7b32cd493226bc6d86fa 100644 GIT binary patch literal 4558 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 Date: Sun, 16 Apr 2023 11:20:59 -0500 Subject: [PATCH 47/48] mark a couple more lines as flaky coverage --- graphblas/binary/numpy.py | 2 +- graphblas/core/recorder.py | 4 ++-- graphblas/core/ss/matrix.py | 2 +- graphblas/core/vector.py | 2 +- graphblas/io.py | 2 +- graphblas/monoid/numpy.py | 2 +- graphblas/semiring/numpy.py | 2 +- graphblas/tests/conftest.py | 2 +- graphblas/tests/test_formatting.py | 5 ++--- graphblas/tests/test_numpyops.py | 2 +- graphblas/unary/numpy.py | 2 +- 11 files changed, 13 insertions(+), 14 deletions(-) diff --git a/graphblas/binary/numpy.py b/graphblas/binary/numpy.py index 4ab582004..7c03977e4 100644 --- a/graphblas/binary/numpy.py +++ b/graphblas/binary/numpy.py @@ -133,7 +133,7 @@ def __dir__(): if not _supports_udfs and not _config["mapnumpy"]: # float_power is special: it's constructed from builtin operators - return globals().keys() | {"float_power"} + return globals().keys() | {"float_power"} # FLAKY COVERAGE attrs = _delayed.keys() | _binary_names if not _supports_udfs: attrs &= _numpy_to_graphblas.keys() diff --git a/graphblas/core/recorder.py b/graphblas/core/recorder.py index ce79c85ff..2268c31eb 100644 --- a/graphblas/core/recorder.py +++ b/graphblas/core/recorder.py @@ -137,10 +137,10 @@ def _repr_base_(self): tail = "\n\n\n" return "\n".join(head), tail - def _repr_html_(self): # pragma: no cover + def _repr_html_(self): try: from IPython.display import Code - except ImportError as exc: + except ImportError as exc: # pragma: no cover (import) raise NotImplementedError from exc lines = self._get_repr_lines() code = Code("\n".join(lines), language="C") diff --git a/graphblas/core/ss/matrix.py b/graphblas/core/ss/matrix.py index 649cb5f3b..cac0296c7 100644 --- a/graphblas/core/ss/matrix.py +++ b/graphblas/core/ss/matrix.py @@ -896,7 +896,7 @@ def _export(self, format=None, *, sort=False, give_ownership=False, raw=False, m col_indices = claim_buffer(ffi, Aj[0], Aj_size[0] // index_dtype.itemsize, index_dtype) values = claim_buffer(ffi, Ax[0], Ax_size[0] // dtype.itemsize, dtype) if not raw: - if indptr.size > nrows + 1: # pragma: no branch (suitesparse) + if indptr.size > nrows + 1: # pragma: no cover (suitesparse) indptr = indptr[: nrows + 1] if col_indices.size > nvals: col_indices = col_indices[:nvals] diff --git a/graphblas/core/vector.py b/graphblas/core/vector.py index 542bd440a..57851420d 100644 --- a/graphblas/core/vector.py +++ b/graphblas/core/vector.py @@ -1860,7 +1860,7 @@ def _prep_for_assign(self, resolved_indexes, value, mask, is_submask, replace, o shape = values.shape try: vals = Vector.from_dense(values, dtype=dtype) - except Exception: # pragma: no cover (safety) + except Exception: vals = None else: if dtype.np_type.subdtype is not None: diff --git a/graphblas/io.py b/graphblas/io.py index 8ece47a57..23b9b30b7 100644 --- a/graphblas/io.py +++ b/graphblas/io.py @@ -11,7 +11,7 @@ from .exceptions import GraphblasException as _GraphblasException -def draw(m): # pragma: no cover +def draw(m): # pragma: no cover (deprecated) """Draw a square adjacency Matrix as a graph. Requires `networkx `_ and diff --git a/graphblas/monoid/numpy.py b/graphblas/monoid/numpy.py index 6040d4037..f46d57143 100644 --- a/graphblas/monoid/numpy.py +++ b/graphblas/monoid/numpy.py @@ -160,7 +160,7 @@ def __dir__(): if not _supports_udfs and not _config.get("mapnumpy"): - return globals().keys() + return globals().keys() # FLAKY COVERAGE attrs = _delayed.keys() | _monoid_identities.keys() if not _supports_udfs: attrs &= _numpy_to_graphblas.keys() diff --git a/graphblas/semiring/numpy.py b/graphblas/semiring/numpy.py index 87f947c07..3a59090cc 100644 --- a/graphblas/semiring/numpy.py +++ b/graphblas/semiring/numpy.py @@ -134,7 +134,7 @@ def __dir__(): if not _supports_udfs and not _config.get("mapnumpy"): - return globals().keys() + return globals().keys() # FLAKY COVERAGE attrs = _delayed.keys() | _semiring_names if not _supports_udfs: attrs &= { diff --git a/graphblas/tests/conftest.py b/graphblas/tests/conftest.py index 7f2561863..e52ebbb7a 100644 --- a/graphblas/tests/conftest.py +++ b/graphblas/tests/conftest.py @@ -52,7 +52,7 @@ def pytest_configure(config): rec.start() def save_records(): - with Path("record.txt").open("w") as f: # pragma: no cover + with Path("record.txt").open("w") as f: # pragma: no branch f.write("\n".join(rec.data)) # I'm sure there's a `pytest` way to do this... diff --git a/graphblas/tests/test_formatting.py b/graphblas/tests/test_formatting.py index 44ca82de2..faadc983b 100644 --- a/graphblas/tests/test_formatting.py +++ b/graphblas/tests/test_formatting.py @@ -40,9 +40,8 @@ def _printer(text, name, repr_name, indent): # line = f"f'{{CSS_STYLE}}'" in_style = False is_style = True - else: # pragma: no cover (???) - # This definitely gets covered, but why is it not picked up? - continue + else: + continue # FLAKY COVERAGE if repr_name == "repr_html" and line.startswith("