Skip to main content

A Python library for Multi-Criteria Decision Making (TOPSIS, AHP, VIKOR, Entropy) with Web Interface

Project description

TOPSISX ๐Ÿ“Š

PyPI Version Python Version Downloads License

TOPSISX is a comprehensive Python library for Multi-Criteria Decision Making (MCDM) that provides both a powerful programming API and an intuitive web interface. Make data-driven decisions using proven algorithms like TOPSIS, VIKOR, AHP, and Entropy weighting.


๐ŸŒŸ Key Features

  • ๐Ÿ Python Library - Use in your code like pandas, numpy
  • ๐ŸŒ Web Interface - Beautiful Streamlit dashboard for non-coders
  • ๐Ÿ’ป CLI Support - Command-line interface for automation
  • ๐Ÿ“Š Multiple Methods - TOPSIS, VIKOR, AHP, Entropy weighting
  • ๐Ÿ“ˆ Visualizations - Interactive charts and rankings
  • ๐Ÿ“„ PDF Reports - Professional report generation
  • ๐Ÿ”ง Easy Integration - Works with pandas, numpy, CSV, Excel
  • ๐ŸŽฏ Well Tested - Comprehensive test suite included

๐Ÿ“ฆ Installation

Quick Install

pip install topsisx

From Source (for development)

git clone https://github.com/SuvitKumar003/ranklib.git
cd ranklib
pip install -e .

Requirements

  • Python 3.8+
  • pandas >= 2.0.0
  • numpy >= 1.24.0
  • matplotlib >= 3.8.0
  • streamlit >= 1.34.0 (for web interface)
  • fpdf >= 1.7.2 (for PDF reports)

๐Ÿš€ Quick Start

Method 1: Web Interface (No Coding Required!)

Perfect for non-programmers and quick analysis:

# Launch the web interface
topsisx --web

This opens a beautiful dashboard in your browser where you can:

  • ๐Ÿ“ค Upload CSV files
  • ๐Ÿ“‹ Use sample datasets
  • โœ๏ธ Enter data manually
  • ๐ŸŽจ Configure methods interactively
  • ๐Ÿ“Š View results with charts
  • ๐Ÿ’พ Download results (CSV & PDF)

Screenshot of Web Interface:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ๐Ÿ“Š TOPSISX Decision Making Tool            โ”‚
โ”‚  Multi-Criteria Decision Analysis          โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  Sidebar:                                   โ”‚
โ”‚  โ€ข Upload CSV / Use Samples / Manual Entry  โ”‚
โ”‚  โ€ข Select Methods (TOPSIS/VIKOR)           โ”‚
โ”‚  โ€ข Choose Weighting (Entropy/AHP/Equal)    โ”‚
โ”‚  โ€ข Define Impacts (+/-)                    โ”‚
โ”‚                                            โ”‚
โ”‚  Main Panel:                               โ”‚
โ”‚  โ€ข Data Preview                            โ”‚
โ”‚  โ€ข Run Analysis Button                     โ”‚
โ”‚  โ€ข Results Table                           โ”‚
โ”‚  โ€ข Visualizations                          โ”‚
โ”‚  โ€ข Download CSV & PDF                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Method 2: Python Library (For Programmers)

Use TOPSISX in your Python code just like pandas or numpy:

Basic TOPSIS Analysis

import pandas as pd
from topsisx.topsis import topsis

# Your data
data = pd.DataFrame({
    'Cost': [250, 200, 300, 275],
    'Quality': [16, 16, 32, 32],
    'Speed': [12, 8, 16, 8]
})

# Define criteria
weights = [0.3, 0.4, 0.3]
impacts = ['-', '+', '+']  # - means lower is better, + means higher is better

# Run TOPSIS
result = topsis(data, weights, impacts)

print(result)

Output:

   Cost  Quality  Speed  Topsis_Score  Rank
0   200       16      8        0.5234     2
1   250       16     12        0.3456     3
2   300       32     16        0.7891     1
3   275       32      8        0.6543     2

Using Pipeline (Recommended - Higher Level API)

from topsisx.pipeline import DecisionPipeline
import pandas as pd

# Your data
data = pd.DataFrame({
    'Cost': [250, 200, 300],
    'Quality': [16, 16, 32],
    'Time': [12, 8, 16]
})

# Create pipeline with automatic weight calculation
pipeline = DecisionPipeline(
    weights='entropy',  # Automatic weights based on data variance
    method='topsis'     # TOPSIS ranking method
)

# Run analysis
result = pipeline.run(
    data, 
    impacts=['-', '+', '-']  # Cost and Time are costs (lower better)
)

print(result)

Method 3: Command Line Interface (For Automation)

Perfect for scripts, batch processing, and automation:

Basic Usage

# Analyze a CSV file
topsisx data.csv --impacts "+,-,+" --output results.csv

With Specific Methods

# TOPSIS with entropy weights
topsisx data.csv --method topsis --weights entropy --impacts "+,-,+"

# VIKOR with equal weights
topsisx data.csv --method vikor --weights equal --impacts "+,+,+"

# Generate PDF report
topsisx data.csv --impacts "+,-,+" --report

Preserve ID Columns

