DEXiPy Classes and Data Types
Classes
DexiModel
dexipy.dexi.DexiModel
is a top-level DEXiPy class that represents a whole DEXi model. The hieararchy of model attributes starts at root. A DexiModel object generally contains its name and description strings, lists of attributes and their IDs, and a list of alternatives.
DexiAttribute
dexipy.dexi.DexiAttribute
is a class representing measurable properties of decision alternatives. Attributes are structured hierarchically, therefore each attribute instance contains a list inputs of its input attributes, i.e., immediate descendants in the hierarchy. When fully defined, each attribute has an associated scale, which is an object of a DexiScale class. Furthermore, each aggregate attribute (non-terminal node in the hierarchy) is normally associated with a DexiFunction object funct, which governs the aggregation of input values to the value of that attribute. Also, an attribute has a name, optional description and an ID string that is unique in the model context.
DexiScale
The
dexipy.dexi.DexiScale
class defines the set of values that can be assigned to the corresponding attribute. A scale might, but need not be preferentially ordered.While DexiScale is a base class, there are two derived scale types that are actually used in DEXi models:
DexiContinousScale
This scale can be associated with basic attributes, i.e., terminal nodes of the model. Only float values can be assigned to such attributes.
Note
Continuous scales have been introduced in DEXiWin and are not supported in DEXi.
DexiDiscreteScale
A discrete scale defines an ordered list of discrete values that can be assigned to the corresponding attribute, for instance
["low", "medium", "high"]
. This scale type can be associated with both basic and aggregate attributes.
DexiFunction
dexipy.dexi.DexiFunction
is a base class for functions that aggregate or discretize the values of some attribute’s inputs to the value of that attribute.Two types of functions are used in DEXiPy:
DexiDiscretizeFunction
This function type is used to map numeric values of a continuous basic attribute to discrete values of a single discrete parent attribute.
Note
This function type has been introduced in DEXiWin and is not supported in DEXi.
DexiTabularFunction
This is the main DEXi aggregation function type that aggregates multiple discrete inputs to a single discrete parent attribute. Essentially, a DexiTabularFunction consists of a lookup table that defines the output value for all combinations of input values. Each table entry is referred to as an elementary decision rule.
DEXi values
DEXi values are used throughout DEXi models.
They provide input values and carry results of evaluations of decision alternatives.
DEXi values are also used in definitions of dexipy.dexi.DexiFunction
and are returned by
dexipy.dexi.DexiFunction.evaluate()
when evaluating some function for a given set of arguments.
In DEXi, values are always bound to the context provided by a dexipy.dexi.DexiScale
. Since each
fully defined dexipy.dexi.DexiAttribute
is associated with some scale, we can generalize the
scale context to attributes and speak about “assigning some value to an attribute”.
In DEXiPy, DEXi values are not represented by classes, but rather by different data types
that are interpreted in the context of given attributes and their scales.
Module dexipy.types
defines the basic type:
type DexiValue = None | float | set[int] | list[float]
DexiValue defines data types that prevalently use numeric data and serve for internal representation of values in DEXiPy. None of this repesentations require a DexiAttribute or DexiScale context in order to be interpreted.
The DexiValueSpecification type extends DexiValue to facilitate a user-friendly entry and display of DEXi values. It adds the tuple and dict value representations and allows using strings individually and in tuples, sets and dictionaries. In this way, it is possible to refer to discrete scale values by their names rather than ordnila numbers and indices:
type DexiValueSpecification =
DexiValue | str | set[int | str] | tuple[int | str, ...] | dict[int | str, float]
For any scale type, the admissible DexiValueSpecification values are None
,
""
or any string starting with "undef"
, indicating an unavailable or unknown value.
All evaluations involving None
result in None.
DexiContinousScale allows only floating-point numbers.
DexiDiscreteScale, as the main scale type used throughout DEXi models, supports a wider range of value types.
The “normal” and most common discrete value is a “single qualitative value”.
For illustration, let us use the scale composed of four qualitative values:
["unacc", "acc", "good", "exc"]
. Then, “a single qualitative value” denotes
one of these words. Internally in DEXiPy, such values are not represented by strings, but rather
by ordinal numbers, so that ord("unacc") == 0
, ord("acc") == 1
, etc. Some DEXiPy functions
can convert between the two representations, for example dexipy.dexi.DexiModel.evaluate()
and dexipy.dexi.alternative()
.
In order to cope with missing, incomplete or uncertain data, DEX extends the concept of single values to value sets and distributions. In DEXiPy, wherever it is possible to use a single qualitative value, it is also possible to use a value set or distribution. This includes all data representing alternatives and all functions that return qualitative values.
Note
DEXi software supports only sets. Value distributions have been introduced in DEXiWin.
A DEXi value set is a subset of the full range of a dexipy.dexi.DexiDiscreteScale
values.
For the above scale example, the full range of ordinal values is {0, 1, 2, 3}
,
and some possible subsets are {1}
, (1, 3)
, and (1, 2, 3)
.
Both tuples and sets can be used, however tuples are internally converted to sets.
The string "*"
can be used to indicate a full set of values of the corresponding discrete scale.
When a value set is used in a scale context, it can be specified also in terms of value names,
for instance {"acc"}
, {"acc", "exc"}
, and ("acc", "good", "exc")
.
Mixed format is acceptable, too: ("acc", 2, "exc")
.
This format can be used in dictionaries that contain data about alternatives,
and is also produced by dexipy.dexi.DexiModel.alt_text()
.
A DEXi value distribution associates each DexiDiscreteScale value with some
number, generally denoted \(p\) and normally expected to be the [0,1] interval.
Depending on the context and used evaluation method (see Evaluation of alternatives),
\(p\) can be interpreted as a probability or fuzzy set membership. In DEXiPy,
value distributions are internally represented by a list of floating-point numbers.
For example, [0.5, 0, 0.2, 0.3]
represents a value distribution over the
above scale example, assigning
\(p\) = 0.5 to
"unacc"
,\(p\) = 0.0 to
"acc"
,\(p\) = 0.2 to
"good"
and\(p\) = 0.3 to
"exc"
.
An extended and generally more readable external representation of distributions uses the dictionary format, for instance:
using value indices:
{0: 0.5, 2: 0.2, 3: 0.3}
using value names:
{"unacc": 0.5, "good": 0.2, "exc": 0.3}
mixed:
{"unacc": 0.5, 2: 0.2, "exc": 0.3}
Alternatives
Alternatives (more specifically, decision alternatives) are objects evaluated by DEXi models. In DEXiPy, an alternative is represented by a dictionary whose:
keys denote attributes, and
values contain DEXi values of the corresponding attributes.
In general, keys can be either string attribute IDs or integer attribute indices
(the former are preferred).
In addition, there are two special keys "name"
and "description"
,
which provide a name and description string of the alternative; both are optional.
Attribute keys can refer to any attribute in the model.
An alternative that is to be evaluated by dexipy.dexi.evaluate()
is expected to contain key/value pairs of all basic attributes of the model.
After this alternative has been evaluated, calculated values that correspond to
aggregate attributes are added to the dictionary, possibly overwriting previous values.
In dexipy.types
, the following alternatives-related types are defined:
type DexiAlternative = dict[str, DexiValue | str]
type DexiAlternatives = list[DexiAlternative]
type DexiAltData = DexiAlternative | DexiAlternatives
DexiAlternative represents a single alternative. DexiAlternatives represents a list of alternatives. DexiAltData denotes a union of both representations.
Example of an evaluated alternative:
{'name': 'MyCar1a',
'CAR': {0, 3}, 'PRICE': {0, 2}, 'BUY.PRICE': 2, 'MAINT.PRICE': {0, 1, 2},
'TECH.CHAR.': 2, 'COMFORT': 2, '#PERS': 2, '#DOORS': 2, 'LUGGAGE': 2,
'SAFETY': 1}
Representation using attribute indices is also possible:
{'name': 'MyCar1a',
1: {0, 3}, 2: {0, 2}, 3: 2, 4: {0, 1, 2}, 5: 2, 6: 2, 7: 2, 8: 2, 9: 2, 10: 1}
Multiple alternatives can be combined together in a list. The method
dexipy.dexi.DexiFunction.evaluate()
, which evaluates alternatives,
accepts DexiAltData, i.e., either a single alternative or a list of alternatives.
Evaluation of alternatives
In DEXiPy, decision alternatives can be evaluated using the method dexipy.dexi.DexiModel.evaluate()
or function dexipy.dexi.evaluate()
. They accept almost the same arguments and the former is actually
just a suitable alias for calling the latter.
Essentially, evaluation of alternatives in DEX is a bottom-up aggregation method:
starting with basic attributes (or “pruned” aggregate attributes), values of each alternative
are gradually aggregated towards the root attribute.
The aggregation at each individual dexipy.dexi.DexiAttribute
is governed by
the corresponding dexipy.dexi.DexiFunction
.
When alternative values are sets or distributions (see DEXi values),
then evaluate() traverses all possible combinations of values of input attributes.
Four aggregation methods are supported: “set”, “prob”, “fuzzy” and “fuzzynorm”.
Note
DEXi software supports only the “set” evaluation method. DEXiWin supports all methods.
The “set” method interprets DEXi values as sets. The output value assigned to some attribute is composed of the union of all attribute.funct evaluations for all possible combinations of values of attribute.inputs.
The remaining three methods interpret DEXi values as value distributions:
“prob” as probability distributions (requires \(\sum{p} = 1\) in value distributions),
“fuzzy” as fuzzy sets, and
“fuzzynorm” as normalized fuzzy sets (requires \(\max{p} = 1\) in value distributions).
This functionality is achieved by using different methods
(see dexipy.eval.DexiEvalParameters
) for
normalization, and conjunctive and disjunctive aggregation of values.
The evaluation at some aggregate attribute is carried out in four steps:
All value distributions involved in calculations are normalized by the method DexiEvalParameters.norm.
All combinations of attribute.inputs’ values are individually evaluated by the corresponding tabular function attribute.funct.
The value \(p\) of each set of attribute.funct arguments is determined by the conjunctive aggregation function DexiEvalParameters.and_op over \(p\)’s of individual arguments.
The \(p\) of some output value val is determined by the disjunctive aggregation function DexiEvalParameters.or_op, applied on the \(p\)’s of all partial evaluations that map to val.
For mathematical background and more details about aggregation in DEX, please see (Trdin, Bohanec, 2018).