bulanik.plot¶
Needs the plot extra (pip install "bulanik[plot]"). The package re-exports
the plotting functions of its submodules (numbers, sets, inference,
mcdm) and the house style (PALETTE, theme, current_theme).
plot ¶
Publication-quality plots of fuzzy numbers, linguistic variables, inference and MCDM results.
Needs the plot extra (pip install "bulanik[plot]", which installs
matplotlib); the rest of bulanik stays dependency-free.
Every function takes keyword-only options and an optional ax; without one it
creates a new figure. It returns the matplotlib Axes and never calls
plt.show(), so you can add annotations, save or show the figure yourself.
Inputs are validated with the library's usual errors (TypeError for a wrong
type, ValueError for a bad value).
- Fuzzy numbers:
membership,alpha_cuts,defuzzification,orthopair,iv_orthopair,picture,spherical,neutrosophic. - Sets and scales:
variable,it2_set,it2_number. - Inference:
mamdani_output,surface. - MCDM:
ranking,weights,dematel.
House style: one validated categorical palette (PALETTE)
in fixed slot order, 2 px lines with soft translucent fills, hairline axes and
grid, direct labels instead of legends. Wrap plotting and saving in
theme to get the light or dark variant; outside a
theme the light variant's colours are used.
Examples:
>>> from bulanik import TFN, plot
>>> with plot.theme("light"):
... ax = plot.membership([TFN(1, 2, 4), TFN(2, 4, 5)], labels=["A", "B"])
>>> ax.get_xlabel()
'$x$'
PALETTE
module-attribute
¶
PALETTE: Mapping[str, tuple[str, ...]] = MappingProxyType({'light': ('#2a78d6', '#eb6834', '#1baf7a', '#eda100', '#e87ba4', '#008300', '#6250d6', '#e34948'), 'dark': ('#3987e5', '#d95926', '#199e70', '#c98500', '#d55181', '#2ea32e', '#9085e9', '#e66767')})
The categorical palette: eight hues in a fixed order, one tuple per theme.
Slots are assigned in order and never cycled; a ninth series is an error, not a
generated colour. The order passes the dataviz palette validator (lightness band,
chroma floor, colour-vision-deficiency separation, normal-vision floor) on a
white surface ("light") and on the Material for MkDocs slate surface #1e2129
("dark"). Three light slots (aqua, yellow, magenta) are below 3:1 contrast on
white, so every plot that uses them also labels its series directly.
Examples:
>>> from bulanik.plot import PALETTE
>>> PALETTE["light"][:2]
('#2a78d6', '#eb6834')
>>> len(PALETTE["dark"])
8
current_theme ¶
current_theme() -> Mapping[str, Any]
The tokens of the active theme, as a read-only mapping.
Keys: name ("light" or "dark"), surface (background), text,
text_secondary, muted (ink for labels and annotations), grid, axis
(hairlines), series (the categorical palette), ramp (five ordinal blue
steps, nearest the surface first), sequential (the blue magnitude ramp)
and fill_alpha (opacity of the soft fills under curves). Use them to
annotate a figure in the house style.
Returns:
| Type | Description |
|---|---|
Mapping[str, Any]
|
The tokens of the innermost active |
Mapping[str, Any]
|
|
Examples:
>>> from bulanik import plot
>>> plot.current_theme()["name"]
'light'
>>> with plot.theme("dark"):
... plot.current_theme()["surface"]
'#1e2129'
theme ¶
theme(name: str = 'light') -> Iterator[Mapping[str, Any]]
Context manager that applies the house style in a light or dark variant.
Inside the block, matplotlib's rc parameters (fonts, sizes, surface and ink
colours, hairline axes, 2 px lines, tight saving at 200 dpi) follow the
theme, and every bulanik.plot function picks the matching palette. Save
figures inside the block so the background matches. Themes nest; the
previous settings come back on exit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
|
'light'
|
Yields:
| Type | Description |
|---|---|
Mapping[str, Any]
|
The theme tokens, as returned by |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Examples:
>>> from bulanik import TFN, plot
>>> with plot.theme("dark") as tokens:
... ax = plot.membership(TFN(1, 2, 4))
>>> tokens["name"], type(ax).__name__
('dark', 'Axes')
mamdani_output ¶
mamdani_output(fis: MamdaniFIS, inputs: Mapping[str, float], output: str | None = None, *, ax: Axes | None = None) -> Axes
How a Mamdani system reaches its crisp output for one set of inputs.
The output variable's terms are drawn as thin outlines. Every rule that
fires contributes its consequent set, clipped (implication="min") or
scaled ("prod") by its firing strength, as a filled area in its term's
colour. The aggregated set (the system's aggregation of the implied sets,
on the system's own sampling grid) is the dark outline, and the crisp output
from MamdaniFIS.evaluate
is the vertical marker. When no rule fires and the system has a default,
only the default value is marked.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fis
|
MamdaniFIS
|
A |
required |
inputs
|
Mapping[str, float]
|
Crisp value of every input variable, by name. |
required |
output
|
str | None
|
Output variable name; |
None
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
NoRuleFiredError
|
If no rule fires for the output and the system has
no |
Examples:
>>> from bulanik import plot
>>> from bulanik.sets import LinguisticVariable, triangular
>>> from bulanik.inference import MamdaniFIS
>>> service = LinguisticVariable("service", (0, 10), {
... "poor": triangular(0, 0, 5), "good": triangular(5, 10, 10)})
>>> tip = LinguisticVariable("tip", (0, 20), {
... "low": triangular(0, 0, 10), "high": triangular(10, 20, 20)})
>>> fis = MamdaniFIS([service], [tip], [
... "IF service IS poor THEN tip IS low", "IF service IS good THEN tip IS high"])
>>> ax = plot.mamdani_output(fis, {"service": 7.5})
>>> type(ax).__name__
'Axes'
surface ¶
surface(fis: Any, output: str | None = None, *, resolution: int = 41, ax: Axes | None = None) -> Axes
Input-output map of a fuzzy system: a 3-D surface (2 inputs) or a curve (1 input).
Works with every system that has inputs, outputs and evaluate
(MamdaniFIS,
SugenoFIS,
TsukamotoFIS and the interval
type-2 systems). Each input universe is sampled at resolution evenly spaced
points; where no rule fires (and there is no default) the output is left
as a gap. A surface is coloured by height with a one-hue sequential ramp.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fis
|
Any
|
The fuzzy inference system. |
required |
output
|
str | None
|
Output variable name; |
None
|
resolution
|
int
|
Samples per input, an integer of at least 2. |
41
|
ax
|
Axes | None
|
Axes to draw into (3-D for two inputs); |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If the system has more than 2 inputs, |
Examples:
>>> from bulanik import plot
>>> from bulanik.sets import LinguisticVariable, triangular
>>> from bulanik.inference import SugenoFIS, SugenoOutput
>>> x = LinguisticVariable("x", (0, 10), {"lo": triangular(0, 0, 10), "hi": triangular(0, 10, 10)})
>>> y = SugenoOutput("y", {"a": 1.0, "b": 5.0})
>>> fis = SugenoFIS([x], [y], ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"])
>>> ax = plot.surface(fis, resolution=21)
>>> type(ax).__name__
'Axes'
dematel ¶
dematel(result: DEMATELResult, *, arrows: bool = True, ax: Axes | None = None) -> Axes
DEMATEL cause-effect diagram: prominence against relation, with the strong influences.
Each factor is a point at \((D + R,\, D - R)\): right means more involved in
the system (prominence), up means a net giver of influence (relation). A
hairline at \(D - R = 0\) splits the cause group above from the
effect group below; causes take the first palette slot and effects the
second. With arrows, every influence \(t_{ij}\) above the threshold
(result.relations) is a thin muted arrow from factor \(i\) to factor \(j\),
stopping at the edge of its marker; two factors that influence each other
get two arrows bent to opposite sides. A stronger influence is a heavier,
darker arrow, and the arrow ends that meet on one marker are spread around
its edge so the heads stay apart. Factor names are placed clear of the
points, the arrows and each other.
The number of arrows is set by the analysis, not by the plot: raise
dematel(..., threshold=...) to keep only the strongest influences (the
default threshold, the mean of \(T\), often keeps half of them), or pass
arrows=False.
The group key ("cause group", "effect group") sits in the right margin, just past the end of the zero line. On a figure of your own with tight subplots, leave some room on the right (constrained layout does this) or the key can be clipped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
DEMATELResult
|
required | |
arrows
|
bool
|
Draw the relations above the threshold. |
True
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Examples:
>>> from bulanik import plot
>>> from bulanik.mcdm import dematel
>>> r = dematel([[0, 3, 2], [1, 0, 3], [2, 1, 0]], ["a", "b", "c"])
>>> ax = plot.dematel(r)
>>> ax.get_xlabel()
'prominence $D + R$'
References
Gabus and Fontela (1973), Perceptions of the World Problematique: Communication Procedure, Communicating With Those Bearing Collective Responsibility, DEMATEL Report No. 1, Battelle Geneva Research Centre (the cause-effect diagram).
ranking ¶
ranking(result: RankingResult, *, ax: Axes | None = None) -> Axes
Alternatives sorted best first, as a dot plot of their scores.
Rows follow result.ranking (best at the top, numbered), so methods where
a lower score is better (VIKOR) read the same way as the others; the x label
says which direction is better (VIKOR is known to be lower-is-better; for
other methods the direction is read off the ranking). The best alternative is
emphasised in the accent colour; every dot carries its score, the others in
small muted ink.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
RankingResult
|
required | |
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Examples:
>>> from bulanik import plot
>>> from bulanik.mcdm import topsis
>>> r = topsis([[250, 16], [200, 16], [300, 32]], [0.5, 0.5], ["cost", "benefit"])
>>> ax = plot.ranking(r)
>>> type(ax).__name__
'Axes'
weights ¶
weights(result: WeightingResult | BWMResult, *, ax: Axes | None = None) -> Axes
Criteria weights as horizontal bars, largest first, value at each tip.
Bars follow result.ranking. If the method reports a consistency ratio
(AHP, fuzzy AHP, BWM), it is shown in the corner.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
result
|
WeightingResult | BWMResult
|
A |
required |
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Examples:
>>> from bulanik import plot
>>> from bulanik.mcdm import ahp
>>> r = ahp([[1, 3, 5], [1 / 3, 1, 3], [1 / 5, 1 / 3, 1]], criteria=["cost", "quality", "risk"])
>>> ax = plot.weights(r)
>>> type(ax).__name__
'Axes'
alpha_cuts ¶
alpha_cuts(number: TFN | TrFN, *, levels: int | Sequence[float] = 11, ax: Axes | None = None) -> Axes
The \(\alpha\)-cuts of a number as stacked horizontal intervals.
Every level \(\alpha\) is drawn as the interval
alpha_cut(α) at height \(\alpha\), coloured
from light (support, \(\alpha = 0\)) to strong (core, \(\alpha = 1\)), inside the
outline of the membership function. This is the picture behind interval
arithmetic on fuzzy numbers: an operation acts on each cut separately.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
number
|
TFN | TrFN
|
required | |
levels
|
int | Sequence[float]
|
Number of evenly spaced levels from 0 to 1 (at least 2), or the levels themselves. |
11
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Examples:
>>> from bulanik import TFN, plot
>>> ax = plot.alpha_cuts(TFN(1, 2, 4), levels=6)
>>> type(ax).__name__
'Axes'
defuzzification ¶
defuzzification(number: TFN | TrFN, *, scores: Sequence[str] | None = None, ax: Axes | None = None) -> Axes
A number with markers at the crisp values of its score functions.
Each score (score: "centroid",
"graded_mean", "mean") is a stem from the axis up to the membership
curve, labelled with its name and value. Scores that coincide (the centroid
and the mean of a triangle) share one stem.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
number
|
TFN | TrFN
|
required | |
scores
|
Sequence[str] | None
|
Score names to show; |
None
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Examples:
>>> from bulanik import TrFN, plot
>>> ax = plot.defuzzification(TrFN(1, 2, 3, 6))
>>> type(ax).__name__
'Axes'
it2_number ¶
it2_number(numbers: IT2TrFN | Sequence[IT2TrFN], *, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes
Interval type-2 trapezoidal numbers: upper and lower trapezoids and the footprint between them.
Each IT2TrFN is drawn as its upper trapezoid
\((a^U_1, 0), (a^U_2, h^U_1), (a^U_3, h^U_2), (a^U_4, 0)\) in a full line,
its lower trapezoid (same form, heights \(h^L_1, h^L_2\), which may be below 1)
in a thinner line, and the footprint of uncertainty, the area between
them, as a soft wash of the same colour (lighter on the dark theme and when
many footprints overlap). Numbers take the palette slots in order. Heights
below 1 get their own ticks on the membership axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
numbers
|
IT2TrFN | Sequence[IT2TrFN]
|
An |
required |
labels
|
Sequence[str] | None
|
One label per number, written above the peak of its upper trapezoid. |
None
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a number is not an |
ValueError
|
If there are no numbers or more than 8, or the label count differs from the number count. |
Examples:
>>> from bulanik import IT2TrFN, plot
>>> low = IT2TrFN((0, 0.1, 0.1, 0.3, 1, 1), (0.05, 0.1, 0.1, 0.2, 0.9, 0.9))
>>> ax = plot.it2_number(low, labels=["low"])
>>> [line.get_gid() for line in ax.lines]
['upper', 'lower']
References
Mendel, John and Liu (2006), IEEE Transactions on Fuzzy Systems 14(6), 808-821, doi:10.1109/TFUZZ.2006.879986 (footprint of uncertainty). Chen and Lee (2010), Expert Systems with Applications 37(1), 824-833, doi:10.1016/j.eswa.2009.06.094 (the trapezoidal form).
iv_orthopair ¶
iv_orthopair(numbers: IVQROFN | Sequence[IVQROFN], *, q: int | None = None, regions: Sequence[int] | None = None, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes
Interval-valued orthopair numbers as rectangles in the \(\mu\)–\(\nu\) plane.
An IVQROFN \(([\mu_L, \mu_U], [\nu_L, \nu_U])\)
is the rectangle \([\mu_L, \mu_U] \times [\nu_L, \nu_U]\): every orthopair
\((\mu, \nu)\) it admits. Since \(\mu_U^q + \nu_U^q \le 1\), its upper-right
corner, and so the whole rectangle, lies in the feasible region of rung
\(q\), drawn as in orthopair. Each number takes
the next palette slot from the second on (the first, blue, is the region
ramp), as a solid outline over a translucent fill. The fill sits on a
knockout of the surface, so its hue stays clean over the region washes
(on the dark theme the knockout stays bare: a warm tint over the slate
surface turns brown); the region boundaries are drawn over it. A degenerate interval still
shows: a zero-width side is a line and a crisp pair is a dot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
numbers
|
IVQROFN | Sequence[IVQROFN]
|
An |
required |
q
|
int | None
|
Rung of the one region to draw when |
None
|
regions
|
Sequence[int] | None
|
Rungs whose regions are drawn, e.g. |
None
|
labels
|
Sequence[str] | None
|
One label per number, written by the upper-right corner of its rectangle. |
None
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a number is not an interval-valued orthopair number. |
ValueError
|
If |
Examples:
>>> from bulanik import IVIFN, IVPFN, plot
>>> ax = plot.iv_orthopair([IVIFN(0.5, 0.6, 0.2, 0.3), IVPFN(0.6, 0.8, 0.3, 0.5)], labels=["a", "b"])
>>> type(ax).__name__
'Axes'
References
Atanassov and Gargov (1989), Fuzzy Sets and Systems 31(3), 343-349, doi:10.1016/0165-0114(89)90205-4 (interval-valued intuitionistic sets).
membership ¶
membership(numbers: TFN | TrFN | Sequence[TFN | TrFN], *, labels: Sequence[str] | None = None, alpha_cut: float | None = None, fill: bool = True, ax: Axes | None = None) -> Axes
Membership functions of triangular and trapezoidal numbers on one axis.
Each number is drawn as its exact piecewise-linear membership function with
a soft translucent fill, one palette slot per number, and is labelled above
its peak. A single number gets its defining points as x ticks. With
alpha_cut, every number's \(\alpha\)-cut
(alpha_cut) is drawn as a band at
height \(\alpha\) with guides down to the axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
numbers
|
TFN | TrFN | Sequence[TFN | TrFN]
|
required | |
labels
|
Sequence[str] | None
|
One label per number; |
None
|
alpha_cut
|
float | None
|
Level in \([0, 1]\) of an \(\alpha\)-cut band to draw, or |
None
|
fill
|
bool
|
Shade the area under each curve. |
True
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a number is not a |
ValueError
|
If there are no numbers or more than 8, the label count
differs from the number count, or |
Examples:
>>> from bulanik import TFN, TrFN, plot
>>> ax = plot.membership([TFN(1, 2, 4), TrFN(3, 4, 5, 7)], labels=["A", "B"], alpha_cut=0.5)
>>> type(ax).__name__
'Axes'
neutrosophic ¶
neutrosophic(numbers: NeutrosophicFN | Sequence[NeutrosophicFN], *, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes
Neutrosophic numbers as \(T\)/\(I\)/\(F\) radar triangles.
A NeutrosophicFN \((t, i, f)\) has three
independent parts in \([0, 1]\); each number is a filled triangle on three
spokes (truth at the top, indeterminacy lower left, falsity lower right)
over a triangular grid at 0.25 steps. Up to 8 numbers, one palette slot
each; several numbers (or given labels) are named in a legend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
numbers
|
NeutrosophicFN | Sequence[NeutrosophicFN]
|
A |
required |
labels
|
Sequence[str] | None
|
One label per number; |
None
|
ax
|
Axes | None
|
A 2-D axes to draw into (its frame is hidden); |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a number is not a |
ValueError
|
If there are no numbers or more than 8, |
Examples:
>>> from bulanik import NeutrosophicFN, plot
>>> ax = plot.neutrosophic([NeutrosophicFN(0.7, 0.2, 0.1), NeutrosophicFN(0.3, 0.6, 0.5)])
>>> type(ax).__name__
'Axes'
orthopair ¶
orthopair(numbers: QROFN | Sequence[QROFN], *, q: int | None = None, regions: Sequence[int] | None = None, labels: Sequence[str] | None = None, hesitancy: bool = False, ax: Axes | None = None) -> Axes
Orthopair numbers as points in the \(\mu\)–\(\nu\) plane with their feasible regions.
The region of rung \(q\) is \(\mu^q + \nu^q \le 1\); each requested rung is drawn
as its boundary curve with a light wash, so nested regions (IFN \(\subset\)
PFN \(\subset\) FFN) read as steps of one blue ramp. Numbers are points; with
hesitancy=True each point gets a segment along the diagonal to the boundary
of its own rung, whose length grows with the hesitancy
π (a number on its boundary has none).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
numbers
|
QROFN | Sequence[QROFN]
|
A |
required |
q
|
int | None
|
Rung of the one region to draw when |
None
|
regions
|
Sequence[int] | None
|
Rungs whose regions are drawn, e.g. |
None
|
labels
|
Sequence[str] | None
|
One label per number, written next to its point. |
None
|
hesitancy
|
bool
|
Draw the hesitancy segments. |
False
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a number is not an orthopair number. |
ValueError
|
If |
Examples:
>>> from bulanik import IFN, PFN, plot
>>> ax = plot.orthopair([IFN(0.6, 0.3), PFN(0.7, 0.6)], regions=(1, 2, 3), hesitancy=True)
>>> type(ax).__name__
'Axes'
picture ¶
picture(numbers: PictureFN | Sequence[PictureFN], *, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes
Picture fuzzy numbers on the \(\mu\)–\(\eta\)–\(\nu\) ternary simplex.
A PictureFN \((\mu, \eta, \nu)\) has
\(\mu + \eta + \nu \le 1\); the rest \(\rho = 1 - \mu - \eta - \nu\) is the
refusal degree. The point sits at the barycentric position of
\((\mu, \eta, \nu)\) normalised to sum 1 (its balance between positive,
neutral and negative membership), and a translucent halo whose radius grows
with \(\rho\) shows how much is refused.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
numbers
|
PictureFN | Sequence[PictureFN]
|
A |
required |
labels
|
Sequence[str] | None
|
One label per number, written next to its point. |
None
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a number is not a |
ValueError
|
If there are no numbers, a number has all three parts 0, or the label count differs from the number count. |
Examples:
>>> from bulanik import PictureFN, plot
>>> ax = plot.picture([PictureFN(0.5, 0.2, 0.1), PictureFN(0.2, 0.3, 0.4)], labels=["p", "r"])
>>> type(ax).__name__
'Axes'
spherical ¶
spherical(numbers: SphericalFN | Sequence[SphericalFN], *, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes
Spherical fuzzy numbers inside the positive octant of the unit sphere.
A SphericalFN \((\mu, \nu, \pi)\) satisfies
\(\mu^2 + \nu^2 + \pi^2 \le 1\): it is a point of the unit ball's positive
octant. The sphere patch is drawn translucent with a few parallels and
meridians; each point has a drop line to the \(\mu\)–\(\nu\) floor to make its
depth readable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
numbers
|
SphericalFN | Sequence[SphericalFN]
|
A |
required |
labels
|
Sequence[str] | None
|
One label per number. |
None
|
ax
|
Axes | None
|
A 3-D axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib 3-D |
Raises:
| Type | Description |
|---|---|
TypeError
|
If a number is not a |
ValueError
|
If there are no numbers, |
Examples:
>>> from bulanik import SphericalFN, plot
>>> ax = plot.spherical([SphericalFN(0.5, 0.4, 0.3)], labels=["a"])
>>> ax.name
'3d'
it2_set ¶
it2_set(mf_or_term: IT2MF | IT2LinguisticVariable, *, universe: tuple[float, float] | None = None, label: str | None = None, ax: Axes | None = None) -> Axes
Footprint of uncertainty of interval type-2 sets.
The region between the lower \(\underline{\mu}\) and upper \(\overline{\mu}\)
membership functions (the footprint of uncertainty, FOU) is shaded; the upper
bound is a full line, the lower bound a thinner one. Given an
IT2LinguisticVariable, every term is
drawn and named above its peak.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mf_or_term
|
IT2MF | IT2LinguisticVariable
|
An |
required |
universe
|
tuple[float, float] | None
|
The |
None
|
label
|
str | None
|
Name written above a single set's peak. |
None
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Examples:
>>> from bulanik import plot
>>> from bulanik.type2 import gaussian_uncertain_mean
>>> ax = plot.it2_set(gaussian_uncertain_mean(4, 6, 1), label="medium")
>>> type(ax).__name__
'Axes'
variable ¶
variable(var_or_scale: LinguisticVariable | LinguisticScale | IT2LinguisticVariable, *, x: float | None = None, ax: Axes | None = None) -> Axes
Every term of a linguistic variable or scale, direct-labelled.
- A
LinguisticVariable, or aLinguisticScaleofTFN/TrFNterms: all membership functions on one axis with soft fills, each named above its peak. Up to 8 terms take the categorical palette in order; longer scales (Saaty's 1-9) take an ordered blue ramp. Withx, a crisp input is marked and its membership degree in every term it touches is shown. - A scale of orthopair, picture, spherical or neutrosophic terms is drawn by
orthopair,picture,sphericalorneutrosophic, labelled with the term names. - An
IT2LinguisticVariableis drawn byit2_set.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
var_or_scale
|
LinguisticVariable | LinguisticScale | IT2LinguisticVariable
|
The variable or scale. |
required |
x
|
float | None
|
A crisp input to mark (type-1 variables and |
None
|
ax
|
Axes | None
|
Axes to draw into; |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The matplotlib |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Examples:
>>> from bulanik import plot
>>> from bulanik.scales import EXAMPLE_TFN_7
>>> ax = plot.variable(EXAMPLE_TFN_7, x=4)
>>> type(ax).__name__
'Axes'