# Keep the 'Model' column in results
topsisx laptops.csv --impacts "-,+,+,-" --id-col "Model" --output results.csv

AHP Weighting

# Use AHP pairwise comparison for weights
topsisx data.csv --weights ahp --ahp-matrix pairwise.csv --impacts "+,-,+"

VIKOR with Custom Parameters

# VIKOR with v=0.7 (more emphasis on group utility)
topsisx data.csv --method vikor --vikor-v 0.7 --impacts "+,+,+"

Verbose Output

# Show detailed processing information
topsisx data.csv --impacts "+,-,+" --verbose

CLI Help:

topsisx --help

๐Ÿ“š Detailed Usage Guide

1. TOPSIS Method

TOPSIS (Technique for Order of Preference by Similarity to Ideal Solution) ranks alternatives based on their distance from ideal and anti-ideal solutions.

When to Use:

  • General-purpose ranking
  • Balanced decision-making
  • When you have quantitative criteria
  • Multiple conflicting objectives

Basic Example:

from topsisx.topsis import topsis
import pandas as pd

data = pd.DataFrame({
    'Price': [800, 1200, 1000, 900],
    'RAM': [8, 16, 16, 8],
    'Battery': [6, 4, 8, 7],
    'Weight': [2.0, 2.5, 1.8, 2.2]
})

# Define impacts: Price and Weight are costs (lower is better)
impacts = ['-', '+', '+', '-']

# Define weights (must sum to 1, or will be normalized)
weights = [0.3, 0.3, 0.2, 0.2]

result = topsis(data, weights, impacts)
print(result)

With Automatic Weighting (Entropy):

from topsisx.pipeline import DecisionPipeline

pipeline = DecisionPipeline(weights='entropy', method='topsis')
result = pipeline.run(data, impacts=['-', '+', '+', '-'])

2. VIKOR Method

VIKOR finds compromise solutions by considering both group utility and individual regret.

When to Use:

  • Conflicting criteria
  • Need compromise solutions
  • Want to balance majority preference and minority concerns
  • Dealing with incommensurable units

Basic Example:

from topsisx.vikor import vikor
import pandas as pd

data = pd.DataFrame({
    'Criterion1': [7, 8, 6, 9],
    'Criterion2': [9, 7, 8, 6],
    'Criterion3': [9, 6, 8, 7]
})

weights = [0.33, 0.33, 0.34]
impacts = ['+', '+', '+']

# v parameter: 0 = consensus, 1 = individual regret, 0.5 = balanced
result = vikor(data, weights, impacts, v=0.5)
print(result)

Understanding VIKOR Output:

# Result columns:
# S = Group utility measure (lower is better)
# R = Individual regret measure (lower is better)
# Q = Compromise ranking index (lower is better)
# Rank = Final ranking (1 is best)

3. AHP Weighting

AHP (Analytic Hierarchy Process) calculates weights through pairwise comparisons.

When to Use:

  • Subjective criteria
  • Expert judgments needed
  • Hierarchical decision problems
  • Need to check consistency of judgments

Pairwise Comparison Scale:

1 = Equal importance
3 = Moderate importance
5 = Strong importance
7 = Very strong importance
9 = Extreme importance
2, 4, 6, 8 = Intermediate values

Example:

from topsisx.ahp import ahp
import pandas as pd

# Pairwise comparison matrix
# Example: Quality > Price > Speed
pairwise = pd.DataFrame([
    [1,     '1/3',  5],      # Price row
    [3,     1,      7],      # Quality row (most important)
    ['1/5', '1/7',  1]       # Speed row (least important)
])

# Calculate weights
weights = ahp(pairwise, verbose=True)
print(f"Calculated weights: {weights}")

# Use with TOPSIS
from topsisx.topsis import topsis

data = pd.DataFrame({
    'Price': [800, 1200, 1000],
    'Quality': [7, 9, 8],
    'Speed': [5, 6, 7]
})

result = topsis(data, weights, impacts=['-', '+', '+'])
print(result)

Using Pipeline with AHP:

from topsisx.pipeline import DecisionPipeline

pipeline = DecisionPipeline(weights='ahp', method='topsis')
result = pipeline.run(
    data, 
    impacts=['-', '+', '+'],
    pairwise_matrix=pairwise
)

4. Entropy Weighting

Entropy calculates objective weights based on data variance/information content.

When to Use:

  • Objective weighting needed
  • Want to minimize subjective bias
  • Data-driven decisions
  • Don't have expert knowledge for weights

Example:

from topsisx.entropy import entropy_weights
import numpy as np

# Data matrix
data = np.array([
    [250, 16, 12],
    [200, 16, 8],
    [300, 32, 16]
])

# Calculate weights automatically
weights = entropy_weights(data)
print(f"Entropy weights: {weights}")

# Interpretation: 
# Higher weight = more variance/information = more important for discrimination

With Pipeline (Automatic):

from topsisx.pipeline import DecisionPipeline
import pandas as pd

data = pd.DataFrame({
    'Cost': [250, 200, 300],
    'Quality': [16, 16, 32],
    'Speed': [12, 8, 16]
})

pipeline = DecisionPipeline(weights='entropy', method='topsis')
result = pipeline.run(data, impacts=['-', '+', '+'])

