link-rep 0.0.1__tar.gz
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.
- link_rep-0.0.1/LICENSE +21 -0
- link_rep-0.0.1/PKG-INFO +156 -0
- link_rep-0.0.1/README.md +136 -0
- link_rep-0.0.1/link_rep/Comment.py +68 -0
- link_rep-0.0.1/link_rep/LinkMethod.py +82 -0
- link_rep-0.0.1/link_rep/LinkRep.py +119 -0
- link_rep-0.0.1/link_rep/LinkRepMetaObject.py +25 -0
- link_rep-0.0.1/link_rep/LinkSet.py +68 -0
- link_rep-0.0.1/link_rep/LinkTerm.py +79 -0
- link_rep-0.0.1/link_rep/VarDef.py +68 -0
- link_rep-0.0.1/link_rep/__init__.py +15 -0
- link_rep-0.0.1/pyproject.toml +18 -0
link_rep-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TopologicalKnotIndexer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
link_rep-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: link-rep
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: representation for a composite topological link.
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Author: GGN_2015
|
|
8
|
+
Author-email: premierbob@qq.com
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Requires-Dist: typing_extensions
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# LinkRep
|
|
21
|
+
A Cross-Platform Universal Representation for Composite Links
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install link-rep
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from link_rep import LinkRep
|
|
33
|
+
|
|
34
|
+
real_serial = ( # human readable presentation
|
|
35
|
+
"""
|
|
36
|
+
// this is comment line 1
|
|
37
|
+
// this is comment line 2
|
|
38
|
+
L2a1: [[4, 1, 3, 2], [2, 3, 1, 4]]
|
|
39
|
+
L4a1: [[6, 1, 7, 2], [8, 3, 5, 4], [2, 5, 3, 6], [4, 7, 1, 8]]
|
|
40
|
+
K3a1: [[1, 5, 2, 4], [3, 1, 4, 6], [5, 3, 6, 2]]
|
|
41
|
+
[L2a1, L4a1, K3a1]
|
|
42
|
+
L[1, 1]#L[2, 1]
|
|
43
|
+
L[2, 2]#L[3, 1]
|
|
44
|
+
""").lstrip()
|
|
45
|
+
|
|
46
|
+
link_r = LinkRep()
|
|
47
|
+
link_r.deserialize(real_serial)
|
|
48
|
+
|
|
49
|
+
print(link_r.json_serialize()) # machine readable presentation
|
|
50
|
+
print(link_r.serialize()) # human readable presentation
|
|
51
|
+
|
|
52
|
+
json_str = link_r.json_serialize()
|
|
53
|
+
new_link_r = LinkRep()
|
|
54
|
+
new_link_r.json_deserialize(json_str) # get data from json serial
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## LinkRep Format
|
|
58
|
+
|
|
59
|
+
The content of LinkRep consists of four parts:
|
|
60
|
+
|
|
61
|
+
1. Comment Lines: Lines starting with `//`, as well as lines containing only whitespace characters, are comment lines. Lines containing only whitespace should be ignored during parsing, while comment lines should be retained as informational content.
|
|
62
|
+
|
|
63
|
+
2. Variable Definitions (VarDef): Used to define variables that represent PdCodes (Planar Diagram Codes), for example:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
L2a1: [[4, 1, 3, 2], [2, 3, 1, 4]]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The above statement defines a variable named `L2a1` that stores a PdCode `[[4, 1, 3, 2], [2, 3, 1, 4]]`. The variable name (VarName) should be a string composed of letters, numbers, and underscores, and must not start with a number. Multiple variables with different names can be defined.
|
|
70
|
+
|
|
71
|
+
While the rules allow arbitrary variable naming, in practice it is recommended to use standard knot or link names to name PdCodes. Warnings should be issued for variable definitions using non-standard PdCodes.
|
|
72
|
+
|
|
73
|
+
3. Link Set Description (LinkSet): A sequence of variable names describing all links used, where the order affects subsequent usage. This description can only appear once in LinkRep.
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
[L2a1, L4a1, K3a1]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
This line describes the knot information before performing connected sums. In the connection method descriptor, `L[i, j]` is used to denote the j-th connected component of the i-th link variable. Both `i` and `j` are numbered starting from 1 and increment upwards.
|
|
80
|
+
|
|
81
|
+
4. Connection Method Descriptor (LinkMethod): Describes which connected components of which links should be connected together, for example:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
L[1, 1]#L[2, 2]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
This can be used to indicate that the first connected component of the first link should be connected (via connected sum) with the second connected component of the second link.
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
L[1, 2]#L[2, 2]#L[3, 1]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
This can be used to indicate that the second connected component of the first link should be connected (via connected sum) with the second connected component of the second link, and this connected component should then be connected (via connected sum) with the first connected component of the third link.
|
|
94
|
+
|
|
95
|
+
## Formal Definition
|
|
96
|
+
|
|
97
|
+
Lexical Units:
|
|
98
|
+
```
|
|
99
|
+
CommentLine => "//[^\n]*\n"
|
|
100
|
+
VarName => "[A-Za-z_][A-Za-z0-9_]*"
|
|
101
|
+
PdCode => "(\[\])|(\[\[\d+,\s*\d+,\s*\d+,\s*\d+\](,\[\d+,\s*\d+,\s*\d+,\s*\d+\])*\])"
|
|
102
|
+
PosName => "L\[\d+,\s*\d+\]"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
VarLine: Defines a single variable
|
|
106
|
+
```
|
|
107
|
+
VarLine -> VarName ":" PdCode "\n"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
VarDef: Defines all variables
|
|
111
|
+
```
|
|
112
|
+
VarDef -> VarLine
|
|
113
|
+
VarDef -> VarLine VarDef
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
VarNameList: List of variable names
|
|
117
|
+
```
|
|
118
|
+
VarNameList -> VarName
|
|
119
|
+
VarNameList -> VarName "," VarNameList
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
LinkSet: Defines all links to be used
|
|
123
|
+
```
|
|
124
|
+
LinkSet -> "[" VarNameList "]" "\n"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
LinkLineList: Connects connected components without line breaks
|
|
128
|
+
```
|
|
129
|
+
LinkLineList -> PosName "#" PosName
|
|
130
|
+
LinkLineList -> PosName "#" PosName "#" LinkLineList
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
LinkLine: Describes the connection of connected components
|
|
134
|
+
```
|
|
135
|
+
LinkLine -> LinkLineList "\n"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
LinkMethod: Describes the connection of connected components
|
|
139
|
+
```
|
|
140
|
+
LinkMethod ->
|
|
141
|
+
LinkMethod -> LinkLine
|
|
142
|
+
LinkMethod -> LinkLine LinkMethod
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Comment:
|
|
146
|
+
```
|
|
147
|
+
Comment ->
|
|
148
|
+
Comment -> CommentLine
|
|
149
|
+
Comment -> CommentLine Comment
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
LinkRep:
|
|
153
|
+
```
|
|
154
|
+
LinkRep -> Comment VarDef LinkSet LinkMethod
|
|
155
|
+
```
|
|
156
|
+
|
link_rep-0.0.1/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# LinkRep
|
|
2
|
+
A Cross-Platform Universal Representation for Composite Links
|
|
3
|
+
|
|
4
|
+
## Installation
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
pip install link-rep
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
from link_rep import LinkRep
|
|
14
|
+
|
|
15
|
+
real_serial = ( # human readable presentation
|
|
16
|
+
"""
|
|
17
|
+
// this is comment line 1
|
|
18
|
+
// this is comment line 2
|
|
19
|
+
L2a1: [[4, 1, 3, 2], [2, 3, 1, 4]]
|
|
20
|
+
L4a1: [[6, 1, 7, 2], [8, 3, 5, 4], [2, 5, 3, 6], [4, 7, 1, 8]]
|
|
21
|
+
K3a1: [[1, 5, 2, 4], [3, 1, 4, 6], [5, 3, 6, 2]]
|
|
22
|
+
[L2a1, L4a1, K3a1]
|
|
23
|
+
L[1, 1]#L[2, 1]
|
|
24
|
+
L[2, 2]#L[3, 1]
|
|
25
|
+
""").lstrip()
|
|
26
|
+
|
|
27
|
+
link_r = LinkRep()
|
|
28
|
+
link_r.deserialize(real_serial)
|
|
29
|
+
|
|
30
|
+
print(link_r.json_serialize()) # machine readable presentation
|
|
31
|
+
print(link_r.serialize()) # human readable presentation
|
|
32
|
+
|
|
33
|
+
json_str = link_r.json_serialize()
|
|
34
|
+
new_link_r = LinkRep()
|
|
35
|
+
new_link_r.json_deserialize(json_str) # get data from json serial
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## LinkRep Format
|
|
39
|
+
|
|
40
|
+
The content of LinkRep consists of four parts:
|
|
41
|
+
|
|
42
|
+
1. Comment Lines: Lines starting with `//`, as well as lines containing only whitespace characters, are comment lines. Lines containing only whitespace should be ignored during parsing, while comment lines should be retained as informational content.
|
|
43
|
+
|
|
44
|
+
2. Variable Definitions (VarDef): Used to define variables that represent PdCodes (Planar Diagram Codes), for example:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
L2a1: [[4, 1, 3, 2], [2, 3, 1, 4]]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The above statement defines a variable named `L2a1` that stores a PdCode `[[4, 1, 3, 2], [2, 3, 1, 4]]`. The variable name (VarName) should be a string composed of letters, numbers, and underscores, and must not start with a number. Multiple variables with different names can be defined.
|
|
51
|
+
|
|
52
|
+
While the rules allow arbitrary variable naming, in practice it is recommended to use standard knot or link names to name PdCodes. Warnings should be issued for variable definitions using non-standard PdCodes.
|
|
53
|
+
|
|
54
|
+
3. Link Set Description (LinkSet): A sequence of variable names describing all links used, where the order affects subsequent usage. This description can only appear once in LinkRep.
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
[L2a1, L4a1, K3a1]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This line describes the knot information before performing connected sums. In the connection method descriptor, `L[i, j]` is used to denote the j-th connected component of the i-th link variable. Both `i` and `j` are numbered starting from 1 and increment upwards.
|
|
61
|
+
|
|
62
|
+
4. Connection Method Descriptor (LinkMethod): Describes which connected components of which links should be connected together, for example:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
L[1, 1]#L[2, 2]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This can be used to indicate that the first connected component of the first link should be connected (via connected sum) with the second connected component of the second link.
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
L[1, 2]#L[2, 2]#L[3, 1]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This can be used to indicate that the second connected component of the first link should be connected (via connected sum) with the second connected component of the second link, and this connected component should then be connected (via connected sum) with the first connected component of the third link.
|
|
75
|
+
|
|
76
|
+
## Formal Definition
|
|
77
|
+
|
|
78
|
+
Lexical Units:
|
|
79
|
+
```
|
|
80
|
+
CommentLine => "//[^\n]*\n"
|
|
81
|
+
VarName => "[A-Za-z_][A-Za-z0-9_]*"
|
|
82
|
+
PdCode => "(\[\])|(\[\[\d+,\s*\d+,\s*\d+,\s*\d+\](,\[\d+,\s*\d+,\s*\d+,\s*\d+\])*\])"
|
|
83
|
+
PosName => "L\[\d+,\s*\d+\]"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
VarLine: Defines a single variable
|
|
87
|
+
```
|
|
88
|
+
VarLine -> VarName ":" PdCode "\n"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
VarDef: Defines all variables
|
|
92
|
+
```
|
|
93
|
+
VarDef -> VarLine
|
|
94
|
+
VarDef -> VarLine VarDef
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
VarNameList: List of variable names
|
|
98
|
+
```
|
|
99
|
+
VarNameList -> VarName
|
|
100
|
+
VarNameList -> VarName "," VarNameList
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
LinkSet: Defines all links to be used
|
|
104
|
+
```
|
|
105
|
+
LinkSet -> "[" VarNameList "]" "\n"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
LinkLineList: Connects connected components without line breaks
|
|
109
|
+
```
|
|
110
|
+
LinkLineList -> PosName "#" PosName
|
|
111
|
+
LinkLineList -> PosName "#" PosName "#" LinkLineList
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
LinkLine: Describes the connection of connected components
|
|
115
|
+
```
|
|
116
|
+
LinkLine -> LinkLineList "\n"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
LinkMethod: Describes the connection of connected components
|
|
120
|
+
```
|
|
121
|
+
LinkMethod ->
|
|
122
|
+
LinkMethod -> LinkLine
|
|
123
|
+
LinkMethod -> LinkLine LinkMethod
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Comment:
|
|
127
|
+
```
|
|
128
|
+
Comment ->
|
|
129
|
+
Comment -> CommentLine
|
|
130
|
+
Comment -> CommentLine Comment
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
LinkRep:
|
|
134
|
+
```
|
|
135
|
+
LinkRep -> Comment VarDef LinkSet LinkMethod
|
|
136
|
+
```
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from typing_extensions import override
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from .LinkRepMetaObject import LinkRepMetaObject
|
|
6
|
+
except:
|
|
7
|
+
from LinkRepMetaObject import LinkRepMetaObject
|
|
8
|
+
|
|
9
|
+
# 注释部分:记录每一行的注释信息
|
|
10
|
+
# 存储的注释信息中不含 "//" 与行末的换行符
|
|
11
|
+
class Comment(LinkRepMetaObject):
|
|
12
|
+
def __init__(self) -> None:
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.msg_list = []
|
|
15
|
+
|
|
16
|
+
# 设置注释内容
|
|
17
|
+
def set_msg_list(self, new_msg_list:list[str]):
|
|
18
|
+
# 需要删除所有换行符
|
|
19
|
+
self.msg_list = list(map(
|
|
20
|
+
lambda line: line.replace("\n", ""),
|
|
21
|
+
new_msg_list
|
|
22
|
+
))
|
|
23
|
+
|
|
24
|
+
@override
|
|
25
|
+
def serialize(self) -> str:
|
|
26
|
+
return "".join(list(map(
|
|
27
|
+
lambda line: "//" + line + "\n",
|
|
28
|
+
self.msg_list
|
|
29
|
+
)))
|
|
30
|
+
|
|
31
|
+
@override
|
|
32
|
+
def deserialize(self, s:str) -> None:
|
|
33
|
+
self.set_msg_list([
|
|
34
|
+
item[2:]
|
|
35
|
+
for item in s.split("\n")
|
|
36
|
+
if item.startswith("//")
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
@override
|
|
40
|
+
def json_serialize(self) -> str:
|
|
41
|
+
return json.dumps({
|
|
42
|
+
"type": "Comment",
|
|
43
|
+
"msg_list": self.msg_list
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
@override
|
|
47
|
+
def json_deserialize(self, s:str) -> None:
|
|
48
|
+
obj_now = json.loads(s)
|
|
49
|
+
|
|
50
|
+
# 控制类型
|
|
51
|
+
if obj_now.get("type") != "Comment":
|
|
52
|
+
raise AssertionError()
|
|
53
|
+
|
|
54
|
+
# 必须包含完整信息
|
|
55
|
+
if not isinstance(obj_now.get("msg_list"), list):
|
|
56
|
+
raise AssertionError()
|
|
57
|
+
|
|
58
|
+
# 设置元素内容
|
|
59
|
+
self.set_msg_list(obj_now["msg_list"])
|
|
60
|
+
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
ser = """//line1
|
|
63
|
+
//line2
|
|
64
|
+
//line3"""
|
|
65
|
+
|
|
66
|
+
obj = Comment()
|
|
67
|
+
obj.deserialize(ser)
|
|
68
|
+
print(obj.json_serialize())
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from typing_extensions import override
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from .LinkRepMetaObject import LinkRepMetaObject
|
|
6
|
+
from .LinkTerm import LinkTerm
|
|
7
|
+
except:
|
|
8
|
+
from LinkRepMetaObject import LinkRepMetaObject
|
|
9
|
+
from LinkTerm import LinkTerm
|
|
10
|
+
|
|
11
|
+
# component list 里面的元素是 LinkTerm
|
|
12
|
+
class LinkMethod(LinkRepMetaObject):
|
|
13
|
+
def __init__(self) -> None:
|
|
14
|
+
super().__init__()
|
|
15
|
+
self.component_list = []
|
|
16
|
+
|
|
17
|
+
# 设置变量名的映射关系
|
|
18
|
+
def set_component_list(self, new_component_list:list[LinkTerm]) -> None:
|
|
19
|
+
self.component_list = new_component_list
|
|
20
|
+
for term in new_component_list:
|
|
21
|
+
if not isinstance(term, LinkTerm):
|
|
22
|
+
raise AssertionError()
|
|
23
|
+
|
|
24
|
+
@override
|
|
25
|
+
def serialize(self) -> str:
|
|
26
|
+
return "".join(list(map(
|
|
27
|
+
lambda link_term: link_term.serialize(),
|
|
28
|
+
self.component_list
|
|
29
|
+
)))
|
|
30
|
+
|
|
31
|
+
@override
|
|
32
|
+
def deserialize(self, s:str) -> None:
|
|
33
|
+
new_arr = []
|
|
34
|
+
for term in s.split("\n"):
|
|
35
|
+
if term.find("#") != -1:
|
|
36
|
+
link_term = LinkTerm()
|
|
37
|
+
link_term.deserialize(term.strip())
|
|
38
|
+
new_arr.append(link_term)
|
|
39
|
+
self.set_component_list(new_arr)
|
|
40
|
+
|
|
41
|
+
@override
|
|
42
|
+
def json_serialize(self) -> str:
|
|
43
|
+
return json.dumps({
|
|
44
|
+
"type": "LinkMethod",
|
|
45
|
+
"component_list": [
|
|
46
|
+
json.loads(link_term.json_serialize())
|
|
47
|
+
for link_term in self.component_list
|
|
48
|
+
]
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
@override
|
|
52
|
+
def json_deserialize(self, s:str) -> None:
|
|
53
|
+
obj_now = json.loads(s)
|
|
54
|
+
|
|
55
|
+
# 控制类型
|
|
56
|
+
if obj_now.get("type") != "LinkMethod":
|
|
57
|
+
raise AssertionError()
|
|
58
|
+
|
|
59
|
+
# 必须包含完整信息
|
|
60
|
+
if not isinstance(obj_now.get("component_list"), list):
|
|
61
|
+
raise AssertionError()
|
|
62
|
+
|
|
63
|
+
# 为了纯函数编程
|
|
64
|
+
def map_json_val_to_link_term(json_val:dict) -> LinkTerm:
|
|
65
|
+
link_term = LinkTerm()
|
|
66
|
+
link_term.json_deserialize(json.dumps(json_val))
|
|
67
|
+
return link_term
|
|
68
|
+
|
|
69
|
+
# 设置元素内容
|
|
70
|
+
self.set_component_list([
|
|
71
|
+
map_json_val_to_link_term(term)
|
|
72
|
+
for term in obj_now["component_list"]
|
|
73
|
+
])
|
|
74
|
+
|
|
75
|
+
if __name__ == "__main__":
|
|
76
|
+
var_def = LinkMethod()
|
|
77
|
+
var_def.deserialize("""\nL[1, 2]#L[2, 3]\nL[1, 3]#L[3, 3]\n""")
|
|
78
|
+
|
|
79
|
+
json_str = '{"type": "LinkMethod", "component_list": [{"type": "LinkTerm", "component_list": [[1, 2], [2, 3]]}, {"type": "LinkTerm", "component_list": [[1, 3], [3, 3]]}]}'
|
|
80
|
+
new_link = LinkMethod()
|
|
81
|
+
new_link.json_deserialize(json_str)
|
|
82
|
+
print(new_link.serialize())
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from typing_extensions import override
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from .LinkRepMetaObject import LinkRepMetaObject
|
|
6
|
+
from .Comment import Comment
|
|
7
|
+
from .VarDef import VarDef
|
|
8
|
+
from .LinkSet import LinkSet
|
|
9
|
+
from .LinkMethod import LinkMethod
|
|
10
|
+
except:
|
|
11
|
+
from LinkRepMetaObject import LinkRepMetaObject
|
|
12
|
+
from Comment import Comment
|
|
13
|
+
from VarDef import VarDef
|
|
14
|
+
from LinkSet import LinkSet
|
|
15
|
+
from LinkMethod import LinkMethod
|
|
16
|
+
|
|
17
|
+
# 存储所有的变量定义
|
|
18
|
+
class LinkRep(LinkRepMetaObject):
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
super().__init__()
|
|
21
|
+
self.comment = Comment()
|
|
22
|
+
self.var_def = VarDef()
|
|
23
|
+
self.link_set = LinkSet()
|
|
24
|
+
self.link_method = LinkMethod()
|
|
25
|
+
|
|
26
|
+
@override
|
|
27
|
+
def serialize(self) -> str:
|
|
28
|
+
return (
|
|
29
|
+
self.comment.serialize() +
|
|
30
|
+
self.var_def.serialize() +
|
|
31
|
+
self.link_set.serialize() +
|
|
32
|
+
self.link_method.serialize()
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
@override
|
|
36
|
+
def deserialize(self, s:str) -> None:
|
|
37
|
+
s = s.strip()
|
|
38
|
+
|
|
39
|
+
comment_list = []
|
|
40
|
+
var_def_list = []
|
|
41
|
+
link_method_list = []
|
|
42
|
+
link_set_list = []
|
|
43
|
+
for line in s.split("\n"):
|
|
44
|
+
line = line.strip()
|
|
45
|
+
if line == "":
|
|
46
|
+
continue
|
|
47
|
+
if line.startswith("//"):
|
|
48
|
+
comment_list.append(line)
|
|
49
|
+
elif line.find(":") != -1:
|
|
50
|
+
var_def_list.append(line)
|
|
51
|
+
elif line.find("#") != -1:
|
|
52
|
+
link_method_list.append(line)
|
|
53
|
+
elif line.startswith("[") and line.endswith("]"):
|
|
54
|
+
link_set_list.append(line)
|
|
55
|
+
else:
|
|
56
|
+
raise AssertionError()
|
|
57
|
+
|
|
58
|
+
if len(link_set_list) != 1:
|
|
59
|
+
raise AssertionError()
|
|
60
|
+
|
|
61
|
+
# 依次对所有元素进行反序列化
|
|
62
|
+
self.comment.deserialize("\n".join(comment_list))
|
|
63
|
+
self.var_def.deserialize("\n".join(var_def_list))
|
|
64
|
+
self.link_set.deserialize(link_set_list[0])
|
|
65
|
+
self.link_method.deserialize("\n".join(link_method_list))
|
|
66
|
+
|
|
67
|
+
@override
|
|
68
|
+
def json_serialize(self) -> str:
|
|
69
|
+
return json.dumps({
|
|
70
|
+
"type": "LinkRep",
|
|
71
|
+
"comment": json.loads(self.comment.json_serialize()),
|
|
72
|
+
"var_def": json.loads(self.var_def.json_serialize()),
|
|
73
|
+
"link_set": json.loads(self.link_set.json_serialize()),
|
|
74
|
+
"link_method": json.loads(self.link_method.json_serialize())
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
@override
|
|
78
|
+
def json_deserialize(self, s:str) -> None:
|
|
79
|
+
obj_now = json.loads(s)
|
|
80
|
+
|
|
81
|
+
# 控制类型
|
|
82
|
+
if obj_now.get("type") != "LinkRep":
|
|
83
|
+
raise AssertionError()
|
|
84
|
+
|
|
85
|
+
# 必须包含完整信息
|
|
86
|
+
for term_name in ["comment", "var_def", "link_set", "link_method"]:
|
|
87
|
+
if not isinstance(obj_now.get(term_name), dict):
|
|
88
|
+
raise AssertionError()
|
|
89
|
+
|
|
90
|
+
instance_now = self.__getattribute__(term_name)
|
|
91
|
+
if not isinstance(instance_now, LinkRepMetaObject):
|
|
92
|
+
raise AssertionError()
|
|
93
|
+
instance_now.json_deserialize(json.dumps(obj_now.get(term_name)))
|
|
94
|
+
|
|
95
|
+
if __name__ == "__main__":
|
|
96
|
+
real_serial = (
|
|
97
|
+
"""
|
|
98
|
+
// this is comment line 1
|
|
99
|
+
// this is comment line 2
|
|
100
|
+
L2a1: [[4, 1, 3, 2], [2, 3, 1, 4]]
|
|
101
|
+
L4a1: [[6, 1, 7, 2], [8, 3, 5, 4], [2, 5, 3, 6], [4, 7, 1, 8]]
|
|
102
|
+
K3a1: [[1, 5, 2, 4], [3, 1, 4, 6], [5, 3, 6, 2]]
|
|
103
|
+
[L2a1, L4a1, K3a1]
|
|
104
|
+
L[1, 1]#L[2, 1]
|
|
105
|
+
L[2, 2]#L[3, 1]
|
|
106
|
+
""").lstrip()
|
|
107
|
+
|
|
108
|
+
rev_obj = LinkRep()
|
|
109
|
+
rev_obj.deserialize(real_serial)
|
|
110
|
+
assert rev_obj.serialize() == real_serial
|
|
111
|
+
|
|
112
|
+
json_serialize = rev_obj.json_serialize()
|
|
113
|
+
rev_obj_2 = LinkRep()
|
|
114
|
+
rev_obj_2.json_deserialize(json_serialize)
|
|
115
|
+
|
|
116
|
+
assert rev_obj_2.serialize() == real_serial
|
|
117
|
+
assert rev_obj_2.json_serialize() == rev_obj.json_serialize()
|
|
118
|
+
|
|
119
|
+
print(rev_obj_2.serialize())
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
class LinkRepMetaObject(ABC):
|
|
4
|
+
def __init__(self) -> None:
|
|
5
|
+
pass
|
|
6
|
+
|
|
7
|
+
# 标准字符串序列号化
|
|
8
|
+
@abstractmethod
|
|
9
|
+
def serialize(self) -> str:
|
|
10
|
+
return ""
|
|
11
|
+
|
|
12
|
+
# 标准字符串反序列化
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def deserialize(self, s:str) -> None:
|
|
15
|
+
return
|
|
16
|
+
|
|
17
|
+
# JSON 字符串序列号化
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def json_serialize(self) -> str:
|
|
20
|
+
return ""
|
|
21
|
+
|
|
22
|
+
# JSON 字符串反序列化
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def json_deserialize(self, s:str) -> None:
|
|
25
|
+
return
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from typing_extensions import override
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from .LinkRepMetaObject import LinkRepMetaObject
|
|
6
|
+
except:
|
|
7
|
+
from LinkRepMetaObject import LinkRepMetaObject
|
|
8
|
+
|
|
9
|
+
# 存储所有的变量定义
|
|
10
|
+
class LinkSet(LinkRepMetaObject):
|
|
11
|
+
def __init__(self) -> None:
|
|
12
|
+
super().__init__()
|
|
13
|
+
self.var_list = []
|
|
14
|
+
|
|
15
|
+
# 设置变量名的映射关系
|
|
16
|
+
def set_var_list(self, new_var_list:list[str]) -> None:
|
|
17
|
+
self.var_list = new_var_list
|
|
18
|
+
|
|
19
|
+
@override
|
|
20
|
+
def serialize(self) -> str:
|
|
21
|
+
return "[" + ", ".join(self.var_list) + "]\n"
|
|
22
|
+
|
|
23
|
+
@override
|
|
24
|
+
def deserialize(self, s:str) -> None:
|
|
25
|
+
s = s.strip()
|
|
26
|
+
|
|
27
|
+
if not s.startswith("["):
|
|
28
|
+
raise AssertionError()
|
|
29
|
+
if not s.endswith("]"):
|
|
30
|
+
raise AssertionError()
|
|
31
|
+
|
|
32
|
+
self.set_var_list([
|
|
33
|
+
item.strip()
|
|
34
|
+
for item in s[1:-1].split(",")
|
|
35
|
+
])
|
|
36
|
+
|
|
37
|
+
@override
|
|
38
|
+
def json_serialize(self) -> str:
|
|
39
|
+
return json.dumps({
|
|
40
|
+
"type": "LinkSet",
|
|
41
|
+
"var_list": self.var_list
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
@override
|
|
45
|
+
def json_deserialize(self, s:str) -> None:
|
|
46
|
+
obj_now = json.loads(s)
|
|
47
|
+
|
|
48
|
+
# 控制类型
|
|
49
|
+
if obj_now.get("type") != "LinkSet":
|
|
50
|
+
raise AssertionError()
|
|
51
|
+
|
|
52
|
+
# 必须包含完整信息
|
|
53
|
+
if not isinstance(obj_now.get("var_list"), list):
|
|
54
|
+
raise AssertionError()
|
|
55
|
+
|
|
56
|
+
# 设置元素内容
|
|
57
|
+
self.set_var_list(obj_now["var_list"])
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
var_def = LinkSet()
|
|
61
|
+
var_def.set_var_list(["L2a1", "L4a1", "K3a1"])
|
|
62
|
+
|
|
63
|
+
ser = var_def.serialize()
|
|
64
|
+
print(ser)
|
|
65
|
+
|
|
66
|
+
new_val = LinkSet()
|
|
67
|
+
new_val.json_deserialize('{"type": "LinkSet", "var_list": ["L2a1", "L4a1", "K3a1"]}')
|
|
68
|
+
print(new_val.json_serialize())
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from typing_extensions import override
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from .LinkRepMetaObject import LinkRepMetaObject
|
|
6
|
+
except:
|
|
7
|
+
from LinkRepMetaObject import LinkRepMetaObject
|
|
8
|
+
|
|
9
|
+
# 这个 component_list 里面放的东西是一个 list of list
|
|
10
|
+
# 每个 sub_list 中有两个整数,L[i, j] 中的 i, j
|
|
11
|
+
class LinkTerm(LinkRepMetaObject):
|
|
12
|
+
def __init__(self) -> None:
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.component_list = []
|
|
15
|
+
|
|
16
|
+
# 设置变量名的映射关系
|
|
17
|
+
def set_component_list(self, new_component_list:list[list[int]]) -> None:
|
|
18
|
+
self.component_list = new_component_list
|
|
19
|
+
for term in new_component_list:
|
|
20
|
+
if not isinstance(term, list):
|
|
21
|
+
raise AssertionError()
|
|
22
|
+
if len(term) != 2:
|
|
23
|
+
raise AssertionError()
|
|
24
|
+
for sub_term in term:
|
|
25
|
+
if not isinstance(sub_term, int):
|
|
26
|
+
raise AssertionError()
|
|
27
|
+
|
|
28
|
+
@override
|
|
29
|
+
def serialize(self) -> str:
|
|
30
|
+
return "#".join(list(map(
|
|
31
|
+
lambda pr: f"L[{pr[0]}, {pr[1]}]", # 把连通分量编号
|
|
32
|
+
self.component_list
|
|
33
|
+
))) + "\n"
|
|
34
|
+
|
|
35
|
+
@override
|
|
36
|
+
def deserialize(self, s:str) -> None:
|
|
37
|
+
new_arr = []
|
|
38
|
+
for term in s.split("#"):
|
|
39
|
+
term = term.strip()
|
|
40
|
+
if term == "":
|
|
41
|
+
raise AssertionError()
|
|
42
|
+
if not (term.startswith("L[") and term.endswith("]")):
|
|
43
|
+
raise AssertionError()
|
|
44
|
+
li, ri = term[2:-1].split(",")
|
|
45
|
+
new_arr.append([int(li), int(ri)])
|
|
46
|
+
self.set_component_list(new_arr)
|
|
47
|
+
|
|
48
|
+
@override
|
|
49
|
+
def json_serialize(self) -> str:
|
|
50
|
+
return json.dumps({
|
|
51
|
+
"type": "LinkTerm",
|
|
52
|
+
"component_list": self.component_list
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
@override
|
|
56
|
+
def json_deserialize(self, s:str) -> None:
|
|
57
|
+
obj_now = json.loads(s)
|
|
58
|
+
|
|
59
|
+
# 控制类型
|
|
60
|
+
if obj_now.get("type") != "LinkTerm":
|
|
61
|
+
raise AssertionError()
|
|
62
|
+
|
|
63
|
+
# 必须包含完整信息
|
|
64
|
+
if not isinstance(obj_now.get("component_list"), list):
|
|
65
|
+
raise AssertionError()
|
|
66
|
+
|
|
67
|
+
# 设置元素内容
|
|
68
|
+
self.set_component_list(obj_now["component_list"])
|
|
69
|
+
|
|
70
|
+
if __name__ == "__main__":
|
|
71
|
+
var_def = LinkTerm()
|
|
72
|
+
var_def.set_component_list([[1, 1], [2, 1], [3, 2]])
|
|
73
|
+
|
|
74
|
+
ser = var_def.serialize()
|
|
75
|
+
print(ser)
|
|
76
|
+
|
|
77
|
+
new_var = LinkTerm()
|
|
78
|
+
new_var.deserialize("L[1, 1]#L[2, 1]#L[3, 2]")
|
|
79
|
+
print(new_var.json_serialize())
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from typing_extensions import override
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from .LinkRepMetaObject import LinkRepMetaObject
|
|
6
|
+
except:
|
|
7
|
+
from LinkRepMetaObject import LinkRepMetaObject
|
|
8
|
+
|
|
9
|
+
# 存储所有的变量定义
|
|
10
|
+
class VarDef(LinkRepMetaObject):
|
|
11
|
+
def __init__(self) -> None:
|
|
12
|
+
super().__init__()
|
|
13
|
+
self.var_map = dict()
|
|
14
|
+
|
|
15
|
+
# 设置变量名的映射关系
|
|
16
|
+
def set_var_map(self, new_var_map:dict[str, list]) -> None:
|
|
17
|
+
self.var_map = new_var_map
|
|
18
|
+
|
|
19
|
+
@override
|
|
20
|
+
def serialize(self) -> str:
|
|
21
|
+
return "".join([
|
|
22
|
+
var_name + ": " + json.dumps(self.var_map[var_name]) + "\n"
|
|
23
|
+
for var_name in self.var_map
|
|
24
|
+
])
|
|
25
|
+
|
|
26
|
+
@override
|
|
27
|
+
def deserialize(self, s:str) -> None:
|
|
28
|
+
self.set_var_map({
|
|
29
|
+
item.split(":")[0].strip()
|
|
30
|
+
:json.loads(item.split(":")[-1])
|
|
31
|
+
for item in s.split("\n")
|
|
32
|
+
if item.find(":") != -1
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
@override
|
|
36
|
+
def json_serialize(self) -> str:
|
|
37
|
+
return json.dumps({
|
|
38
|
+
"type": "VarDef",
|
|
39
|
+
"var_map": self.var_map
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
@override
|
|
43
|
+
def json_deserialize(self, s:str) -> None:
|
|
44
|
+
obj_now = json.loads(s)
|
|
45
|
+
|
|
46
|
+
# 控制类型
|
|
47
|
+
if obj_now.get("type") != "VarDef":
|
|
48
|
+
raise AssertionError()
|
|
49
|
+
|
|
50
|
+
# 必须包含完整信息
|
|
51
|
+
if not isinstance(obj_now.get("var_map"), dict):
|
|
52
|
+
raise AssertionError()
|
|
53
|
+
|
|
54
|
+
# 设置元素内容
|
|
55
|
+
self.set_var_map(obj_now["var_map"])
|
|
56
|
+
|
|
57
|
+
if __name__ == "__main__":
|
|
58
|
+
var_def = VarDef()
|
|
59
|
+
var_def.set_var_map({
|
|
60
|
+
"L2a1": [[4, 1, 3, 2], [2, 3, 1, 4]],
|
|
61
|
+
"L4a1": [[6, 1, 7, 2], [8, 3, 5, 4], [2, 5, 3, 6], [4, 7, 1, 8]]
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
ser = """L2a1: [[4, 1, 3, 2], [2, 3, 1, 4]]
|
|
65
|
+
L4a1: [[6, 1, 7, 2], [8, 3, 5, 4], [2, 5, 3, 6], [4, 7, 1, 8]]"""
|
|
66
|
+
|
|
67
|
+
var_def.deserialize(ser)
|
|
68
|
+
print(var_def.json_serialize())
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .Comment import Comment
|
|
2
|
+
from .LinkMethod import LinkMethod
|
|
3
|
+
from .LinkRep import LinkRep
|
|
4
|
+
from .LinkSet import LinkSet
|
|
5
|
+
from .LinkTerm import LinkTerm
|
|
6
|
+
from .VarDef import VarDef
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"Comment",
|
|
10
|
+
"LinkMethod",
|
|
11
|
+
"LinkRep", # 其中最重要的是 LinkRep
|
|
12
|
+
"LinkSet",
|
|
13
|
+
"LinkTerm",
|
|
14
|
+
"VarDef"
|
|
15
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "link-rep"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "representation for a composite topological link."
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "GGN_2015",email = "premierbob@qq.com"}
|
|
7
|
+
]
|
|
8
|
+
license = {text = "MIT"}
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"typing_extensions"
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
[build-system]
|
|
17
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
18
|
+
build-backend = "poetry.core.masonry.api"
|