Source code for bw2calc.restricted_sparse_matrix_dict

from typing import Any

from matrix_utils import SparseMatrixDict
from pydantic import BaseModel


[docs] class RestrictionsValidator(BaseModel):
[docs] restrictions: dict[tuple[str, ...], list[tuple[str, ...]]]
[docs] class RestrictedSparseMatrixDict(SparseMatrixDict): def __init__(self, restrictions: dict, *args, **kwargs): """Like SparseMatrixDict, but follows `restrictions` on what can be multiplied. Only for use with normalization and weighting.""" super().__init__(*args, **kwargs) RestrictionsValidator(restrictions=restrictions)
[docs] self._restrictions = restrictions
[docs] def _get_first_element(self, elem: Any) -> tuple: """Get the first LCIA key from `elem`. The keys can have the form `(("some", "lcia"), "functional-unit-id")` or `("some", "lcia").""" if isinstance(elem[0], tuple): return elem[0] else: assert isinstance(elem, tuple), f"Wrong type: {type(elem)} should be tuple" return elem
[docs] def _concatenate(self, a: tuple, b: tuple) -> tuple: """Combine `a` and `b` while unwrapping `b`, if necessary.""" if isinstance(b[0], tuple): return (a, *b) else: return (a, b)
def __matmul__(self, other: Any) -> SparseMatrixDict: """Define logic for `@` matrix multiplication operator. Note that the sparse matrix dict must come first, i.e. `self @ other`. """ if isinstance(other, (SparseMatrixDict, RestrictedSparseMatrixDict)): return SparseMatrixDict( { self._concatenate(a, b): c @ d for a, c in self.items() for b, d in other.items() if self._get_first_element(b) in self._restrictions[a] } ) else: return super().__matmul__(other)