# Weights are calculated automatically!

๐ŸŽฏ Real-World Examples

Example 1: Laptop Selection

from topsisx.pipeline import DecisionPipeline
import pandas as pd

# Laptop options
laptops = pd.DataFrame({
    'Model': ['Dell XPS', 'MacBook Pro', 'ThinkPad', 'HP Spectre'],
    'Price': [1200, 2000, 1500, 1300],
    'RAM_GB': [16, 16, 32, 16],
    'Battery_Hours': [8, 12, 6, 10],
    'Weight_KG': [1.8, 1.4, 2.2, 1.6],
    'Screen_Size': [13, 13, 14, 13]
})

print("Laptop Options:")
print(laptops)

# Separate ID column from criteria
models = laptops['Model']
criteria = laptops[['Price', 'RAM_GB', 'Battery_Hours', 'Weight_KG', 'Screen_Size']]

# Create pipeline
pipeline = DecisionPipeline(weights='entropy', method='topsis')

# Run analysis
result = pipeline.run(
    criteria,
    impacts=['-', '+', '+', '-', '+']  
    # Price & Weight: lower is better
    # RAM, Battery, Screen: higher is better
)

# Add model names back
result.insert(0, 'Model', models.values)

print("\nRanked Laptops:")
print(result[['Model', 'Topsis_Score', 'Rank']])

# Get recommendation
best = result.iloc[0]
print(f"\n๐Ÿ† Recommended: {best['Model']}")
print(f"   Score: {best['Topsis_Score']:.4f}")

Example 2: Supplier Selection

from topsisx.pipeline import DecisionPipeline
import pandas as pd

# Supplier evaluation data
suppliers = pd.DataFrame({
    'Supplier': ['ABC Corp', 'XYZ Ltd', 'DEF Inc', 'GHI Co'],
    'Cost': [250000, 200000, 300000, 275000],
    'Quality_Score': [85, 78, 92, 88],
    'Delivery_Time_Days': [15, 12, 20, 10],
    'Service_Rating': [4.2, 3.8, 4.7, 4.5],
    'Flexibility': [7, 6, 9, 8]
})

print("Supplier Options:")
print(suppliers)

# Define importance using AHP
from topsisx.ahp import ahp

# Pairwise matrix: Quality > Service > Flexibility > Cost > Delivery Time
pairwise = pd.DataFrame([
    [1,     3,     5,     7,     9],      # Quality
    ['1/3', 1,     3,     5,     7],      # Service
    ['1/5', '1/3', 1,     3,     5],      # Flexibility
    ['1/7', '1/5', '1/3', 1,     3],      # Cost
    ['1/9', '1/7', '1/5', '1/3', 1]       # Delivery Time
])

print("\nCalculating AHP weights...")
weights = ahp(pairwise, verbose=True)

# Run analysis
criteria = suppliers[['Quality_Score', 'Service_Rating', 'Flexibility', 'Cost', 'Delivery_Time_Days']]

from topsisx.topsis import topsis
result = topsis(
    criteria, 
    weights, 
    impacts=['+', '+', '+', '-', '-']
)

result.insert(0, 'Supplier', suppliers['Supplier'].values)

print("\nRanked Suppliers:")
print(result[['Supplier', 'Topsis_Score', 'Rank']])

# Generate report
from topsisx.reports import generate_report
generate_report(result, method='topsis', filename='supplier_selection_report.pdf')
print("\n๐Ÿ“„ PDF report saved!")

Example 3: Investment Portfolio Selection

from topsisx.pipeline import DecisionPipeline
import pandas as pd

# Investment options
investments = pd.DataFrame({
    'Option': ['Stock A', 'Stock B', 'Bond X', 'Bond Y', 'Real Estate'],
    'Expected_Return_%': [12.5, 8.3, 5.5, 6.0, 9.2],
    'Risk_Score': [8, 6, 2, 3, 5],
    'Liquidity_Score': [9, 8, 7, 8, 4],
    'Min_Investment': [5000, 1000, 500, 500, 50000],
    'Historical_Performance': [7.5, 6.2, 4.8, 5.1, 8.0]
})

print("Investment Options:")
print(investments)

# Run analysis
pipeline = DecisionPipeline(weights='entropy', method='topsis')

criteria = investments[['Expected_Return_%', 'Risk_Score', 'Liquidity_Score', 
                        'Min_Investment', 'Historical_Performance']]

result = pipeline.run(
    criteria,
    impacts=['+', '-', '+', '-', '+']
    # Return, Liquidity, Performance: higher is better
    # Risk, Min Investment: lower is better
)

result.insert(0, 'Option', investments['Option'].values)

print("\nRanked Investment Options:")
print(result[['Option', 'Topsis_Score', 'Rank']])

# Top 3 recommendations
print("\n๐Ÿ† Top 3 Recommendations:")
for i, row in result.head(3).iterrows():
    print(f"{row['Rank']}. {row['Option']} (Score: {row['Topsis_Score']:.4f})")

Example 4: Compare Multiple Methods

from topsisx.pipeline import DecisionPipeline
import pandas as pd

data = pd.DataFrame({
    'Alternative': ['A', 'B', 'C', 'D'],
    'Cost': [250, 200, 300, 275],
    'Quality': [16, 16, 32, 32],
    'Time': [12, 8, 16, 8]
})

