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:

  1. All value distributions involved in calculations are normalized by the method DexiEvalParameters.norm.

  2. All combinations of attribute.inputs’ values are individually evaluated by the corresponding tabular function attribute.funct.

  3. 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.

  4. 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).