flutter_decision_making 2.0.0
flutter_decision_making: ^2.0.0 copied to clipboard
Flutter package for multi-criteria decision-making using AHP, SAW, and TOPSIS algorithms.
✨ About #
Flutter package for practical Multi-Criteria Decision Making (MCDM). Providing algorithms such as AHP, SAW, and TOPSIS to help developers perform weighting, evaluation, and ranking of alternatives easily and accurately within their Flutter applications.
| Status | Algorithm | Available in version |
|---|---|---|
| ✅ | AHP (Analytic Hierarchy Process) | 1.0.0 |
| ✅ | SAW (Simple Additive Weighting) | 1.1.0 |
| ✅ | TOPSIS (Technique for Order Preference by Similarity to Ideal Solution) | 1.2.0 |
| Feature | Available in version |
|---|---|
Self-explaining (detailed) results with toJson() |
2.0.0 |
| Weight sensitivity analysis & rank reversal check | 2.0.0 |
Pure Dart core (decision_making_core) |
2.0.0 |
🎯 Typical Use Cases #
Suitable for building decision support features such as:
- HR candidate or promotion selection
- Vendor or project evaluation
- Scholarship or student ranking
- Feature prioritization in product management
- Internal corporate decision-making systems
- Recommendation or comparison apps
📦 Installation #
flutter pub add flutter_decision_making
import 'package:flutter_decision_making/flutter_decision_making.dart';
Need the algorithms without Flutter (CLI, server, Dart backend)? Use the pure Dart package
decision_making_core.
📚 Usage Guide #
You can use this package in two ways depending on your needs:
- Using all algorithms together
Initialize theFlutterDecisionMakingclass to access all available algorithms.
late FlutterDecisionMaking _decisionMaking;
AhpResult? _ahpResult;
List<WeightedDecisionResult>? _sawResult;
List<WeightedDecisionResult>? _topsisResult;
@override
void initState() {
super.initState();
_decisionMaking = FlutterDecisionMaking();
}
// Usage example:
// for AHP
_ahpResult = await _decisionMaking.ahp.getAhpResult(...);
// for SAW
_sawResult = await _decisionMaking.saw.getSawResult(...);
// for TOPSIS
_topsisResult = await _decisionMaking.topsis.getTopsisResult(...);
This is the easiest way if you want to use multiple algorithms in your project.
- Using a specific algorithm only
If you only need a single algorithm (e.g., AHP), you can import and initialize it directly:
late AHP _ahp;
AhpResult? _ahpResult;
@override
void initState() {
super.initState();
_ahp = AHP();
}
// Usage example:
_ahpResult = await _ahp.getAhpResult(...);
🔍 Explainable Results #
Every algorithm can return all intermediate steps, not only the final ranking. Useful for reports, audits and teaching.
final saw = await _decisionMaking.saw.getSawDetailedResult(matrix: matrix);
saw.normalizedMatrix; // r_ij
saw.normalizedWeights; // w_j (sum = 1)
saw.weightedMatrix; // v_ij
saw.scores; // final scores and ranks
final topsis = await _decisionMaking.topsis.getTopsisDetailedResult(matrix: topsisMatrix);
topsis.positiveIdeal; // A+
topsis.negativeIdeal; // A-
topsis.separationPlus; // D+
topsis.separationMinus; // D-
final ahp = await _decisionMaking.ahp.getAhpDetailedResult(...);
ahp.criteriaEvaluation; // comparison/normalized matrix, weights, lambda max, CI, RI, CR
final json = saw.toJson(); // every detailed result can be serialized
The existing getSawResult, getTopsisResult and getAhpResult are unchanged.
🧪 Sensitivity Analysis & Rank Reversal (SAW, TOPSIS) #
Check how stable a ranking is.
final result = await _decisionMaking.saw.analyzeSensitivity(matrix: matrix, delta: 0.10);
result.isStable; // false if any perturbation or removal changes the order
result.sensitivityCases; // each criterion weight +/- 10% (relative), others rescaled
result.rankReversalCases; // each alternative removed in turn (needs 3+ alternatives)
Rank reversal is detected, not prevented. Results depend on
deltaand on the normalization method of each algorithm. Skipped cases (for example fewer than 3 alternatives) are reported with a reason and are not counted as unstable.
📖 Algorithm Docs #
For details on how to use the algorithm, you can visit the following documentation.
| Link | Description |
|---|---|
| AHP Doc | If you need a method that is able to determine weights accurately through pairwise comparisons, validate the consistency of assessments, and work well on subjective or multilevel criteria. |
| SAW Doc | If you need a simple, fast, easy to calculate, and easy to implement method for ranking alternatives based on criteria weights and values. |
| TOPSIS Doc | If you need a method that ranks alternatives based on their distance to the ideal best and ideal worst solutions, providing a more discriminative and robust decision-making result. |
The wiki pages describe each algorithm. For detailed results, sensitivity analysis and
useIsolate, see the sections above.
📈 Performance Profiling #
Major method logs:
- Start and end timestamps.
- Execution duration (in milliseconds).
Useful for debugging and optimization during development.
⚡ When to Use Isolates (useIsolate) #
By default all calculations run on the main thread (useIsolate: false). Isolates are opt-in via useIsolate: true.
Measured on Apple Silicon (macOS), --profile mode, public API, median [min–max] of 10 runs after 3 warm-ups:
| Case (alternatives × criteria) | Main thread (ms) | Isolate, warm (ms) | Main thread blocked (ms) |
|---|---|---|---|
| SAW 80 × 25 | 0.19 [0.18–0.35] | 4.35 [3.01–5.86] | 0.85 [0.00–3.03] |
| SAW 2000 × 50 | 8.71 [8.39–12.27] | 449.24 [411.99–477.15] | 244.23 [219.73–262.51] |
| TOPSIS 80 × 25 | 0.52 [0.50–0.55] | 4.02 [3.33–6.18] | 0.80 [0.00–3.34] |
| TOPSIS 2000 × 50 | 47.53 [40.32–52.14] | 526.39 [464.34–605.88] | 277.99 [223.17–306.31] |
| AHP 80 × 10 | 31.71 [31.21–52.50] | 51.01 [47.90–66.97] | 25.84 [23.09–39.94] |
"Main thread blocked" is estimated with an event-loop lag monitor; values near 0 mean the blocking was below its detection threshold (about 1 ms), not that it is exactly zero. Mobile devices will be slower than these numbers, so profile on your target device.
Recommendation: keep the default. Sending data to an isolate costs more (serialization) than the calculation itself in every case measured. Use useIsolate: true only if you must keep very large calculations off the UI thread and accept a longer total time. Note that AHP needs n(n-1)/2 pairwise judgments per matrix, so very large AHP inputs are rarely practical for human evaluators.
⬆️ Upgrading from 1.x #
- Isolates are no longer used automatically. Pass
useIsolate: trueif you relied on that behaviour. DecisionIsolateMainand the isolate message/worker types are no longer exported from the main library.- TOPSIS in 1.2.0 returned wrong rankings above 80 alternatives or 25 criteria. Upgrade if you use TOPSIS with large inputs.
See the CHANGELOG for details.
💡 Want Another Algorithm? #
We are continuously improving this package 🚀
If you would like to see a new algorithm (e.g., WP, ELECTRE, MOORA, PROMETHEE, etc.) added:
⚠️ Note: New algorithms will be prioritized based on:
- Community interest
- Contribution support (PRs are welcome!)
- Maintainer availability
Contributions are highly appreciated 🙌
🎁 Support Me #
🙋♂️ Contributing #
We welcome all contributions and suggestions!
👉 Open an issue or submit a pull request at GitHub Repo