criteria = data[['Cost', 'Quality', 'Time']]

# Create pipeline
pipeline = DecisionPipeline(weights='equal', method='topsis')

# Compare TOPSIS vs VIKOR
comparison = pipeline.compare_methods(
    criteria,
    impacts=['-', '+', '-']
)

print("TOPSIS Results:")
print(comparison['topsis'][['Rank', 'Topsis_Score']])

print("\nVIKOR Results:")
print(comparison['vikor'][['Rank', 'Q']])

print("\nRank Comparison:")
print(comparison['comparison'])

# Analyze differences
diff = comparison['comparison']['Rank_Difference']
if diff.max() == 0:
    print("\nโœ… Both methods agree completely!")
elif diff.max() <= 1:
    print("\nโœ… Methods have minor differences (acceptable)")
else:
    print(f"\nโš ๏ธ  Methods differ significantly (max difference: {diff.max()})")

๐Ÿ”ง Advanced Usage

1. Custom Workflow Integration

import pandas as pd
from topsisx.pipeline import DecisionPipeline

def evaluate_options(csv_file, criteria_config):
    """
    Custom function that integrates TOPSISX into your workflow
    
    Args:
        csv_file: Path to CSV with options
        criteria_config: Dict mapping column to impact direction
    
    Returns:
        Best option as dictionary
    """
    # Load data
    df = pd.read_csv(csv_file)
    
    # Extract criteria
    criteria_cols = list(criteria_config.keys())
    criteria_data = df[criteria_cols]
    
    # Extract impacts
    impacts = [criteria_config[col] for col in criteria_cols]
    
    # Run analysis
    pipeline = DecisionPipeline(weights='entropy', method='topsis')
    result = pipeline.run(criteria_data, impacts=impacts)
    
    # Add back all original columns
    for col in df.columns:
        if col not in result.columns:
            result[col] = df[col].values
    
    # Return best option
    best = result.iloc[0].to_dict()
    return best, result

# Usage
config = {
    'Price': '-',
    'Quality': '+',
    'Speed': '+'
}

best_option, full_results = evaluate_options('options.csv', config)
print(f"Best option: {best_option}")

2. Batch Processing Multiple Files

import glob
from topsisx.pipeline import DecisionPipeline
import pandas as pd

def process_batch(folder_pattern, impacts):
    """
    Process multiple CSV files in batch
    """
    results_summary = []
    
    for csv_file in glob.glob(folder_pattern):
        print(f"Processing: {csv_file}")
        
        # Load data
        df = pd.read_csv(csv_file)
        
        # Run analysis
        pipeline = DecisionPipeline(weights='entropy', method='topsis')
        result = pipeline.run(df, impacts=impacts)
        
        # Save individual result
        output_file = csv_file.replace('.csv', '_results.csv')
        result.to_csv(output_file, index=False)
        
        # Store summary
        results_summary.append({
            'file': csv_file,
            'best_score': result.iloc[0]['Topsis_Score'],
            'alternatives': len(result)
        })
    
    # Save summary
    summary_df = pd.DataFrame(results_summary)
    summary_df.to_csv('batch_summary.csv', index=False)
    
    return summary_df

# Usage
summary = process_batch('data/*.csv', impacts=['-', '+', '+'])
print(summary)

3. Integration with Flask/FastAPI

from fastapi import FastAPI, UploadFile
import pandas as pd
from topsisx.pipeline import DecisionPipeline
import io

app = FastAPI()

@app.post("/analyze")
async def analyze_decision(
    file: UploadFile,
    method: str = "topsis",
    weights: str = "entropy",
    impacts: str = "+,-,+"
):
    """
    API endpoint for decision analysis
    """
    # Read uploaded CSV
    contents = await file.read()
    df = pd.read_csv(io.StringIO(contents.decode('utf-8')))
    
    # Parse impacts
    impacts_list = impacts.split(',')
    
    # Run analysis
    pipeline = DecisionPipeline(weights=weights, method=method)
    result = pipeline.run(df, impacts=impacts_list)
    
    # Return as JSON
    return {
        "status": "success",
        "method": method,
        "best_alternative": result.iloc[0].to_dict(),
        "all_results": result.to_dict('records')
    }

# Run with: uvicorn app:app --reload

4. Jupyter Notebook Usage

# In Jupyter Notebook

import pandas as pd
from topsisx.pipeline import DecisionPipeline
import matplotlib.pyplot as plt

# Load data
df = pd.read_csv('data.csv')

# Display data
display(df)

# Run analysis
pipeline = DecisionPipeline(weights='entropy', method='topsis')
result = pipeline.run(df, impacts=['+', '-', '+'])

# Display results
display(result)

# Visualize
fig, ax = plt.subplots(figsize=(10, 6))
result.plot.bar(x='Alternative', y='Topsis_Score', ax=ax, color='skyblue')
ax.set_title('TOPSIS Scores')
ax.set_ylabel('Score')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

# Interactive widgets
from ipywidgets import interact, widgets

