102303812-topsis 1.0.0__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 @@
1
+ from .topsis import topsis
@@ -0,0 +1,180 @@
1
+ """
2
+ TOPSIS (Technique for Order of Preference by Similarity to Ideal Solution) Implementation
3
+
4
+ This module implements the TOPSIS multi-criteria decision analysis method.
5
+ TOPSIS ranks alternatives based on their distance from the ideal positive solution
6
+ and distance from the ideal negative solution.
7
+
8
+ Author: Harsh Tanwar
9
+ Roll Number: 102303812
10
+ Email: htanwar_be23@thapar.edu
11
+ """
12
+
13
+ import sys
14
+ import pandas as pd
15
+ import numpy as np
16
+ import os
17
+
18
+
19
+ def check_numeric(df):
20
+ """
21
+ Validates that all columns from the 2nd column onwards contain numeric values.
22
+
23
+ Args:
24
+ df (pd.DataFrame): Input dataframe to validate
25
+
26
+ Returns:
27
+ bool: True if all columns (from 2nd onwards) are numeric, False otherwise
28
+ """
29
+ try:
30
+ # Check from 2nd column (index 1) to the end
31
+ df.iloc[:, 1:].astype(float)
32
+ return True
33
+ except ValueError:
34
+ return False
35
+
36
+
37
+ def topsis(input_file, weights, impacts, result_file):
38
+ """
39
+ Implements the TOPSIS algorithm to rank alternatives based on multiple criteria.
40
+
41
+ The algorithm follows these steps:
42
+ 1. Load and validate input data
43
+ 2. Normalize the decision matrix using vector normalization
44
+ 3. Apply weights to the normalized matrix
45
+ 4. Determine ideal best and ideal worst solutions
46
+ 5. Calculate Euclidean distances from ideal solutions
47
+ 6. Compute performance scores and rank alternatives
48
+
49
+ Args:
50
+ input_file (str): Path to CSV file containing alternatives and criteria values
51
+ weights (str): Comma-separated string of weights for each criterion
52
+ impacts (str): Comma-separated string of impacts ('+' for beneficial, '-' for non-beneficial)
53
+ result_file (str): Path for output CSV file with TOPSIS scores and ranks
54
+
55
+ Returns:
56
+ None: Writes results to the specified output file
57
+ """
58
+ try:
59
+ # Step 1: Load Data
60
+ try:
61
+ df = pd.read_csv(input_file)
62
+ except FileNotFoundError:
63
+ print(f"Error: File '{input_file}' not found.")
64
+ return
65
+
66
+ # Step 2: Input Validation
67
+ if len(df.columns) < 3:
68
+ print("Error: Input file must contain three or more columns.")
69
+ return
70
+
71
+ if not check_numeric(df):
72
+ print("Error: From 2nd to last columns must contain numeric values only.")
73
+ return
74
+
75
+ # Calculate number of criteria (excluding the first column which contains alternative names)
76
+ cols = len(df.columns) - 1
77
+
78
+ # Parse weights and impacts from comma-separated strings
79
+ weights = [float(w) for w in weights.split(',')]
80
+ impacts = impacts.split(',')
81
+
82
+ # Validate that weights, impacts, and criteria count match
83
+ if len(weights) != cols or len(impacts) != cols:
84
+ print("Error: The number of weights, number of impacts and number of columns (from 2nd to last columns) must be the same.")
85
+ return
86
+
87
+ # Validate impact values are either '+' or '-'
88
+ if not all(i in ['+', '-'] for i in impacts):
89
+ print("Error: Impacts must be either +ve or -ve.")
90
+ return
91
+
92
+ # Step 3: TOPSIS Algorithm Implementation
93
+
94
+ # 3.1 Vector Normalization
95
+ # Create a copy of numeric columns for calculations to preserve original data
96
+ df_calc = df.iloc[:, 1:].copy().astype(float)
97
+
98
+ # Calculate root sum of squares for each criterion
99
+ rss = np.sqrt((df_calc**2).sum())
100
+
101
+ # Normalize the decision matrix using vector normalization
102
+ df_norm = df_calc / rss
103
+
104
+ # 3.2 Weighted Normalization
105
+ # Apply criterion weights to the normalized matrix
106
+ df_weighted = df_norm * weights
107
+
108
+ # 3.3 Determine Ideal Best and Ideal Worst Solutions
109
+ ideal_best = []
110
+ ideal_worst = []
111
+
112
+ for i in range(cols):
113
+ if impacts[i] == '+':
114
+ # For beneficial criteria: maximum is ideal best, minimum is ideal worst
115
+ ideal_best.append(df_weighted.iloc[:, i].max())
116
+ ideal_worst.append(df_weighted.iloc[:, i].min())
117
+ else:
118
+ # For non-beneficial criteria: minimum is ideal best, maximum is ideal worst
119
+ ideal_best.append(df_weighted.iloc[:, i].min())
120
+ ideal_worst.append(df_weighted.iloc[:, i].max())
121
+
122
+ # 3.4 Calculate Euclidean Distances
123
+ # Distance from ideal positive solution (best)
124
+ s_plus = np.sqrt(((df_weighted - ideal_best) ** 2).sum(axis=1))
125
+
126
+ # Distance from ideal negative solution (worst)
127
+ s_minus = np.sqrt(((df_weighted - ideal_worst) ** 2).sum(axis=1))
128
+
129
+ # 3.5 Calculate Performance Score
130
+ # Performance score = distance from worst / (distance from best + distance from worst)
131
+ # Higher score indicates better performance
132
+ total_dist = s_plus + s_minus
133
+ performance_score = s_minus / total_dist
134
+
135
+ # Step 4: Generate Output
136
+ # Add TOPSIS score and rank columns to the original dataframe
137
+ df['Topsis Score'] = performance_score
138
+
139
+ # Rank alternatives in descending order of TOPSIS score (higher score = better rank)
140
+ df['Rank'] = df['Topsis Score'].rank(ascending=False).astype(int)
141
+
142
+ # Write results to output CSV file
143
+ df.to_csv(result_file, index=False)
144
+ print(f"Result file '{result_file}' created successfully.")
145
+
146
+ except Exception as e:
147
+ print(f"An error occurred: {e}")
148
+
149
+
150
+ def main():
151
+ """
152
+ Main entry point for command-line execution of TOPSIS algorithm.
153
+
154
+ Parses command-line arguments and calls the topsis function.
155
+ Expected arguments:
156
+ - InputDataFile: Path to input CSV file
157
+ - Weights: Comma-separated weights string
158
+ - Impacts: Comma-separated impacts string
159
+ - OutputResultFileName: Path to output CSV file
160
+ """
161
+ if len(sys.argv) != 5:
162
+ print("Usage: python <program.py> <InputDataFile> <Weights> <Impacts> <OutputResultFileName>")
163
+ print('Example: python topsis.py data.csv "1,1,1,2,1" "+,+,+,-,+" result.csv')
164
+ return
165
+
166
+ input_file = sys.argv[1]
167
+ weights = sys.argv[2]
168
+ impacts = sys.argv[3]
169
+ result_file = sys.argv[4]
170
+
171
+ # Additional file existence check before processing
172
+ if not os.path.exists(input_file):
173
+ print(f"Error: File '{input_file}' not found.")
174
+ return
175
+
176
+ topsis(input_file, weights, impacts, result_file)
177
+
178
+
179
+ if __name__ == "__main__":
180
+ main()
@@ -0,0 +1,185 @@
1
+ Metadata-Version: 2.4
2
+ Name: 102303812-topsis
3
+ Version: 1.0.0
4
+ Summary: A Python package to implement TOPSIS
5
+ Home-page: https://github.com/htan11/course-materials/tree/main/UCS654/Assignment1-Topsis
6
+ Author: Harsh Tanwar
7
+ Author-email: htanwar_be23@thapar.edu
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Dynamic: author
14
+ Dynamic: author-email
15
+ Dynamic: classifier
16
+ Dynamic: description
17
+ Dynamic: description-content-type
18
+ Dynamic: home-page
19
+ Dynamic: license-file
20
+ Dynamic: summary
21
+
22
+ # 102303812-topsis
23
+
24
+ A Python package to implement **TOPSIS** (Technique for Order of Preference by Similarity to Ideal Solution) for multi-criteria decision analysis.
25
+
26
+ **Author:** Harsh Tanwar
27
+ **Roll No:** 102303812
28
+ **Email:** htanwar_be23@thapar.edu
29
+
30
+ **Repository:** [Assignment1-Topsis](https://github.com/htan11/course-materials/tree/main/UCS654/Assignment1-Topsis)
31
+
32
+ ---
33
+
34
+ ## What is TOPSIS?
35
+
36
+ TOPSIS ranks alternatives by comparing each to an *ideal positive* and *ideal negative* solution. Alternatives closer to the ideal positive and farther from the ideal negative get higher scores and better ranks. The method uses vector normalization, weighted criteria, and Euclidean distances to compute a performance score for each alternative.
37
+
38
+ ---
39
+
40
+ ## Requirements
41
+
42
+ - Python 3.6+
43
+ - **pandas** – data handling
44
+ - **numpy** – numerical operations
45
+
46
+ Install dependencies:
47
+
48
+ ```bash
49
+ pip install pandas numpy
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Installation
55
+
56
+ ### From PyPI (if published)
57
+
58
+ ```bash
59
+ pip install 102303812-topsis
60
+ ```
61
+
62
+ ### From source (clone or download the repo)
63
+
64
+ ```bash
65
+ git clone https://github.com/htan11/course-materials.git
66
+ cd course-materials/UCS654/Assignment1-Topsis
67
+ pip install .
68
+ ```
69
+
70
+ Or, in the folder containing `setup.py`:
71
+
72
+ ```bash
73
+ pip install .
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Usage
79
+
80
+ ### Command line
81
+
82
+ ```bash
83
+ topsis <InputDataFile> <Weights> <Impacts> <OutputResultFileName>
84
+ ```
85
+
86
+ **Example (with 5 criteria):**
87
+
88
+ ```bash
89
+ topsis data.csv "1,1,1,1,1" "+,+,-,+,-" result.csv
90
+ ```
91
+
92
+ ### As a Python module
93
+
94
+ (Because the package name contains a hyphen, use `importlib` to import.)
95
+
96
+ ```python
97
+ import importlib
98
+ topsis = getattr(importlib.import_module("102303812-topsis"), "topsis")
99
+
100
+ topsis("data.csv", "1,1,1,1,1", "+,+,-,+,-", "result.csv")
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Parameters
106
+
107
+ | Parameter | Description |
108
+ |-----------|-------------|
109
+ | **InputDataFile** | Path to a CSV file: first column = alternative names, remaining columns = numeric criterion values. Must have a header row. |
110
+ | **Weights** | Comma-separated weights for each criterion (e.g. `"1,1,1,2,1"`). Number of values must match number of criteria. |
111
+ | **Impacts** | Comma-separated impacts: `+` for beneficial (higher is better), `-` for non-beneficial (lower is better). Same count as criteria. |
112
+ | **OutputResultFileName** | Path for the output CSV. Contains original columns plus **Topsis Score** and **Rank**. |
113
+
114
+ - Beneficial (`+`): e.g. Quality, Customer Rating — higher value is better.
115
+ - Non-beneficial (`-`): e.g. Price, Delivery Time — lower value is better.
116
+
117
+ ---
118
+
119
+ ## Input file format
120
+
121
+ CSV with a header; first column = alternative names, rest = numeric only.
122
+
123
+ **Example (`data.csv`):**
124
+
125
+ | Product | Quality | Price | Features | Customer Rating | Delivery Time |
126
+ |---------|---------|-------|----------|-----------------|---------------|
127
+ | A1 | 8.5 | 450 | 7.2 | 4.3 | 3 |
128
+ | A2 | 7.8 | 380 | 8.1 | 4.5 | 5 |
129
+ | ... | ... | ... | ... | ... | ... |
130
+
131
+ - Column 1: labels (not used in math).
132
+ - Columns 2–6: criteria. Weights and impacts must be given for each of these in order.
133
+
134
+ ---
135
+
136
+ ## Example with this dataset
137
+
138
+ For 5 criteria (Quality, Price, Features, Customer Rating, Delivery Time):
139
+
140
+ - **Weights:** `"1,1,1,1,1"` (equal weight).
141
+ - **Impacts:** `"+,+,-,+,-"` (Quality +, Price +, Features -, Customer Rating +, Delivery Time -).
142
+
143
+ Run:
144
+
145
+ ```bash
146
+ topsis data.csv "1,1,1,1,1" "+,+,-,+,-" result.csv
147
+ ```
148
+
149
+ Output CSV will have all input columns plus:
150
+
151
+ - **Topsis Score** – higher is better.
152
+ - **Rank** – 1 = best alternative.
153
+
154
+ ---
155
+
156
+ ## Output
157
+
158
+ The result file contains:
159
+
160
+ - All original columns.
161
+ - **Topsis Score** – performance score in [0, 1].
162
+ - **Rank** – integer rank (1 = best).
163
+
164
+ Example message: `Result file 'result.csv' created successfully.`
165
+
166
+ ---
167
+
168
+ ## Project structure
169
+
170
+ ```
171
+ assignment1_DS-main/
172
+ ├── README.md
173
+ ├── setup.py
174
+ ├── data.csv # Sample input
175
+ ├── 102303812-topsis/
176
+ │ ├── __init__.py
177
+ │ └── topsis.py # TOPSIS implementation
178
+ └── LICENSE
179
+ ```
180
+
181
+ ---
182
+
183
+ ## License
184
+
185
+ MIT License. See [LICENSE](LICENSE) for details.
@@ -0,0 +1,9 @@
1
+ _topsis_entry.py,sha256=PCUM9ICDx5x9_kO0aRPctJrxw4IDcVW_KbHwOZjlCCM,193
2
+ 102303812-topsis/__init__.py,sha256=ySjTkNVa20OI1QFkLvToedIHgoOwlWAQvHCbV2Rg1E0,27
3
+ 102303812-topsis/topsis.py,sha256=N3RUop503QA2gidqQ7NNMpbzh2zZqtJAebfSmrb5oEI,6521
4
+ 102303812_topsis-1.0.0.dist-info/licenses/LICENSE,sha256=6NELaJnBocT4i7N4PC8oB4bJdSSNn_DpzaCJeHTR2fQ,1069
5
+ 102303812_topsis-1.0.0.dist-info/METADATA,sha256=ulbRuoWKvKMDR8rVDk-IoYhrHkRPbVoKf2Wx97rH8Zc,5141
6
+ 102303812_topsis-1.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
7
+ 102303812_topsis-1.0.0.dist-info/entry_points.txt,sha256=QE4af7gZl6iT4r0Ey-LCr1dPJlxyXB0X8hy_AhCynQ8,46
8
+ 102303812_topsis-1.0.0.dist-info/top_level.txt,sha256=9vdaHen8jLGH1YjxkEN_zQnyyVJcy7wUXehITda_YCQ,31
9
+ 102303812_topsis-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ topsis = _topsis_entry:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Harsh Tanwar
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.
@@ -0,0 +1,2 @@
1
+ 102303812-topsis
2
+ _topsis_entry
_topsis_entry.py ADDED
@@ -0,0 +1,7 @@
1
+ """Entry point for the topsis console script (package name has a hyphen)."""
2
+ from importlib import import_module
3
+
4
+
5
+ def main():
6
+ mod = import_module("102303812-topsis.topsis")
7
+ mod.main()