pydasa 0.4.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.
Files changed (58) hide show
  1. pydasa/__init__.py +103 -0
  2. pydasa/_version.py +6 -0
  3. pydasa/analysis/__init__.py +0 -0
  4. pydasa/analysis/scenario.py +584 -0
  5. pydasa/analysis/simulation.py +1158 -0
  6. pydasa/context/__init__.py +0 -0
  7. pydasa/context/conversion.py +11 -0
  8. pydasa/context/system.py +17 -0
  9. pydasa/context/units.py +15 -0
  10. pydasa/core/__init__.py +15 -0
  11. pydasa/core/basic.py +287 -0
  12. pydasa/core/cfg/default.json +136 -0
  13. pydasa/core/constants.py +27 -0
  14. pydasa/core/io.py +102 -0
  15. pydasa/core/setup.py +269 -0
  16. pydasa/dimensional/__init__.py +0 -0
  17. pydasa/dimensional/buckingham.py +728 -0
  18. pydasa/dimensional/fundamental.py +146 -0
  19. pydasa/dimensional/model.py +1077 -0
  20. pydasa/dimensional/vaschy.py +633 -0
  21. pydasa/elements/__init__.py +19 -0
  22. pydasa/elements/parameter.py +218 -0
  23. pydasa/elements/specs/__init__.py +22 -0
  24. pydasa/elements/specs/conceptual.py +161 -0
  25. pydasa/elements/specs/numerical.py +469 -0
  26. pydasa/elements/specs/statistical.py +229 -0
  27. pydasa/elements/specs/symbolic.py +394 -0
  28. pydasa/serialization/__init__.py +27 -0
  29. pydasa/serialization/parser.py +133 -0
  30. pydasa/structs/__init__.py +0 -0
  31. pydasa/structs/lists/__init__.py +0 -0
  32. pydasa/structs/lists/arlt.py +578 -0
  33. pydasa/structs/lists/dllt.py +18 -0
  34. pydasa/structs/lists/ndlt.py +262 -0
  35. pydasa/structs/lists/sllt.py +746 -0
  36. pydasa/structs/tables/__init__.py +0 -0
  37. pydasa/structs/tables/htme.py +182 -0
  38. pydasa/structs/tables/scht.py +774 -0
  39. pydasa/structs/tools/__init__.py +0 -0
  40. pydasa/structs/tools/hashing.py +53 -0
  41. pydasa/structs/tools/math.py +149 -0
  42. pydasa/structs/tools/memory.py +54 -0
  43. pydasa/structs/types/__init__.py +0 -0
  44. pydasa/structs/types/functions.py +131 -0
  45. pydasa/structs/types/generics.py +54 -0
  46. pydasa/validations/__init__.py +0 -0
  47. pydasa/validations/decorators.py +510 -0
  48. pydasa/validations/error.py +100 -0
  49. pydasa/validations/patterns.py +32 -0
  50. pydasa/workflows/__init__.py +1 -0
  51. pydasa/workflows/influence.py +497 -0
  52. pydasa/workflows/phenomena.py +529 -0
  53. pydasa/workflows/practical.py +765 -0
  54. pydasa-0.4.7.dist-info/METADATA +320 -0
  55. pydasa-0.4.7.dist-info/RECORD +58 -0
  56. pydasa-0.4.7.dist-info/WHEEL +5 -0
  57. pydasa-0.4.7.dist-info/licenses/LICENSE +674 -0
  58. pydasa-0.4.7.dist-info/top_level.txt +1 -0