@interact(
    method=widgets.Dropdown(options=['topsis', 'vikor'], description='Method:'),
    weights=widgets.Dropdown(options=['entropy', 'equal'], description='Weights:')
)
def analyze(method, weights):
    pipeline = DecisionPipeline(weights=weights, method=method)
    result = pipeline.run(df, impacts=['+', '-', '+'])
    display(result.head())

๐Ÿ“Š Data Format Guidelines

CSV File Format

Your CSV should have:

  • Rows: Alternatives/options to evaluate
  • Columns: Criteria for evaluation
  • Optional: ID column (will be preserved in results)

Example CSV:

Model,Price,RAM_GB,Battery_Hours,Weight_KG
Laptop A,800,8,6,2.0
Laptop B,1200,16,4,2.5
Laptop C,1000,16,8,1.8
Laptop D,900,8,7,2.2

Impact Direction

  • + : Benefit criterion (higher is better)
    • Examples: Quality, Speed, RAM, Battery Life, Customer Rating
  • - : Cost criterion (lower is better)
    • Examples: Price, Time, Weight, Energy Consumption, Error Rate

Weights

Weights can be specified in three ways:

  1. Manual Weights (must sum to 1):

    weights = [0.3, 0.4, 0.3]  # Sums to 1.0
    
  2. Entropy (Automatic):

    pipeline = DecisionPipeline(weights='entropy', method='topsis')
    # Weights calculated from data variance
    
  3. Equal Weights:

    pipeline = DecisionPipeline(weights='equal', method='topsis')
    # All criteria equally important
    
  4. AHP (Pairwise Comparison):

    pairwise = pd.DataFrame([
        [1, 3, 5],
        ['1/3', 1, 3],
        ['1/5', '1/3', 1]
    ])
    weights = ahp(pairwise)
    

๐Ÿ“ˆ Output Format

TOPSIS Output

# Columns in result:
# - Original criteria columns
# - Topsis_Score: Similarity to ideal solution (0-1, higher is better)
# - Rank: Final ranking (1 is best)

   Cost  Quality  Speed  Topsis_Score  Rank
0   200       16      8        0.5234     2
1   300       32     16        0.7891     1

VIKOR Output

# Columns in result:
# - Original criteria columns
# - S: Group utility measure (lower is better)
# - R: Individual regret measure (lower is better)
# - Q: Compromise ranking index (lower is better)
# - Rank: Final ranking (1 is best)

   C1  C2  C3     S      R      Q  Rank
0   7   9   9  0.00  0.000  0.000     1
1   8   7   6  0.33  0.333  0.333     2

๐ŸŽ“ Methodology Explanation

TOPSIS Algorithm

  1. Normalize decision matrix using vector normalization
  2. Weight normalized matrix by criteria weights
  3. Identify ideal best (A+) and ideal worst (A-) solutions
  4. Calculate Euclidean distances to A+ and A-
  5. Compute relative closeness = distance to A- / (distance to A+ + distance to A-)
  6. Rank alternatives by closeness (higher is better)

VIKOR Algorithm

  1. Determine ideal and anti-ideal values for each criterion
  2. Calculate S (group utility) and R (individual regret) for each alternative
  3. Compute Q values: Q = v*(S-S*)/(S'-S*) + (1-v)(R-R)/(R'-R*)
    • v = strategy weight (0-1)
    • v=0.5 means balanced between consensus and individual regret
  4. Rank by Q values (lower is better)
  5. Verify compromise solution conditions

Entropy Weighting

  1. Normalize data to create probability distribution
  2. Calculate entropy for each criterion: E_j = -k * ฮฃ(p_ij * ln(p_ij))
  3. Compute diversity measure: d_j = 1 - E_j
  4. Normalize diversities to get weights: w_j = d_j / ฮฃ(d_j)
  5. Higher entropy = less information = lower weight

AHP Process

  1. Create pairwise comparison matrix using 1-9 scale
  2. Normalize matrix by dividing each element by column sum
  3. Calculate priority weights as row averages
  4. Check consistency ratio (CR < 0.1 is acceptable)
  5. CR = CI / RI, where CI = (ฮป_max - n) / (n-1)

๐Ÿงช Testing Your Installation

Run the included test suite:

# Save as test_installation.py
from topsisx.topsis import topsis
from topsisx.vikor import vikor
from topsisx.entropy import entropy_weights
from topsisx.ahp import ahp
import pandas as pd
import numpy as np

print("Testing TOPSISX Installation...")

# Test 1: TOPSIS
try:
    data = pd.DataFrame({'C1': [1, 2, 3], 'C2': [4, 5, 6]})
    result = topsis(data, [0.5, 0.5], ['+', '+'])
    print("โœ… TOPSIS working")
except Exception as e:
    print(f"โŒ TOPSIS failed: {e}")

# Test 2: VIKOR
try:
    result = vikor(data, [0.5, 0.5], ['+', '+'], v=0.5)
    print("โœ… VIKOR working")
except Exception as e:
    print(f"โŒ VIKOR failed: {e}")

# Test 3: Entropy
try:
    weights = entropy_weights(np.array([[1, 2], [3, 4], [5, 6]]))
    print("โœ… Entropy working")
except Exception as e:
    print(f"โŒ Entropy failed: {e}")

