bulanik.aggregate
aggregate ¶
Weighted aggregation: weighted average (WA), weighted geometric (WG), experts.
wa and wg combine fuzzy numbers
of one type with non-negative weights summing to 1, using the type's own
operators (scale / add for the average, power / mul for the geometric
mean). aggregate_experts applies one of
them to a stack of expert rating matrices, cell by cell.
All functions require the inputs to be of one class (and rung, for orthopair
numbers); mixing types raises TypeError.
wa ¶
wa(values: Sequence[FuzzyNumber], weights: Sequence[float] | None = None, *, ops: str = 'algebraic', normalize: bool = False) -> FuzzyNumber
Weighted average \(\sum_i w_i A_i\) with the type's own operators.
Computed as scale of each number by its weight, folded with add. For
triangular numbers this is the componentwise weighted mean of the points;
for intuitionistic numbers it is the classic IFWA operator
\(\left(1 - \prod_i (1 - \mu_i)^{w_i},\; \prod_i \nu_i^{w_i}\right)\).
Picture numbers use the closed form
\(\left(1 - \prod_i (1 - \mu_i)^{w_i},\; \prod_i \eta_i^{w_i},\; \prod_i \nu_i^{w_i}\right)\),
because scaling by a weight below 1 is not closed for them.
weights=None means equal weights \(1/n\). Weights must be non-negative and
sum to 1 unless normalize=True (then they are divided by their sum);
weights that sum to 1 only within \(10^{-9}\) are accepted and silently
rescaled to sum to exactly 1. Inputs with a weight of 0 are ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
Sequence[FuzzyNumber]
|
Fuzzy numbers of one type (and rung). |
required |
weights
|
Sequence[float] | None
|
One weight per value, or |
None
|
ops
|
str
|
Operator set of the type, |
'algebraic'
|
normalize
|
bool
|
Divide the weights by their sum instead of requiring sum 1. |
False
|
Returns:
| Type | Description |
|---|---|
FuzzyNumber
|
The aggregated number, of the type of the inputs. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TypeError
|
If the values are not fuzzy numbers or differ in type. |
References
Xu (2007), IEEE Transactions on Fuzzy Systems 15(6): intuitionistic fuzzy aggregation operators. Wei (2017) for the picture closed forms (retracted by the publisher in 2025; the closed forms are tested against the code, not the paper).
Examples:
>>> from bulanik import TFN, IFN
>>> from bulanik.aggregate import wa
>>> wa([TFN(1, 2, 4), TFN(2, 3, 5)])
TFN(l=1.5, m=2.5, u=4.5)
>>> r = wa([IFN(0.6, 0.3), IFN(0.5, 0.4)], [2, 1], normalize=True)
>>> round(r.mu, 4), round(r.nu, 4)
(0.5691, 0.3302)
>>> wa([TFN(1, 2, 4), TFN(2, 3, 5)], [0.5, 0.2])
Traceback (most recent call last):
...
ValueError: weights must sum to 1, got 0.7
wg ¶
wg(values: Sequence[FuzzyNumber], weights: Sequence[float] | None = None, *, ops: str = 'algebraic', normalize: bool = False) -> FuzzyNumber
Weighted geometric mean \(\prod_i A_i^{w_i}\) with the type's own operators.
Computed as power of each number by its weight, folded with mul. For
positive triangular numbers this is the componentwise weighted geometric
mean of the points. Weights, normalize and ops behave as in
wa. Picture numbers use closed forms
\(\left(\prod_i (\mu_i + \eta_i)^{w_i} - \prod_i \eta_i^{w_i},\;
\prod_i \eta_i^{w_i},\; 1 - \prod_i (1 - \nu_i)^{w_i}\right)\).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
values
|
Sequence[FuzzyNumber]
|
Fuzzy numbers of one type (and rung). |
required |
weights
|
Sequence[float] | None
|
One weight per value, or |
None
|
ops
|
str
|
Operator set of the type, |
'algebraic'
|
normalize
|
bool
|
Divide the weights by their sum instead of requiring sum 1. |
False
|
Returns:
| Type | Description |
|---|---|
FuzzyNumber
|
The aggregated number, of the type of the inputs. |
Raises:
| Type | Description |
|---|---|
ValueError
|
As for |
TypeError
|
If the values are not fuzzy numbers or differ in type. |
References
Xu and Yager (2006), International Journal of General Systems 35(4): intuitionistic fuzzy geometric aggregation operators.
Examples:
>>> from bulanik import TFN
>>> from bulanik.aggregate import wg
>>> r = wg([TFN(1, 2, 4), TFN(2, 3, 5)])
>>> round(r.l, 4), round(r.m, 4), round(r.u, 4)
(1.4142, 2.4495, 4.4721)
aggregate_experts ¶
aggregate_experts(ratings: Sequence[Sequence[Sequence[FuzzyNumber]]], weights: Sequence[float] | None = None, *, method: str = 'wa', ops: str = 'algebraic', normalize: bool = False) -> list[list[FuzzyNumber]]
Aggregate expert ratings indexed [expert][alternative][criterion].
For every alternative-criterion cell the experts' numbers are combined with
wa or wg using the
expert weights.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
Sequence[Sequence[Sequence[FuzzyNumber]]]
|
One matrix per expert; each is a list (alternatives) of lists (criteria) of fuzzy numbers, all of the same shape and type. |
required |
weights
|
Sequence[float] | None
|
One weight per expert, or |
None
|
method
|
str
|
|
'wa'
|
ops
|
str
|
Operator set of the number type. |
'algebraic'
|
normalize
|
bool
|
Divide the expert weights by their sum instead of requiring sum 1. |
False
|
Returns:
| Type | Description |
|---|---|
list[list[FuzzyNumber]]
|
The |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
TypeError
|
If the numbers differ in type. |
Examples:
>>> from bulanik import TFN
>>> from bulanik.aggregate import aggregate_experts
>>> a, b = TFN(1, 2, 4), TFN(2, 3, 5)
>>> experts = [[[a, b]], [[b, a]]] # 2 experts, 1 alternative, 2 criteria
>>> aggregate_experts(experts)
[[TFN(l=1.5, m=2.5, u=4.5), TFN(l=1.5, m=2.5, u=4.5)]]