muflon 1.0.2__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.
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: muflon
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Summary: Library for martice operations
|
|
5
|
+
Home-page: https://github.com/Kiryl24/muflon
|
|
6
|
+
Author: YJakub Kiryła
|
|
7
|
+
Author-email: Jakub Kiryła <kub-kir@wp.pl>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/Kiryl24/muflon
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.10
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: home-page
|
|
16
|
+
Dynamic: requires-python
|
|
17
|
+
|
|
18
|
+
<img alt="logo.png" height="50" src="logo.png" width="50"/>
|
|
19
|
+
|
|
20
|
+
# MUFLON: Matrix Utility for Fuzzy Logic Operations and Norms
|
|
21
|
+
Muflon is a Python library designed for processing Intuitionistic Fuzzy Values (IFVs). It handles complex matrix operations by automatically splitting data into two parallel streams:
|
|
22
|
+
|
|
23
|
+
Membership (μ): Processed via T-Norms.
|
|
24
|
+
|
|
25
|
+
Non-Membership (ν): Processed via S-Conorms.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```pip install muflon```
|
|
30
|
+
|
|
31
|
+
## Core Concept: Tuple Processing
|
|
32
|
+
The system treats every data cell as a tuple $(i_1, i_2)$, representing:
|
|
33
|
+
1. **Membership ($\mu$):** The first value ($i_1$).
|
|
34
|
+
2. **Non-Membership ($\nu$):** The second value ($i_2$).
|
|
35
|
+
|
|
36
|
+
The script automatically splits these into two parallel calculation streams and produces **two distinct result matrices**:
|
|
37
|
+
* **Result 1:** Derived from the matrix of first numbers ($i_1, j_1, \dots$).
|
|
38
|
+
* **Result 2:** Derived from the matrix of second numbers ($i_2, j_2, \dots$).
|
|
39
|
+
|
|
40
|
+
## Data Format Requirements
|
|
41
|
+
|
|
42
|
+
Muflon is designed to work with CSV files where every cell represents a tuple ($\mu$,$\nu$).
|
|
43
|
+
|
|
44
|
+
| Feature | Separator | Example | Notes |
|
|
45
|
+
| :--- |:----------|:---|:---|
|
|
46
|
+
| **Column Separator** | `;` | `col1;col2;col3` | Standard CSV delimiter for this tool. |
|
|
47
|
+
| **Tuple Separator** | `,` | `0.3, 0.7` | **Crucial:** Used strictly to split $\mu$ and $\nu$ values inside a cell. |
|
|
48
|
+
| **Decimal Point** | `.` | `0.5` | Standard float notation. |
|
|
49
|
+
|
|
50
|
+
### CSV Structure Example (`Data.csv`)
|
|
51
|
+
```csv
|
|
52
|
+
0.3, 0.7; 0.2, 0.1; 0.5, 0.9
|
|
53
|
+
0.7, 0.4; 0.6, 0.2; 1.0, 0.5
|
|
54
|
+
```
|
|
55
|
+
Cell `0.3`, `0.7`: The tool parses `0.3` into the Mu Matrix and `0.7` into the Nu Matrix.
|
|
56
|
+
|
|
57
|
+
Empty Tuple Values: If a cell is just `0.5`, the second value defaults to `0.0`.
|
|
58
|
+
|
|
59
|
+
## Quick Start Guide
|
|
60
|
+
|
|
61
|
+
Here is a minimal script to load data, perform a standard Max-Min composition, and save the results.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
import numpy as np
|
|
65
|
+
from src.muflon.io import parse_data_to_matrices, save_results_to_csv
|
|
66
|
+
from src.muflon import fuzzy_composition, solve_vector
|
|
67
|
+
from src.muflon import get_norm
|
|
68
|
+
|
|
69
|
+
# Load Data
|
|
70
|
+
import pandas as pd
|
|
71
|
+
|
|
72
|
+
df = pd.read_csv('data.csv', sep=';', header=None)
|
|
73
|
+
|
|
74
|
+
# Parse into Mu and Nu Matrices
|
|
75
|
+
# The library automatically splits the tuples for you
|
|
76
|
+
matrix_mu, matrix_nu = parse_data_to_matrices(df)
|
|
77
|
+
|
|
78
|
+
# Perform Composition (C = A o B)
|
|
79
|
+
# Mu uses Minimum T-Norm
|
|
80
|
+
res_mu = fuzzy_composition(matrix_mu, matrix_mu, operator='min', aggregator=np.max)
|
|
81
|
+
|
|
82
|
+
# Nu uses Maximum S-Conorm
|
|
83
|
+
res_nu = fuzzy_composition(matrix_nu, matrix_nu, operator='max', aggregator=np.min)
|
|
84
|
+
|
|
85
|
+
# 4. Save Results
|
|
86
|
+
# Generates 'output_Mu.csv' and 'output_Nu.csv'
|
|
87
|
+
save_results_to_csv(res_mu, res_nu, "output.csv")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
# Available Operators
|
|
91
|
+
|
|
92
|
+
| Type | Code | Alias | Description |
|
|
93
|
+
|:------------|:-------|:----------------|:---|
|
|
94
|
+
| **T-Norms** | `T_M` | `min` | Minimum (Zadeh) |
|
|
95
|
+
| | `T_P` | `product` | Algebraic Product |
|
|
96
|
+
| | `T_L` | `lukasiewicz` | Bounded Difference |
|
|
97
|
+
| **S-Conorms** | `S_M` | `max` | Maximum |
|
|
98
|
+
| | `S_P` | `probabilistic` | Probabilistic Sum |
|
|
99
|
+
| | `S_L` | `bounded_sum` | Bounded Sum |
|
|
100
|
+
| **Implications** | `I_TM` | | Godel Implication |
|
|
101
|
+
| | `I_TP` | | Goguen Implication |
|
|
102
|
+
| | `I_TL` | | Lukasiewicz Implication |
|
|
103
|
+
|
|
104
|
+
## 1. Perform Matrix Composition: Calculates $C = A \circ B$
|
|
105
|
+
### Reads columns 0-2 for Matrix A, and 0-1 for Matrix B
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
## 2. Solve System: Solves $A \circ x = b$ for separate $\mu$ and $\nu$
|
|
109
|
+
### Solves for vector x given Matrix A and Vector b
|
|
110
|
+
```python
|
|
111
|
+
# Assume we have Matrix A and Vector b loaded
|
|
112
|
+
A_mu, A_nu = parse_data_to_matrices(df_A)
|
|
113
|
+
b_mu, b_nu = parse_data_to_matrices(df_b)
|
|
114
|
+
|
|
115
|
+
# Solve for Mu using Godel Implication (Induced by Min)
|
|
116
|
+
x_mu = solve_fuzzy_vector(A_mu, b_mu, implication='I_TM', aggregator=np.min)
|
|
117
|
+
|
|
118
|
+
# Solve for Nu using Lukasiewicz Implication (Induced by Lukasiewicz T-Norm)
|
|
119
|
+
x_nu = solve_fuzzy_vector(A_nu, b_nu, implication='I_TL', aggregator=np.max)
|
|
120
|
+
```
|
|
121
|
+
## Core Concepts & Logic
|
|
122
|
+
### Dual Matrix Processing
|
|
123
|
+
|
|
124
|
+
This script splits every input matrix into two parallel streams based on the tuple data:
|
|
125
|
+
|
|
126
|
+
Mu Stream ($\mu$): Uses the first value of the tuple. Processed using T-norms (e.g., Minimum) and Max aggregation.
|
|
127
|
+
|
|
128
|
+
Nu Stream ($\nu$): Uses the second value of the tuple. Processed using S-conorms (e.g., Maximum) and Min aggregation.
|
|
129
|
+
|
|
130
|
+
### Column Scoping
|
|
131
|
+
|
|
132
|
+
Data loading is controlled by parameters in get_data_from_csv (called internally by the run functions):
|
|
133
|
+
|
|
134
|
+
`col_start`: Index of the first column to read.
|
|
135
|
+
|
|
136
|
+
`col_end`: Index of the column to stop at (exclusive).
|
|
137
|
+
|
|
138
|
+
`header_rows`: Number of top rows to skip (e.g., for labels).
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
### Configuration
|
|
142
|
+
|
|
143
|
+
You can define new fuzzy logic operators (T-norms, S-conorms, or Implications) in two ways:
|
|
144
|
+
|
|
145
|
+
### Option 1: The Quick Way (Script-Level)
|
|
146
|
+
|
|
147
|
+
If you are experimenting and don't want to modify the library code, you can simply define a Python function in your script and pass it directly to the composition engine.
|
|
148
|
+
|
|
149
|
+
The function must accept two arguments (`x`, `y`).
|
|
150
|
+
|
|
151
|
+
It must work with `NumPy` arrays (use `np.maximum`, `np.where`, etc., instead of standard `max` or if).
|
|
152
|
+
|
|
153
|
+
Example code:
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
import numpy as np
|
|
157
|
+
from src.muflon import fuzzy_composition
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# 1. Define your custom operator (e.g., Einstein Product)
|
|
161
|
+
def t_einstein(x, y):
|
|
162
|
+
"""Calculates (x * y) / (2 - (x + y - x*y))"""
|
|
163
|
+
return (x * y) / (2 - (x + y - x * y))
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# 2. Pass the function directly to the composition tool
|
|
167
|
+
result = fuzzy_composition(matrix_A, matrix_B, operator=t_einstein, aggregator=np.max)
|
|
168
|
+
```
|
|
169
|
+
### Option 2: The Permanent Way (Library-Level)
|
|
170
|
+
|
|
171
|
+
If you want your new operator to be part of the library (so you can call it via string like `T_EINSTEIN`), follow these steps:
|
|
172
|
+
|
|
173
|
+
Open `muflon/norms.py` Add your function definition at the end of the appropriate section (e.g., under T-NORMS).
|
|
174
|
+
```python
|
|
175
|
+
# In muflon/norms.py
|
|
176
|
+
|
|
177
|
+
def t_hamacher(x, y):
|
|
178
|
+
"""Hamacher Product (simplified parameter)"""
|
|
179
|
+
numerator = x * y
|
|
180
|
+
denominator = x + y - (x * y)
|
|
181
|
+
# Avoid division by zero if both are 0
|
|
182
|
+
return np.where(denominator == 0, 0, numerator / denominator)
|
|
183
|
+
```
|
|
184
|
+
Register it in NORM_MAP Scroll down to the NORM_MAP dictionary in the same file and add a key-value pair.
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
NORM_MAP = {
|
|
188
|
+
# ... previous norms ...
|
|
189
|
+
'T_M': t_M,
|
|
190
|
+
'T_P': t_P,
|
|
191
|
+
|
|
192
|
+
# for clarity better to add new norms at the dictionary end:
|
|
193
|
+
'T_HAMACHER': t_hamacher,
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
Update get_norm (Optional but recommended) If you want to allow case-insensitive lookup (e.g., 'Hamacher'), add a quick alias in the get_norm function.
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
def get_norm(identifier):
|
|
200
|
+
# ... rest of function ...
|
|
201
|
+
key = identifier.upper()
|
|
202
|
+
|
|
203
|
+
# alias
|
|
204
|
+
if key == 'HAMACHER': key = 'T_HAMACHER'
|
|
205
|
+
```
|
|
206
|
+
Now You can use your new string identifier anywhere in your project.
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
from src.muflon import get_norm
|
|
210
|
+
|
|
211
|
+
res = fuzzy_composition(A, B, operator='T_HAMACHER', aggregator=np.max)
|
|
212
|
+
```
|
|
213
|
+
Example usage script for library:
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
import numpy as np
|
|
217
|
+
|
|
218
|
+
from src.muflon.io import parse_data_to_matrices, save_results_to_csv
|
|
219
|
+
from src.muflon import fuzzy_composition_multi, solve_fuzzy_vector
|
|
220
|
+
from src.muflon import get_norm, NORM_MAP
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def get_data_wrapper(filename, col_start, col_end, header_rows=0):
|
|
224
|
+
"""Wrapper to handle loading using your library's io module"""
|
|
225
|
+
import pandas as pd
|
|
226
|
+
try:
|
|
227
|
+
df = pd.read_csv(filename, sep=';', header=None, skiprows=header_rows)
|
|
228
|
+
df_subset = df.iloc[:, col_start:col_end]
|
|
229
|
+
return parse_data_to_matrices(df_subset)
|
|
230
|
+
except Exception as e:
|
|
231
|
+
print(f"Error reading {filename}: {e}")
|
|
232
|
+
return None, None
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def run_multiplication(file1, range1, header1, file2, range2, header2):
|
|
236
|
+
print(f"\n=== RUNNING MODE: MULTIPLICATION ===")
|
|
237
|
+
|
|
238
|
+
A_mu, A_nu = get_data_wrapper(file1, range1[0], range1[1], header_rows=header1)
|
|
239
|
+
B_mu, B_nu = get_data_wrapper(file2, range2[0], range2[1], header_rows=header2)
|
|
240
|
+
|
|
241
|
+
if A_mu is None: return
|
|
242
|
+
|
|
243
|
+
t_norm = get_norm('T_M') # Min
|
|
244
|
+
s_conorm = get_norm('S_M') # Max
|
|
245
|
+
|
|
246
|
+
print("Computing Mu (First values)...")
|
|
247
|
+
res_mu = fuzzy_composition_multi(A_mu, B_mu, [t_norm], np.max)
|
|
248
|
+
|
|
249
|
+
print("Computing Nu (Second values)...")
|
|
250
|
+
res_nu = fuzzy_composition_multi(A_nu, B_nu, [s_conorm], np.min)
|
|
251
|
+
|
|
252
|
+
save_results_to_csv(res_mu, res_nu, "Result_Multiplication.csv")
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def run_finding_vector(file_matrix, range_matrix, header_matrix, file_vector, range_vector, header_vector):
|
|
256
|
+
print(f"\nRUNNING MODE: FINDING VECTOR")
|
|
257
|
+
|
|
258
|
+
A_mu, A_nu = get_data_wrapper(file_matrix, range_matrix[0], range_matrix[1], header_matrix)
|
|
259
|
+
b_mu, b_nu = get_data_wrapper(file_vector, range_vector[0], range_vector[1], header_vector)
|
|
260
|
+
|
|
261
|
+
if A_mu is None: return
|
|
262
|
+
|
|
263
|
+
# Use names defined in your NORM_MAP in norms.py
|
|
264
|
+
imp_func_mu = get_norm('I_TM')
|
|
265
|
+
imp_func_nu = get_norm('I_TL')
|
|
266
|
+
|
|
267
|
+
print("Computing vector x for Mu...")
|
|
268
|
+
res_x_mu = solve_fuzzy_vector(A_mu, b_mu, imp_func_mu, np.min)
|
|
269
|
+
|
|
270
|
+
print("Computing vector x for Nu...")
|
|
271
|
+
res_x_nu = solve_fuzzy_vector(A_nu, b_nu, imp_func_nu, np.max)
|
|
272
|
+
|
|
273
|
+
save_results_to_csv(res_x_mu, res_x_nu, "Result_Vector.csv")
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
if __name__ == "__main__":
|
|
277
|
+
try:
|
|
278
|
+
'''
|
|
279
|
+
run_multiplication(
|
|
280
|
+
file1='Data1.csv', range1=(0, 2), header1=0,
|
|
281
|
+
file2='Data2.csv', range2=(0, 1), header2=0
|
|
282
|
+
)
|
|
283
|
+
'''
|
|
284
|
+
run_finding_vector(
|
|
285
|
+
file_matrix='Data1.csv', range_matrix=(0, 2), header_matrix=0,
|
|
286
|
+
file_vector='Data2.csv', range_vector=(0, 1), header_vector=0
|
|
287
|
+
)
|
|
288
|
+
except Exception as e:
|
|
289
|
+
print(f"Execution failed: {e}")
|
|
290
|
+
```
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
muflon-1.0.2.dist-info/METADATA,sha256=Zzh4hVmEOFdT3H22PSHSHTqdSjPUBTuN9m0L8VngvPc,10345
|
|
2
|
+
muflon-1.0.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
3
|
+
muflon-1.0.2.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
4
|
+
muflon-1.0.2.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|