topsis-dikshant-102303201 0.1.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.
- topsis_dikshant_102303201/__init__.py +1 -0
- topsis_dikshant_102303201/topsis.py +149 -0
- topsis_dikshant_102303201-0.1.1.dist-info/METADATA +44 -0
- topsis_dikshant_102303201-0.1.1.dist-info/RECORD +8 -0
- topsis_dikshant_102303201-0.1.1.dist-info/WHEEL +5 -0
- topsis_dikshant_102303201-0.1.1.dist-info/entry_points.txt +2 -0
- topsis_dikshant_102303201-0.1.1.dist-info/licenses/LICENSE +0 -0
- topsis_dikshant_102303201-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# ============================================
|
|
2
|
+
# STEP 0 — Import Required Libraries
|
|
3
|
+
# ============================================
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main():
|
|
11
|
+
# ============================================
|
|
12
|
+
# STEP 1 — Validate Number of Command-Line Arguments
|
|
13
|
+
# ============================================
|
|
14
|
+
|
|
15
|
+
if len(sys.argv) != 5:
|
|
16
|
+
print("Usage: python topsis.py <inputFileName> <Weights> <Impacts> <resultFileName>")
|
|
17
|
+
sys.exit(1)
|
|
18
|
+
|
|
19
|
+
input_file = sys.argv[1]
|
|
20
|
+
weights_input = sys.argv[2]
|
|
21
|
+
impacts_input = sys.argv[3]
|
|
22
|
+
output_file = sys.argv[4]
|
|
23
|
+
|
|
24
|
+
# ============================================
|
|
25
|
+
# STEP 2 — Parse Weights and Impacts
|
|
26
|
+
# ============================================
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
weights = np.array([float(w) for w in weights_input.split(",")])
|
|
30
|
+
except ValueError:
|
|
31
|
+
print("Error: Weights must be numeric and comma-separated.")
|
|
32
|
+
sys.exit(1)
|
|
33
|
+
|
|
34
|
+
impacts = impacts_input.split(",")
|
|
35
|
+
|
|
36
|
+
for impact in impacts:
|
|
37
|
+
if impact not in ['+', '-']:
|
|
38
|
+
print("Error: Impacts must be either '+' or '-'.")
|
|
39
|
+
sys.exit(1)
|
|
40
|
+
|
|
41
|
+
# ============================================
|
|
42
|
+
# STEP 3 — Load Input File (File Not Found Handling)
|
|
43
|
+
# ============================================
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
df = pd.read_excel(input_file)
|
|
47
|
+
except FileNotFoundError:
|
|
48
|
+
print("Error: Input file not found.")
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
except Exception as e:
|
|
51
|
+
print("Error while reading input file:", e)
|
|
52
|
+
sys.exit(1)
|
|
53
|
+
|
|
54
|
+
# ============================================
|
|
55
|
+
# STEP 4 — Validate Minimum Column Requirement
|
|
56
|
+
# ============================================
|
|
57
|
+
|
|
58
|
+
if df.shape[1] < 3:
|
|
59
|
+
print("Error: Input file must contain at least three columns.")
|
|
60
|
+
sys.exit(1)
|
|
61
|
+
|
|
62
|
+
# ============================================
|
|
63
|
+
# STEP 5 — Separate Identifier and Criteria Columns
|
|
64
|
+
# ============================================
|
|
65
|
+
|
|
66
|
+
data = df.iloc[:, 1:]
|
|
67
|
+
|
|
68
|
+
# ============================================
|
|
69
|
+
# STEP 6 — Validate Numeric Criteria Columns
|
|
70
|
+
# ============================================
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
data = data.astype(float)
|
|
74
|
+
except ValueError:
|
|
75
|
+
print("Error: From 2nd to last columns must contain numeric values only.")
|
|
76
|
+
sys.exit(1)
|
|
77
|
+
|
|
78
|
+
# ============================================
|
|
79
|
+
# STEP 7 — Validate Weights & Impacts Length
|
|
80
|
+
# ============================================
|
|
81
|
+
|
|
82
|
+
if len(weights) != data.shape[1] or len(impacts) != data.shape[1]:
|
|
83
|
+
print("Error: Number of weights and impacts must match number of criteria columns.")
|
|
84
|
+
sys.exit(1)
|
|
85
|
+
|
|
86
|
+
# ============================================
|
|
87
|
+
# STEP 8 — Normalize the Decision Matrix
|
|
88
|
+
# ============================================
|
|
89
|
+
|
|
90
|
+
norm_data = data / np.sqrt((data ** 2).sum())
|
|
91
|
+
|
|
92
|
+
# ============================================
|
|
93
|
+
# STEP 9 — Apply Weights
|
|
94
|
+
# ============================================
|
|
95
|
+
|
|
96
|
+
weighted_data = norm_data * weights
|
|
97
|
+
|
|
98
|
+
# ============================================
|
|
99
|
+
# STEP 10 — Determine Ideal Best & Ideal Worst
|
|
100
|
+
# ============================================
|
|
101
|
+
|
|
102
|
+
ideal_best = []
|
|
103
|
+
ideal_worst = []
|
|
104
|
+
|
|
105
|
+
for i in range(len(impacts)):
|
|
106
|
+
if impacts[i] == '+':
|
|
107
|
+
ideal_best.append(weighted_data.iloc[:, i].max())
|
|
108
|
+
ideal_worst.append(weighted_data.iloc[:, i].min())
|
|
109
|
+
else:
|
|
110
|
+
ideal_best.append(weighted_data.iloc[:, i].min())
|
|
111
|
+
ideal_worst.append(weighted_data.iloc[:, i].max())
|
|
112
|
+
|
|
113
|
+
ideal_best = np.array(ideal_best)
|
|
114
|
+
ideal_worst = np.array(ideal_worst)
|
|
115
|
+
|
|
116
|
+
# ============================================
|
|
117
|
+
# STEP 11 — Calculate Distance from Ideal Solutions
|
|
118
|
+
# ============================================
|
|
119
|
+
|
|
120
|
+
dist_best = np.sqrt(((weighted_data - ideal_best) ** 2).sum(axis=1))
|
|
121
|
+
dist_worst = np.sqrt(((weighted_data - ideal_worst) ** 2).sum(axis=1))
|
|
122
|
+
|
|
123
|
+
# ============================================
|
|
124
|
+
# STEP 12 — Calculate TOPSIS Score
|
|
125
|
+
# ============================================
|
|
126
|
+
|
|
127
|
+
topsis_score = dist_worst / (dist_best + dist_worst)
|
|
128
|
+
|
|
129
|
+
# ============================================
|
|
130
|
+
# STEP 13 — Rank the Alternatives
|
|
131
|
+
# ============================================
|
|
132
|
+
|
|
133
|
+
df['Topsis Score'] = topsis_score
|
|
134
|
+
df['Rank'] = df['Topsis Score'].rank(ascending=False).astype(int)
|
|
135
|
+
|
|
136
|
+
# ============================================
|
|
137
|
+
# STEP 14 — Write Output File
|
|
138
|
+
# ============================================
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
df.to_csv(output_file, index=False)
|
|
142
|
+
print("TOPSIS analysis completed successfully.")
|
|
143
|
+
except Exception as e:
|
|
144
|
+
print("Error while writing output file:", e)
|
|
145
|
+
sys.exit(1)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
if __name__ == "__main__":
|
|
149
|
+
main()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: topsis-dikshant-102303201
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: TOPSIS implementation for multi-criteria decision making
|
|
5
|
+
Author: Dikshant
|
|
6
|
+
Author-email: dikshantarora15@gmail.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.7
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: numpy
|
|
14
|
+
Requires-Dist: pandas
|
|
15
|
+
Requires-Dist: openpyxl
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: author-email
|
|
18
|
+
Dynamic: classifier
|
|
19
|
+
Dynamic: description
|
|
20
|
+
Dynamic: description-content-type
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-dist
|
|
23
|
+
Dynamic: requires-python
|
|
24
|
+
Dynamic: summary
|
|
25
|
+
|
|
26
|
+
# Topsis-Dikshant-123456
|
|
27
|
+
|
|
28
|
+
## Description
|
|
29
|
+
This package implements the TOPSIS (Technique for Order Preference by Similarity to Ideal Solution) method.
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
pip install topsis-dikshant-102303201
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
topsis data.xlsx "1,1,1,1,1" "+,+,-,+,+" result.csv
|
|
37
|
+
|
|
38
|
+
## Input Format
|
|
39
|
+
- First column: Alternative names
|
|
40
|
+
- Remaining columns: Numeric criteria
|
|
41
|
+
|
|
42
|
+
## Output
|
|
43
|
+
- Adds TOPSIS Score
|
|
44
|
+
- Adds Rank
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
topsis_dikshant_102303201/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
|
|
2
|
+
topsis_dikshant_102303201/topsis.py,sha256=7nH6KeUjH3BjFB7pwcuZvyeYtO83MY4z57G22JHgTWk,4824
|
|
3
|
+
topsis_dikshant_102303201-0.1.1.dist-info/licenses/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
topsis_dikshant_102303201-0.1.1.dist-info/METADATA,sha256=NHlhAXfDKSQKFz1-6v7tnna7k8rUCTRbvRHY1D08X1Y,1090
|
|
5
|
+
topsis_dikshant_102303201-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
6
|
+
topsis_dikshant_102303201-0.1.1.dist-info/entry_points.txt,sha256=t7QdrDIWPeFyrJdO4EfaYS2iVdtnfZuHl07f4C98PNg,65
|
|
7
|
+
topsis_dikshant_102303201-0.1.1.dist-info/top_level.txt,sha256=uDwAHu4lCEoS3HmccJ_XJWA59NRrW9tgcdsiX-ODvY8,26
|
|
8
|
+
topsis_dikshant_102303201-0.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
topsis_dikshant_102303201
|