knit-graphs 0.0.6__py3-none-any.whl → 0.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- knit_graphs-0.0.6.dist-info/licenses/LICENSE → LICENSE +21 -21
- README.md +75 -0
- docs/Makefile +20 -0
- docs/make.bat +35 -0
- docs/source/api/knit_graphs.artin_wale_braids.rst +58 -0
- docs/source/api/knit_graphs.rst +74 -0
- docs/source/conf.py +335 -0
- docs/source/index.rst +71 -0
- docs/source/installation.rst +67 -0
- knit_graphs/Course.py +156 -104
- knit_graphs/Knit_Graph.py +249 -186
- knit_graphs/Knit_Graph_Visualizer.py +680 -0
- knit_graphs/Loop.py +141 -155
- knit_graphs/Pull_Direction.py +68 -23
- knit_graphs/Yarn.py +424 -267
- knit_graphs/__init__.py +3 -3
- knit_graphs/_base_classes.py +173 -0
- knit_graphs/artin_wale_braids/Crossing_Direction.py +74 -15
- knit_graphs/artin_wale_braids/Loop_Braid_Graph.py +95 -62
- knit_graphs/artin_wale_braids/Wale.py +169 -93
- knit_graphs/artin_wale_braids/Wale_Braid.py +50 -30
- knit_graphs/artin_wale_braids/Wale_Braid_Word.py +99 -54
- knit_graphs/artin_wale_braids/Wale_Group.py +136 -88
- knit_graphs/{knit_graph_generators/basic_knit_graph_generators.py → basic_knit_graph_generators.py} +302 -248
- knit_graphs-0.0.7.dist-info/LICENSE +21 -0
- {knit_graphs-0.0.6.dist-info → knit_graphs-0.0.7.dist-info}/METADATA +33 -24
- knit_graphs-0.0.7.dist-info/RECORD +29 -0
- {knit_graphs-0.0.6.dist-info → knit_graphs-0.0.7.dist-info}/WHEEL +1 -1
- knit_graphs/__about__.py +0 -4
- knit_graphs/knit_graph_generators/__init__.py +0 -0
- knit_graphs/knit_graph_visualizer/Stitch_Visualizer.py +0 -427
- knit_graphs/knit_graph_visualizer/__init__.py +0 -0
- knit_graphs-0.0.6.dist-info/RECORD +0 -22
|
@@ -1,93 +1,169 @@
|
|
|
1
|
-
"""Module containing the Wale Class
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
:
|
|
36
|
-
:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
1
|
+
"""Module containing the Wale Class.
|
|
2
|
+
|
|
3
|
+
This module defines the Wale class which represents a vertical column of stitches in a knitted structure, maintaining the sequence and relationships between loops in that column.
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Iterator, cast
|
|
8
|
+
|
|
9
|
+
from networkx import dfs_preorder_nodes
|
|
10
|
+
|
|
11
|
+
from knit_graphs._base_classes import _Base_Wale
|
|
12
|
+
from knit_graphs.Loop import Loop
|
|
13
|
+
from knit_graphs.Pull_Direction import Pull_Direction
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Wale(_Base_Wale):
|
|
17
|
+
"""A data structure representing stitch relationships between loops in a vertical column of a knitted structure.
|
|
18
|
+
|
|
19
|
+
A wale represents a vertical sequence of loops connected by stitch edges, forming a column in the knitted fabric.
|
|
20
|
+
This class manages the sequential relationships between loops and tracks the pull directions of stitches within the wale.
|
|
21
|
+
|
|
22
|
+
Attributes:
|
|
23
|
+
first_loop (Loop | None): The first (bottom) loop in the wale sequence.
|
|
24
|
+
last_loop (Loop | None): The last (top) loop in the wale sequence.
|
|
25
|
+
stitches (DiGraph): Stores the directed graph of stitch connections within this wale.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, first_loop: Loop | None = None) -> None:
|
|
29
|
+
"""Initialize a wale optionally starting with a specified loop.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
first_loop (Loop | None, optional): The initial loop to start the wale with. If provided, it will be added as both the first and last loop. Defaults to None.
|
|
33
|
+
"""
|
|
34
|
+
super().__init__()
|
|
35
|
+
self.first_loop: None | Loop = first_loop
|
|
36
|
+
self.last_loop: None | Loop = None
|
|
37
|
+
if isinstance(self.first_loop, Loop):
|
|
38
|
+
self.add_loop_to_end(self.first_loop, pull_direction=None)
|
|
39
|
+
|
|
40
|
+
def add_loop_to_end(self, loop: Loop, pull_direction: Pull_Direction | None = Pull_Direction.BtF) -> None:
|
|
41
|
+
"""Add a loop to the end (top) of the wale with the specified pull direction.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
loop (Loop): The loop to add to the end of the wale.
|
|
45
|
+
pull_direction (Pull_Direction | None, optional): The direction to pull the loop through its parent loop. Defaults to Pull_Direction.BtF. Can be None only for the first loop in the wale.
|
|
46
|
+
"""
|
|
47
|
+
if self.last_loop is None:
|
|
48
|
+
self.stitches.add_node(loop)
|
|
49
|
+
self.first_loop = loop
|
|
50
|
+
self.last_loop = loop
|
|
51
|
+
else:
|
|
52
|
+
assert isinstance(pull_direction, Pull_Direction)
|
|
53
|
+
self.stitches.add_edge(self.last_loop, loop, pull_direction=pull_direction)
|
|
54
|
+
self.last_loop = loop
|
|
55
|
+
|
|
56
|
+
def add_loop_to_beginning(self, loop: Loop, pull_direction: Pull_Direction = Pull_Direction.BtF) -> None:
|
|
57
|
+
"""Add a loop to the beginning (bottom) of the wale with the specified pull direction.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
loop (Loop): The loop to add to the beginning of the wale.
|
|
61
|
+
pull_direction (Pull_Direction, optional): The direction to pull the existing first loop through this new loop. Defaults to Pull_Direction.BtF.
|
|
62
|
+
"""
|
|
63
|
+
if self.first_loop is None:
|
|
64
|
+
self.stitches.add_node(loop)
|
|
65
|
+
self.first_loop = loop
|
|
66
|
+
self.last_loop = loop
|
|
67
|
+
else:
|
|
68
|
+
self.stitches.add_edge(loop, self.first_loop, pull_direction=pull_direction)
|
|
69
|
+
self.first_loop = loop
|
|
70
|
+
|
|
71
|
+
def get_stitch_pull_direction(self, u: Loop, v: Loop) -> Pull_Direction:
|
|
72
|
+
"""Get the pull direction of the stitch edge between two loops in this wale.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
u (Loop): The parent loop in the stitch connection.
|
|
76
|
+
v (Loop): The child loop in the stitch connection.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Pull_Direction: The pull direction of the stitch between loops u and v.
|
|
80
|
+
"""
|
|
81
|
+
return cast(Pull_Direction, self.stitches.edges[u, v]["pull_direction"])
|
|
82
|
+
|
|
83
|
+
def split_wale(self, split_loop: Loop) -> tuple[Wale, Wale | None]:
|
|
84
|
+
"""Split this wale at the specified loop into two separate wales.
|
|
85
|
+
|
|
86
|
+
The split loop becomes the last loop of the first wale and the first loop of the second wale.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
split_loop (Loop): The loop at which to split the wale. This loop will appear in both resulting wales.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
tuple[Wale, Wale | None]:
|
|
93
|
+
A tuple containing:
|
|
94
|
+
* The first wale (from start to split_loop). This will be the whole wale if the split_loop is not found.
|
|
95
|
+
* The second wale (from split_loop to end). This will be None if the split_loop is not found.
|
|
96
|
+
"""
|
|
97
|
+
first_wale = Wale(self.first_loop)
|
|
98
|
+
growing_wale = first_wale
|
|
99
|
+
found_loop = False
|
|
100
|
+
for l in cast(list[Loop], self[1:]):
|
|
101
|
+
if l is split_loop:
|
|
102
|
+
growing_wale.add_loop_to_end(l, self.get_stitch_pull_direction(cast(Loop, growing_wale.last_loop), l))
|
|
103
|
+
growing_wale = Wale(split_loop)
|
|
104
|
+
found_loop = True
|
|
105
|
+
else:
|
|
106
|
+
growing_wale.add_loop_to_end(l, self.get_stitch_pull_direction(cast(Loop, growing_wale.last_loop), l))
|
|
107
|
+
if not found_loop:
|
|
108
|
+
return self, None
|
|
109
|
+
return first_wale, growing_wale
|
|
110
|
+
|
|
111
|
+
def __len__(self) -> int:
|
|
112
|
+
"""Get the number of loops in this wale.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
int: The total number of loops in this wale.
|
|
116
|
+
"""
|
|
117
|
+
return len(self.stitches.nodes)
|
|
118
|
+
|
|
119
|
+
def __iter__(self) -> Iterator[Loop]:
|
|
120
|
+
"""Iterate over loops in this wale from first to last.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Iterator[Loop]: An iterator over the loops in this wale in their sequential order from bottom to top.
|
|
124
|
+
"""
|
|
125
|
+
return cast(Iterator[Loop], dfs_preorder_nodes(self.stitches, source=self.first_loop))
|
|
126
|
+
|
|
127
|
+
def __getitem__(self, item: int | slice) -> Loop | list[Loop]:
|
|
128
|
+
"""Get loop(s) at the specified index or slice within this wale.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
item (int | slice): The index of a single loop or a slice for multiple loops.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Loop | list[Loop]: The loop at the specified index, or a list of loops for a slice.
|
|
135
|
+
"""
|
|
136
|
+
if isinstance(item, int):
|
|
137
|
+
return cast(Loop, self.stitches.nodes[item])
|
|
138
|
+
elif isinstance(item, slice):
|
|
139
|
+
return list(self)[item]
|
|
140
|
+
|
|
141
|
+
def __contains__(self, item: Loop) -> bool:
|
|
142
|
+
"""Check if a loop is contained in this wale.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
item (Loop): The loop to check for membership in this wale.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
bool: True if the loop is in this wale, False otherwise.
|
|
149
|
+
"""
|
|
150
|
+
return bool(self.stitches.has_node(item))
|
|
151
|
+
|
|
152
|
+
def __hash__(self) -> int:
|
|
153
|
+
"""Get the hash value of this wale based on its first loop.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
int: Hash value based on the first loop in this wale.
|
|
157
|
+
"""
|
|
158
|
+
return hash(self.first_loop)
|
|
159
|
+
|
|
160
|
+
def overlaps(self, other: Wale) -> bool:
|
|
161
|
+
"""Check if this wale has any loops in common with another wale.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
other (Wale): The other wale to compare against for overlapping loops.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
bool: True if the other wale has any overlapping loop(s) with this wale, False otherwise.
|
|
168
|
+
"""
|
|
169
|
+
return any(loop in other for loop in self)
|
|
@@ -1,30 +1,50 @@
|
|
|
1
|
-
"""Model of knitted structure as a set of crossing wales using artin braid groups
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
self.wale_words =
|
|
1
|
+
"""Model of knitted structure as a set of crossing wales using artin braid groups.
|
|
2
|
+
|
|
3
|
+
This module provides the Wale_Braid class which represents complex cable knitting patterns as mathematical braid structures,
|
|
4
|
+
using concepts from algebraic topology to model how wales cross over and under each other.
|
|
5
|
+
"""
|
|
6
|
+
from knit_graphs.artin_wale_braids.Wale_Braid_Word import Wale_Braid_Word
|
|
7
|
+
from knit_graphs.artin_wale_braids.Wale_Group import Wale_Group
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Wale_Braid:
|
|
11
|
+
"""A model of knitted structure as a set of crossing wales using Artin braid groups.
|
|
12
|
+
|
|
13
|
+
This class represents complex cable knitting patterns using mathematical braid theory,
|
|
14
|
+
where wales are treated as strands in a braid and their crossings are represented as braid operations.
|
|
15
|
+
This provides a formal mathematical framework for analyzing and manipulating cable patterns.
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
wale_groups (list[Wale_Group]): The collection of wale groups that participate in the braid structure.
|
|
19
|
+
wale_words (list[Wale_Braid_Word]): The sequence of braid words that describe the crossing operations between wales.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, wale_groups: list[Wale_Group], wale_words: list[Wale_Braid_Word]) -> None:
|
|
23
|
+
"""Initialize a wale braid with the specified groups and braid words.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
wale_groups (list[Wale_Group]): The wale groups that participate in this braid structure.
|
|
27
|
+
wale_words (list[Wale_Braid_Word]): The sequence of braid words describing the crossing operations.
|
|
28
|
+
"""
|
|
29
|
+
self.wale_groups: list[Wale_Group] = wale_groups
|
|
30
|
+
self.wale_words: list[Wale_Braid_Word] = wale_words
|
|
31
|
+
|
|
32
|
+
def reduce(self) -> None:
|
|
33
|
+
"""Simplify the braid by removing pairs of braid words that invert each other.
|
|
34
|
+
|
|
35
|
+
This method modifies the wale_words list by identifying and removing adjacent pairs of braid words that are inverses of each other,
|
|
36
|
+
effectively canceling out their operations to create a simplified but equivalent braid representation.
|
|
37
|
+
"""
|
|
38
|
+
reduced_words: list[Wale_Braid_Word] = []
|
|
39
|
+
remaining_words: list[Wale_Braid_Word] = [*self.wale_words[1:]]
|
|
40
|
+
while len(remaining_words) > 0:
|
|
41
|
+
if len(reduced_words) == 0:
|
|
42
|
+
reduced_words.append(remaining_words.pop(0))
|
|
43
|
+
else:
|
|
44
|
+
next_word = remaining_words.pop(0)
|
|
45
|
+
current_word = reduced_words[-1]
|
|
46
|
+
if next_word.is_inversion(current_word):
|
|
47
|
+
reduced_words.pop() # remove current word because its inverted
|
|
48
|
+
else:
|
|
49
|
+
reduced_words.append(next_word)
|
|
50
|
+
self.wale_words = reduced_words
|
|
@@ -1,54 +1,99 @@
|
|
|
1
|
-
"""Module
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
1
|
+
"""Module containing the Wale Braid Word Class.
|
|
2
|
+
|
|
3
|
+
This module provides the Wale_Braid_Word class which represents a single step in a braid operation, describing how loops cross over each other within a course of knitting.
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from knit_graphs.artin_wale_braids.Crossing_Direction import Crossing_Direction
|
|
8
|
+
from knit_graphs.Loop import Loop
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Wale_Braid_Word:
|
|
12
|
+
"""A representation of loop crossings over a set of loops in a common course.
|
|
13
|
+
|
|
14
|
+
This class represents a single braid word in the mathematical sense, describing how a set of loops cross over or under each other within a horizontal course.
|
|
15
|
+
Each braid word can be inverted and applied to determine the new ordering of loops after the crossing operations.
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
loops (list[Loop]): The ordered list of loops that participate in this braid word.
|
|
19
|
+
crossings (dict[int, Crossing_Direction]): A mapping from loop indices to their crossing directions, where each key represents the index of a loop that crosses with the loop at index+1.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, loops: list[Loop], crossings: dict[int, Crossing_Direction]) -> None:
|
|
23
|
+
"""Initialize a wale braid word with the specified loops and crossing operations.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
loops (list[Loop]): The ordered list of loops that participate in this braid word.
|
|
27
|
+
crossings (dict[int, Crossing_Direction]): A dictionary mapping loop indices to crossing directions.
|
|
28
|
+
Each index-key indicates that the loop at that index crosses with the loop at index+1 in the specified direction.
|
|
29
|
+
"""
|
|
30
|
+
self.loops: list[Loop] = loops
|
|
31
|
+
self.crossings: dict[int, Crossing_Direction] = crossings
|
|
32
|
+
|
|
33
|
+
def new_loop_order(self) -> list[Loop]:
|
|
34
|
+
"""Calculate the new ordering of loops after applying all crossing operations.
|
|
35
|
+
|
|
36
|
+
This method applies all the crossing operations defined in this braid word to determine the final ordering of loops.
|
|
37
|
+
Crossings are applied from right to left (highest index to lowest) to maintain proper braid semantics.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
list[Loop]: The list of loops in their new order after all crossing operations have been applied.
|
|
41
|
+
"""
|
|
42
|
+
new_loops: list[Loop] = [*self.loops]
|
|
43
|
+
for i in sorted(self.crossings.keys(), reverse=True):
|
|
44
|
+
moves_left = new_loops[i + 1]
|
|
45
|
+
new_loops[i + 1] = new_loops[i]
|
|
46
|
+
new_loops[i] = moves_left
|
|
47
|
+
|
|
48
|
+
return new_loops
|
|
49
|
+
|
|
50
|
+
def __invert__(self) -> Wale_Braid_Word:
|
|
51
|
+
"""Create the inverse braid word that undoes the operations of this braid word.
|
|
52
|
+
|
|
53
|
+
The inverse braid word uses the new loop order as its starting configuration and inverts all crossing directions to reverse the effect of the original braid word.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Wale_Braid_Word: A new braid word that represents the inverse operation of this braid word.
|
|
57
|
+
"""
|
|
58
|
+
new_loops = self.new_loop_order()
|
|
59
|
+
new_crossings = {i: ~c for i, c in self.crossings.items()}
|
|
60
|
+
return Wale_Braid_Word(new_loops, new_crossings)
|
|
61
|
+
|
|
62
|
+
def __eq__(self, other: Wale_Braid_Word) -> bool:
|
|
63
|
+
"""Check equality with another wale braid word.
|
|
64
|
+
|
|
65
|
+
Two braid words are equal if they have the same loops in the same order and the same crossing operations at the same indices.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
other (Wale_Braid_Word): The other braid word to compare with.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
bool: True if both braid words have identical loops, loop ordering, and crossing operations, False otherwise.
|
|
72
|
+
"""
|
|
73
|
+
if (len(self) != len(other)
|
|
74
|
+
or any(l != o for l, o in zip(self.loops, other.loops))
|
|
75
|
+
or any(i not in other.crossings for i in self.crossings)
|
|
76
|
+
or any(other.crossings[i] != cd for i, cd in self.crossings.items())):
|
|
77
|
+
return False
|
|
78
|
+
else:
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
def is_inversion(self, other: Wale_Braid_Word) -> bool:
|
|
82
|
+
"""Check if another braid word is the inverse of this braid word.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
other (Wale_Braid_Word): The other braid word to compare against for inversion relationship.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
bool: True if the other braid word is equal to the inverse of this braid word, False otherwise.
|
|
89
|
+
"""
|
|
90
|
+
invert = ~self
|
|
91
|
+
return other == invert
|
|
92
|
+
|
|
93
|
+
def __len__(self) -> int:
|
|
94
|
+
"""Get the number of loops in this braid word.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
int: The total number of loops participating in this braid word.
|
|
98
|
+
"""
|
|
99
|
+
return len(self.loops)
|