mirror of
https://git.proxmox.com/git/proxmox-resource-scheduling
synced 2025-10-04 14:19:11 +00:00
drop Topsis prefix of all the types in topsis::
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
4ac19a0016
commit
5a50196a13
@ -1,7 +1,7 @@
|
|||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::topsis::TopsisMatrix;
|
use crate::topsis;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
@ -115,7 +115,7 @@ pub fn score_nodes_to_start_service(
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let scores =
|
let scores =
|
||||||
crate::topsis::score_alternatives(&TopsisMatrix::new(matrix)?, &PVE_HA_TOPSIS_CRITERIA)?;
|
topsis::score_alternatives(&topsis::Matrix::new(matrix)?, &PVE_HA_TOPSIS_CRITERIA)?;
|
||||||
|
|
||||||
Ok(scores
|
Ok(scores
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -17,7 +17,7 @@ fn l2_norm(values: &[f64]) -> f64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A criterion that can be used when scoring with the TOPSIS algorithm.
|
/// A criterion that can be used when scoring with the TOPSIS algorithm.
|
||||||
pub struct TopsisCriterion {
|
pub struct Criterion {
|
||||||
/// Name of the criterion.
|
/// Name of the criterion.
|
||||||
name: String,
|
name: String,
|
||||||
/// The relative weight of the criterion. Is non-negative.
|
/// The relative weight of the criterion. Is non-negative.
|
||||||
@ -26,8 +26,8 @@ pub struct TopsisCriterion {
|
|||||||
maximize: bool,
|
maximize: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TopsisCriterion {
|
impl Criterion {
|
||||||
/// Construct a new `TopsisCriterion`. Use a negative weight if the value for the criterion
|
/// Construct a new `Criterion`. Use a negative weight if the value for the criterion
|
||||||
/// should be minimized rather than maximized.
|
/// should be minimized rather than maximized.
|
||||||
///
|
///
|
||||||
/// Assumes that `weight` is finite.
|
/// Assumes that `weight` is finite.
|
||||||
@ -38,7 +38,7 @@ impl TopsisCriterion {
|
|||||||
(false, -weight)
|
(false, -weight)
|
||||||
};
|
};
|
||||||
|
|
||||||
TopsisCriterion {
|
Criterion {
|
||||||
name,
|
name,
|
||||||
weight,
|
weight,
|
||||||
maximize,
|
maximize,
|
||||||
@ -46,14 +46,14 @@ impl TopsisCriterion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A normalized array of `TopsisCriterion`.
|
/// A normalized array of `Criterion`.
|
||||||
pub struct TopsisCriteria<const N_CRITERIA: usize>([TopsisCriterion; N_CRITERIA]);
|
pub struct Criteria<const N_CRITERIA: usize>([Criterion; N_CRITERIA]);
|
||||||
|
|
||||||
impl<const N: usize> TopsisCriteria<N> {
|
impl<const N: usize> Criteria<N> {
|
||||||
/// Create a new instance of normalized TOPSIS criteria.
|
/// Create a new instance of normalized TOPSIS criteria.
|
||||||
///
|
///
|
||||||
/// Assumes that the sum of weights can be calculated to a finite, non-zero value.
|
/// Assumes that the sum of weights can be calculated to a finite, non-zero value.
|
||||||
pub fn new(mut criteria: [TopsisCriterion; N]) -> Result<Self, Error> {
|
pub fn new(mut criteria: [Criterion; N]) -> Result<Self, Error> {
|
||||||
let divisor = criteria
|
let divisor = criteria
|
||||||
.iter()
|
.iter()
|
||||||
.fold(0.0, |sum, criterion| sum + criterion.weight);
|
.fold(0.0, |sum, criterion| sum + criterion.weight);
|
||||||
@ -73,7 +73,7 @@ impl<const N: usize> TopsisCriteria<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TopsisCriteria(criteria))
|
Ok(Criteria(criteria))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Weigh each value according to the weight of its corresponding criterion.
|
/// Weigh each value according to the weight of its corresponding criterion.
|
||||||
@ -86,9 +86,9 @@ impl<const N: usize> TopsisCriteria<N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A normalized matrix used for scoring with the TOPSIS algorithm.
|
/// A normalized matrix used for scoring with the TOPSIS algorithm.
|
||||||
pub struct TopsisMatrix<const N_CRITERIA: usize>(Vec<[f64; N_CRITERIA]>);
|
pub struct Matrix<const N_CRITERIA: usize>(Vec<[f64; N_CRITERIA]>);
|
||||||
|
|
||||||
impl<const N: usize> TopsisMatrix<N> {
|
impl<const N: usize> Matrix<N> {
|
||||||
/// Values of the matrix for the fixed critierion with index `index`.
|
/// Values of the matrix for the fixed critierion with index `index`.
|
||||||
fn fixed_criterion(&self, index: usize) -> Vec<f64> {
|
fn fixed_criterion(&self, index: usize) -> Vec<f64> {
|
||||||
self.0
|
self.0
|
||||||
@ -105,12 +105,12 @@ impl<const N: usize> TopsisMatrix<N> {
|
|||||||
.collect::<Vec<&mut _>>()
|
.collect::<Vec<&mut _>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a normalized `TopsisMatrix` based on the given values.
|
/// Create a normalized `Matrix` based on the given values.
|
||||||
///
|
///
|
||||||
/// Assumes that the sum of squares for each fixed criterion in `matrix` can be calculated to a
|
/// Assumes that the sum of squares for each fixed criterion in `matrix` can be calculated to a
|
||||||
/// finite value.
|
/// finite value.
|
||||||
pub fn new(matrix: Vec<[f64; N]>) -> Result<Self, Error> {
|
pub fn new(matrix: Vec<[f64; N]>) -> Result<Self, Error> {
|
||||||
let mut matrix = TopsisMatrix(matrix);
|
let mut matrix = Matrix(matrix);
|
||||||
for n in 0..N {
|
for n in 0..N {
|
||||||
let divisor = l2_norm(&matrix.fixed_criterion(n));
|
let divisor = l2_norm(&matrix.fixed_criterion(n));
|
||||||
|
|
||||||
@ -129,17 +129,17 @@ impl<const N: usize> TopsisMatrix<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Idealized alternatives from a `TopsisMatrix`. That is, the alternative consisting of the best
|
/// Idealized alternatives from a `Matrix`. That is, the alternative consisting of the best
|
||||||
/// (respectively worst) value among the alternatives in the matrix for each single criterion.
|
/// (respectively worst) value among the alternatives in the matrix for each single criterion.
|
||||||
struct TopsisIdealAlternatives<const N_CRITERIA: usize> {
|
struct IdealAlternatives<const N_CRITERIA: usize> {
|
||||||
best: [f64; N_CRITERIA],
|
best: [f64; N_CRITERIA],
|
||||||
worst: [f64; N_CRITERIA],
|
worst: [f64; N_CRITERIA],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize> TopsisIdealAlternatives<N> {
|
impl<const N: usize> IdealAlternatives<N> {
|
||||||
/// Compute the idealized alternatives from the given `matrix`. The `criteria` are required to know
|
/// Compute the idealized alternatives from the given `matrix`. The `criteria` are required to know
|
||||||
/// if a critierion should be maximized or minimized.
|
/// if a critierion should be maximized or minimized.
|
||||||
fn compute(matrix: &TopsisMatrix<N>, criteria: &TopsisCriteria<N>) -> Self {
|
fn compute(matrix: &Matrix<N>, criteria: &Criteria<N>) -> Self {
|
||||||
let criteria = &criteria.0;
|
let criteria = &criteria.0;
|
||||||
|
|
||||||
let mut best = [0.0; N];
|
let mut best = [0.0; N];
|
||||||
@ -170,10 +170,10 @@ impl<const N: usize> TopsisIdealAlternatives<N> {
|
|||||||
/// alternative. Scores range from 0.0 to 1.0 and a low score indicates closness to the ideal worst
|
/// alternative. Scores range from 0.0 to 1.0 and a low score indicates closness to the ideal worst
|
||||||
/// and/or distance to the ideal best alternatives.
|
/// and/or distance to the ideal best alternatives.
|
||||||
pub fn score_alternatives<const N: usize>(
|
pub fn score_alternatives<const N: usize>(
|
||||||
matrix: &TopsisMatrix<N>,
|
matrix: &Matrix<N>,
|
||||||
criteria: &TopsisCriteria<N>,
|
criteria: &Criteria<N>,
|
||||||
) -> Result<Vec<f64>, Error> {
|
) -> Result<Vec<f64>, Error> {
|
||||||
let ideal_alternatives = TopsisIdealAlternatives::compute(matrix, criteria);
|
let ideal_alternatives = IdealAlternatives::compute(matrix, criteria);
|
||||||
let ideal_best = &ideal_alternatives.best;
|
let ideal_best = &ideal_alternatives.best;
|
||||||
let ideal_worst = &ideal_alternatives.worst;
|
let ideal_worst = &ideal_alternatives.worst;
|
||||||
|
|
||||||
@ -201,8 +201,8 @@ pub fn score_alternatives<const N: usize>(
|
|||||||
|
|
||||||
/// Similar to `score_alternatives`, but returns the list of indices decreasing by score.
|
/// Similar to `score_alternatives`, but returns the list of indices decreasing by score.
|
||||||
pub fn rank_alternatives<const N: usize>(
|
pub fn rank_alternatives<const N: usize>(
|
||||||
matrix: &TopsisMatrix<N>,
|
matrix: &Matrix<N>,
|
||||||
criteria: &TopsisCriteria<N>,
|
criteria: &Criteria<N>,
|
||||||
) -> Result<Vec<usize>, Error> {
|
) -> Result<Vec<usize>, Error> {
|
||||||
let scores = score_alternatives(matrix, criteria)?;
|
let scores = score_alternatives(matrix, criteria)?;
|
||||||
|
|
||||||
@ -243,10 +243,10 @@ macro_rules! criteria_struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
::lazy_static::lazy_static! {
|
::lazy_static::lazy_static! {
|
||||||
static ref $criteria_name: $crate::topsis::TopsisCriteria<$count_name> =
|
static ref $criteria_name: $crate::topsis::Criteria<$count_name> =
|
||||||
$crate::topsis::TopsisCriteria::new([
|
$crate::topsis::Criteria::new([
|
||||||
$(
|
$(
|
||||||
$crate::topsis::TopsisCriterion::new($crit_name.to_string(), $crit_weight),
|
$crate::topsis::Criterion::new($crit_name.to_string(), $crit_weight),
|
||||||
)*
|
)*
|
||||||
])
|
])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
154
tests/topsis.rs
154
tests/topsis.rs
@ -1,64 +1,60 @@
|
|||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
|
||||||
use proxmox_resource_scheduling::topsis::{
|
use proxmox_resource_scheduling::topsis::{rank_alternatives, Criteria, Criterion, Matrix};
|
||||||
rank_alternatives, TopsisCriteria, TopsisCriterion, TopsisMatrix,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_topsis_single_criterion() -> Result<(), Error> {
|
fn test_topsis_single_criterion() -> Result<(), Error> {
|
||||||
let criteria_pos =
|
let criteria_pos = Criteria::new([Criterion::new("the one and only".to_string(), 1.0)])?;
|
||||||
TopsisCriteria::new([TopsisCriterion::new("the one and only".to_string(), 1.0)])?;
|
|
||||||
|
|
||||||
let criteria_neg =
|
let criteria_neg = Criteria::new([Criterion::new("the one and only".to_string(), -1.0)])?;
|
||||||
TopsisCriteria::new([TopsisCriterion::new("the one and only".to_string(), -1.0)])?;
|
|
||||||
|
|
||||||
let matrix = vec![[0.0]];
|
let matrix = vec![[0.0]];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_pos)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_pos)?,
|
||||||
vec![0],
|
vec![0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_neg)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_neg)?,
|
||||||
vec![0],
|
vec![0],
|
||||||
);
|
);
|
||||||
|
|
||||||
let matrix = vec![[0.0], [2.0]];
|
let matrix = vec![[0.0], [2.0]];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_pos)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_pos)?,
|
||||||
vec![1, 0],
|
vec![1, 0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_neg)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_neg)?,
|
||||||
vec![0, 1],
|
vec![0, 1],
|
||||||
);
|
);
|
||||||
|
|
||||||
let matrix = vec![[1.0], [2.0]];
|
let matrix = vec![[1.0], [2.0]];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_pos)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_pos)?,
|
||||||
vec![1, 0],
|
vec![1, 0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_neg)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_neg)?,
|
||||||
vec![0, 1],
|
vec![0, 1],
|
||||||
);
|
);
|
||||||
|
|
||||||
let matrix = vec![[1.0], [2.0], [5.0], [3.0], [4.0]];
|
let matrix = vec![[1.0], [2.0], [5.0], [3.0], [4.0]];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_pos)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_pos)?,
|
||||||
vec![2, 4, 3, 1, 0],
|
vec![2, 4, 3, 1, 0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_neg)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_neg)?,
|
||||||
vec![0, 1, 3, 4, 2],
|
vec![0, 1, 3, 4, 2],
|
||||||
);
|
);
|
||||||
|
|
||||||
let matrix = vec![[-2.0], [-5.0], [-4.0], [1.0], [-3.0]];
|
let matrix = vec![[-2.0], [-5.0], [-4.0], [1.0], [-3.0]];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_pos)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_pos)?,
|
||||||
vec![3, 0, 4, 2, 1],
|
vec![3, 0, 4, 2, 1],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_neg)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_neg)?,
|
||||||
vec![1, 2, 4, 0, 3],
|
vec![1, 2, 4, 0, 3],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -67,38 +63,38 @@ fn test_topsis_single_criterion() -> Result<(), Error> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_topsis_two_criteria() -> Result<(), Error> {
|
fn test_topsis_two_criteria() -> Result<(), Error> {
|
||||||
let criteria_max_min = TopsisCriteria::new([
|
let criteria_max_min = Criteria::new([
|
||||||
TopsisCriterion::new("max".to_string(), 1.0),
|
Criterion::new("max".to_string(), 1.0),
|
||||||
TopsisCriterion::new("min".to_string(), -1.0),
|
Criterion::new("min".to_string(), -1.0),
|
||||||
])?;
|
])?;
|
||||||
let criteria_min_max = TopsisCriteria::new([
|
let criteria_min_max = Criteria::new([
|
||||||
TopsisCriterion::new("min".to_string(), -1.0),
|
Criterion::new("min".to_string(), -1.0),
|
||||||
TopsisCriterion::new("max".to_string(), 1.0),
|
Criterion::new("max".to_string(), 1.0),
|
||||||
])?;
|
])?;
|
||||||
let criteria_min_min = TopsisCriteria::new([
|
let criteria_min_min = Criteria::new([
|
||||||
TopsisCriterion::new("min1".to_string(), -1.0),
|
Criterion::new("min1".to_string(), -1.0),
|
||||||
TopsisCriterion::new("min2".to_string(), -1.0),
|
Criterion::new("min2".to_string(), -1.0),
|
||||||
])?;
|
])?;
|
||||||
let criteria_max_max = TopsisCriteria::new([
|
let criteria_max_max = Criteria::new([
|
||||||
TopsisCriterion::new("max1".to_string(), 1.0),
|
Criterion::new("max1".to_string(), 1.0),
|
||||||
TopsisCriterion::new("max2".to_string(), 1.0),
|
Criterion::new("max2".to_string(), 1.0),
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
let matrix = vec![[0.0, 0.0]];
|
let matrix = vec![[0.0, 0.0]];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_max_min)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_max_min)?,
|
||||||
vec![0],
|
vec![0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_min_max)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_min_max)?,
|
||||||
vec![0],
|
vec![0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_min_min)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_min_min)?,
|
||||||
vec![0],
|
vec![0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_max_max)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_max_max)?,
|
||||||
vec![0],
|
vec![0],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -111,19 +107,19 @@ fn test_topsis_two_criteria() -> Result<(), Error> {
|
|||||||
[0.0, 0.0],
|
[0.0, 0.0],
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_max_min)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_max_min)?,
|
||||||
vec![2, 1, 4, 3, 0],
|
vec![2, 1, 4, 3, 0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_min_max)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_min_max)?,
|
||||||
vec![0, 3, 4, 1, 2],
|
vec![0, 3, 4, 1, 2],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_min_min)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_min_min)?,
|
||||||
vec![2, 4, 1, 0, 3],
|
vec![2, 4, 1, 0, 3],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_max_max)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_max_max)?,
|
||||||
vec![3, 0, 1, 4, 2],
|
vec![3, 0, 1, 4, 2],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -137,19 +133,19 @@ fn test_topsis_two_criteria() -> Result<(), Error> {
|
|||||||
[4.0, 7.0],
|
[4.0, 7.0],
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_max_min)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_max_min)?,
|
||||||
vec![0, 1, 4, 2, 3],
|
vec![0, 1, 4, 2, 3],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_min_max)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_min_max)?,
|
||||||
vec![3, 2, 4, 1, 0],
|
vec![3, 2, 4, 1, 0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_min_min)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_min_min)?,
|
||||||
vec![2, 3, 1, 0, 4],
|
vec![2, 3, 1, 0, 4],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_max_max)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_max_max)?,
|
||||||
vec![4, 0, 1, 3, 2],
|
vec![4, 0, 1, 3, 2],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -158,25 +154,25 @@ fn test_topsis_two_criteria() -> Result<(), Error> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_topsis_three_criteria() -> Result<(), Error> {
|
fn test_topsis_three_criteria() -> Result<(), Error> {
|
||||||
let criteria_first = TopsisCriteria::new([
|
let criteria_first = Criteria::new([
|
||||||
TopsisCriterion::new("more".to_string(), 10.0),
|
Criterion::new("more".to_string(), 10.0),
|
||||||
TopsisCriterion::new("less".to_string(), 0.2),
|
Criterion::new("less".to_string(), 0.2),
|
||||||
TopsisCriterion::new("least".to_string(), 0.1),
|
Criterion::new("least".to_string(), 0.1),
|
||||||
])?;
|
])?;
|
||||||
let criteria_second = TopsisCriteria::new([
|
let criteria_second = Criteria::new([
|
||||||
TopsisCriterion::new("less".to_string(), 0.2),
|
Criterion::new("less".to_string(), 0.2),
|
||||||
TopsisCriterion::new("more".to_string(), 10.0),
|
Criterion::new("more".to_string(), 10.0),
|
||||||
TopsisCriterion::new("least".to_string(), 0.1),
|
Criterion::new("least".to_string(), 0.1),
|
||||||
])?;
|
])?;
|
||||||
let criteria_third = TopsisCriteria::new([
|
let criteria_third = Criteria::new([
|
||||||
TopsisCriterion::new("less".to_string(), 0.2),
|
Criterion::new("less".to_string(), 0.2),
|
||||||
TopsisCriterion::new("least".to_string(), 0.1),
|
Criterion::new("least".to_string(), 0.1),
|
||||||
TopsisCriterion::new("more".to_string(), 10.0),
|
Criterion::new("more".to_string(), 10.0),
|
||||||
])?;
|
])?;
|
||||||
let criteria_min = TopsisCriteria::new([
|
let criteria_min = Criteria::new([
|
||||||
TopsisCriterion::new("most".to_string(), -10.0),
|
Criterion::new("most".to_string(), -10.0),
|
||||||
TopsisCriterion::new("more".to_string(), -5.0),
|
Criterion::new("more".to_string(), -5.0),
|
||||||
TopsisCriterion::new("less".to_string(), 0.1),
|
Criterion::new("less".to_string(), 0.1),
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
@ -186,19 +182,19 @@ fn test_topsis_three_criteria() -> Result<(), Error> {
|
|||||||
[0.0, 0.0, 1.0],
|
[0.0, 0.0, 1.0],
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_first)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_first)?,
|
||||||
vec![0, 1, 2],
|
vec![0, 1, 2],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_second)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_second)?,
|
||||||
vec![1, 0, 2],
|
vec![1, 0, 2],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_third)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_third)?,
|
||||||
vec![2, 0, 1],
|
vec![2, 0, 1],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_min)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_min)?,
|
||||||
vec![2, 1, 0],
|
vec![2, 1, 0],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -210,19 +206,19 @@ fn test_topsis_three_criteria() -> Result<(), Error> {
|
|||||||
];
|
];
|
||||||
// normalization ensures that it's still the same as above
|
// normalization ensures that it's still the same as above
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_first)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_first)?,
|
||||||
vec![0, 1, 2],
|
vec![0, 1, 2],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_second)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_second)?,
|
||||||
vec![1, 0, 2],
|
vec![1, 0, 2],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_third)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_third)?,
|
||||||
vec![2, 0, 1],
|
vec![2, 0, 1],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_min)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_min)?,
|
||||||
vec![2, 1, 0],
|
vec![2, 1, 0],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -233,19 +229,19 @@ fn test_topsis_three_criteria() -> Result<(), Error> {
|
|||||||
[0.0, 0.0, 1.0],
|
[0.0, 0.0, 1.0],
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_first)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_first)?,
|
||||||
vec![2, 1, 0],
|
vec![2, 1, 0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_second)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_second)?,
|
||||||
vec![2, 0, 1],
|
vec![2, 0, 1],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix.clone())?, &criteria_third)?,
|
rank_alternatives(&Matrix::new(matrix.clone())?, &criteria_third)?,
|
||||||
vec![2, 1, 0],
|
vec![2, 1, 0],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_min)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_min)?,
|
||||||
vec![0, 1, 2],
|
vec![0, 1, 2],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -260,22 +256,22 @@ fn test_nan() {
|
|||||||
[0.0, -1.0, 0.0],
|
[0.0, -1.0, 0.0],
|
||||||
[0.0, f64::NAN, 1.0],
|
[0.0, f64::NAN, 1.0],
|
||||||
];
|
];
|
||||||
assert!(TopsisMatrix::new(matrix).is_err());
|
assert!(Matrix::new(matrix).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_zero() -> Result<(), Error> {
|
fn test_zero() -> Result<(), Error> {
|
||||||
let criteria_zero = TopsisCriteria::new([
|
let criteria_zero = Criteria::new([
|
||||||
TopsisCriterion::new("z".to_string(), 0.0),
|
Criterion::new("z".to_string(), 0.0),
|
||||||
TopsisCriterion::new("e".to_string(), 0.0),
|
Criterion::new("e".to_string(), 0.0),
|
||||||
TopsisCriterion::new("ro".to_string(), 0.0),
|
Criterion::new("ro".to_string(), 0.0),
|
||||||
]);
|
]);
|
||||||
assert!(criteria_zero.is_err());
|
assert!(criteria_zero.is_err());
|
||||||
|
|
||||||
let criteria_first = TopsisCriteria::new([
|
let criteria_first = Criteria::new([
|
||||||
TopsisCriterion::new("more".to_string(), 10.0),
|
Criterion::new("more".to_string(), 10.0),
|
||||||
TopsisCriterion::new("less".to_string(), 0.2),
|
Criterion::new("less".to_string(), 0.2),
|
||||||
TopsisCriterion::new("least".to_string(), 0.1),
|
Criterion::new("least".to_string(), 0.1),
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
@ -285,7 +281,7 @@ fn test_zero() -> Result<(), Error> {
|
|||||||
[0.0, 0.0, 1.0],
|
[0.0, 0.0, 1.0],
|
||||||
];
|
];
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
rank_alternatives(&TopsisMatrix::new(matrix)?, &criteria_first)?,
|
rank_alternatives(&Matrix::new(matrix)?, &criteria_first)?,
|
||||||
vec![1, 2, 0],
|
vec![1, 2, 0],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user