# Test 4: AHP
try:
    pairwise = pd.DataFrame([[1, 3], ['1/3', 1]])
    weights = ahp(pairwise)
    print("โœ… AHP working")
except Exception as e:
    print(f"โŒ AHP failed: {e}")

print("\n๐ŸŽ‰ All tests passed! TOPSISX is ready to use.")

Run with:

python test_installation.py

๐Ÿ› Troubleshooting

Issue: "Module not found"

# Solution: Reinstall package
pip uninstall topsisx
pip install topsisx

Issue: "Invalid impacts"

# Problem: Wrong number of impacts
impacts = ['+', '-']  # But you have 3 criteria

# Solution: Match number of impacts to criteria
impacts = ['+', '-', '+']  # Now correct for 3 criteria

Issue: "NaN in results"

# Problem: Missing values or all zeros in a column
data = pd.DataFrame({'C1': [1, np.nan, 3], 'C2': [4, 5, 6]})

# Solution: Clean data before analysis
data = data.dropna()  # Remove rows with missing values
# OR
data = data.fillna(data.mean())  # Fill with column mean

Issue: "Division by zero"

# Problem: All values in a column are identical
data = pd.DataFrame({'C1': [5, 5, 5], 'C2': [1, 2, 3]})

# Solution: Remove constant columns or add small variance
data['C1'] = data['C1'] + np.random.normal(0, 0.01, len(data))

Issue: "Web interface not launching"

# Solution 1: Install streamlit
pip install streamlit

# Solution 2: Launch manually
streamlit run path/to/topsisx/app.py

# Solution 3: Check if port is available
streamlit run app.py --server.port 8502

Issue: "PDF generation fails"

# Solution: Install fpdf
pip install fpdf==1.7.2

# If still fails, check matplotlib is installed
pip install matplotlib

๐Ÿ’ก Best Practices

1. Data Preparation

import pandas as pd
import numpy as np

# Load data
df = pd.read_csv('data.csv')

# Check for issues
print("Missing values:", df.isnull().sum())
print("Data types:", df.dtypes)
print("Summary statistics:", df.describe())

# Clean data
df = df.dropna()  # Remove missing values
df = df[df['Price'] > 0]  # Remove invalid values

# Separate ID columns from criteria
id_cols = ['Model', 'Name', 'ID']
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
criteria_data = df[numeric_cols]

# Now analyze
from topsisx.pipeline import DecisionPipeline
pipeline = DecisionPipeline(weights='entropy', method='topsis')
result = pipeline.run(criteria_data, impacts=['+', '-', '+'])

# Add ID columns back
for col in id_cols:
    if col in df.columns:
        result.insert(0, col, df[col].values)

2. Choosing the Right Method

Use TOPSIS when:

  • You have clear ideal/worst scenarios
  • Criteria are measurable and quantitative
  • You want a simple, intuitive method
  • You need quick results

Use VIKOR when:

  • You have conflicting criteria
  • You need compromise solutions
  • You want to balance group and individual preferences
  • Criteria have different units/scales

Use Entropy weights when:

  • You want objective, data-driven weights
  • You don't have expert knowledge
  • You want to minimize bias
  • Data variance is meaningful

Use AHP weights when:

  • You have expert judgments
  • Criteria importance is subjective
  • You can make pairwise comparisons
  • You need consistent weights

3. Validating Results

from topsisx.pipeline import DecisionPipeline
import pandas as pd

data = pd.DataFrame({
    'Cost': [250, 200, 300],
    'Quality': [16, 16, 32],
    'Speed': [12, 8, 16]
})

# Method 1: Compare with different weighting methods
for weight_method in ['entropy', 'equal']:
    pipeline = DecisionPipeline(weights=weight_method, method='topsis')
    result = pipeline.run(data, impacts=['-', '+', '+'])
    print(f"\n{weight_method.upper()} weighting:")
    print(result[['Rank', 'Topsis_Score']])

# Method 2: Compare TOPSIS vs VIKOR
pipeline = DecisionPipeline(weights='equal', method='topsis')
comparison = pipeline.compare_methods(data, impacts=['-', '+', '+'])
print("\nRank differences:")
print(comparison['comparison'])

# Method 3: Sensitivity analysis - vary weights
import numpy as np
for weight_cost in [0.2, 0.3, 0.4, 0.5]:
    weight_quality = (1 - weight_cost) * 0.6
    weight_speed = (1 - weight_cost) * 0.4
    weights = [weight_cost, weight_quality, weight_speed]
    
    from topsisx.topsis import topsis
    result = topsis(data, weights, ['-', '+', '+'])
    print(f"\nCost weight={weight_cost}: Best is Alternative {result.iloc[0].name + 1}")

4. Handling Large Datasets

import pandas as pd
from topsisx.pipeline import DecisionPipeline

# For large datasets, use chunking
def analyze_large_dataset(csv_file, impacts, chunk_size=1000):
    """
    Analyze large datasets in chunks
    """
    results = []
    
    for chunk in pd.read_csv(csv_file, chunksize=chunk_size):
        # Analyze each chunk
        pipeline = DecisionPipeline(weights='entropy', method='topsis')
        result = pipeline.run(chunk, impacts=impacts)
        results.append(result)
    
    # Combine results
    final_result = pd.concat(results, ignore_index=True)
    
    # Re-rank across all chunks
    final_result['Rank'] = final_result['Topsis_Score'].rank(
        ascending=False, method='min'
    ).astype(int)
    
    return final_result.sort_values('Rank')

