Skip to content

Commit

Permalink
Merge pull request #341 from PermutaTriangle/develop
Browse files Browse the repository at this point in the history
Release Version 4.2.0
  • Loading branch information
jaypantone authored Jan 18, 2023
2 parents ef252a7 + 8024e97 commit 9baae92
Show file tree
Hide file tree
Showing 26 changed files with 473 additions and 309 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.8
python-version: "3.10"
- name: install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
31 changes: 17 additions & 14 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,22 @@ jobs:
fail-fast: false
matrix:
include:
- python: 3.8
- python: "3.10"
toxenv: flake8
os: ubuntu-latest
- python: 3.8
- python: "3.10"
toxenv: mypy
os: ubuntu-latest
- python: 3.8
- python: "3.10"
toxenv: pylint
os: ubuntu-latest
- python: 3.8
- python: "3.10"
toxenv: black
os: ubuntu-latest
- python: 3.8
- python: "3.10"
toxenv: tilescope
os: ubuntu-latest

- python: 3.7
toxenv: py37
os: ubuntu-latest
- python: 3.8
toxenv: py38
os: ubuntu-latest
Expand All @@ -37,15 +34,21 @@ jobs:
- python: "3.10"
toxenv: py310
os: ubuntu-latest
- python: pypy-3.7
toxenv: pypy37
- python: "3.11"
toxenv: py311
os: ubuntu-latest
- python: pypy-3.8
toxenv: pypy38
os: ubuntu-latest
- python: pypy-3.9
toxenv: pypy39
os: ubuntu-latest

- python: 3.8
toxenv: py38
- python: "3.10"
toxenv: py310
os: macos-latest
- python: 3.8
toxenv: py38
- python: "3.11"
toxenv: py311
os: windows-latest

runs-on: ${{ matrix.os }}
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
repos:
- repo: https://github.com/psf/black
rev: 21.10b0
rev: 22.10.0
hooks:
- id: black
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]


## [4.2.0] 2023-01-18
### Changed
- Update dependency on psutil from 5.8 to 5.9.4
- Update dependency on sympy from 1.9 to 1.10.1
- Update dependency on pympler from 0.9 to 1.0.1
- Update dependency on requests from 2.26.0 to 2.28.1
- Update dependency on typing-extensions from 4.0.0 to 4.4.0
- Update dependency on tabulate from 0.8.9 to 0.9.0
- Updated dependencies in the tox file

## [4.1.0] 2022-01-17
### Added
- Make specification iterable
- Add a `get_comb_class` method to combinatorial specification
- `StrategyPack.add_expansion` and `StrategyPack.remove_strategy` methods
- Add a flag `classdb` and `classqueue` to `comb_spec_searcher.__init__`

### Changed
- The `get_terms` now have unique keys for the parameters to save memory.
Expand Down
2 changes: 1 addition & 1 deletion comb_spec_searcher/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
VerificationStrategy,
)

__version__ = "4.1.0"
__version__ = "4.2.0"