File without changes
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Configuration module for...
4
+
5
+ # TODO: Add description of the module.
6
+
7
+ *IMPORTANT:* Based on the theory from:
8
+
9
+ # H.Gorter, *Dimensionalanalyse: Eine Theoririe der physikalischen Dimensionen mit Anwendungen*
10
+ """
11
+ # TODO add UnitConverter for one variable/parameter
@@ -0,0 +1,17 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Module domain.py
4
+ ===========================================
5
+
6
+ Configuration module for...
7
+
8
+ # TODO: Add description of the module.
9
+
10
+ Classes:
11
+ **UnitManager**: Manages units and their conversions, including validation and error handling.
12
+
13
+ *IMPORTANT:* Based on the theory from:
14
+
15
+ # H.Gorter, *Dimensionalanalyse: Eine Theoririe der physikalischen Dimensionen mit Anwendungen*
16
+ """
17
+ # TODO add UnitManager class
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Module units.py
4
+ ===========================================
5
+
6
+ This module provides the Measurement class for handling physical measurements with units, values, and validation.
7
+
8
+ Classes:
9
+ **Measurement**: Represents a physical measurement with a value, unit, and validation logic.
10
+
11
+ *IMPORTANT:* Based on the theory from:
12
+
13
+ # H.Gorter, *Dimensionalanalyse: Eine Theoririe der physikalischen Dimensionen mit Anwendungen*
14
+ """
15
+ # TODO complete implementation of Measurement class
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Package data
4
+ ===========================================
5
+
6
+ Data persistence and I/O operations for PyDASA.
7
+
8
+ This package provides functions for reading and writing data to files,
9
+ handling different data formats, and ensuring compatibility with the
10
+ data structures used in PyDASA.
11
+ """
12
+
13
+ from pydasa.core.io import load, save, load_json, save_json
14
+
15
+ __all__ = ['load', 'save', 'load_json', 'save_json']
pydasa/core/basic.py ADDED
@@ -0,0 +1,287 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Module basic.py
4
+ ===========================================
5
+
6
+ This module provides base classes with common validation logic used across FDU, Parameter, and Variable classes to eliminate code duplication.
7
+
8
+ Classes:
9
+ **Foundation**: enforces common validation logic.
10
+ **IdxBasis**: enforces index/precedence validation logic.
11
+ **SymBasis**: enforces symbol and framework validation logic.
12
+
13
+ *IMPORTANT:* Based on the theory from:
14
+
15
+ # H.Gorter, *Dimensionalanalyse: Eine Theoririe der physikalischen Dimensionen mit Anwendungen*
16
+ """
17
+ # native python modules
18
+ # forward references + postpone eval type hints
19
+ from __future__ import annotations
20
+ from dataclasses import dataclass
21
+ from typing import Optional
22
+
23
+ # indicate it is an abstract base class
24
+ from abc import ABC
25
+
26
+ # import global variables
27
+ from pydasa.core.setup import Frameworks
28
+ from pydasa.core.setup import PYDASA_CFG
29
+ from pydasa.validations.patterns import LATEX_RE
30
+
31
+ # import validation decorators
32
+ from pydasa.validations.decorators import validate_type
33
+ from pydasa.validations.decorators import validate_emptiness
34
+ from pydasa.validations.decorators import validate_choices
35
+ from pydasa.validations.decorators import validate_pattern
36
+ from pydasa.validations.decorators import validate_index
37
+
38
+
39
+ @dataclass
40
+ class SymBasis(ABC):
41
+ """**SymBasis** Foundation class for entities with symbols and framework functionalities.
42
+
43
+ Attributes:
44
+ _sym (str): Symbol representation.
45
+ _alias (str): Python-compatible alias for use in code.
46
+ _fwk (str): Frameworks context.
47
+ """
48
+
49
+ # :attr: _sym
50
+ _sym: str = ""
51
+ """Symbol representation (LaTeX or alphanumeric)."""
52
+
53
+ # :attr: _fwk
54
+ _fwk: str = Frameworks.PHYSICAL.value
55
+ """Frameworks context (PHYSICAL, COMPUTATION, SOFTWARE, CUSTOM)."""
56
+
57
+ # :attr: _alias
58
+ _alias: str = ""
59
+ """Python-compatible alias for symbol, used in executable code. e.g.: `\\rho_{1}` -> `rho_1`."""
60
+
61
+ def __post_init__(self) -> None:
62
+ """*__post_init__()* Post-initialization processing with symbol and framework validation.
63
+ """
64
+ # super().__post_init__()
65
+ # Validate the symbol and framework
66
+ if not self._sym:
67
+ self._sym = self._sym.strip()
68
+ if not self._fwk:
69
+ self._fwk = self._fwk.strip()
70
+ if not self._alias:
71
+ self._alias = self._alias.strip()
72
+
73
+ @property
74
+ def sym(self) -> str:
75
+ """*sym* Get the symbol.
76
+
77
+ Returns:
78
+ str: Symbol value.
79
+ """
80
+ return self._sym
81
+
82
+ @sym.setter
83
+ @validate_type(str)
84
+ @validate_emptiness()
85
+ @validate_pattern(LATEX_RE, allow_alnum=True)
86
+ def sym(self, val: str) -> None:
87
+ """*sym* Set the symbol with validation.
88
+
89
+ Args:
90
+ val (str): Symbol value.
91
+
92
+ Raises:
93
+ ValueError: If symbol format is invalid.
94
+ """
95
+ self._sym = val
96
+
97
+ @property
98
+ def fwk(self) -> str:
99
+ """*fwk* Get the framework.
100
+
101
+ Returns:
102
+ str: Frameworks value.
103
+ """
104
+ return self._fwk
105
+
106
+ @fwk.setter
107
+ @validate_type(str)
108
+ @validate_choices(PYDASA_CFG.frameworks)
109
+ def fwk(self, val: str) -> None:
110
+ """*fwk* Set the framework with validation.
111
+
112
+ Args:
113
+ val (str): Frameworks value.
114
+
115
+ Raises:
116
+ ValueError: If framework is not supported.
117
+ """
118
+ self._fwk = val
119
+
120
+ @property
121
+ def alias(self) -> Optional[str]:
122
+ """*alias* Get the Python variable synonym.
123
+
124
+ Returns:
125
+ Optional[str]: Python variable name. e.g.: `\\rho_{1}` -> `rho_1`.
126
+ """
127
+ return self._alias
128
+
129
+ @alias.setter
130
+ @validate_type(str)
131
+ @validate_emptiness()
132
+ def alias(self, val: str) -> None:
133
+ """*alias* Set the Python variable synonym.
134
+
135
+ Args:
136
+ val (str): Python variable name. e.g.: `\\rho_{1}` -> `rho_1`.
137
+
138
+ Raises:
139
+ ValueError: If variable name is empty.
140
+ """
141
+ self._alias = val
142
+
143
+ def clear(self) -> None:
144
+ """*clear()* Reset symbol and framework attributes to default values.
145
+
146
+ Resets the entity's symbol-related properties to their initial state.
147
+ """
148
+ # Reset symbol attributes
149
+ self._sym = ""
150
+ self._alias = ""
151
+ self._fwk = Frameworks.PHYSICAL.value
152
+
153
+
154
+ @dataclass
155
+ class IdxBasis(SymBasis):
156
+ """**IdxBasis** Foundation class for entities with index/precedence functionality.
157
+
158
+ Attributes:
159
+ _idx (int): Index/precedence value
160
+ """
161
+
162
+ # :attr: _idx
163
+ _idx: int = -1
164
+ """Unique identifier/index for ordering in dimensional matrix."""
165
+
166
+ def __post_init__(self) -> None:
167
+ """*__post_init__()* Post-initialization processing with symbol and framework validation.
168
+ """
169
+ super().__post_init__()
170
+ if self._idx != -1:
171
+ self.idx = self._idx
172
+
173
+ @property
174
+ def idx(self) -> int:
175
+ """*idx* Get the index/precedence value.
176
+
177
+ Returns:
178
+ int: Index value.
179
+ """
180
+ return self._idx
181
+
182
+ @idx.setter
183
+ @validate_type(int, allow_none=False)
184
+ @validate_index()
185
+ def idx(self, val: int) -> None:
186
+ """*idx* Set the index/precedence value.
187
+
188
+ Args:
189
+ val (int): Index value (must be non-negative).
190
+
191
+ Raises:
192
+ ValueError: If index is not a non-negative integer.
193
+ """
194
+ self._idx = val
195
+
196
+ def clear(self) -> None:
197
+ """*clear()* Reset index and inherited attributes to default values.
198
+
199
+ Resets the entity's index and symbol-related properties to their initial state.
200
+ """
201
+ # Reset parent class attributes
202
+ super().clear()
203
+
204
+ # Reset index attribute
205
+ self._idx = -1
206
+
207
+
208
+ @dataclass
209
+ class Foundation(IdxBasis):
210
+ """**Foundation** Foundation class for all dimensional analysis entities.
211
+
212
+ Provides common validation logic and attributes shared by FDU, Variable, and Coeffcient classes.
213
+
214
+ Attributes:
215
+ name (str): User-friendly name
216
+ description (str): Brief summary or description
217
+ """
218
+
219
+ # :attr: _name
220
+ _name: str = ""
221
+ """User-friendly name of the entity."""
222
+
223
+ # :attr: description
224
+ description: str = ""
225
+ """Brief summary or description of the entity."""
226
+
227
+ def __post_init__(self) -> None:
228
+ """*__post_init__()* Post-initialization processing with description capitalization.
229
+ """
230
+ if self.description:
231
+ self.description = self.description.strip()
232
+
233
+ @property
234
+ def name(self) -> str:
235
+ """*name* Get the name.
236
+
237
+ Returns:
238
+ str: Name value.
239
+ """
240
+ return self._name
241
+
242
+ @name.setter
243
+ @validate_type(str, allow_none=False)
244
+ def name(self, val: str) -> None:
245
+ """*name* Set the name with validation.
246
+
247
+ Args:
248
+ val (str): Name value.
249
+
250
+ Raises:
251
+ ValueError: If name is not a non-empty string.
252
+ """
253
+ self._name = val.strip()
254
+
255
+ def clear(self) -> None:
256
+ """*clear()* Reset all attributes to default values.
257
+
258
+ Resets the entity's properties to their initial state.
259
+ """
260
+ # Reset parent class attributes
261
+ super().clear()
262
+
263
+ # Reset name and description attributes
264
+ self.name = ""
265
+ self.description = ""
266
+
267
+ def __str__(self) -> str:
268
+ """*__str__()* String representation showing all non-private attributes.
269
+
270
+ Returns:
271
+ str: Formatted string representation.
272
+ """
273
+ attr_list = []
274
+ for attr, val in vars(self).items():
275
+ if attr.startswith("__"):
276
+ continue
277
+ attr_name = attr.lstrip("_")
278
+ attr_list.append(f"{attr_name}={repr(val)}")
279
+ return f"{self.__class__.__name__}({', '.join(attr_list)})"
280
+
281
+ def __repr__(self) -> str:
282
+ """*__repr__()* Detailed string representation.
283
+
284
+ Returns:
285
+ str: String representation.
286
+ """
287
+ return self.__str__()
@@ -0,0 +1,136 @@
1
+ {
2
+ "frameworks": {
3
+ "PHYSICAL": {
4
+ "name": "Physical Framework",
5
+ "description": "Traditional physical dimensional framework (e.g., Length, Mass, Time).",
6
+ "fdus": {
7
+ "L": {
8
+ "unit": "m",
9
+ "name": "Length",
10
+ "description": "Distance between two points in space."
11
+ },
12
+ "M": {
13
+ "unit": "kg",
14
+ "name": "Mass",
15
+ "description": "Amount of matter in an object."
16
+ },
17
+ "T": {
18
+ "unit": "s",
19
+ "name": "Time",
20
+ "description": "Duration of an event or interval."
21
+ },
22
+ "K": {
23
+ "unit": "K",
24
+ "name": "Temperature",
25
+ "description": "Measure of average kinetic energy of particles."
26
+ },
27
+ "I": {
28
+ "unit": "A",
29
+ "name": "Electric Current",
30
+ "description": "Flow of electric charge."
31
+ },
32
+ "N": {
33
+ "unit": "mol",
34
+ "name": "Amount of Substance",
35
+ "description": "Quantity of entities (e.g., atoms, molecules)."
36
+ },
37
+ "C": {
38
+ "unit": "cd",
39
+ "name": "Luminous Intensity",
40
+ "description": "Perceived power of light in a given direction."
41
+ }
42
+ }
43
+ },
44
+ "COMPUTATION": {
45
+ "name": "Computation Framework",
46
+ "description": "Computer science dimensional framework (e.g., Time, Space, Complexity).",
47
+ "fdus": {
48
+ "T": {
49
+ "unit": "s",
50
+ "name": "Time",
51
+ "description": "Duration of an event or interval."
52
+ },
53
+ "S": {
54
+ "unit": "bit",
55
+ "name": "Space",
56
+ "description": "Physical extent in three dimensions."
57
+ },
58
+ "N": {
59
+ "unit": "op",
60
+ "name": "Complexity",
61
+ "description": "Measure of interconnectedness or intricacy in a system."
62
+ }
63
+ }
64
+ },
65
+ "SOFTWARE": {
66
+ "name": "Software Framework",
67
+ "description": "Software architecture dimensional framework (e.g., Time, Data, Connectivity).",
68
+ "fdus": {
69
+ "T": {
70
+ "unit": "s",
71
+ "name": "Time",
72
+ "description": "Duration of an event or interval."
73
+ },
74
+ "D": {
75
+ "unit": "bit",
76
+ "name": "Data",
77
+ "description": "Information processed by a system."
78
+ },
79
+ "E": {
80
+ "unit": "req",
81
+ "name": "Effort",
82
+ "description": "Measure of computational effort/complexity."
83
+ },
84
+ "C": {
85
+ "unit": "node",
86
+ "name": "Connectivity",
87
+ "description": "Measure of interconnections between components."
88
+ },
89
+ "A": {
90
+ "unit": "process",
91
+ "name": "Capacity",
92
+ "description": "Maximum amount of data that can be stored/processed."
93
+ }
94
+ }
95
+ },
96
+ "CUSTOM": {
97
+ "name": "Custom Framework",
98
+ "description": "User-defined dimensional framework for specific use cases.",
99
+ "fdus": {}
100
+ }
101
+ },
102
+ "variable_cardinality": {
103
+ "IN": {
104
+ "name": "Input Variables",
105
+ "description": "Variables that influence the system (e.g., known inputs)."
106
+ },
107
+ "OUT": {
108
+ "name": "Output Variables",
109
+ "description": "Variable that represent the results of the analysis."
110
+ },
111
+ "CTRL": {
112
+ "name": "Control Variables",
113
+ "description": "Variables used to control or constrain the system (e.g., constants)."
114
+ }
115
+ },
116
+ "coefficient_cardinality": {
117
+ "COMPUTED": {
118
+ "name": "Computed Coefficients",
119
+ "description": "Coefficients directly calculated using the Dimensional Matrix."
120
+ },
121
+ "DERIVED": {
122
+ "name": "Derived Coefficients",
123
+ "description": "Coefficients obtained by combining or manipulating Computed Coefficients."
124
+ }
125
+ },
126
+ "analytic_modes": {
127
+ "SYM": {
128
+ "name": "Symbolic Mode",
129
+ "description": "Analysis for symbolic processable parameters (e.g., 'z = x + y')."
130
+ },
131
+ "NUM": {
132
+ "name": "Numeric Mode",
133
+ "description": "Analysis for numeric variable ranges (e.g., 1.0, 2.5)."
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,27 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Module constants.py
4
+ ===========================================
5
+
6
+ This module specifies the Fundamental Dimensional Units (FDUs) available by default in *PyDASA*. The default framework are the Physical FDUs.
7
+
8
+ The three main types of FDUs are:
9
+ 1. Physical FDUs: in `PHY_FDU_PREC_DT` representing the standard physical dimensions.
10
+ 2. Digital FDUs: in `COMPU_FDU_PREC_DT` representing dimensions relevant to computation.
11
+ 3. Software Architecture FDUs: in `SOFT_FDU_PREC_DT` representing dimensions specific to software architecture.
12
+
13
+ The fourth FDU framework is:
14
+ 4. Custom FDUs: user-defined FDUs that can be specified as needed.
15
+ """
16
+ # python native modules
17
+
18
+ # global variables
19
+
20
+ # Default config folder name + settings
21
+ # :attr: DFLT_CFG_FOLDER
22
+ DFLT_CFG_FOLDER: str = "cfg"
23
+ # :attr: DFLT_CFG_FILE
24
+ DFLT_CFG_FILE: str = "default.json"
25
+ """
26
+ *PyDASA* default configuration folder and file names.
27
+ """
pydasa/core/io.py ADDED
@@ -0,0 +1,102 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Module io.py
4
+ ===========================================
5
+
6
+ Generic I/O operations for PyDASA.
7
+
8
+ This module provides functions for reading and writing data to files, handling different data formats (JSON, CSV, etc.), and ensuring compatibility with the data structures used in PyDASA.
9
+
10
+ *IMPORTANT:* based on the implementations proposed by the following authors/books:
11
+
12
+ #. Algorithms, 4th Edition, Robert Sedgewick and Kevin Wayne.
13
+ #. Data Structure and Algorithms in Python, M.T. Goodrich, R. Tamassia, M.H. Goldwasser.
14
+ """
15
+
16
+ import json
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+ # global variable to define supported formats
21
+ READ = "r"
22
+ WRITE = "w"
23
+ PATTERN = "utf-8"
24
+ AVAIL_FMT = [".json"]
25
+
26
+
27
+ def load_json(file_path: str | Path) -> dict[str, Any]:
28
+ """*load_json()* reads a JSON file and returns its content as a dictionary.
29
+
30
+ Args:
31
+ file_path (str | Path): Path to the JSON file.
32
+
33
+ Returns:
34
+ dict[str, Any]: Dictionary with the JSON content.
35
+ """
36
+ file_path = Path(file_path)
37
+ with open(file_path, READ, encoding=PATTERN) as f:
38
+ return json.load(f)
39
+
40
+
41
+ def save_json(data: dict[str, Any],
42
+ file_path: str | Path,
43
+ indent: int = 4) -> None:
44
+ """*save_json()* writes a dictionary to a JSON file.
45
+
46
+ Args:
47
+ data (dict[str, Any]): Dictionary to be saved.
48
+ file_path (str | Path): Path to the output JSON file.
49
+ indent (int, optional): Indentation level. Defaults to 4.
50
+ """
51
+ file_path = Path(file_path)
52
+ file_path.parent.mkdir(parents=True, exist_ok=True)
53
+
54
+ with open(file_path, WRITE, encoding=PATTERN) as f:
55
+ json.dump(data, f, indent=indent, ensure_ascii=False)
56
+
57
+
58
+ def load(file_path: str | Path) -> dict[str, Any]:
59
+ """*load()* generic load function - detects format from file extension.
60
+
61
+ Args:
62
+ file_path (str | Path): Input file path.
63
+
64
+ Raises:
65
+ ValueError: If unsupported file format.
66
+
67
+ Returns:
68
+ dict[str, Any]: Loaded data as a dictionary.
69
+ """
70
+ file_path = Path(file_path)
71
+ suffix = file_path.suffix.lower()
72
+
73
+ if suffix in AVAIL_FMT:
74
+ return load_json(file_path)
75
+ else:
76
+ _msg = f"Unsupported file format: {suffix}. "
77
+ _msg += f"Supported: {', '.join(AVAIL_FMT)}"
78
+ raise ValueError(_msg)
79
+
80
+
81
+ def save(data: dict[str, Any],
82
+ file_path: str | Path, **kwargs) -> None:
83
+ """*save()* generic save function - detects format from file extension.
84
+
85
+ Args:
86
+ data (dict[str, Any]): Data to be saved.
87
+ file_path (str | Path): Output file path.
88
+ **kwargs: Additional keyword arguments for specific save functions.
89
+
90
+ Raises:
91
+ ValueError: If unsupported file format.
92
+ """
93
+ file_path = Path(file_path)
94
+ suffix = file_path.suffix.lower()
95
+
96
+ if suffix in AVAIL_FMT:
97
+ indent = kwargs.get("indent", 4)
98
+ save_json(data, file_path, indent=indent)
99
+ else:
100
+ _msg = f"Unsupported file format: {suffix}. "
101
+ _msg += f"Supported: {', '.join(AVAIL_FMT)}"
102
+ raise ValueError(_msg)