# Usage
result = analyze_large_dataset('large_data.csv', impacts=['+', '-', '+'])

๐Ÿ”’ Data Privacy & Security

TOPSISX processes data locally on your machine:

  • โœ… No data sent to external servers
  • โœ… No internet connection required (after installation)
  • โœ… Your data stays on your computer
  • โœ… Open source - you can audit the code

๐Ÿ“– API Reference

Core Functions

topsis(data, weights, impacts)

Parameters:
  data (DataFrame): Decision matrix with criteria
  weights (list): Criteria weights (must sum to 1)
  impacts (list): '+' for benefit, '-' for cost
  
Returns:
  DataFrame: Original data + Topsis_Score + Rank columns

vikor(data, weights, impacts, v=0.5)

Parameters:
  data (DataFrame): Decision matrix
  weights (list): Criteria weights
  impacts (list): '+' for benefit, '-' for cost
  v (float): Strategy weight, 0-1 (default: 0.5)
  
Returns:
  DataFrame: Original data + S, R, Q, Rank columns

ahp(pairwise_matrix, verbose=False)

Parameters:
  pairwise_matrix (DataFrame): Pairwise comparison matrix
  verbose (bool): Print detailed calculations
  
Returns:
  ndarray: Calculated weights

entropy_weights(matrix)

Parameters:
  matrix (ndarray): Decision matrix
  
Returns:
  ndarray: Calculated weights based on entropy

Pipeline API

DecisionPipeline(weights, method, verbose=False)

Parameters:
  weights (str): 'entropy', 'ahp', or 'equal'
  method (str): 'topsis' or 'vikor'
  verbose (bool): Show detailed logs
  
Methods:
  run(data, impacts, pairwise_matrix=None, **kwargs)
  compare_methods(data, impacts, pairwise_matrix=None)

Report Generation

generate_report(data, method, filename)

Parameters:
  data (DataFrame): Analysis results
  method (str): 'topsis' or 'vikor'
  filename (str): Output PDF filename
  
Generates:
  PDF report with tables, charts, and methodology

๐ŸŒ Use Cases

Business & Management

  • Supplier Selection - Choose best vendors
  • Project Prioritization - Rank project proposals
  • Location Selection - Find optimal site for facility
  • Resource Allocation - Distribute budget/resources
  • Performance Evaluation - Rank employees/departments

Engineering & Technology

  • Material Selection - Choose optimal materials
  • Design Alternative Selection - Compare design options
  • System Configuration - Select best configuration
  • Technology Assessment - Evaluate technologies
  • Quality Control - Rank product quality

Finance & Investment

  • Portfolio Selection - Choose investment options
  • Credit Risk Assessment - Rank loan applicants
  • Bank Branch Selection - Evaluate branch performance
  • Financial Product Selection - Compare financial products

Healthcare

  • Treatment Selection - Compare treatment options
  • Hospital Location - Select optimal location
  • Medical Equipment Selection - Choose equipment
  • Healthcare Provider Selection - Rank providers

Education & Research

  • University Selection - Rank universities
  • Course Selection - Choose courses
  • Research Proposal Evaluation - Rank proposals
  • Scholarship Selection - Evaluate candidates

๐Ÿค Contributing

We welcome contributions! Here's how:

Reporting Bugs

1. Check existing issues first
2. Create new issue with:
   - Clear description
   - Steps to reproduce
   - Expected vs actual behavior
   - Your environment (Python version, OS)
   - Sample data (if applicable)

Suggesting Features

1. Open an issue with [Feature Request] tag
2. Describe the feature
3. Explain use case
4. Provide examples if possible

Code Contributions

# 1. Fork the repository
# 2. Clone your fork
git clone https://github.com/YOUR-USERNAME/ranklib.git

# 3. Create a branch
git checkout -b feature/your-feature-name

# 4. Make changes and test
python -m pytest tests/

# 5. Commit and push
git add .
git commit -m "Add: your feature description"
git push origin feature/your-feature-name

# 6. Open a Pull Request

Development Setup

# Clone repository
git clone https://github.com/SuvitKumar003/ranklib.git
cd ranklib

# Install in development mode
pip install -e .

# Install development dependencies
pip install pytest flake8 black

# Run tests
python run_all_tests.py

# Format code
black topsisx/

# Check code style
flake8 topsisx/

๐Ÿ“ Citation

If you use TOPSISX in your research, please cite:

