physdes-py 0.1__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.
physdes/__init__.py ADDED
@@ -0,0 +1,16 @@
1
+ import sys
2
+
3
+ if sys.version_info[:2] >= (3, 8):
4
+ # TODO: Import directly (no need for conditional) when `python_requires = >= 3.9`
5
+ from importlib.metadata import PackageNotFoundError, version # pragma: no cover
6
+ else:
7
+ from importlib_metadata import PackageNotFoundError, version # pragma: no cover
8
+
9
+ try:
10
+ # Change here if project is renamed and does not equal the package name
11
+ dist_name = "physdes-py"
12
+ __version__ = version(dist_name)
13
+ except PackageNotFoundError: # pragma: no cover
14
+ __version__ = "unknown"
15
+ finally:
16
+ del version, PackageNotFoundError
physdes/generic.py ADDED
@@ -0,0 +1,273 @@
1
+ r"""
2
+ Generic Operations for Physical Design (src\physdes\generic.py)
3
+
4
+ This code defines a set of generic operations that are commonly used in physical design calculations. These operations are designed to work with different types of objects, including simple numbers (scalars) and more complex objects like intervals.
5
+
6
+ The code contains four main functions: overlap, contain, intersection, and min_dist. Each of these functions takes two inputs, typically referred to as 'lhs' (left-hand side) and 'rhs' (right-hand side), and performs a specific operation on them.
7
+
8
+ The 'overlap' function checks if two objects overlap or are equal. It returns True if they do overlap, and False otherwise. This function is useful for determining if two physical entities share some common space or value.
9
+
10
+ The 'contain' function checks if one object contains another. It returns True if the left-hand side object contains the right-hand side object, and False otherwise. This can be used to determine if one physical entity is completely within another.
11
+
12
+ The 'intersection' function finds the common part between two objects. If the objects are numbers, it returns the number if they're equal. For more complex objects, it returns the overlapping region. This is useful for finding where two physical entities meet or share space.
13
+
14
+ The 'min_dist' function calculates the minimum Manhattan distance between two objects. For numbers, it simply calculates the absolute difference. For more complex objects, it uses a special method to determine the closest points between the objects. This can be used to find how far apart two physical entities are.
15
+
16
+ Each of these functions is designed to work with both simple numbers and more complex objects. They do this by first checking if the input objects have special methods (like 'overlaps', 'contains', 'intersect_with', or 'min_dist_with'). If these methods exist, the functions use them. If not, they fall back to simpler calculations assuming the inputs are just numbers.
17
+
18
+ The code also includes many examples (in the form of doctests) to show how each function works with different types of inputs. These examples help illustrate the behavior of the functions and can be used to automatically test that the functions are working correctly.
19
+
20
+ Overall, this code provides a flexible set of tools for performing common operations in physical design calculations, capable of working with both simple numbers and more complex geometric objects.
21
+ """
22
+
23
+
24
+ def overlap(lhs, rhs) -> bool:
25
+ """
26
+ The `overlap` function checks if two objects have an overlapping property or are equal.
27
+
28
+ :param lhs: The `lhs` parameter represents the left-hand side object that we want to check for
29
+ overlap with the `rhs` parameter
30
+
31
+ :param rhs: The parameter `rhs` is the right-hand side of the comparison. It can be any object that
32
+ supports the `overlaps` method or a scalar value
33
+
34
+ :return: a boolean value.
35
+
36
+ Examples:
37
+ >>> overlap(1, 1)
38
+ True
39
+ >>> overlap(1, 3)
40
+ False
41
+ >>> from physdes.interval import Interval
42
+ >>> overlap(Interval(1, 2), Interval(2, 3))
43
+ True
44
+ >>> overlap(Interval(1, 2), Interval(3, 4))
45
+ False
46
+ >>> overlap(Interval(1, 2), 2)
47
+ True
48
+ >>> overlap(Interval(1, 2), 4)
49
+ False
50
+ >>> overlap(2, Interval(2, 3))
51
+ True
52
+ >>> overlap(1, Interval(3, 4))
53
+ False
54
+ >>> overlap(1, Interval(1, 2))
55
+ True
56
+ """
57
+ if hasattr(lhs, "overlaps"):
58
+ return lhs.overlaps(rhs)
59
+ elif hasattr(rhs, "overlaps"):
60
+ return rhs.overlaps(lhs)
61
+ else: # assume scalar
62
+ return lhs == rhs
63
+
64
+
65
+ def contain(lhs, rhs) -> bool:
66
+ """
67
+ The `contain` function checks if one object contains another object.
68
+
69
+ :param lhs: The `lhs` parameter represents the left-hand side of the comparison, while the `rhs`
70
+ parameter represents the right-hand side of the comparison
71
+
72
+ :param rhs: The `rhs` parameter represents the right-hand side of the comparison. It can be any
73
+ value or object that you want to check if it is contained within the `lhs` object
74
+
75
+ :return: a boolean value.
76
+
77
+ Examples:
78
+ >>> contain(1, 1)
79
+ True
80
+ >>> contain(1, 3)
81
+ False
82
+ >>> from physdes.interval import Interval
83
+ >>> contain(Interval(1, 4), Interval(2, 3))
84
+ True
85
+ >>> contain(Interval(1, 2), Interval(3, 4))
86
+ False
87
+ >>> contain(Interval(1, 2), 2)
88
+ True
89
+ >>> contain(Interval(1, 2), 4)
90
+ False
91
+ >>> contain(2, Interval(2, 3))
92
+ False
93
+ >>> contain(1, Interval(3, 4))
94
+ False
95
+ """
96
+ if hasattr(lhs, "contains"):
97
+ return lhs.contains(rhs)
98
+ elif hasattr(rhs, "contains"):
99
+ return False
100
+ else: # assume scalar
101
+ return lhs == rhs
102
+
103
+
104
+ def intersection(lhs, rhs):
105
+ """
106
+ The `intersection` function returns the intersection of two objects if they have an
107
+ `intersect_with` method, otherwise it returns the objects themselves if they are equal.
108
+
109
+ :param lhs: The `lhs` parameter represents the left-hand side of the intersection operation, while
110
+ the `rhs` parameter represents the right-hand side of the intersection operation
111
+
112
+ :param rhs: The `rhs` parameter is the second input to the `intersection` function. It represents
113
+ the right-hand side of the intersection operation
114
+
115
+ :return: the intersection of `lhs` and `rhs`.
116
+
117
+ Examples:
118
+ >>> print(intersection(1, 1))
119
+ 1
120
+ >>> from physdes.interval import Interval
121
+ >>> print(intersection(Interval(1, 2), Interval(2, 3)))
122
+ [2, 2]
123
+ >>> print(intersection(Interval(1, 2), 2))
124
+ [2, 2]
125
+ >>> print(intersection(2, Interval(2, 3)))
126
+ [2, 2]
127
+ >>> print(intersection(1, Interval(1, 2)))
128
+ [1, 1]
129
+ >>> print(intersection(Interval(1, 2), Interval(1, 2)))
130
+ [1, 2]
131
+ >>> print(intersection(Interval(1, 2), Interval(2, 3)))
132
+ [2, 2]
133
+ >>> print(intersection(Interval(1, 2), 2))
134
+ [2, 2]
135
+ """
136
+ if hasattr(lhs, "intersect_with"):
137
+ return lhs.intersect_with(rhs)
138
+ elif hasattr(rhs, "intersect_with"):
139
+ return rhs.intersect_with(lhs)
140
+ else: # assume scalar
141
+ assert lhs == rhs
142
+ return lhs
143
+
144
+
145
+ def min_dist(lhs, rhs):
146
+ """
147
+ The `min_dist` function calculates the minimum Manhattan distance between two objects, using their
148
+ `min_dist_with` method if available, or by subtracting them if they are scalars.
149
+
150
+ :param lhs: The `lhs` parameter represents the left-hand side value or object that we want to
151
+ calculate the minimum Manhattan distance with
152
+
153
+ :param rhs: The parameter `rhs` represents the right-hand side value or object that we want to
154
+ compare with the left-hand side value or object `lhs`
155
+
156
+ :return: the minimum Manhattan distance between `lhs` and `rhs`.
157
+
158
+ Examples:
159
+ >>> min_dist(1, 1)
160
+ 0
161
+ >>> min_dist(1, 3)
162
+ 2
163
+ >>> from physdes.interval import Interval
164
+ >>> min_dist(Interval(1, 2), Interval(2, 3))
165
+ 0
166
+ >>> min_dist(Interval(1, 2), Interval(3, 4))
167
+ 1
168
+ >>> min_dist(Interval(1, 2), 2)
169
+ 0
170
+ >>> min_dist(Interval(1, 2), 4)
171
+ 2
172
+ >>> min_dist(2, Interval(2, 3))
173
+ 0
174
+ >>> min_dist(1, Interval(3, 4))
175
+ 2
176
+ >>> min_dist(1, Interval(1, 2))
177
+ 0
178
+ >>> min_dist(Interval(1, 2), Interval(1, 2))
179
+ 0
180
+ >>> min_dist(Interval(1, 2), Interval(2, 3))
181
+ 0
182
+ >>> min_dist(Interval(1, 2), 2)
183
+ 0
184
+ >>> min_dist(2, Interval(2, 3))
185
+ 0
186
+ """
187
+ if hasattr(lhs, "min_dist_with"):
188
+ return lhs.min_dist_with(rhs)
189
+ elif hasattr(rhs, "min_dist_with"):
190
+ return rhs.min_dist_with(lhs)
191
+ else: # assume scalar
192
+ return abs(lhs - rhs)
193
+
194
+
195
+ # def min_dist_change(lhs, rhs):
196
+ # """
197
+ # The `min_dist_change` function calculates the minimum Manhattan distance change between two objects.
198
+ #
199
+ # :param lhs: The `lhs` parameter represents the left-hand side value or object that you want to
200
+ # compare
201
+ # :param rhs: The `rhs` parameter represents the right-hand side value or object that we want to
202
+ # compare with the `lhs` parameter
203
+ # :return: The function `min_dist_change` returns the minimum Manhattan distance change between `lhs` and `rhs`.
204
+ #
205
+ # Examples:
206
+ # >>> min_dist_change(1, 1)
207
+ # 0
208
+ # >>> min_dist_change(1, 3)
209
+ # 2
210
+ # >>> min_dist_change(Interval(1, 2), Interval(2, 3))
211
+ # 0
212
+ # >>> min_dist_change(Interval(1, 2), Interval(3, 4))
213
+ # 1
214
+ # >>> min_dist_change(Interval(1, 2), 2)
215
+ # 0
216
+ # >>> min_dist_change(Interval(1, 2), 4)
217
+ # 2
218
+ # >>> min_dist_change(2, Interval(2, 3))
219
+ # 0
220
+ # >>> min_dist_change(1, Interval(3, 4))
221
+ # 2
222
+ # >>> min_dist_change(1, Interval(1, 2))
223
+ # 0
224
+ # >>> min_dist_change(Interval(1, 2), Interval(1, 2))
225
+ # 0
226
+ # >>> min_dist_change(Interval(1, 2), Interval(2, 3))
227
+ # 0
228
+ # >>> min_dist_change(Interval(1, 2), 2)
229
+ # 0
230
+ # """
231
+ # if hasattr(lhs, "min_dist_change_with"):
232
+ # return lhs.min_dist_change_with(rhs)
233
+ # elif hasattr(rhs, "min_dist_change_with"):
234
+ # return rhs.min_dist_change_with(lhs)
235
+ # else: # assume scalar
236
+ # return abs(lhs - rhs)
237
+
238
+
239
+ def displacement(lhs, rhs):
240
+ """
241
+ The `displacement` function calculates the displacement between two objects or scalars.
242
+
243
+ :param lhs: The `lhs` parameter represents the left-hand side of the displacement operation. It can
244
+ be either an object that has a `displace` method or a scalar value
245
+
246
+ :param rhs: The `rhs` parameter represents the displacement value that needs to be subtracted from
247
+ the `lhs` parameter
248
+
249
+ :return: the displacement between `lhs` and `rhs`. If `lhs` has a `displace` method, it calls that
250
+ method passing `rhs` as an argument. Otherwise, it assumes `lhs` is a scalar and returns the
251
+ difference between `lhs` and `rhs`.
252
+
253
+ Examples:
254
+ >>> displacement(1, 1)
255
+ 0
256
+ >>> displacement(1, 3)
257
+ -2
258
+ >>> from physdes.interval import Interval
259
+ >>> print(displacement(Interval(1, 2), Interval(2, 3)))
260
+ [-1, -1]
261
+ >>> print(displacement(Interval(1, 2), Interval(3, 4)))
262
+ [-2, -2]
263
+ """
264
+ if hasattr(lhs, "displace"):
265
+ return lhs.displace(rhs)
266
+ else: # assume scalar
267
+ return lhs - rhs
268
+
269
+
270
+ if __name__ == "__main__":
271
+ import doctest
272
+
273
+ doctest.testmod()
physdes/generic.tpy ADDED
@@ -0,0 +1,89 @@
1
+ def overlap(lhs, rhs) -> bool:
2
+ """[summary]
3
+
4
+ Args:
5
+ lhs ([type]): [description]
6
+ rhs ([type]): [description]
7
+
8
+ Returns:
9
+ bool: [description]
10
+ """
11
+ if hasattr(lhs, "overlaps"):
12
+ return lhs.overlaps(rhs)
13
+ elif hasattr(rhs, "overlaps"):
14
+ return rhs.overlaps(lhs)
15
+ else: # assume scalar
16
+ return lhs == rhs
17
+
18
+
19
+ def contain(lhs, rhs) -> bool:
20
+ """[summary]
21
+
22
+ Args:
23
+ lhs ([type]): [description]
24
+ rhs ([type]): [description]
25
+
26
+ Returns:
27
+ bool: [description]
28
+ """
29
+ if hasattr(lhs, "contains"):
30
+ return lhs.contains(rhs)
31
+ elif hasattr(rhs, "contains"):
32
+ return False
33
+ else: # assume scalar
34
+ return lhs == rhs
35
+
36
+
37
+ def intersection(lhs, rhs):
38
+ """[summary]
39
+
40
+ Args:
41
+ lhs ([type]): [description]
42
+ rhs ([type]): [description]
43
+
44
+ Returns:
45
+ [type]: [description]
46
+ """
47
+ if hasattr(lhs, "intersect_with"):
48
+ return lhs.intersect_with(rhs)
49
+ elif hasattr(rhs, "intersect_with"):
50
+ return rhs.intersect_with(lhs)
51
+ else: # assume scalar
52
+ assert lhs == rhs
53
+ return lhs
54
+
55
+
56
+ def min_dist(lhs, rhs):
57
+ """[summary]
58
+
59
+ Args:
60
+ lhs ([type]): [description]
61
+ rhs ([type]): [description]
62
+
63
+ Returns:
64
+ [type]: [description]
65
+ """
66
+ if hasattr(lhs, "min_dist_with"):
67
+ return lhs.min_dist_with(rhs)
68
+ elif hasattr(rhs, "min_dist_with"):
69
+ return rhs.min_dist_with(lhs)
70
+ else: # assume scalar
71
+ return abs(lhs - rhs)
72
+
73
+
74
+ def min_dist_change(lhs, rhs):
75
+ """[summary]
76
+
77
+ Args:
78
+ lhs ([type]): [description]
79
+ rhs ([type]): [description]
80
+
81
+ Returns:
82
+ [type]: [description]
83
+ """
84
+ if hasattr(lhs, "min_dist_change_with"):
85
+ return lhs.min_dist_change_with(rhs)
86
+ elif hasattr(rhs, "min_dist_change_with"):
87
+ return rhs.min_dist_change_with(lhs)
88
+ else: # assume scalar
89
+ return abs(lhs - rhs)