From 4f2d8dcadf597fb08fb9f06029dad0dd9bc6e3e4 Mon Sep 17 00:00:00 2001 From: LukasWestholt Date: Fri, 10 Dec 2021 20:03:43 +0100 Subject: [PATCH] Extend project with the following functions: + totaly revised more information soon v2021.12.2 --- .idea/SetSolver1.iml | 1 + README.md | 40 +- SetSolver1/MODE.py | 183 ++++++++- SetSolver1/MathSet.py | 126 ++++++ SetSolver1/MultiMathSet.py | 114 ++++++ SetSolver1/RelationMathSet.py | 278 +++++++++++++ SetSolver1/ResultWay.py | 23 ++ SetSolver1/STATUS.py | 6 - SetSolver1/SimpleMathSet.py | 124 ++++++ SetSolver1/TinyMathSet.py | 18 + SetSolver1/__init__.py | 7 + SetSolver1/helper/BaseTypes.py | 27 ++ SetSolver1/helper/transformer.py | 38 ++ SetSolver1/helper/update.py | 24 +- SetSolver1/main.py | 320 +++++++-------- SetSolver1/math_set.py | 365 ------------------ TODO.txt | 4 - beispiele.md | 319 +++++++++++++-- examples/multisets/exercice0.py | 28 ++ examples/multisets/exercice1.py | 27 ++ examples/multisets/exercice2.py | 28 ++ examples/sets-relations/aufgabe1.py | 21 - examples/sets-relations/aufgabe4.py | 21 - examples/sets-relations/exercice0.py | 31 ++ examples/sets-relations/exercice1.py | 32 ++ examples/sets-relations/exercice2.py | 32 ++ examples/sets-relations/exercice3.py | 31 ++ examples/sets-relations/exercice4.py | 31 ++ examples/sets/aufgabe0.py | 20 - examples/sets/aufgabe1.py | 20 - examples/sets/aufgabe2.py | 20 - examples/sets/aufgabe3.py | 21 - examples/sets/aufgabe4.py | 21 - examples/sets/aufgabe5.py | 20 - examples/sets/{aufgabe6.py => exercice0.py} | 19 +- examples/sets/exercice1.py | 25 ++ .../aufgabe0.py => sets/exercice2.py} | 20 +- .../aufgabe2.py => sets/exercice3.py} | 21 +- examples/sets/exercice4.py | 28 ++ examples/sets/exercice5.py | 27 ++ .../aufgabe3.py => sets/exercice6.py} | 20 +- setup.py | 2 +- tests/one-liner_vs_fast.py | 5 +- tests/overall_speed.py | 4 +- 44 files changed, 1770 insertions(+), 822 deletions(-) create mode 100644 SetSolver1/MathSet.py create mode 100644 SetSolver1/MultiMathSet.py create mode 100644 SetSolver1/RelationMathSet.py create mode 100644 SetSolver1/ResultWay.py delete mode 100644 SetSolver1/STATUS.py create mode 100644 SetSolver1/SimpleMathSet.py create mode 100644 SetSolver1/TinyMathSet.py create mode 100644 SetSolver1/helper/BaseTypes.py create mode 100644 SetSolver1/helper/transformer.py delete mode 100644 SetSolver1/math_set.py delete mode 100644 TODO.txt create mode 100644 examples/multisets/exercice0.py create mode 100644 examples/multisets/exercice1.py create mode 100644 examples/multisets/exercice2.py delete mode 100644 examples/sets-relations/aufgabe1.py delete mode 100644 examples/sets-relations/aufgabe4.py create mode 100644 examples/sets-relations/exercice0.py create mode 100644 examples/sets-relations/exercice1.py create mode 100644 examples/sets-relations/exercice2.py create mode 100644 examples/sets-relations/exercice3.py create mode 100644 examples/sets-relations/exercice4.py delete mode 100644 examples/sets/aufgabe0.py delete mode 100644 examples/sets/aufgabe1.py delete mode 100644 examples/sets/aufgabe2.py delete mode 100644 examples/sets/aufgabe3.py delete mode 100644 examples/sets/aufgabe4.py delete mode 100644 examples/sets/aufgabe5.py rename examples/sets/{aufgabe6.py => exercice0.py} (60%) create mode 100644 examples/sets/exercice1.py rename examples/{sets-relations/aufgabe0.py => sets/exercice2.py} (52%) rename examples/{sets-relations/aufgabe2.py => sets/exercice3.py} (56%) create mode 100644 examples/sets/exercice4.py create mode 100644 examples/sets/exercice5.py rename examples/{sets-relations/aufgabe3.py => sets/exercice6.py} (54%) diff --git a/.idea/SetSolver1.iml b/.idea/SetSolver1.iml index 9305f7a..e5841d2 100644 --- a/.idea/SetSolver1.iml +++ b/.idea/SetSolver1.iml @@ -8,6 +8,7 @@ + diff --git a/README.md b/README.md index 0f1006d..a5cd399 100644 --- a/README.md +++ b/README.md @@ -3,44 +3,52 @@ This script is solving set problems by brute-force. See [HOWTO](#HOWTO). # HOWTO Use python3.10 or newer. Download it [here](https://www.python.org/downloads/). -``` +```shell "python.exe" -m pip install SetSolver1 ``` First import the module: -``` +```python import SetSolver1 ``` Now you can use the method: ``` -SetSolver1.search(const_sets: dict[str, set[frozenset | int | tuple] | MathSet], result: set[frozenset | int | tuple] | MathSet, not_allowed: list = None, identity: Identity = None) -> list[MathSet] | None +SetSolver1.search(const_dict: dict[str, set[frozenset | int | tuple] | MathSet] | ConstDictType, + result: set[frozenset | int | tuple] | MathSet | ResultType, + not_allowed: list[MODE] = None, + identity: RelationMathSet | None = None, + overflow: int = 30, + range_int: int = 20, + do_print: bool = True) -> ResultWay | None ``` -Where `const_sets` is a dictionary for the predefined constants and `result` is the wanted solution. -With the method `search` you can find the probably shortest way to this solution by the predefined constants -and normal set operations. With this method you will get a list of valid ways (mostly one way) back. +Where `const_dict` is a dictionary for the predefined constants and `result` is the wanted solution. +With the method `search` you can find probably the shortest way to this solution by the predefined constants +and normal set operations. With this method you will get an ResultWay object back. -Little example: -``` +[little example](/examples/sets/exercice2.py): +```python import SetSolver1 # Here you set your predefined constants. # Please make sure that you do not assign a variable letter twice. # Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int]] = { - "A": {frozenset({2, frozenset()}), frozenset({5})}, - "B": {frozenset(), frozenset({3}), frozenset({5})} -} +const_dict = SetSolver1.SimpleMathSetConstDictType( + { + "A": {frozenset({2, frozenset()}), frozenset({5})}, # string "[[2, []],[5]]" is allowed too + "B": {frozenset(), frozenset({3}), frozenset({5})} + } +) # Here you set your wanted solution. -result = {frozenset(), frozenset({3}), frozenset({5}), frozenset({frozenset()})} +result = SetSolver1.SimpleMathSetResultType({frozenset(), frozenset({3}), frozenset({5}), frozenset({frozenset()})}) -output = SetSolver1.search(const_sets, result) +output = SetSolver1.search(const_dict, result) ``` - -See German examples [here](beispiele.md) with outputs. +More examples are [here](/examples) +See German examples explanation [here](beispiele.md) with outputs. # Requirements diff --git a/SetSolver1/MODE.py b/SetSolver1/MODE.py index c1faed6..447234a 100644 --- a/SetSolver1/MODE.py +++ b/SetSolver1/MODE.py @@ -1,19 +1,164 @@ -# tuple of index, used_vars, priority -UNION = 0, (1, 2), 1 -COMPLEMENT_X = 1, (1, 2), 1 -COMPLEMENT_Y = 2, (2, 1), 1 -INTERSECTION = 3, (1, 2), 2 -COMPOSITION_X = 4, (1, 2), 3 -COMPOSITION_Y = 5, (2, 1), 3 -POWER_SET_X = 6, (1,), 4 -POWER_SET_Y = 7, (2,), 4 -CONVERSE_RELATION_X = 8, (1,), 3 -CONVERSE_RELATION_Y = 9, (2,), 3 -REFLEXIVE_CLOSURE_X = 10, (1,), 2 -REFLEXIVE_CLOSURE_Y = 11, (2,), 2 -TRANSITIVE_CLOSURE_X = 12, (1,), 2 -TRANSITIVE_CLOSURE_Y = 13, (2,), 2 - -CHOOSE_BY_INDEX = (UNION, COMPLEMENT_X, COMPLEMENT_Y, INTERSECTION, COMPOSITION_X, COMPOSITION_Y, POWER_SET_X, - POWER_SET_Y, CONVERSE_RELATION_X, CONVERSE_RELATION_Y, REFLEXIVE_CLOSURE_X, REFLEXIVE_CLOSURE_Y, - TRANSITIVE_CLOSURE_X, TRANSITIVE_CLOSURE_Y) +#!/usr/bin/env python3 +# coding: utf-8 + + +class MODE: + _value: tuple[tuple[int], int, int] + _print_str: str + + def __init__(self, used_vars, priority, is_commutative, print_str): + """ + Constructor method + :type used_vars: tuple[int] + :type priority: int + :type is_commutative: int + :type print_str: str + """ + self._value = (used_vars, priority, is_commutative) + self._print_str = print_str + + def __getitem__(self, item): + """ + __getitem__ method + :type item: int + :rtype: int | tuple + """ + return self._value[item] + + def __lt__(self, other): + if type(other) == self.__class__: + return self[1] < other[1] + + def __repr__(self): + return list(GET_BY_KEY.keys())[list(GET_BY_KEY.values()).index(self)] + + def format(self, x, y): + """ + returns format _print_str with x and y + :type x: str + :type y: str + :rtype: str + """ + return self._print_str.format(x=x, y=y) + + def is_multi_mode(self): + return self[0] == (1, 2) + + def is_single_mode(self): + return not self.is_multi_mode() + + +CONST = MODE( + used_vars=tuple(), + priority=1, + is_commutative=1, + print_str='{x}' +) +IDENTITY = MODE( + used_vars=tuple(), + priority=1, + is_commutative=1, + print_str='' +) +TEMPORARY_CREATED = MODE( + used_vars=tuple(), + priority=1, + is_commutative=1, + print_str='' +) +UNION = MODE( + used_vars=(1, 2), + priority=1, + is_commutative=1, + print_str='({x}+{y})' +) +COMPLEMENT = MODE( + used_vars=(1, 2), + priority=1, + is_commutative=0, + print_str='({x}-{y})' +) +INTERSECTION = MODE( + used_vars=(1, 2), + priority=2, + is_commutative=1, + print_str='({x}&{y})' +) +COMPOSITION = MODE( + used_vars=(1, 2), + priority=3, + is_commutative=0, + print_str='({x}.{y})' +) +POWER_SET = MODE( + used_vars=(1,), + priority=4, + is_commutative=1, + print_str='pow({x})' +) +SYMMETRIC_DIFFERENCE = MODE( + used_vars=(1, 2), + priority=99, # TODO + is_commutative=1, + print_str='({x}sym{y})' +) +CONVERSE_RELATION = MODE( + used_vars=(1,), + priority=3, + is_commutative=1, + print_str='inverse({x})' +) +REFLEXIVE_CLOSURE = MODE( + used_vars=(1,), + priority=2, + is_commutative=1, + print_str='reflexive_cl({x})' +) +TRANSITIVE_CLOSURE = MODE( + used_vars=(1,), + priority=2, + is_commutative=1, + print_str='transitive_cl({x})' +) +MULTISET_DISJOINT_UNION = MODE( + used_vars=(1, 2), + priority=2, + is_commutative=1, + print_str='({x}+{y})' +) +MULTISET_DIFFERENCE = MODE( + used_vars=(1, 2), + priority=2, + is_commutative=0, + print_str='({x}-{y})' +) + +GET_BY_KEY = { + "CONST": CONST, + "IDENTITY": IDENTITY, + "TEMPORARY_CREATED": TEMPORARY_CREATED, + "union": UNION, + "complement": COMPLEMENT, + "intersection": INTERSECTION, + "composition": COMPOSITION, + "power_set": POWER_SET, + "symmetric_difference": SYMMETRIC_DIFFERENCE, + "converse_relation": CONVERSE_RELATION, + "reflexive_closure": REFLEXIVE_CLOSURE, + "transitive_closure": TRANSITIVE_CLOSURE, + "disjoint_union": MULTISET_DISJOINT_UNION, + "multi_set_difference": MULTISET_DIFFERENCE +} + +CHOOSE_BY_INDEX = [UNION, COMPLEMENT, INTERSECTION, COMPOSITION, POWER_SET, CONVERSE_RELATION, REFLEXIVE_CLOSURE, + TRANSITIVE_CLOSURE, MULTISET_DISJOINT_UNION, MULTISET_DIFFERENCE] +SORTED_CHOOSE_BY_INDEX = sorted(CHOOSE_BY_INDEX) + +DEFAULT_NOT_ALLOWED = [COMPOSITION, CONVERSE_RELATION, REFLEXIVE_CLOSURE, TRANSITIVE_CLOSURE, MULTISET_DISJOINT_UNION, + MULTISET_DIFFERENCE] +NOT_ALLOWED_EVERYTHING = CHOOSE_BY_INDEX + +RESULT = TEMPORARY_CREATED +TEMPORARY_CREATED_WAY = (TEMPORARY_CREATED, None, None) +CONST_WAY = (CONST, None, None) +IDENTITY_WAY = (IDENTITY, None, None) diff --git a/SetSolver1/MathSet.py b/SetSolver1/MathSet.py new file mode 100644 index 0000000..8e8f561 --- /dev/null +++ b/SetSolver1/MathSet.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from __future__ import annotations + +from SetSolver1.MODE import MODE, TEMPORARY_CREATED, CONST, CONST_WAY +from SetSolver1.TinyMathSet import TinyMathSet + + +class MathSet: + """ + BaseClass BaseSet + """ + def __init__(self, value, way): + """ + Constructor method + :type value: any + :type way: (MODE, any, any) + """ + self.value = value + self.way = way + + def __repr__(self): + return "{0}({1})".format(type(self).__name__, self.__dict__) + + def __str__(self): + return str(self.value) + + def __hash__(self): + # Default: hash(x)==id(x)/16 + # https://stackoverflow.com/a/11324771 + # https://docs.python.org/3/glossary.html#term-hashable + return hash(self.value) + + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.value == other.value + print("NotImplemented Equality Compare") + return NotImplemented + + def __len__(self): + """ + :rtype: int + """ + return len(self.value) + + def correct_way(self): + """ + Helper method to set correct way to consts + """ + if self.way == CONST_WAY: + self.way = (CONST, self, None) + + def walk_way(self, going_by=None): + """ + Walk through the way and count steps + :param going_by: value adding per step of way + :type going_by: int + :raises ValueError: + :return: steps of way + :rtype: int + """ + mode = self.way[0] + if mode == TEMPORARY_CREATED: + raise ValueError("MODE.TEMPORARY_CREATED not allowed here") + if mode == CONST: + return 0 + lt = list() + for i in mode[0]: + if self.way[i] is not None: + lt.append(self.way[i].walk_way(going_by)) + return sum(lt) + (going_by if going_by is not None else mode[1]) + + def sort_key(self): + """ + ascending order so: 2 is before 5 + :rtype: (int, int) + """ + # TODO ist there a way to sort by second key only if needed? + return self.walk_way(going_by=1), self.walk_way() + + def deep_len(self): + return sum(el.deep_len() if type(el) == TinyMathSet else 1 for el in self.value) + + def total_deep_len(self): + return sum(el.total_deep_len()+1 if type(el) == TinyMathSet else 1 for el in self.value) + + def is_empty(self): + """ + Is MathSet empty? + :rtype: bool + """ + return len(self.value) == 0 + + def union(self, y): + raise RuntimeError("this operation is not allowed") + + def complement(self, y): + raise RuntimeError("this operation is not allowed") + + def intersection(self, y): + raise RuntimeError("this operation is not allowed") + + def power_set(self): + raise RuntimeError("this operation is not allowed") + + def symmetric_difference(self, y): + raise RuntimeError("this operation is not allowed") + + def composition(self, y): + raise RuntimeError("this operation is not allowed") + + def converse_relation(self): + raise RuntimeError("this operation is not allowed") + + def reflexive_closure(self): + raise RuntimeError("this operation is not allowed") + + def transitive_closure(self): + raise RuntimeError("this operation is not allowed") + + def disjoint_union(self, y): + raise RuntimeError("this operation is not allowed") + + def multi_set_difference(self, y): + raise RuntimeError("this operation is not allowed") diff --git a/SetSolver1/MultiMathSet.py b/SetSolver1/MultiMathSet.py new file mode 100644 index 0000000..6af94c9 --- /dev/null +++ b/SetSolver1/MultiMathSet.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from __future__ import annotations + +from SetSolver1.MathSet import MathSet +from SetSolver1.MODE import MODE, GET_BY_KEY, CONST_WAY, RESULT +from SetSolver1.helper.BaseTypes import ConstDictType, ResultType + + +class MultiMathSet(MathSet): + """ + Class MultiMathSet, inherit by 'BaseSet' + """ + value: dict[str, int] + way: tuple[MODE, (MultiMathSet | None), (MultiMathSet | None)] + + def __init__(self, value, way): + """ + Constructor method + :type value: dict[str, int] + :type way: (MODE, MultiMathSet | None, MultiMathSet | None) + """ + super().__init__(value, way) + + def __hash__(self): + return hash(tuple(sorted(self.value.items()))) + + def is_empty(self): + """ + Is MultiMathSet empty? + :rtype: bool + """ + return self.value == dict() + + def total_deep_len(self): + a = self.value.values() + return len(a) + sum(a) + + def union(self, y): + """ + German: Vereinigung + :type y: MultiMathSet + :rtype: MultiMathSet + """ + copy = self.value.copy() + for y1 in y.value.keys(): + if not y.value[y1] == 0: + copy[y1] = max(copy.get(y1, 0), y.value[y1]) + return MultiMathSet(copy, (GET_BY_KEY[self.union.__name__], self, y)) + + def disjoint_union(self, y): + """ + German: disjunkte Vereinigung + :type y: MultiMathSet + :rtype: MultiMathSet + """ + copy = self.value.copy() + for y1 in y.value.keys(): + if not y.value[y1] == 0: + copy[y1] = copy.get(y1, 0) + y.value[y1] + return MultiMathSet(copy, (GET_BY_KEY[self.disjoint_union.__name__], self, y)) + + def multi_set_difference(self, y): + """ + German: Differenz + :type y: MultiMathSet + :rtype: MultiMathSet + """ + + copy = self.value.copy() + for y1 in y.value.keys(): + if not y.value[y1] == 0 and y1 in copy.keys() and copy[y1] > y.value[y1]: + copy[y1] = copy[y1] - y.value[y1] + return MultiMathSet(copy, (GET_BY_KEY[self.multi_set_difference.__name__], self, y)) + + def intersection(self, y): + """ + German: Schnitt + :type y: MultiMathSet + :rtype: MultiMathSet + """ + copy = self.value.copy() + for y1 in set(copy.keys()).union(y.value.keys()): + copy[y1] = min(copy.get(y1, 0), y.value.get(y1, 0)) + if copy[y1] == 0: + del copy[y1] + return MultiMathSet(copy, (GET_BY_KEY[self.intersection.__name__], self, y)) + + +class MultiMathSetConstDictType(ConstDictType): + def __init__(self, data): + """ + :type data: dict[str, dict[str, int]] + :raises ValueError: + """ + _const = dict() + for letter in data.keys(): + for i in data[letter].values(): + if i < 1: # check every int is not negative or 0 + raise ValueError("no negative or zero value allowed in ConstDictType") + _const[letter] = MultiMathSet(data[letter], CONST_WAY) + _const[letter].correct_way() + super().__init__(_const) + + +class MultiMathSetResultType(ResultType): + _result: MultiMathSet + + def __init__(self, data): + """ + :type data: dict[str, int] + """ + super().__init__(MultiMathSet(data, RESULT)) diff --git a/SetSolver1/RelationMathSet.py b/SetSolver1/RelationMathSet.py new file mode 100644 index 0000000..a0bfc29 --- /dev/null +++ b/SetSolver1/RelationMathSet.py @@ -0,0 +1,278 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from __future__ import annotations + +from SetSolver1.MODE import MODE, GET_BY_KEY, CONST_WAY, RESULT, IDENTITY_WAY +from SetSolver1.SimpleMathSet import SimpleMathSet +from SetSolver1.helper.BaseTypes import ConstDictType, ResultType + + +class RelationMathSet(SimpleMathSet): + """ + Class RelationMathSet, inherit by 'BaseSet' + """ + value: frozenset[tuple[int | str, int | str]] + identity: RelationMathSet | None + way: tuple[MODE, (RelationMathSet | None), (RelationMathSet | None)] + + def __init__(self, value, identity, way): + """ + init RelationMathSet + :type value: frozenset[(int, int)] | collections.abc.Iterable[(int, int)] + :type identity: RelationMathSet | None + :type way: (MODE, RelationMathSet | None, RelationMathSet | None) + """ + self.identity = identity + super().__init__(value, way) + + def type_check(self, y): + """ + Check if the type of MathSets is comparable + :type y: RelationMathSet + :raises TypeError: + """ + if self.identity != y.identity: + raise TypeError("type_check error") + + def is_identity(self, set_to_identity_of_itself=False): + """ + :type set_to_identity_of_itself: bool + :rtype: RelationMathSet | bool + :raises ValueError: + """ + if set_to_identity_of_itself: + if self.identity is not None: + raise ValueError("It is not allowed to change attribute value of this class") + self.identity = self + return self + else: + return self.identity == self + + def union(self, y): + """ + German: Vereinigungsmenge + :type y: RelationMathSet + :rtype: RelationMathSet + """ + self.type_check(y) + copy = set(self.value) + copy.update(y.value) + return RelationMathSet(copy, self.identity, (GET_BY_KEY[self.union.__name__], self, y)) + + def complement(self, y): + """ + German: Komplement - Subtraktion von Mengen + :type y: RelationMathSet + :rtype: RelationMathSet + """ + self.type_check(y) + return RelationMathSet(self.value.difference(y.value), self.identity, + (GET_BY_KEY[self.complement.__name__], self, y)) + + def intersection(self, y): + """ + German: Schnittmenge + :type y: RelationMathSet + :rtype: RelationMathSet + """ + self.type_check(y) + return RelationMathSet(self.value.intersection(y.value), self.identity, + (GET_BY_KEY[self.intersection.__name__], self, y)) + + def symmetric_difference(self, y): + """ + German: Symmetrische Differenz + :type y: RelationMathSet + :rtype: RelationMathSet + """ + self.type_check(y) + return RelationMathSet(self.value.symmetric_difference(y.value), self.identity, + (GET_BY_KEY[self.symmetric_difference.__name__], self, y)) + + def composition(self, y): + """ + TODO optimization + German: Verkettung + :type y: RelationMathSet + :rtype: RelationMathSet + """ + self.type_check(y) + lst = list() + for x1 in self.value: + for y1 in y.value: + if x1[1] == y1[0]: + lst.append((x1[0], y1[1])) + return RelationMathSet(lst, self.identity, (GET_BY_KEY[self.composition.__name__], self, y)) + + def converse_relation(self): + """ + TODO optimization + German: Inverse (Umkehrrelation) + :rtype: RelationMathSet + """ + return RelationMathSet(((x1[1], x1[0]) for x1 in self.value), self.identity, + (GET_BY_KEY[self.converse_relation.__name__], self, None)) + + def reflexive_closure(self): + """ + TODO optimization + German: Reflexive Hülle + :rtype: RelationMathSet + """ + return RelationMathSet(list(self.value) + [(x3, x3) for x3 in set([x1[x2] + for x2 in range(2) for x1 in self.value])], + self.identity, (GET_BY_KEY[self.reflexive_closure.__name__], self, None)) + + def transitive_closure(self): + """ + TODO optimization + German: Transitive Hülle + :rtype: RelationMathSet + """ + return RelationMathSet(list(self.value) + [(x1[0], x2[1]) + for x2 in self.value for x1 in self.value if x1[1] == x2[0]], + self.identity, (GET_BY_KEY[self.transitive_closure.__name__], self, None)) + + def is_reflexive(self): + """ + :rtype: bool + """ + if self.identity is None: + return self.value == self.reflexive_closure().value + return self.identity.is_subset(self) + + def is_irreflexive(self): + """ + :rtype: bool + """ + if self.identity is None: + """ + One-Line + return frozenset((x3, x3) for x3 in set([x1[x2] for x2 in range(2) for x1 in self.value]) + if (x3, x3) in self.value) == frozenset() + """ + for x1 in self.value: + if (x1[0], x1[0]) in self.value or (x1[1], x1[1]) in self.value: + return False + return True + return self.intersection(self.identity).is_empty() + + def is_subset(self, y): + """ + is_subset + :type y: RelationMathSet + :rtype: bool + """ + # self.value.issubset(y.value) + self.type_check(y) + for x1 in self.value: + if x1 not in y.value: + return False + return True + + def is_symmetric_relation(self): + """ + :rtype: bool + """ + return self.converse_relation().is_subset(self) + + def is_asymmetric_relation(self): + """ + :rtype: bool + """ + return self.intersection(self.converse_relation()).is_empty() + + def is_antisymmetric_relation(self): + """ + :rtype: bool + """ + if self.identity is None: + for x1 in self.value: + if x1[::-1] in self.value and not x1[0] == x1[1]: + return False + return True + return self.intersection(self.converse_relation()).is_subset(self.identity) + + def is_transitive(self): + """ + :rtype: bool + """ + return self.value == self.transitive_closure().value + + def is_preorder(self): + """ + German: Quasiordnung + :return: bool + """ + return self.is_reflexive() and self.is_transitive() + + def is_equivalence_relation(self): + """ + German: Äquivalenzrelation (symmetrische Quasiordnung) + :return: bool + """ + return self.is_preorder() and self.is_symmetric_relation() + + def is_non_strict_partial_order(self): + """ + German: Halbordnung (partielle Ordnung) + :return: bool + """ + return self.is_reflexive() and self.is_antisymmetric_relation() and self.is_transitive() + + def is_strict_partial_order(self): + """ + German: Strikte Ordnung + :return: bool + """ + return self.is_irreflexive() and self.is_transitive() and self.is_asymmetric_relation() + + def print_properties(self): + """ + Print all properties of this set with relations + :return: None + """ + print("is_reflexive: " + str(self.is_reflexive())) + print("is_irreflexive: " + str(self.is_irreflexive())) + print("is_symmetrisch: " + str(self.is_symmetric_relation())) + print("is_asymmetrisch: " + str(self.is_asymmetric_relation())) + print("is_antisymmetrisch: " + str(self.is_antisymmetric_relation())) + print("is_transitiv: " + str(self.is_transitive())) + + +class RelationMathSetConstDictType(ConstDictType): + def __init__(self, data, identity=None): + """ + :type data: dict[str, set[tuple]] + :type identity: RelationMathSet | None + :raises ValueError: + """ + _const = dict() + for letter in data.keys(): + _const[letter] = RelationMathSet(data[letter], identity, CONST_WAY) + _const[letter].correct_way() + super().__init__(_const) + + +class RelationMathSetResultType(ResultType): + _result: RelationMathSet + + def __init__(self, data, identity): + """ + Constructor method + :type data: set[tuple] + :type identity: RelationMathSet | None + """ + super().__init__(RelationMathSet(data, identity, RESULT)) + + +class RelationMathSetIdentityType(ResultType): + _result: RelationMathSet + + def __init__(self, data): + """ + Constructor method + :type data: set[(int, int)] + """ + super().__init__(RelationMathSet(data, None, IDENTITY_WAY).is_identity(True)) diff --git a/SetSolver1/ResultWay.py b/SetSolver1/ResultWay.py new file mode 100644 index 0000000..f87c146 --- /dev/null +++ b/SetSolver1/ResultWay.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1.MathSet import MathSet +from SetSolver1.helper.BaseTypes import ConstDictType + + +class ResultWay: + def __init__(self, result, const_dict, reversed_const_dict, results): + """ + Constructor method + :type result: MathSet + :type const_dict: dict[str, MathSet] | ConstDictType + :type reversed_const_dict: dict[MathSet, str] + :type results: set[MathSet] + """ + self.result = result + self.const_dict = const_dict + self.reversed_const_dict = reversed_const_dict + self.results = results + + def __repr__(self): + return str(self.result) diff --git a/SetSolver1/STATUS.py b/SetSolver1/STATUS.py deleted file mode 100644 index e62e793..0000000 --- a/SetSolver1/STATUS.py +++ /dev/null @@ -1,6 +0,0 @@ -from enum import Enum - - -class STATUS(Enum): - CONST = 1 - NONE = 2 diff --git a/SetSolver1/SimpleMathSet.py b/SetSolver1/SimpleMathSet.py new file mode 100644 index 0000000..02f7aa8 --- /dev/null +++ b/SetSolver1/SimpleMathSet.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from __future__ import annotations + +from itertools import chain, combinations +from SetSolver1.MathSet import MathSet +from SetSolver1.MODE import MODE, GET_BY_KEY, CONST_WAY, RESULT +from SetSolver1.TinyMathSet import TinyMathSet +from SetSolver1.helper.BaseTypes import ConstDictType, ResultType +from SetSolver1.helper.update import to_tiny_math_set + + +class SimpleMathSet(MathSet): + """ + Class SimpleMathSet, inherit by 'BaseSet' + """ + value: frozenset[TinyMathSet | tuple | int | str] + way: tuple[MODE, (SimpleMathSet | None), (SimpleMathSet | None)] + + def __init__(self, value, way): + """ + init SimpleMathSet + :type value: frozenset[TinyMathSet | tuple | int | str] | collections.abc.Iterable[ + TinyMathSet | tuple | int | str] + :type way: (MODE, SimpleMathSet | None, SimpleMathSet | None) + """ + if type(value) != frozenset: + value = frozenset(value) + super().__init__(value, way) + + def __str__(self): + if self.is_empty(): + return "{}" + return str(set(self.value)) + + def is_empty(self): + """ + Is SimpleMathSet empty? + :rtype: bool + """ + return self.value == frozenset() + + def union(self, y): + """ + German: Vereinigungsmenge + :type y: SimpleMathSet + :rtype: SimpleMathSet + """ + # self.value.union(y.value) # TODO ist faster? + copy = set(self.value) + copy.update(y.value) + return SimpleMathSet(copy, (GET_BY_KEY[self.union.__name__], self, y)) + + def complement(self, y): + """ + German: Komplement - Subtraktion von Mengen + :type y: SimpleMathSet + :rtype: SimpleMathSet + """ + return SimpleMathSet(self.value.difference(y.value), (GET_BY_KEY[self.complement.__name__], self, y)) + + def intersection(self, y): + """ + German: Schnittmenge + :type y: SimpleMathSet + :rtype: SimpleMathSet + """ + return SimpleMathSet(self.value.intersection(y.value), (GET_BY_KEY[self.intersection.__name__], self, y)) + + def power_set(self): + """ + German: Potenzmenge + :rtype: SimpleMathSet + """ + return SimpleMathSet( + [TinyMathSet(y) for y in chain.from_iterable( + combinations(self.value, i) for i in range(len(self) + 1))], + (GET_BY_KEY[self.power_set.__name__], self, None)) + + def symmetric_difference(self, y): + """ + German: Symmetrische Differenz + :type y: SimpleMathSet + :rtype: SimpleMathSet + """ + return SimpleMathSet(self.value.symmetric_difference(y.value), + (GET_BY_KEY[self.symmetric_difference.__name__], self, y)) + + +class SimpleMathSetConstDictType(ConstDictType): + def __init__(self, data): + """ + :type data: dict[str, set[frozenset | int] | str] + :raises ValueError: + """ + _const = dict() + for letter in data.keys(): + if type(data[letter]) == str: + from ast import literal_eval + _const[letter] = SimpleMathSet(to_tiny_math_set( + literal_eval(data[letter].replace("{", "[").replace("}", "]")) + ), CONST_WAY) + else: + # _const[letter] = SimpleMathSet(data[letter], CONST_WAY) + _const[letter] = SimpleMathSet(to_tiny_math_set(data[letter]), CONST_WAY) + _const[letter].correct_way() + super().__init__(_const) + + +class SimpleMathSetResultType(ResultType): + _result: SimpleMathSet + + def __init__(self, data): + """ + :type data: set[frozenset | int] | str + """ + if type(data) == str: + from ast import literal_eval + super().__init__(SimpleMathSet( + to_tiny_math_set(literal_eval(data.replace("{", "[").replace("}", "]"))), + RESULT)) + else: + super().__init__(SimpleMathSet(to_tiny_math_set(data), RESULT)) diff --git a/SetSolver1/TinyMathSet.py b/SetSolver1/TinyMathSet.py new file mode 100644 index 0000000..cbad8d4 --- /dev/null +++ b/SetSolver1/TinyMathSet.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +class TinyMathSet(frozenset): + _total_deep_len = None + + def __repr__(self): + if self == frozenset(): + return "{}" + return str(set(self)) + + def deep_len(self): + return sum(el.deep_len() if isinstance(el, TinyMathSet) else 1 for el in self) + + def total_deep_len(self): + if self._total_deep_len is None: + self._total_deep_len = sum(el.total_deep_len()+1 if isinstance(el, TinyMathSet) else 1 for el in self) + return self._total_deep_len diff --git a/SetSolver1/__init__.py b/SetSolver1/__init__.py index c272704..bed73b7 100644 --- a/SetSolver1/__init__.py +++ b/SetSolver1/__init__.py @@ -1 +1,8 @@ +#!/usr/bin/env python3 +# coding: utf-8 + from .main import search +from . import MODE +from .SimpleMathSet import SimpleMathSetConstDictType, SimpleMathSetResultType +from .RelationMathSet import RelationMathSetConstDictType, RelationMathSetResultType, RelationMathSetIdentityType +from .MultiMathSet import MultiMathSetConstDictType, MultiMathSetResultType diff --git a/SetSolver1/helper/BaseTypes.py b/SetSolver1/helper/BaseTypes.py new file mode 100644 index 0000000..861e679 --- /dev/null +++ b/SetSolver1/helper/BaseTypes.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1.MathSet import MathSet + + +class ConstDictType(dict): + def __init__(self, data): + """ + Constructor method + :type data: collections.abc.Mapping + """ + super().__init__(data) + + +class ResultType: + _result: MathSet + + def __init__(self, data): + """ + Constructor method + :type data: MathSet + """ + self._result = data + + def get(self): + return self._result diff --git a/SetSolver1/helper/transformer.py b/SetSolver1/helper/transformer.py new file mode 100644 index 0000000..dcc6a05 --- /dev/null +++ b/SetSolver1/helper/transformer.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1.MODE import TEMPORARY_CREATED_WAY +from SetSolver1.RelationMathSet import RelationMathSet + + +def do(value): + """ + German: Erstelle Relation aus Menge + :rtype: SimpleMathSet + """ + items = list() + for x1 in value: + if type(x1) != int and type(x1) != str: + return None + else: + for x2 in value: + items.append((x1, x2)) + return RelationMathSet(items, None, TEMPORARY_CREATED_WAY) + + +def identity_relation(value): + """ + Identity relation based on the binary relation + if there are missing values in the binary relation, they will miss in the Identity + You should not really use this + :rtype: RelationMathSet | None + """ + items = list() + for x in value: + if type(x) != int and type(x) != str: + return None + else: + items.append((x, x)) + id_relation = RelationMathSet(items, None, TEMPORARY_CREATED_WAY) + id_relation.is_identity(True) + return id_relation diff --git a/SetSolver1/helper/update.py b/SetSolver1/helper/update.py index 1077d34..1c65d85 100644 --- a/SetSolver1/helper/update.py +++ b/SetSolver1/helper/update.py @@ -1,16 +1,18 @@ -from SetSolver1.math_set import TinyMathSet +#!/usr/bin/env python3 +# coding: utf-8 +from SetSolver1.TinyMathSet import TinyMathSet -def to_tiny_math_set(set_of_frozenset_s): + +def to_tiny_math_set(data): """ helper method to update to 2021.11.3 - :type set_of_frozenset_s: set[frozenset | int | tuple] | frozenset | int | tuple - :rtype: TinyMathSet | int | tuple + :type data: any + :rtype: TinyMathSet | any """ - if type(set_of_frozenset_s) == frozenset or type(set_of_frozenset_s) == set: - items = list() - for x1 in set_of_frozenset_s: - items.append(to_tiny_math_set(x1)) - # print(items) - return TinyMathSet(items) - return set_of_frozenset_s + if type(data) == frozenset or type(data) == set or type(data) == list: + lst = list() + for x in data: + lst.append(to_tiny_math_set(x)) + return TinyMathSet(lst) + return data diff --git a/SetSolver1/main.py b/SetSolver1/main.py index 865e81d..6b82127 100644 --- a/SetSolver1/main.py +++ b/SetSolver1/main.py @@ -1,226 +1,204 @@ -from itertools import combinations_with_replacement -from SetSolver1.math_set import MathSet, Identity, STATUS +#!/usr/bin/env python3 +# coding: utf-8 + +from itertools import combinations_with_replacement, product, chain, compress +from SetSolver1.SimpleMathSet import SimpleMathSet +from SetSolver1.MODE import MODE, CHOOSE_BY_INDEX, RESULT, CONST_WAY +import SetSolver1.MODE import SetSolver1.helper.update +from SetSolver1.helper.BaseTypes import ConstDictType, ResultType +from SetSolver1.MathSet import MathSet +from SetSolver1.RelationMathSet import RelationMathSet +from SetSolver1.ResultWay import ResultWay -def tools(t, x, y): +def tools(t, x, y, overflow): """ - :type t: int + Switch tool by MODE t + For tool use variables x and y + :type t: MODE :type x: MathSet - :type y: MathSet - :rtype: MathSet + :type y: MathSet | None + :type overflow: int + :rtype: MathSet | None + :raises ValueError: """ - way = (t, x, y) - match t: + match CHOOSE_BY_INDEX.index(t): case 0: - return x.union(y, way) + return x.union(y) case 1: - return x.complement(y, way) + return x.complement(y) case 2: - return y.complement(x, way) + return x.intersection(y) case 3: - return x.intersection(y, way) + return x.composition(y) case 4: - return x.composition(y, way) - case 5: - return y.composition(x, way) - case 6: if x.total_deep_len() >= (overflow / 2): - return MathSet(frozenset(), x.identity, way) - return x.power_set(way) - case 7: - if y.total_deep_len() >= (overflow / 2): - return MathSet(frozenset(), y.identity, way) - return y.power_set(way) - case 8: - return x.converse_relation(way) - case 9: - return y.converse_relation(way) - case 10: - return x.reflexive_closure(way) - case 11: - return y.reflexive_closure(way) - case 12: - return x.transitive_closure(way) - case 13: - return y.transitive_closure(way) - case _: - raise ValueError("value not found") - - -def s_tools(t, x, y): - """ - :type t: int - :type x: str - :type y: str - :rtype: str - """ - print("way: " + str(t) + " " + str([x, y])) if DEBUG else None - match t: - case 0: - return "("+x+"+"+y+")" - case 1: - return "("+x+"-"+y+")" - case 2: - return "("+y+"-"+x+")" - case 3: - return "("+x+"&"+y+")" - case 4: - return "("+x+"."+y+")" + return None + return x.power_set() case 5: - return "("+y+"."+x+")" + return x.converse_relation() case 6: - return "pow("+x+")" + return x.reflexive_closure() case 7: - return "pow("+y+")" + return x.transitive_closure() case 8: - return "inverse("+x+")" + return x.multi_set_difference(y) case 9: - return "inverse("+y+")" - case 10: - return "reflexive_cl("+x+")" - case 11: - return "reflexive_cl("+y+")" - case 12: - return "transitive_cl("+x+")" - case 13: - return "transitive_cl("+y+")" + return x.disjoint_union(y) case _: raise ValueError("value not found") -def format_way_helper(operand, item, const_sets, results): +def format_way_helper(operand, reversed_const_dict, results): """ + Create a string for way by operand :type operand: MathSet | None - :type item: MathSet - :type const_sets: dict[str, MathSet] + :type reversed_const_dict: dict[MathSet, str] :type results: set[MathSet] :rtype: str + :raises SyntaxError: """ if operand is None: return "" - elif operand in const_sets.values(): - return list(const_sets.keys())[list(const_sets.values()).index(operand)] + elif operand in reversed_const_dict: + return reversed_const_dict[operand] else: - for a in results: - # TODO is this fastest? - if operand == a: - return format_way(a, const_sets, results) - raise SyntaxError(item.way) + if operand in results: + for a in results: + if operand == a: + return format_way(a.way, reversed_const_dict, results) + raise SyntaxError() -def format_way(item, const_sets, results): +def format_way(way, reversed_const_dict, results): """ - :type item: MathSet - :type const_sets: dict[str, MathSet] + make way printable + :type way: (MODE, (MathSet | None), (MathSet | None)) + :type reversed_const_dict: dict[MathSet, str] :type results: set[MathSet] :rtype: str + :raises SyntaxError: """ - if item.way == STATUS.CONST: - return list(const_sets.keys())[list(const_sets.values()).index(item)] - operator, operand1, operand2 = item.way - return s_tools(operator, format_way_helper(operand1, item, const_sets, results), - format_way_helper(operand2, item, const_sets, results)) - - -def check_set(check, const_sets, results): - """ - :type check: MathSet - :type const_sets: dict[str, MathSet] - :type results: set[MathSet] - """ - if check.total_deep_len() <= overflow: - results.add(check) - print(format_way(check, const_sets, results) + " --> " + str(check)) if DEBUG else None + operator, operand1, operand2 = way + try: + way_string = operator.format(format_way_helper(operand1, reversed_const_dict, results), + format_way_helper(operand2, reversed_const_dict, results)) + except SyntaxError: + raise SyntaxError(way) + return way_string -def get_valid_results(const_sets, result, results, do_print): +def found_result(reversed_const_dict, result, results, do_print): """ - :type const_sets: dict[str, MathSet] + search for 'result' in 'results' + if found return it else None + :type reversed_const_dict: dict[MathSet, str] :type result: MathSet :type results: set[MathSet] :type do_print: bool - :return: set[set] + :rtype: MathSet | None """ - valid_results = list() for a in results: - # TODO is this fastest? if result.value == a.value: - valid_results.append(a) - print("Calculated result: " + format_way(a, const_sets, results) + " --> " + str(a)) if do_print else None - return valid_results + if do_print: + print("Calculated result: " + format_way(a.way, reversed_const_dict, results) + " --> " + str(a)) + return a + return None -def search(const_sets, result, not_allowed=None, identity=None, do_print=True): +def search(const_dict, result, not_allowed=None, identity=None, overflow=30, range_int=20, do_print=True): """ - :type const_sets: dict[str, set[frozenset | int | tuple] | MathSet] - :type result: set[frozenset | int | tuple] | MathSet - :type not_allowed: list - :type identity: Identity + Search for way to get from consts by 'const_dict' to result + :type const_dict: dict[str, set[frozenset | int | tuple] | MathSet] | ConstDictType + :type result: set[frozenset | int | tuple] | MathSet | ResultType + :type not_allowed: list[MODE] + :type identity: RelationMathSet | None + :type overflow: int + :type range_int: int :type do_print: bool - :rtype: list[MathSet] | None + :rtype: ResultWay | None + :raises ValueError: """ - if not_allowed is None: - not_allowed = [4, 5, 8, 9, 10, 11, 12, 13] - - # UPDATE const_sets with frozen-sets to const_sets with MathSets - for y in const_sets.keys(): - if type(const_sets[y]) == set: - const_sets[y] = MathSet(SetSolver1.helper.update.to_tiny_math_set(const_sets[y]), identity, STATUS.CONST) - # UPDATE result with frozen-sets to result with MathSets - result = MathSet(SetSolver1.helper.update.to_tiny_math_set(result), identity, STATUS.CONST) - - if list(const_sets.values()) == set(list(const_sets.values())): + not_allowed = SetSolver1.MODE.DEFAULT_NOT_ALLOWED + + # UPDATE const_dict with frozen-sets to const_dict with MathSets + for y in const_dict.keys(): + if type(const_dict[y]) == set: + if sum(1 for x in const_dict[y] if type(x) != tuple) == 0: + const_dict[y] = RelationMathSet(const_dict[y], identity, CONST_WAY) + else: + const_dict[y] = SimpleMathSet(SetSolver1.helper.update.to_tiny_math_set(const_dict[y]), CONST_WAY) + const_dict[y].correct_way() + + const_dict: dict[str, MathSet] | ConstDictType + consts = list(const_dict.values()) + if consts == set(consts): raise ValueError('the dictionary values of set constants must be unique') + reversed_const_dict = dict((v, k) for k, v in const_dict.items()) + sorted_results = sorted_consts = sorted(consts, key=lambda i: i.sort_key()) - results: set[MathSet] = set(const_sets.values()) - - len_results_old = None - for len_obj in range(range_int): - len_results = len(results) - print(str(round((len_obj/(range_int-1))*100)) + "% / " + str(len_results)) if do_print else None - if len_results == len_results_old: - break # performance optimization - len_results_old = len_results - # TODO is sorted results.copy() better? - for x in results.copy(): - for y in [x for x in range(14) if x not in not_allowed]: - for z in const_sets.values(): - new = tools(y, x, z) - check_set(new, const_sets, results) - valid_results = get_valid_results(const_sets, result, results, do_print) - if len(valid_results) > 0: - return valid_results - - len_results_old = None - for len_obj in range(range_int): - len_results = len(results) - print("all: " + str(round((len_obj/(range_int-1))*100)) + "% / " + str(len_results)) if do_print else None - if len_results == len_results_old: - break # performance optimization - len_results_old = len_results - temp_results_list_for_power_set = results.copy() - # for x, y in combinations_with_replacement(results, 2): - for x, y in combinations_with_replacement(sorted(results, key=lambda i: i.sort_key()), 2): - for c in [x for x in range(14) if x not in not_allowed + [6, 7]]: - new = tools(c, x, y) - check_set(new, const_sets, results) - if 6 not in not_allowed: - # TODO is sorted temp_results_list_for_power_set better? - for x in temp_results_list_for_power_set: - new = MathSet(frozenset(), x.identity, (6, x, None)) if x.total_deep_len() >= (overflow / 2) \ - else x.power_set((6, x, None)) - # TODO None could be here a MathSet with value = None - check_set(new, const_sets, results) - valid_results = get_valid_results(const_sets, result, results, do_print) - if len(valid_results) > 0: - return valid_results + # UPDATE result with frozen-sets to result with MathSets + if type(result) == set: + result = SimpleMathSet(SetSolver1.helper.update.to_tiny_math_set(result), RESULT) + if isinstance(result, ResultType): + result = result.get() + result: MathSet + + very_cool = [1 if x.is_multi_mode() else 0 for x in SetSolver1.MODE.SORTED_CHOOSE_BY_INDEX if x not in not_allowed] + + results: set[MathSet] = set(consts) + + for mode in (1, 2): + len_results_old = None + for len_obj in range(range_int): + len_results = len(results) + print(str(mode) + ": " + str(round((len_obj/(range_int-1))*100)) + "% / " + str(len_results))\ + if do_print else None + if len_results == len_results_old: + break # performance optimization + len_results_old = len_results + if mode == 1: + my_iter = product( + sorted_results, + chain( + *( + product( + sorted_consts if x.is_multi_mode() else [False], + [x] + ) for x in SetSolver1.MODE.SORTED_CHOOSE_BY_INDEX if x not in not_allowed) + ) + ) + iter_list = list() + for x, (y, c) in my_iter: + iter_list.append((x, y, c)) + else: + my_iter = compress( + product( + combinations_with_replacement(sorted_results, 2), + [x for x in SetSolver1.MODE.SORTED_CHOOSE_BY_INDEX if x not in not_allowed] + ), [ + 1 if x or y == len(sorted_results)-z-1 else 0 + for z in range(len(sorted_results)) + for y in range(len(sorted_results)-z) + for x in very_cool + ] + ) + iter_list = list() + for (x, y), c in my_iter: + iter_list.append((x, y, c)) + + for x, y, c in iter_list: + new = tools(c, x, y, overflow) + results.add(new) if new is not None and new.total_deep_len() <= overflow else None + if c[2] == 0: + new = tools(c, y, x, overflow) + results.add(new) if new is not None and new.total_deep_len() <= overflow else None + valid_result = found_result(reversed_const_dict, result, results, do_print) + if valid_result is not None: + return ResultWay(valid_result, const_dict, reversed_const_dict, results) + sorted_results = sorted(results, key=lambda i: i.sort_key()) print("Nothing found :(") if do_print else None return None - - -overflow = 30 -range_int = 20 -DEBUG = False diff --git a/SetSolver1/math_set.py b/SetSolver1/math_set.py deleted file mode 100644 index aec115b..0000000 --- a/SetSolver1/math_set.py +++ /dev/null @@ -1,365 +0,0 @@ -from __future__ import annotations -from itertools import chain, combinations -import SetSolver1.MODE -from SetSolver1.STATUS import STATUS - - -class Identity: - value: frozenset[int] - - def __init__(self, value): - if type(value) == frozenset: - self.value = value - elif type(value) == set or type(value) == list: - self.value = frozenset(value) - else: - raise ValueError("value not found") - - self.math_set = MathSet(self.value, self, STATUS.NONE) - - def __repr__(self): - return "{0}({1})".format(type(self).__name__, set(self.value)) - - def __hash__(self): - return hash(self.value) - - -class TinyMathSet(frozenset): - _total_deep_len = None - - def __repr__(self): - if self == frozenset(): - return "{}" - return str(set(self)) - - def deep_len(self): - return sum(el.deep_len() if isinstance(el, TinyMathSet) else 1 for el in self) - - def total_deep_len(self): - if self._total_deep_len is None: - self._total_deep_len = sum(el.total_deep_len()+1 if isinstance(el, TinyMathSet) else 1 for el in self) - return self._total_deep_len - - -class MathSet: - value: frozenset[TinyMathSet | int | tuple] - identity: Identity | None - way: (int, MathSet | None, MathSet | None) | STATUS - - def __init__(self, value, identity, way): - """ - init MathSet - :type value: frozenset | collections.abc.Iterable - :type identity: Identity | None - :type way: (int, MathSet | None, MathSet | None) | STATUS - """ - if type(value) == frozenset: - self.value = value - else: - self.value = frozenset(value) - - self.identity = identity - if way is None: - way = STATUS.NONE - self.way = way - - def __str__(self): - if self.is_empty(): - return "{}" - return str(set(self.value)) - - def __repr__(self): - return self.value, self.identity, self.way - - def __hash__(self): - # Default: hash(x)==id(x)/16 - # https://stackoverflow.com/a/11324771 - # https://docs.python.org/3/glossary.html#term-hashable - return hash(self.value) - - def __eq__(self, other): - if isinstance(other, MathSet): - return self.value == other.value - print("NotImplemented Equality Compare") - return NotImplemented - - def __len__(self): - """ - :rtype: int - """ - return len(self.value) - - def type_check(self, y): - """ - Check if the type of MathSets is comparable - :type y: MathSet - """ - if self.identity != y.identity: - raise TypeError("type_check error") - - def deep_len(self): - return sum(el.deep_len() if isinstance(el, TinyMathSet) else 1 for el in self.value) - - def total_deep_len(self): - return sum(el.total_deep_len()+1 if isinstance(el, TinyMathSet) else 1 for el in self.value) - - def walk_way(self, going_by=None): - if self.way == STATUS.NONE: - raise ValueError("STATUS.NONE not allowed here") - if self.way == STATUS.CONST: - return 0 - - mode = SetSolver1.MODE.CHOOSE_BY_INDEX[self.way[0]] - if going_by is None: - going_by = mode[2] - # set to priority of operator - # to sort equal length like (pow(pow((A-A)))+B) / (pow((pow(A)&B))+B) [Aufgabe 2] - lt = list() - for i in mode[1]: - if self.way[i] is not None: - lt.append(self.way[i].walk_way()) - return sum(lt) + going_by - - def sort_key(self): - return self.walk_way(going_by=1), self.walk_way() - - def is_empty(self): - """ - Is MathSet empty? - :rtype: bool - """ - return self.value == frozenset() - - def union(self, y, way=None): - """ - German: Vereinigungsmenge - :type y: MathSet - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - self.type_check(y) - # self.value.union(y.value) - copy = set(self.value) - copy.update(y.value) - return MathSet(copy, self.identity, way) - - def complement(self, y, way=None): - """ - German: Komplement - Subtraktion von Mengen - :type y: MathSet - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - self.type_check(y) - return MathSet(self.value.difference(y.value), self.identity, way) - - def intersection(self, y, way=None): - """ - German: Schnittmenge - :type y: MathSet - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - self.type_check(y) - return MathSet(self.value.intersection(y.value), self.identity, way) - - def power_set(self, way=None): - """ - German: Potenzmenge - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - return MathSet( - [TinyMathSet(y) for y in chain.from_iterable( - combinations(self.value, i) for i in range(len(self) + 1))], - self.identity, way) - - def composition(self, y, way=None): - """ - TODO optimization - German: Verkettung - :type y: MathSet - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - self.type_check(y) - lst = list() - for x1 in self.value: - for y1 in y.value: - if x1[1] == y1[0]: - lst.append((x1[0], y1[1])) - return MathSet(lst, self.identity, way) - - def symmetric_difference(self, y, way=None): - """ - German: Symmetrische Differenz - :type y: MathSet - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - self.type_check(y) - return MathSet(self.value.symmetric_difference(y.value), self.identity, way) - - def do(self): - """ - German: Erstelle Relation aus Menge - :rtype: MathSet - """ - items = list() - for x1 in self.value: - if type(x1) != int and type(x1) != str: - return None - else: - for x2 in self.value: - items.append((x1, x2)) - return MathSet(items, self.identity, STATUS.NONE) - - def converse_relation(self, way=None): - """ - TODO optimization - German: Inverse (Umkehrrelation) - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - return MathSet(((x1[1], x1[0]) for x1 in self.value), self.identity, way) - - def reflexive_closure(self, way=None): - """ - TODO optimization - German: Reflexive Hülle - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - return MathSet(list(self.value) + [(x3, x3) for x3 in set([x1[x2] for x2 in range(2) for x1 in self.value])], - self.identity, way) - - def transitive_closure(self, way=None): - """ - TODO optimization - German: Transitive Hülle - :type way: (int, MathSet | None, MathSet | None) | STATUS - :rtype: MathSet - """ - # {(1 , 1) , (2 , #3#) , (#3# , 1)} -> {(1 , 1) , #(2 , 1)# , (2 , 3), (3 , 1)} - return MathSet(list(self.value) + [(x1[0], x2[1]) for x2 in self.value for x1 in self.value if x1[1] == x2[0]], - self.identity, way) - - def is_reflexive(self): - """ - :rtype: bool - """ - if self.identity is None: - return self.value == self.reflexive_closure().value - return self.identity.math_set.is_subset(self) - - def is_irreflexive(self): - """ - :rtype: bool - """ - if self.identity is None: - """ - One-Line - return frozenset((x3, x3) for x3 in set([x1[x2] for x2 in range(2) for x1 in self.value]) - if (x3, x3) in self.value) == frozenset() - """ - for x1 in self.value: - if (x1[0], x1[0]) in self.value or (x1[1], x1[1]) in self.value: - return False - return True - return self.intersection(self.identity.math_set).is_empty() - - def is_subset(self, y): - """ - is_subset - :type y: MathSet - :rtype: MathSet - """ - # self.value.issubset(y.value) - self.type_check(y) - for x1 in self.value: - if x1 not in y.value: - return False - return True - - def is_symmetric_relation(self): - """ - :rtype: bool - """ - return self.converse_relation().is_subset(self) - - def is_asymmetric_relation(self): - """ - :rtype: bool - """ - return self.intersection(self.converse_relation()).is_empty() - - def is_antisymmetric_relation(self): - """ - :rtype: bool - """ - if self.identity is None: - for x1 in self.value: - if x1[::-1] in self.value and not x1[0] == x1[1]: - return False - return True - return self.intersection(self.converse_relation()).is_subset(self.identity.math_set) - - def is_transitive(self): - """ - :rtype: bool - """ - return self.value == self.transitive_closure().value - - def is_preorder(self): - """ - German: Quasiordnung - :return: bool - """ - return self.is_reflexive() and self.is_transitive() - - def is_equivalence_relation(self): - """ - German: Äquivalenzrelation (symmetrische Quasiordnung) - :return: bool - """ - return self.is_preorder() and self.is_symmetric_relation() - - def is_non_strict_partial_order(self): - """ - German: Halbordnung (partielle Ordnung) - :return: bool - """ - return self.is_reflexive() and self.is_antisymmetric_relation() and self.is_transitive() - - def is_strict_partial_order(self): - """ - German: Strikte Ordnung - :return: bool - """ - return self.is_irreflexive() and self.is_transitive() and self.is_asymmetric_relation() - - def get_identity(self): - """ - Menge auf die die binäre Relation beruht - :rtype: Identity | None - """ - items = list() - for x in self.value: - if type(x) != int and type(x) != str: - return None - else: - items.append((x, x)) - - return Identity(items) - - def print_properties(self): - """ - Print all properties of this set with relations - :return: None - """ - print("is_reflexive: " + str(self.is_reflexive())) - print("is_irreflexive: " + str(self.is_irreflexive())) - print("is_symmetrisch: " + str(self.is_symmetric_relation())) - print("is_asymmetrisch: " + str(self.is_asymmetric_relation())) - print("is_antisymmetrisch: " + str(self.is_antisymmetric_relation())) - print("is_transitiv: " + str(self.is_transitive())) diff --git a/TODO.txt b/TODO.txt deleted file mode 100644 index 8532d96..0000000 --- a/TODO.txt +++ /dev/null @@ -1,4 +0,0 @@ -# TODO max größe vom Ausdruck -# TODO for search for frozenset({}) - -# TODO create own class as subtype of set and use it for union, complement etc. diff --git a/beispiele.md b/beispiele.md index 0572fe0..3c9b961 100644 --- a/beispiele.md +++ b/beispiele.md @@ -1,23 +1,37 @@ # German Examples +Credits for the examples goes to: https://gitlab.imn.htwk-leipzig.de/autotool/all0/ + ## Inhalt ### Mengen -- [Aufgabe (demo)](#aufgabe-demo) -- [Aufgabe 1](#aufgabe-1) -- [Aufgabe 2](#aufgabe-2) -- [Aufgabe 3](#aufgabe-3) -- [Aufgabe 4](#aufgabe-4) -- [Aufgabe 5](#aufgabe-5) -- [Aufgabe 6](#aufgabe-6) +- [Aufgabe 1.demo](#aufgabe-1.demo) +- [Aufgabe 1.1](#aufgabe-1.1) +- [Aufgabe 1.2](#aufgabe-1.2) +- [Aufgabe 1.3](#aufgabe-1.3) +- [Aufgabe 1.4](#aufgabe-1.4) +- [Aufgabe 1.5](#aufgabe-1.5) +- [Aufgabe 1.6](#aufgabe-1.6) ### Mengen mit Relationen -- coming soon +- [Aufgabe 2.demo](#aufgabe-2.demo) +- [Aufgabe 2.1](#aufgabe-2.1) +- [Aufgabe 2.2](#aufgabe-2.2) +- [Aufgabe 2.3](#aufgabe-2.3) +- [Aufgabe 2.4](#aufgabe-2.4) + + +### MultiMengen +- [Aufgabe 3.demo](#aufgabe-3.demo) +- [Aufgabe 3.1](#aufgabe-3.1) +- [Aufgabe 3.2](#aufgabe-3.2) + +--- --- -### [Aufgabe (demo)](/examples/sets/aufgabe0.py) +### [Aufgabe 1.demo](/examples/sets/exercice0.py) Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: @@ -37,14 +51,14 @@ und diese vordefinierten Konstanten: A = {1, 2} B = {1} -Calculated result(s): +Calculated result: (pow(A)-pow(B)) --> {{2}, {1, 2}} - Calculation ended after 0.56 sec + Calculation ended after 0.063 sec * * * -### [Aufgabe 1](/examples/sets/aufgabe1.py) +### [Aufgabe 1.1](/examples/sets/exercice1.py) Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: {{{{3}}}} @@ -63,14 +77,14 @@ und diese vordefinierten Konstanten: A = {{}, {2}, {3}} B = {{}, {{3}}} -Calculated result(s): +Calculated result: (pow((B-A))-A) --> {{{{3}}}} - Calculation ended after 0.005 sec + Calculation ended after 0.001 sec * * * -### [Aufgabe 2](/examples/sets/aufgabe2.py) +### [Aufgabe 1.2](/examples/sets/exercice2.py) Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: {{}, {3}, {5}, {{}}} @@ -89,14 +103,14 @@ und diese vordefinierten Konstanten: A = {{2, {}}, {5}} B = {{}, {3}, {5}} -Calculated result(s): +Calculated result: (pow(pow((A-A)))+B) --> {{3}, {{}}, {}, {5}} - Calculation ended after 0.013 sec + Calculation ended after 0.003 sec * * * -### [Aufgabe 3](/examples/sets/aufgabe3.py) +### [Aufgabe 1.3](/examples/sets/exercice3.py) Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: {6, {2}} @@ -116,14 +130,14 @@ und diese vordefinierten Konstanten: V = {1, 2, 4, 6, {3}} W = {4, {2}} -Calculated result(s): +Calculated result: - (((W-V)+U)-(U-V)) --> {{2}, 6} - Calculation ended after 320.397 sec + ((V+W)-(V-U)) --> {{2}, 6} + Calculation ended after 4.58 sec * * * -### [Aufgabe 4](/examples/sets/aufgabe4.py) +### [Aufgabe 1.4](/examples/sets/exercice4.py) Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: {{}, {1, 2, {3}}, {1, {3}}, {2, {3}}, {{3}}} @@ -142,14 +156,14 @@ und diese vordefinierten Konstanten: A = {1, 2} B = {{3}} -Calculated result(s): +Calculated result: (pow(B)+(pow((A+B))-pow(A))) --> {{{3}, 1}, {{3}, 1, 2}, {}, {{3}, 2}, {{3}}} - Calculation ended after 2.889 sec + Calculation ended after 0.29 sec * * * -### [Aufgabe 5](/examples/sets/aufgabe5.py) +### [Aufgabe 1.5](/examples/sets/exercice5.py) Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: @@ -169,14 +183,14 @@ und diese vordefinierten Konstanten: A = {{2, {5, {1}}}} B = {{}, {5, {}}} -Calculated result(s): +Calculated result: (pow((B-pow(A)))+B) --> {{}, {{}, 5}, {{{}, 5}}} - Calculation ended after 0.008 sec + Calculation ended after 0.002 sec * * * -### [Aufgabe 6](/examples/sets/aufgabe6.py) +### [Aufgabe 1.6](/examples/sets/exercice6.py) Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: @@ -196,7 +210,252 @@ und diese vordefinierten Konstanten: A = {4, {4}, {5}} B = {5, {}, {{}}} -Calculated result(s): +Calculated result: ((A+B)&pow(B)) --> {{}, {{}}, {5}} - Calculation ended after 32.459 sec + Calculation ended after 0.994 sec + +--- +--- + +### [Aufgabe 2.demo](/examples/sets-relations/exercice0.py) + +Die folgende Aufgabe bezieht sich auf Relationen +über dem Grundbereich mkSet + + [ 1, 2, 3] + +Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: + + {(3 , 3)} + +Der Ausdruck soll höchstens die Größe _7_ haben.\ +Sie dürfen diese Symbole benutzen + + Operator-Symbole: + zweistellige : [ +, -, &, .] + einstellige : [ inverse, reflexive_cl, transitive_cl] + nullstellige : [ ] + Funktions-Symbole: [ ] + +und diese vordefinierten Konstanten: + + R = {(1 , 2) , (3 , 2)} + S = {(1 , 1) , (2 , 3) , (3 , 1)} + +Calculated result: + + ((inverse(S)&R).S) --> {(3, 3)} + Calculation ended after 0.004 sec + +* * * + +### [Aufgabe 2.1](/examples/sets-relations/exercice1.py) + +Die folgende Aufgabe bezieht sich auf Relationen +über dem Grundbereich mkSet + + [ 1, 2, 3] + +Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: + + {(1 , 1) , (1 , 2) , (1 , 3), (2 , 1) , (2 , 2)} + +Der Ausdruck soll höchstens die Größe _20_ haben.\ +Sie dürfen diese Symbole benutzen + + Operator-Symbole: + zweistellige : [ +, -, &, .] + einstellige : [ ] + nullstellige : [ ] + Funktions-Symbole: [ ] + +und diese vordefinierten Konstanten: + + R = {(2 , 1) , (3 , 1) , (3 , 2)} + S = {(1 , 2) , (1 , 3) , (2 , 1)} + +Calculated result: + + (S.((S.(S+R))+R)) --> {(1, 2), (2, 1), (2, 2), (1, 1), (1, 3)} + Calculation ended after 0.007 sec + +* * * + +### [Aufgabe 2.2](/examples/sets-relations/exercice2.py) + +Die folgende Aufgabe bezieht sich auf Relationen +über dem Grundbereich mkSet + + [ 1, 2, 3, 4] + +Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: + + {(1 , 3) , (3 , 1) , (3 , 2) , (3 , 4) , (4 , 3)} + +Der Ausdruck soll höchstens die Größe _30_ haben.\ +Sie dürfen diese Symbole benutzen + + Operator-Symbole: + zweistellige : [ +, -, &, .] + einstellige : [ inverse] + nullstellige : [ ] + Funktions-Symbole: [ ] + +und diese vordefinierten Konstanten: + + R = {(1 , 1) , (1 , 4) , (3 , 3) , (4 , 4)} + S = {(2 , 3) , (3 , 1) , (3 , 2) , (3 , 4)} + +Calculated result: + + (R.(inverse(S)+S)) --> {(3, 4), (4, 3), (3, 1), (3, 2), (1, 3)} + Calculation ended after 0.003 sec + +* * * + +### [Aufgabe 2.3](/examples/sets-relations/exercice3.py) + +Die folgende Aufgabe bezieht sich auf Relationen +über dem Grundbereich mkSet + + [ 1, 2, 3, 4] + +Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: + + {(3 , 2) , (3 , 3) , (4 , 1) , (4 , 3) , (4 , 4)} + +Der Ausdruck soll höchstens die Größe _20_ haben.\ +Sie dürfen diese Symbole benutzen + + Operator-Symbole: + zweistellige : [ +, -, &, .] + einstellige : [ inverse, transitive_cl, reflexive_cl] + nullstellige : [ ] + Funktions-Symbole: [ ] + +und diese vordefinierten Konstanten: + + R = {(1 , 3) , (2 , 1) , (3 , 1) , (4 , 3)} + S = {(3 , 2) , (3 , 3) , (4 , 3) , (4 , 4)} + +Calculated result: + + (((S&R).R)+S) --> {(4, 4), (3, 3), (4, 3), (3, 2), (4, 1)} + Calculation ended after 0.009 sec + +* * * + +### [Aufgabe 2.4](/examples/sets-relations/exercice4.py) + +Die folgende Aufgabe bezieht sich auf Relationen +über dem Grundbereich mkSet + + [ 1, 2, 3, 4] + +Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: + + {(3 , 1)} + +Der Ausdruck soll höchstens die Größe _50_ haben.\ +Sie dürfen diese Symbole benutzen + + Operator-Symbole: + zweistellige : [ +, -, &, .] + einstellige : [ inverse, transitive_cl, reflexive_cl] + nullstellige : [ ] + Funktions-Symbole: [ ] + +und diese vordefinierten Konstanten: + + R = {(1 , 2) , (4 , 3)} + S = {(1 , 3) , (2 , 4)} + +Calculated result: + + inverse(((R.S).R)) --> {(3, 1)} + Calculation ended after 0.003 sec + +--- +--- + +### [Aufgabe 3.demo](/examples/multisets/exercice0.py) + +Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: + + {q:1} + +Der Ausdruck soll höchstens die Größe _30_ haben.\ +Sie dürfen diese Symbole benutzen + + Operator-Symbole: + zweistellige : [ +, -, &] + einstellige : [ ] + nullstellige : [ ] + Funktions-Symbole: [ ] + +und diese vordefinierten Konstanten: + + A = {p:1, q:3} + B = {q:2, r:3} + C = {q:1, r:1} + +Calculated result: + + (C&A) --> {'q': 1} + Calculation ended after 0.0 sec + +* * * + +### [Aufgabe 3.1](/examples/multisets/exercice1.py) + +Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: + + {p:3, q:7, s:5} + +Der Ausdruck soll höchstens die Größe _25_ haben.\ +Sie dürfen diese Symbole benutzen + + Operator-Symbole: + zweistellige : [ +, -, &] + einstellige : [ ] + nullstellige : [ ] + Funktions-Symbole: [ ] + +und diese vordefinierten Konstanten: + + A = {p:2, q:1, r:2, t:2, u:4} + B = {p:1, q:5, s:5} + +Calculated result: + + ((A&B)+((A&B)+B)) --> {'p': 3, 'q': 7, 's': 5} + Calculation ended after 0.305 sec + +* * * + +### [Aufgabe 3.2](/examples/multisets/exercice2.py) + +Gesucht ist ein Ausdruck (Term) mit dieser Bedeutung: + + {p:4, r:11, t:5, u:8} + +Der Ausdruck soll höchstens die Größe _30_ haben.\ +Sie dürfen diese Symbole benutzen + + Operator-Symbole: + zweistellige : [ +, -, &] + einstellige : [ ] + nullstellige : [ ] + Funktions-Symbole: [ ] + +und diese vordefinierten Konstanten: + + A = {p:2, r:5, t:3, u:2} + B = {q:5, s:2, t:1} + C = {r:1, u:4} + +Calculated result: + + (((A+C)+A)-B) --> {'p': 4, 'r': 11, 't': 5, 'u': 8} + Calculation ended after 0.004 sec diff --git a/examples/multisets/exercice0.py b/examples/multisets/exercice0.py new file mode 100644 index 0000000..5a961fd --- /dev/null +++ b/examples/multisets/exercice0.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, MODE, MultiMathSetConstDictType, MultiMathSetResultType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = MultiMathSetConstDictType( + { + "A": {"p": 1, "q": 3}, + "B": {"q": 2, "r": 3}, + "C": {"q": 1, "r": 1} + } +) + +# Here you set your wanted solution. +result = MultiMathSetResultType({"q": 1}) + +not_allowed = [MODE.UNION, MODE.COMPLEMENT, MODE.COMPOSITION, MODE.POWER_SET, MODE.CONVERSE_RELATION, + MODE.REFLEXIVE_CLOSURE, MODE.TRANSITIVE_CLOSURE] + +start_time = timer() +search(const_dict, result, not_allowed) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/multisets/exercice1.py b/examples/multisets/exercice1.py new file mode 100644 index 0000000..305fb14 --- /dev/null +++ b/examples/multisets/exercice1.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, MODE, MultiMathSetConstDictType, MultiMathSetResultType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = MultiMathSetConstDictType( + { + "A": {"p": 2, "q": 1, "r": 2, "t": 2, "u": 4}, + "B": {"p": 1, "q": 5, "s": 5} + } +) + +# Here you set your wanted solution. +result = MultiMathSetResultType({"p": 3, "q": 7, "s": 5}) + +not_allowed = [MODE.UNION, MODE.COMPLEMENT, MODE.COMPOSITION, MODE.POWER_SET, MODE.CONVERSE_RELATION, + MODE.REFLEXIVE_CLOSURE, MODE.TRANSITIVE_CLOSURE] + +start_time = timer() +search(const_dict, result, not_allowed) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/multisets/exercice2.py b/examples/multisets/exercice2.py new file mode 100644 index 0000000..c38c3a0 --- /dev/null +++ b/examples/multisets/exercice2.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, MODE, MultiMathSetConstDictType, MultiMathSetResultType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = MultiMathSetConstDictType( + { + "A": {"p": 2, "r": 5, "t": 3, "u": 2}, + "B": {"q": 5, "s": 2, "t": 1}, + "C": {"r": 1, "u": 4} + } +) + +# Here you set your wanted solution. +result = MultiMathSetResultType({"p": 4, "r": 11, "t": 5, "u": 8}) + +not_allowed = [MODE.UNION, MODE.COMPLEMENT, MODE.COMPOSITION, MODE.POWER_SET, MODE.CONVERSE_RELATION, + MODE.REFLEXIVE_CLOSURE, MODE.TRANSITIVE_CLOSURE] + +start_time = timer() +search(const_dict, result, not_allowed, overflow=33) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/aufgabe1.py b/examples/sets-relations/aufgabe1.py deleted file mode 100644 index ff494e7..0000000 --- a/examples/sets-relations/aufgabe1.py +++ /dev/null @@ -1,21 +0,0 @@ -from SetSolver1 import search -from timeit import default_timer as timer - -# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. - -# Here you set your predefined constants. -# Please make sure that you do not assign a variable letter twice. -# Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int | tuple]] = { - "R": {(2, 1), (3, 1), (3, 2)}, - "S": {(1, 2), (1, 3), (2, 1)} -} - -# Here you set your wanted solution. -result = {(1, 1), (1, 2), (1, 3), (2, 1), (2, 2)} - -not_allowed = [6, 7, 8, 9, 10, 11, 12, 13] - -start_time = timer() -search(const_sets, result, not_allowed) -print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/aufgabe4.py b/examples/sets-relations/aufgabe4.py deleted file mode 100644 index 65bfcf8..0000000 --- a/examples/sets-relations/aufgabe4.py +++ /dev/null @@ -1,21 +0,0 @@ -from SetSolver1 import search -from timeit import default_timer as timer - -# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. - -# Here you set your predefined constants. -# Please make sure that you do not assign a variable letter twice. -# Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int | tuple]] = { - "R": {(1, 2), (4, 3)}, - "S": {(1, 3), (2, 4)} -} - -# Here you set your wanted solution. -result = {(3, 1)} - -not_allowed = [6, 7] - -start_time = timer() -search(const_sets, result, not_allowed) -print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/exercice0.py b/examples/sets-relations/exercice0.py new file mode 100644 index 0000000..482e5e2 --- /dev/null +++ b/examples/sets-relations/exercice0.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, MODE, RelationMathSetConstDictType, RelationMathSetResultType,\ + RelationMathSetIdentityType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you can set an identity relation. +identity = RelationMathSetIdentityType({(1, 1), (2, 2), (3, 3)}).get() + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = RelationMathSetConstDictType( + { + "R": {(1, 2), (3, 2)}, + "S": {(1, 1), (2, 3), (3, 1)} + }, + identity=identity +) + +# Here you set your wanted solution. +result = RelationMathSetResultType({(3, 3)}, identity=identity) + +not_allowed = [MODE.POWER_SET, MODE.MULTISET_DIFFERENCE, MODE.MULTISET_DISJOINT_UNION] + +start_time = timer() +search(const_dict, result, not_allowed) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/exercice1.py b/examples/sets-relations/exercice1.py new file mode 100644 index 0000000..28d9366 --- /dev/null +++ b/examples/sets-relations/exercice1.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, MODE, RelationMathSetConstDictType, RelationMathSetResultType, \ + RelationMathSetIdentityType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you can set an identity relation. +identity = RelationMathSetIdentityType({(1, 1), (2, 2), (3, 3)}).get() + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = RelationMathSetConstDictType( + { + "R": {(2, 1), (3, 1), (3, 2)}, + "S": {(1, 2), (1, 3), (2, 1)} + }, + identity=identity +) + +# Here you set your wanted solution. +result = RelationMathSetResultType({(1, 1), (1, 2), (1, 3), (2, 1), (2, 2)}, identity=identity) + +not_allowed = [MODE.POWER_SET, MODE.CONVERSE_RELATION, MODE.REFLEXIVE_CLOSURE, MODE.TRANSITIVE_CLOSURE, + MODE.MULTISET_DIFFERENCE, MODE.MULTISET_DISJOINT_UNION] + +start_time = timer() +search(const_dict, result, not_allowed) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/exercice2.py b/examples/sets-relations/exercice2.py new file mode 100644 index 0000000..8bb7ab3 --- /dev/null +++ b/examples/sets-relations/exercice2.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, MODE, RelationMathSetConstDictType, RelationMathSetResultType, \ + RelationMathSetIdentityType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you can set an identity relation. +identity = RelationMathSetIdentityType({(1, 1), (2, 2), (3, 3)}).get() + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = RelationMathSetConstDictType( + { + "R": {(1, 1), (1, 4), (3, 3), (4, 4)}, + "S": {(2, 3), (3, 1), (3, 2), (3, 4)} + }, + identity=identity +) + +# Here you set your wanted solution. +result = RelationMathSetResultType({(1, 3), (3, 1), (3, 2), (3, 4), (4, 3)}, identity=identity) + +not_allowed = [MODE.POWER_SET, MODE.REFLEXIVE_CLOSURE, MODE.TRANSITIVE_CLOSURE, + MODE.MULTISET_DIFFERENCE, MODE.MULTISET_DISJOINT_UNION] + +start_time = timer() +search(const_dict, result, not_allowed) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/exercice3.py b/examples/sets-relations/exercice3.py new file mode 100644 index 0000000..bd94119 --- /dev/null +++ b/examples/sets-relations/exercice3.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, MODE, RelationMathSetConstDictType, RelationMathSetResultType, \ + RelationMathSetIdentityType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you can set an identity relation. +identity = RelationMathSetIdentityType({(1, 1), (2, 2), (3, 3)}).get() + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = RelationMathSetConstDictType( + { + "R": {(1, 3), (2, 1), (3, 1), (4, 3)}, + "S": {(3, 2), (3, 3), (4, 3), (4, 4)} + }, + identity=identity +) + +# Here you set your wanted solution. +result = RelationMathSetResultType({(3, 2), (3, 3), (4, 1), (4, 3), (4, 4)}, identity=identity) + +not_allowed = [MODE.POWER_SET, MODE.MULTISET_DIFFERENCE, MODE.MULTISET_DISJOINT_UNION] + +start_time = timer() +search(const_dict, result, not_allowed) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/exercice4.py b/examples/sets-relations/exercice4.py new file mode 100644 index 0000000..22a8619 --- /dev/null +++ b/examples/sets-relations/exercice4.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, MODE, RelationMathSetConstDictType, RelationMathSetResultType, \ + RelationMathSetIdentityType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you can set an identity relation. +identity = RelationMathSetIdentityType({(1, 1), (2, 2), (3, 3)}).get() + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = RelationMathSetConstDictType( + { + "R": {(1, 2), (4, 3)}, + "S": {(1, 3), (2, 4)} + }, + identity=identity +) + +# Here you set your wanted solution. +result = RelationMathSetResultType({(3, 1)}, identity=identity) + +not_allowed = [MODE.POWER_SET, MODE.MULTISET_DIFFERENCE, MODE.MULTISET_DISJOINT_UNION] + +start_time = timer() +search(const_dict, result, not_allowed) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/aufgabe0.py b/examples/sets/aufgabe0.py deleted file mode 100644 index 53ba667..0000000 --- a/examples/sets/aufgabe0.py +++ /dev/null @@ -1,20 +0,0 @@ -from SetSolver1 import search -from timeit import default_timer as timer - -# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. - -# Here you set your predefined constants. -# Please make sure that you do not assign a variable letter twice. -# Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int]] = { - "A": {1, 2}, - "B": {1} -} - -# Here you set your wanted solution. -result = {frozenset({1, 2}), frozenset({2})} - - -start_time = timer() -search(const_sets, result) -print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/aufgabe1.py b/examples/sets/aufgabe1.py deleted file mode 100644 index a53639f..0000000 --- a/examples/sets/aufgabe1.py +++ /dev/null @@ -1,20 +0,0 @@ -from SetSolver1 import search -from timeit import default_timer as timer - -# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. - -# Here you set your predefined constants. -# Please make sure that you do not assign a variable letter twice. -# Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int]] = { - "A": {frozenset(), frozenset({2}), frozenset({3})}, - "B": {frozenset(), frozenset({frozenset({3})})} -} - -# Here you set your wanted solution. -result = {frozenset({frozenset({frozenset({3})})})} - - -start_time = timer() -search(const_sets, result) -print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/aufgabe2.py b/examples/sets/aufgabe2.py deleted file mode 100644 index 70fc58e..0000000 --- a/examples/sets/aufgabe2.py +++ /dev/null @@ -1,20 +0,0 @@ -from SetSolver1 import search -from timeit import default_timer as timer - -# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. - -# Here you set your predefined constants. -# Please make sure that you do not assign a variable letter twice. -# Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int]] = { - "A": {frozenset({2, frozenset()}), frozenset({5})}, - "B": {frozenset(), frozenset({3}), frozenset({5})} -} - -# Here you set your wanted solution. -result = {frozenset(), frozenset({3}), frozenset({5}), frozenset({frozenset()})} - - -start_time = timer() -search(const_sets, result) -print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/aufgabe3.py b/examples/sets/aufgabe3.py deleted file mode 100644 index 6be1676..0000000 --- a/examples/sets/aufgabe3.py +++ /dev/null @@ -1,21 +0,0 @@ -from SetSolver1 import search -from timeit import default_timer as timer - -# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. - -# Here you set your predefined constants. -# Please make sure that you do not assign a variable letter twice. -# Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int]] = { - "U": {3, 5, 6, frozenset({1})}, - "V": {1, 2, 4, 6, frozenset({3})}, - "W": {4, frozenset({2})} -} - -# Here you set your wanted solution. -result = {6, frozenset({2})} - - -start_time = timer() -search(const_sets, result) -print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/aufgabe4.py b/examples/sets/aufgabe4.py deleted file mode 100644 index ba0e7f5..0000000 --- a/examples/sets/aufgabe4.py +++ /dev/null @@ -1,21 +0,0 @@ -from SetSolver1 import search -from timeit import default_timer as timer - -# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. - -# Here you set your predefined constants. -# Please make sure that you do not assign a variable letter twice. -# Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int]] = { - "A": {1, 2}, - "B": {frozenset({3})} -} - -# Here you set your wanted solution. -result = {frozenset(), frozenset({1, 2, frozenset({3})}), frozenset({1, frozenset({3})}), - frozenset({2, frozenset({3})}), frozenset({frozenset({3})})} - - -start_time = timer() -search(const_sets, result) -print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/aufgabe5.py b/examples/sets/aufgabe5.py deleted file mode 100644 index 745bb16..0000000 --- a/examples/sets/aufgabe5.py +++ /dev/null @@ -1,20 +0,0 @@ -from SetSolver1 import search -from timeit import default_timer as timer - -# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. - -# Here you set your predefined constants. -# Please make sure that you do not assign a variable letter twice. -# Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int]] = { - "A": {frozenset({2, frozenset({5, frozenset({1})})})}, - "B": {frozenset(), frozenset({5, frozenset()})} -} - -# Here you set your wanted solution. -result = {frozenset(), frozenset(frozenset({5, frozenset({})})), frozenset({frozenset(frozenset({5, frozenset({})}))})} - - -start_time = timer() -search(const_sets, result) -print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/aufgabe6.py b/examples/sets/exercice0.py similarity index 60% rename from examples/sets/aufgabe6.py rename to examples/sets/exercice0.py index 140695c..e9caf49 100644 --- a/examples/sets/aufgabe6.py +++ b/examples/sets/exercice0.py @@ -1,4 +1,7 @@ -from SetSolver1 import search +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, SimpleMathSetConstDictType, SimpleMathSetResultType from timeit import default_timer as timer # THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. @@ -6,15 +9,17 @@ # Here you set your predefined constants. # Please make sure that you do not assign a variable letter twice. # Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int]] = { - "A": {4, frozenset({4}), frozenset({5})}, - "B": {5, frozenset(), frozenset({frozenset()})} -} +const_dict = SimpleMathSetConstDictType( + { + "A": {1, 2}, + "B": {1} + } +) # Here you set your wanted solution. -result = {frozenset(), frozenset({5}), frozenset({frozenset()})} +result = SimpleMathSetResultType({frozenset({1, 2}), frozenset({2})}) start_time = timer() -search(const_sets, result) +search(const_dict, result) print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/exercice1.py b/examples/sets/exercice1.py new file mode 100644 index 0000000..55c2f12 --- /dev/null +++ b/examples/sets/exercice1.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, SimpleMathSetConstDictType, SimpleMathSetResultType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = SimpleMathSetConstDictType( + { + "A": {frozenset(), frozenset({2}), frozenset({3})}, # string "[[],[2],[3]]" is allowed too + "B": {frozenset(), frozenset({frozenset({3})})} # string "{{},{{3}}}" too + } +) + +# Here you set your wanted solution. +result = SimpleMathSetResultType({frozenset({frozenset({frozenset({3})})})}) # as string "{{{{3}}}}" + + +start_time = timer() +search(const_dict, result) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/aufgabe0.py b/examples/sets/exercice2.py similarity index 52% rename from examples/sets-relations/aufgabe0.py rename to examples/sets/exercice2.py index 433c2b0..f5291e5 100644 --- a/examples/sets-relations/aufgabe0.py +++ b/examples/sets/exercice2.py @@ -1,4 +1,7 @@ -from SetSolver1 import search +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, SimpleMathSetConstDictType, SimpleMathSetResultType from timeit import default_timer as timer # THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. @@ -6,16 +9,17 @@ # Here you set your predefined constants. # Please make sure that you do not assign a variable letter twice. # Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int | tuple]] = { - "R": {(1, 2), (3, 2)}, - "S": {(1, 1), (2, 3), (3, 1)} -} +const_dict = SimpleMathSetConstDictType( + { + "A": {frozenset({2, frozenset()}), frozenset({5})}, + "B": {frozenset(), frozenset({3}), frozenset({5})} + } +) # Here you set your wanted solution. -result = {(3, 3)} +result = SimpleMathSetResultType({frozenset(), frozenset({3}), frozenset({5}), frozenset({frozenset()})}) -not_allowed = [6, 7] start_time = timer() -search(const_sets, result, not_allowed) +search(const_dict, result) print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/aufgabe2.py b/examples/sets/exercice3.py similarity index 56% rename from examples/sets-relations/aufgabe2.py rename to examples/sets/exercice3.py index b8d0f14..ba4db4c 100644 --- a/examples/sets-relations/aufgabe2.py +++ b/examples/sets/exercice3.py @@ -1,4 +1,7 @@ -from SetSolver1 import search +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, SimpleMathSetConstDictType, SimpleMathSetResultType from timeit import default_timer as timer # THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. @@ -6,16 +9,18 @@ # Here you set your predefined constants. # Please make sure that you do not assign a variable letter twice. # Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int | tuple]] = { - "R": {(1, 1), (1, 4), (3, 3), (4, 4)}, - "S": {(2, 3), (3, 1), (3, 2), (3, 4)} -} +const_dict = SimpleMathSetConstDictType( + { + "U": {3, 5, 6, frozenset({1})}, + "V": {1, 2, 4, 6, frozenset({3})}, + "W": {4, frozenset({2})} + } +) # Here you set your wanted solution. -result = {(1, 3), (3, 1), (3, 2), (3, 4), (4, 3)} +result = SimpleMathSetResultType({6, frozenset({2})}) -not_allowed = [6, 7, 10, 11, 12, 13] start_time = timer() -search(const_sets, result, not_allowed) +search(const_dict, result) print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/exercice4.py b/examples/sets/exercice4.py new file mode 100644 index 0000000..0ed6f7b --- /dev/null +++ b/examples/sets/exercice4.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, SimpleMathSetConstDictType, SimpleMathSetResultType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = SimpleMathSetConstDictType( + { + "A": {1, 2}, + "B": {frozenset({3})} + } +) + +# Here you set your wanted solution. +result = SimpleMathSetResultType( + {frozenset(), frozenset({1, 2, frozenset({3})}), frozenset({1, frozenset({3})}), + frozenset({2, frozenset({3})}), frozenset({frozenset({3})})} +) + + +start_time = timer() +search(const_dict, result) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets/exercice5.py b/examples/sets/exercice5.py new file mode 100644 index 0000000..3e9a647 --- /dev/null +++ b/examples/sets/exercice5.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, SimpleMathSetConstDictType, SimpleMathSetResultType +from timeit import default_timer as timer + +# THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. + +# Here you set your predefined constants. +# Please make sure that you do not assign a variable letter twice. +# Python dictionaries will otherwise only store the last value and overwrite the previous ones. +const_dict = SimpleMathSetConstDictType( + { + "A": {frozenset({2, frozenset({5, frozenset({1})})})}, + "B": {frozenset(), frozenset({5, frozenset()})} + } +) + +# Here you set your wanted solution. +result = SimpleMathSetResultType( + {frozenset(), frozenset(frozenset({5, frozenset({})})), frozenset({frozenset(frozenset({5, frozenset({})}))})} +) + + +start_time = timer() +search(const_dict, result) +print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/examples/sets-relations/aufgabe3.py b/examples/sets/exercice6.py similarity index 54% rename from examples/sets-relations/aufgabe3.py rename to examples/sets/exercice6.py index 0322d64..b78f8f4 100644 --- a/examples/sets-relations/aufgabe3.py +++ b/examples/sets/exercice6.py @@ -1,4 +1,7 @@ -from SetSolver1 import search +#!/usr/bin/env python3 +# coding: utf-8 + +from SetSolver1 import search, SimpleMathSetConstDictType, SimpleMathSetResultType from timeit import default_timer as timer # THIS IS AN EXAMPLE in /examples. See /beispiele.md for more information. @@ -6,16 +9,17 @@ # Here you set your predefined constants. # Please make sure that you do not assign a variable letter twice. # Python dictionaries will otherwise only store the last value and overwrite the previous ones. -const_sets: dict[str, set[frozenset | int | tuple]] = { - "R": {(1, 3), (2, 1), (3, 1), (4, 3)}, - "S": {(3, 2), (3, 3), (4, 3), (4, 4)} -} +const_dict = SimpleMathSetConstDictType( + { + "A": {4, frozenset({4}), frozenset({5})}, + "B": {5, frozenset(), frozenset({frozenset()})} + } +) # Here you set your wanted solution. -result = {(3, 2), (3, 3), (4, 1), (4, 3), (4, 4)} +result = SimpleMathSetResultType({frozenset(), frozenset({5}), frozenset({frozenset()})}) -not_allowed = [6, 7] start_time = timer() -search(const_sets, result, not_allowed) +search(const_dict, result) print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec") diff --git a/setup.py b/setup.py index da79b10..0b3b6ec 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name='SetSolver1', - version='1!2021.11.2', + version='1!2021.12.2', url='https://github.com/LukasWestholt/SetSolver1', author='lukaswestholt', author_email='support@lukaswestholt.de', diff --git a/tests/one-liner_vs_fast.py b/tests/one-liner_vs_fast.py index 6a35e97..3f03380 100644 --- a/tests/one-liner_vs_fast.py +++ b/tests/one-liner_vs_fast.py @@ -1,9 +1,10 @@ from timeit import default_timer as timer - # Is set irreflexive? + def a(): - return frozenset((x3, x3) for x3 in set([x1[x2] for x2 in range(2) for x1 in value]) if (x3, x3) in value) == frozenset() + return frozenset((x3, x3) for x3 in set([x1[x2] for x2 in range(2) for x1 in value]) if (x3, x3) in value) == \ + frozenset() def b(): diff --git a/tests/overall_speed.py b/tests/overall_speed.py index 5a1453a..cd9f8b2 100644 --- a/tests/overall_speed.py +++ b/tests/overall_speed.py @@ -1,7 +1,7 @@ from SetSolver1 import search from timeit import default_timer as timer -const_sets: dict[str, set[frozenset | int]] = { +const_dict: dict[str, set[frozenset | int]] = { "A": {1, 2}, "B": {1} } @@ -12,5 +12,5 @@ start_time = timer() for x in range(times): - search(const_sets, result) + search(const_dict, result) print("Calculation ended after " + str(round((timer() - start_time) * 1000) / 1000.0) + " sec")