@software{topsisx2025,
  author = {Kumar, Suvit},
  title = {TOPSISX: Multi-Criteria Decision Making Library},
  year = {2025},
  publisher = {GitHub},
  url = {https://github.com/SuvitKumar003/ranklib}
}

๐Ÿ“œ License

This project is licensed under the MIT License - see the LICENSE file for details.

MIT License

Copyright (c) 2025 Suvit Kumar

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

๐Ÿ™‹ FAQ

Q: Can I use TOPSISX for commercial projects?

A: Yes! TOPSISX is MIT licensed, so you can use it freely in commercial projects.

Q: How many alternatives/criteria can TOPSISX handle?

A: Tested with up to 1000 alternatives and 50 criteria. Performance depends on your hardware.

Q: Does TOPSISX work offline?

A: Yes! After installation, no internet connection is required.

Q: Can I modify the algorithms?

A: Yes! The code is open source. Fork it and customize as needed.

Q: Is there a GUI for non-programmers?

A: Yes! Use topsisx --web to launch the web interface.

Q: How do I handle missing data?

A: Remove rows with missing values using df.dropna() or fill them using df.fillna().

Q: Can I use my own weighting method?

A: Yes! Just pass your custom weights array to the functions.

Q: What's the difference between TOPSIS and VIKOR?

A: TOPSIS finds the closest to ideal, VIKOR finds compromise solutions balancing group utility and individual regret.

Q: How do I validate results?

A: Compare multiple methods, check sensitivity to weight changes, verify with domain experts.

Q: Can I integrate TOPSISX with other tools?

A: Yes! Works with pandas, Flask, FastAPI, Jupyter, Excel (via pandas), and more.


๐Ÿ”— Links


๐ŸŒŸ Star History

If you find TOPSISX useful, please consider giving it a star on GitHub! โญ

Star History Chart


๐ŸŽ“ Learning Resources

Tutorials

Academic Papers

  • Hwang, C.L. and Yoon, K., 1981. "Multiple Attribute Decision Making: Methods and Applications"
  • Opricovic, S. and Tzeng, G.H., 2004. "Compromise solution by MCDM methods"
  • Saaty, T.L., 1980. "The Analytic Hierarchy Process"

Video Tutorials

  • Coming soon!

๐Ÿ† Acknowledgments

TOPSISX is built on the shoulders of giants:

  • NumPy - Numerical computing
  • Pandas - Data manipulation
  • Matplotlib - Visualization
  • Streamlit - Web interface
  • FPDF - PDF generation

Special thanks to:

  • The Python community
  • Contributors and users
  • MCDM researchers worldwide

๐Ÿ“Š Project Stats


๐ŸŽ‰ What's New

Version 0.1.4 (Latest)

  • โœจ Enhanced web interface with PDF reports
  • ๐Ÿ› Fixed verbose parameter in DecisionPipeline
  • ๐Ÿ”ง Improved error handling for non-numeric data
  • ๐Ÿ“„ Better PDF report generation
  • ๐ŸŽจ Improved visualizations

Version 0.1.3

  • โœจ Added web interface
  • ๐Ÿ“Š VIKOR method support
  • ๐Ÿ”ง Better error messages

Version 0.1.0

  • ๐ŸŽ‰ Initial release
  • โœ… TOPSIS implementation
  • โœ… AHP weighting
  • โœ… Entropy weighting

๐Ÿš€ Roadmap

Planned Features

  • More MCDM methods (ELECTRE, PROMETHEE)
  • Interactive visualizations (Plotly)
  • Excel plugin
  • Cloud deployment option
  • Mobile app
  • Real-time collaboration
  • Machine learning integration
  • Sensitivity analysis dashboard

๐Ÿ’– Support the Project

If you find TOPSISX helpful:

  • โญ Star the repository
  • ๐Ÿ› Report bugs
  • ๐Ÿ’ก Suggest features
  • ๐Ÿ“ Improve documentation
  • ๐Ÿ”€ Contribute code
  • ๐Ÿ“ข Share with others

๐Ÿ“ž Get Help

Need help? We're here for you:

  1. Check the documentation - Most questions are answered here
  2. Search existing issues - Someone might have asked already
  3. Ask in Discussions - Community forum
  4. Open an issue - For bugs or feature requests
  5. Email us - For private inquiries: suvitkumar03@gmail.com

Made with โค๏ธ for Better Decision Making

TOPSISX - Making Multi-Criteria Decisions Simple

โญ Star on GitHub | ๐Ÿ“ฆ Install from PyPI | ๐Ÿ“– Read the Docs


Happy Decision Making! ๐ŸŽฏ

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

topsisx-0.2.0.tar.gz (57.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

topsisx-0.2.0-py3-none-any.whl (36.9 kB view details)

Uploaded Python 3

File details

Details for the file topsisx-0.2.0.tar.gz.

File metadata

  • Download URL: topsisx-0.2.0.tar.gz
  • Upload date:
  • Size: 57.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.5

File hashes

Hashes for topsisx-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5b29fabb37ebfed9e87d3f864ff068ce35b992777c8758d4641940634abd5043
MD5 10c4ee8a36f4d26852452e63cd13771d
BLAKE2b-256 5a6322f27a5b5196455c7c62070d8913e970b728a3d679b6056dd6659de454e5

See more details on using hashes here.

File details

Details for the file topsisx-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: topsisx-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 36.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.5

File hashes

Hashes for topsisx-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 57f8906a51b5d02f6ee8e7f9a7b3c52ca8927d1bd0dad2d41c6ccc5604fdb964
MD5 3cddb398a376925f7e5cc5b1d5f3e1fc
BLAKE2b-256 328be882447c1f08650c18ad469470a80f1692187e2a6941ecaa9c75835513d9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page