__all__ = [
"CombinatorialSpecificationSearcher",
Expand Down
142 changes: 110 additions & 32 deletions comb_spec_searcher/class_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,107 @@
import time
import zlib
from datetime import timedelta
from typing import Dict, Generic, Iterator, Optional, Type, cast
from typing import (
Dict,
Generic,
Iterator,
List,
MutableMapping,
NamedTuple,
Optional,
Type,
cast,
)

from comb_spec_searcher.typing import ClassKey, CombinatorialClassType, Key


class Info:
"""
Information about a combinatorial class.
- the class,
- the label,
- is it empty?
"""
class Info(NamedTuple):
comb_class: ClassKey
label: int
empty: Optional[bool] = None


class LabelToInfo(MutableMapping[int, Optional[Info]]):
def __init__(
self,
comb_class_list: List[ClassKey],
label_dict: Dict[ClassKey, int],
empty_list: List[Optional[bool]],
):
self.comb_class_list = comb_class_list
self.label_dict = label_dict
self.empty_list = empty_list

def __getitem__(self, label: int) -> Optional[Info]:
try:
return Info(self.comb_class_list[label], label, self.empty_list[label])
except KeyError:
return None

def __setitem__(self, key: int, value: Optional[Info]) -> None:
raise NotImplementedError

def __delitem__(self, key: int) -> None:
raise NotImplementedError

def __init__(self, comb_class: ClassKey, label: int, empty: Optional[bool] = None):
self.comb_class = comb_class
self.label = label
self.empty = empty
def __iter__(self) -> Iterator:
for label in self.label_dict.values():
yield label

def __len__(self) -> int:
return len(self.empty_list)

def __eq__(self, other: object) -> bool:
if not isinstance(other, Info):
if not isinstance(other, LabelToInfo):
return NotImplemented
return (
self.comb_class == self.comb_class
and self.label == self.label
and self.empty == self.empty
self.comb_class_list == other.comb_class_list
and self.label_dict == other.label_dict
and self.empty_list == other.empty_list
)


class ClassToInfo(MutableMapping[ClassKey, Optional[Info]]):
def __init__(
self,
comb_class_list: List[ClassKey],
label_dict: Dict[ClassKey, int],
empty_list: List[Optional[bool]],
):
self.comb_class_list = comb_class_list
self.label_dict = label_dict
self.empty_list = empty_list

def __getitem__(self, class_key: ClassKey) -> Optional[Info]:
try:
label = self.label_dict[class_key]
return Info(self.comb_class_list[label], label, self.empty_list[label])
except KeyError:
return None

def __setitem__(self, key: ClassKey, value: Optional[Info]) -> None:
raise NotImplementedError

def __delitem__(self, key: ClassKey) -> None:
raise NotImplementedError

def __iter__(self) -> Iterator:
raise NotImplementedError

def __len__(self) -> int:
return len(self.empty_list)

def __contains__(self, class_key: ClassKey) -> bool:
return class_key in self.label_dict

def __eq__(self, other: object) -> bool:
if not isinstance(other, ClassToInfo):
return NotImplemented
return (
self.comb_class_list == other.comb_class_list
and self.label_dict == other.label_dict
and self.empty_list == other.empty_list
)


Expand All @@ -55,8 +131,15 @@ class ClassDB(Generic[CombinatorialClassType]):
"""

def __init__(self, combinatorial_class: Type[CombinatorialClassType]):
self.class_to_info: Dict[ClassKey, Info] = {}
self.label_to_info: Dict[int, Info] = {}
self.comb_class_list: List[ClassKey] = []
self.label_dict: Dict[ClassKey, int] = {}
self.empty_list: List[Optional[bool]] = []
self.class_to_info: ClassToInfo = ClassToInfo(
self.comb_class_list, self.label_dict, self.empty_list
)
self.label_to_info: LabelToInfo = LabelToInfo(
self.comb_class_list, self.label_dict, self.empty_list
)
self.combinatorial_class = combinatorial_class
self._empty_time = 0.0
self._empty_num_application = 0
Expand Down Expand Up @@ -95,7 +178,7 @@ def add(self, comb_class: ClassKey, compressed: bool = False) -> None:
"""
if not compressed and not isinstance(comb_class, self.combinatorial_class):
raise TypeError(
("Trying to add something that isn't a" "CombinatorialClass.")
("Trying to add something that isn't a CombinatorialClass.")
)
if not compressed:
assert isinstance(
Expand All @@ -106,11 +189,9 @@ def add(self, comb_class: ClassKey, compressed: bool = False) -> None:
compressed_class = comb_class
if compressed_class not in self.class_to_info:
label = len(self.class_to_info)
info = Info(compressed_class, label)
self.class_to_info[compressed_class] = info
self.label_to_info[label] = info
else:
label = self.class_to_info[compressed_class].label
self.comb_class_list.append(compressed_class)
self.label_dict[compressed_class] = label
self.empty_list.append(None)

def _get_info(self, key: Key) -> Info:
"""
Expand All @@ -132,7 +213,7 @@ def _get_info(self, key: Key) -> Info:
"CombinatorialClass and will decompress with"
f"{self.combinatorial_class}."
)
return info
return cast(Info, info)

def _compress(self, key: CombinatorialClassType) -> ClassKey:
"""
Expand Down Expand Up @@ -183,11 +264,9 @@ def is_empty(
Return True if combinatorial class is empty set, False if not.
"""
if label is None:
info = self._get_info(comb_class)
label = info.label
else:
info = self._get_info(label)
empty = info.empty
label = self.label_dict[self._compress(comb_class)]

empty = self.empty_list[label]
if empty is None:
if not isinstance(comb_class, self.combinatorial_class):
comb_class = self.get_class(comb_class)
Expand All @@ -208,8 +287,7 @@ def set_empty(self, key: Key, empty: bool = True) -> None:
"""
Update database about comb class being empty.
"""
info = self._get_info(key)
info.empty = empty
self.empty_list[self.get_label(key)] = empty

def status(self) -> str:
"""
Expand Down
Loading

0 comments on commit 9baae92

Please sign in to comment.