Перейти к содержанию

Производные свойства

Практические примеры

Рецепты свойств различают точную геометрию и наблюдения на сетке. Записи результатов объясняют каждое возвращаемое поле и показывают явное восстановление.

fuzzyroutines.properties

Контракты вычисления множества поддержки, ядра, границы и высоты скалярных нечётких множеств.

Непрерывные аналитические результаты получаются из объявленной геометрии семейства функций принадлежности, а не сканированием значений с плавающей точкой. Дискретные универсальные множества вычисляются точно во всех объявленных координатах. Для непрерывной выборки возвращается отдельный тип результата, фиксирующий численный способ получения и не допускающий смешения с точным математическим множеством поддержки.

ContinuousInterval dataclass

ContinuousInterval(left: MembershipScalar | None = None, right: MembershipScalar | None = None, leftClosed: bool = False, rightClosed: bool = False)

Один непустой интервал в составе вычисленной непрерывной области.

Attributes:

Name Type Description
left MembershipScalar | None

Конечная левая граница или None для отрицательной бесконечности.

right MembershipScalar | None

Конечная правая граница или None для положительной бесконечности.

leftClosed bool

Включена ли конечная левая граница.

rightClosed bool

Включена ли конечная правая граница.

left class-attribute instance-attribute

left: MembershipScalar | None = None

right class-attribute instance-attribute

right: MembershipScalar | None = None

leftClosed class-attribute instance-attribute

leftClosed: bool = False

rightClosed class-attribute instance-attribute

rightClosed: bool = False

isSingleton property

isSingleton: bool

Проверяет, представляет ли компонента ровно одну координату.

__post_init__

__post_init__() -> None

Validate finite or unbounded endpoints and singleton semantics.

Source code in fuzzyroutines/properties.py
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
def __post_init__(self) -> None:
    """Validate finite or unbounded endpoints and singleton semantics."""

    if not isinstance(self.leftClosed, bool) or not isinstance(self.rightClosed, bool):
        raise InvalidParameterTypeError("interval closure flags must be boolean values")

    if self.left is None:
        if self.leftClosed:
            raise InvalidDomainError("an unbounded left endpoint cannot be closed")

    else:
        object.__setattr__(self, "left", _RequireFiniteReal(self.left, "left"))

    if self.right is None:
        if self.rightClosed:
            raise InvalidDomainError("an unbounded right endpoint cannot be closed")

    else:
        object.__setattr__(self, "right", _RequireFiniteReal(self.right, "right"))

    if self.left is not None and self.right is not None:
        if cast(float, self.left) > cast(float, self.right):
            raise InvalidDomainError("continuous interval endpoints must satisfy left <= right")

        if self.left == self.right and not (self.leftClosed and self.rightClosed):
            raise InvalidDomainError("a singleton interval must be closed at both endpoints")

Contains

Contains(coordinate: MembershipScalar) -> bool

Проверяет, принадлежит ли конечная координата этому интервалу.

Parameters:

Name Type Description Default
coordinate MembershipScalar

Проверяемая конечная вещественная координата.

required

Returns:

Type Description
bool

True тогда и только тогда, когда граничные правила допускают координату.

Raises:

Type Description
TypeError

Координата не является вещественным скаляром.

ValueError

Координата неконечна.

Source code in fuzzyroutines/properties.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
def Contains(self, coordinate: MembershipScalar) -> bool:
    """Return whether a finite coordinate belongs to this interval.

    Args:
        coordinate: Finite real coordinate to test.

    Returns:
        `True` exactly when the endpoint rules admit the coordinate.

    Raises:
        TypeError: If the coordinate is not a real scalar.
        ValueError: If the coordinate is not finite.
    """

    coordinate = _RequireFiniteReal(coordinate, "coordinate")

    if self.left is not None and (
        coordinate < cast(float, self.left) or (coordinate == self.left and not self.leftClosed)
    ):
        return False

    return not (
        self.right is not None
        and (coordinate > cast(float, self.right) or (coordinate == self.right and not self.rightClosed))
    )

ContinuousRegion dataclass

ContinuousRegion(intervals: tuple[ContinuousInterval, ...] = ())

Упорядоченное объединение непересекающихся интервалов в непрерывном скалярном универсальном множестве.

Attributes:

Name Type Description
intervals tuple[ContinuousInterval, ...]

Упорядоченный кортеж неперекрывающихся интервальных компонент.

intervals class-attribute instance-attribute

intervals: tuple[ContinuousInterval, ...] = ()

isEmpty property

isEmpty: bool

Проверяет, не содержит ли область ни одной координаты.

__post_init__

__post_init__() -> None

Require an explicit ordered tuple of non-overlapping components.

Source code in fuzzyroutines/properties.py
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
def __post_init__(self) -> None:
    """Require an explicit ordered tuple of non-overlapping components."""

    if not isinstance(self.intervals, tuple):
        raise InvalidParameterTypeError("continuous region intervals must be an explicit tuple")

    for interval in self.intervals:
        if not isinstance(interval, ContinuousInterval):
            raise InvalidParameterTypeError("continuous region components must be ContinuousInterval values")

    for leftInterval, rightInterval in zip(self.intervals, self.intervals[1:]):
        if leftInterval.right is None or rightInterval.left is None:
            raise InvalidDomainError("continuous region intervals must be strictly ordered")

        if cast(float, leftInterval.right) > cast(float, rightInterval.left):
            raise InvalidDomainError("continuous region intervals must not overlap")

        if (
            leftInterval.right == rightInterval.left
            and leftInterval.rightClosed
            and rightInterval.leftClosed
        ):
            raise InvalidDomainError("continuous region intervals must not share a coordinate")

Contains

Contains(coordinate: MembershipScalar) -> bool

Проверяет, принадлежит ли конечная координата хотя бы одной компоненте.

Parameters:

Name Type Description Default
coordinate MembershipScalar

Проверяемая конечная вещественная координата.

required

Returns:

Type Description
bool

True, если хотя бы одна компонента содержит координату.

Raises:

Type Description
TypeError

Область непустая, а координата не является вещественным скаляром.

ValueError

Область непустая, а координата неконечна.

Source code in fuzzyroutines/properties.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def Contains(self, coordinate: MembershipScalar) -> bool:
    """Return whether a finite coordinate belongs to any component.

    Args:
        coordinate: Finite real coordinate to test.

    Returns:
        `True` when at least one component contains the coordinate.

    Raises:
        TypeError: If the region is non-empty and the coordinate is not a
            real scalar.
        ValueError: If the region is non-empty and the coordinate is not
            finite.
    """

    return any(interval.Contains(coordinate) for interval in self.intervals)

DiscreteRegion dataclass

DiscreteRegion(points: tuple[MembershipScalar, ...] = ())

Упорядоченное подмножество объявленного дискретного универсального множества.

Attributes:

Name Type Description
points tuple[MembershipScalar, ...]

Строго возрастающий кортеж конечных координат.

points class-attribute instance-attribute

points: tuple[MembershipScalar, ...] = ()

isEmpty property

isEmpty: bool

Проверяет, не содержит ли область ни одной объявленной координаты.

__post_init__

__post_init__() -> None

Require finite, strictly increasing, distinct coordinates.

Source code in fuzzyroutines/properties.py
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
def __post_init__(self) -> None:
    """Require finite, strictly increasing, distinct coordinates."""

    if not isinstance(self.points, tuple):
        raise InvalidParameterTypeError("discrete region points must be an explicit tuple")

    validatedPoints = tuple(
        _RequireFiniteReal(point, f"points[{pointIndex}]")
        for pointIndex, point in enumerate(self.points)
    )

    if any(leftPoint >= rightPoint for leftPoint, rightPoint in pairwise(validatedPoints)):
        raise InvalidDomainError("discrete region points must be strictly increasing and distinct")

    object.__setattr__(self, "points", validatedPoints)

Contains

Contains(coordinate: MembershipScalar) -> bool

Проверяет, принадлежит ли конечная координата этой дискретной области.

Parameters:

Name Type Description Default
coordinate MembershipScalar

Проверяемая конечная вещественная координата.

required

Returns:

Type Description
bool

True, если coordinate входит в points.

Raises:

Type Description
TypeError

Координата не является вещественным скаляром.

ValueError

Координата неконечна.

Source code in fuzzyroutines/properties.py
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
def Contains(self, coordinate: MembershipScalar) -> bool:
    """Return whether a finite coordinate belongs to this discrete region.

    Args:
        coordinate: Finite real coordinate to test.

    Returns:
        `True` when `coordinate` is one of `points`.

    Raises:
        TypeError: If the coordinate is not a real scalar.
        ValueError: If the coordinate is not finite.
    """

    coordinate = _RequireFiniteReal(coordinate, "coordinate")
    return coordinate in self.points

ContinuousFuzzyProperties dataclass

ContinuousFuzzyProperties(universe: ContinuousUniverse, positiveSupport: ContinuousRegion, supportClosure: ContinuousRegion, core: ContinuousRegion, boundary: ContinuousRegion, height: MembershipScalar)

Точные аналитические вычисляемые свойства на непрерывном универсальном множестве.

Attributes:

Name Type Description
universe ContinuousUniverse

Непрерывное универсальное множество, которым ограничены все области.

positiveSupport ContinuousRegion

Координаты со строго положительной принадлежностью.

supportClosure ContinuousRegion

Замыкание positiveSupport внутри универсального множества.

core ContinuousRegion

Координаты с принадлежностью один.

boundary ContinuousRegion

Координаты с принадлежностью строго между нулём и единицей согласно контракту аналитического семейства.

height MembershipScalar

Точная верхняя грань степеней на универсальном множестве.

universe instance-attribute

positiveSupport instance-attribute

positiveSupport: ContinuousRegion

supportClosure instance-attribute

supportClosure: ContinuousRegion

core instance-attribute

boundary instance-attribute

boundary: ContinuousRegion

height instance-attribute

isExact property

isExact: bool

Указывает, что геометрия интервалов получена из контракта аналитического семейства.

__post_init__

__post_init__() -> None

Require internally consistent regions and a valid membership height.

Source code in fuzzyroutines/properties.py
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
def __post_init__(self) -> None:
    """Require internally consistent regions and a valid membership height."""

    if not isinstance(self.universe, ContinuousUniverse):
        raise InvalidParameterTypeError("universe must be a ContinuousUniverse")

    for fieldName in ("positiveSupport", "supportClosure", "core", "boundary"):
        region = getattr(self, fieldName)

        if not isinstance(region, ContinuousRegion):
            raise InvalidParameterTypeError(f"{fieldName} must be a ContinuousRegion")

        if _IntersectRegion(region, self.universe) != region:
            raise InvalidDomainError(f"{fieldName} must lie within the declared universe")

    height = _RequireFiniteReal(self.height, "height")

    if not 0 <= height <= 1:
        raise InvalidParameterError("height must lie in [0, 1]")

    object.__setattr__(self, "height", height)

DiscreteFuzzyProperties dataclass

DiscreteFuzzyProperties(universe: DiscreteUniverse, positiveSupport: DiscreteRegion, supportClosure: DiscreteRegion, core: DiscreteRegion, boundary: DiscreteRegion, height: MembershipScalar)

Точные вычисляемые свойства на явно дискретном универсальном множестве.

Attributes:

Name Type Description
universe DiscreteUniverse

Полностью перебранное дискретное универсальное множество.

positiveSupport DiscreteRegion

Объявленные точки с положительной принадлежностью.

supportClosure DiscreteRegion

Совпадает с positiveSupport в дискретной топологии.

core DiscreteRegion

Объявленные точки с принадлежностью один.

boundary DiscreteRegion

Объявленные точки с принадлежностью строго между нулём и единицей.

height MembershipScalar

Максимальная принадлежность среди всех объявленных точек.

universe instance-attribute

universe: DiscreteUniverse

positiveSupport instance-attribute

positiveSupport: DiscreteRegion

supportClosure instance-attribute

supportClosure: DiscreteRegion

core instance-attribute

boundary instance-attribute

boundary: DiscreteRegion

height instance-attribute

isExact property

isExact: bool

Указывает, что вычислена каждая координата объявленного универсального множества.

__post_init__

__post_init__() -> None

Require derived point sets to be subsets of the declared universe.

Source code in fuzzyroutines/properties.py
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
def __post_init__(self) -> None:
    """Require derived point sets to be subsets of the declared universe."""

    if not isinstance(self.universe, DiscreteUniverse):
        raise InvalidParameterTypeError("universe must be a DiscreteUniverse")

    universePoints = set(self.universe.points)

    for fieldName in ("positiveSupport", "supportClosure", "core", "boundary"):
        region = getattr(self, fieldName)

        if not isinstance(region, DiscreteRegion):
            raise InvalidParameterTypeError(f"{fieldName} must be a DiscreteRegion")

        if not set(region.points) <= universePoints:
            raise InvalidDomainError(f"{fieldName} must lie within the declared universe")

    height = _RequireFiniteReal(self.height, "height")

    if not 0 <= height <= 1:
        raise InvalidParameterError("height must lie in [0, 1]")

    object.__setattr__(self, "height", height)

SampledFuzzyProperties dataclass

SampledFuzzyProperties(analysisDomain: IntegrationDomain, sampleCount: int, coordinates: tuple[MembershipScalar, ...], grades: tuple[MembershipScalar, ...], positiveSupportSamples: DiscreteRegion, coreSamples: DiscreteRegion, boundarySamples: DiscreteRegion, heightEstimate: MembershipScalar, method: str = 'uniform-grid')

Приближённые наблюдения конечных координат на непрерывной области.

SampleProperties создаёт равномерную сетку и по степеням принадлежности определяет точки каждой записанной области. При прямом создании объекта проверяются структура таблицы, охват границ, принадлежность точек записанных областей исходной сетке и высота. Равномерность шага не проверяется, а три записанные области не вычисляются заново.

Attributes:

Name Type Description
analysisDomain IntegrationDomain

Замкнутый интервал, покрываемый сеткой.

sampleCount int

Число координат, включая обе границы.

coordinates tuple[MembershipScalar, ...]

Строго возрастающие координаты, охватывающие analysisDomain.

grades tuple[MembershipScalar, ...]

Проверенные степени для coordinates.

positiveSupportSamples DiscreteRegion

Записанное подмножество координат выборки; SampleProperties выбирает степени больше нуля.

coreSamples DiscreteRegion

Записанное подмножество координат выборки; SampleProperties выбирает степени, равные единице.

boundarySamples DiscreteRegion

Записанное подмножество координат выборки; SampleProperties выбирает степени строго между нулём и единицей.

heightEstimate MembershipScalar

Наибольшая наблюдаемая степень, а не доказательство точной верхней грани.

method str

Непустая метка происхождения выборки. SampleProperties использует "uniform-grid".

analysisDomain instance-attribute

analysisDomain: IntegrationDomain

sampleCount instance-attribute

sampleCount: int

coordinates instance-attribute

coordinates: tuple[MembershipScalar, ...]

grades instance-attribute

grades: tuple[MembershipScalar, ...]

positiveSupportSamples instance-attribute

positiveSupportSamples: DiscreteRegion

coreSamples instance-attribute

coreSamples: DiscreteRegion

boundarySamples instance-attribute

boundarySamples: DiscreteRegion

heightEstimate instance-attribute

heightEstimate: MembershipScalar

method class-attribute instance-attribute

method: str = 'uniform-grid'

isExact property

isExact: bool

Не позволяет представлять выборочные наблюдения как точную геометрию.

__post_init__

__post_init__() -> None

Validate the complete provenance and observation table.

Source code in fuzzyroutines/properties.py
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
def __post_init__(self) -> None:
    """Validate the complete provenance and observation table."""

    if not isinstance(self.analysisDomain, IntegrationDomain):
        raise InvalidParameterTypeError("analysisDomain must be an IntegrationDomain")

    if isinstance(self.sampleCount, bool) or not isinstance(self.sampleCount, int):
        raise InvalidParameterTypeError("sampleCount must be an integer")

    if self.sampleCount < 2:
        raise InvalidParameterError("sampleCount must be at least two")

    if not isinstance(self.coordinates, tuple) or not isinstance(self.grades, tuple):
        raise InvalidParameterTypeError("sample coordinates and grades must be explicit tuples")

    if len(self.coordinates) != self.sampleCount or len(self.grades) != self.sampleCount:
        raise InvalidParameterError("sampleCount must match coordinate and grade counts")

    coordinates = tuple(
        _RequireFiniteReal(coordinate, f"coordinates[{coordinateIndex}]")
        for coordinateIndex, coordinate in enumerate(self.coordinates)
    )

    if any(leftCoordinate >= rightCoordinate for leftCoordinate, rightCoordinate in pairwise(coordinates)):
        raise InvalidDomainError("sample coordinates must be strictly increasing and distinct")

    if coordinates[0] != self.analysisDomain.left or coordinates[-1] != self.analysisDomain.right:
        raise InvalidDomainError("sample coordinates must include both analysis-domain endpoints")

    grades = tuple(
        _ValidateMembershipGrade(grade, coordinate)
        for coordinate, grade in zip(coordinates, self.grades)
    )
    samplePoints = set(coordinates)

    for fieldName in ("positiveSupportSamples", "coreSamples", "boundarySamples"):
        region = getattr(self, fieldName)

        if not isinstance(region, DiscreteRegion):
            raise InvalidParameterTypeError(f"{fieldName} must be a DiscreteRegion")

        if not set(region.points) <= samplePoints:
            raise InvalidParameterError(f"{fieldName} must contain only sampled coordinates")

    heightEstimate = _RequireFiniteReal(self.heightEstimate, "heightEstimate")

    if heightEstimate != max(grades):
        raise InvalidParameterError("heightEstimate must equal the maximum sampled grade")

    if not isinstance(self.method, str) or not self.method:
        raise InvalidParameterTypeError("method must be a non-empty string")

    object.__setattr__(self, "coordinates", coordinates)
    object.__setattr__(self, "grades", grades)
    object.__setattr__(self, "heightEstimate", heightEstimate)

DeriveProperties

DeriveProperties(membershipFunction: MembershipFunction | _AnalyticalSource | _LegacyAnalyticalAdapter, universe: ContinuousUniverse) -> ContinuousFuzzyProperties
DeriveProperties(membershipFunction: MembershipFunction | _AnalyticalSource | _LegacyAnalyticalAdapter, universe: DiscreteUniverse) -> DiscreteFuzzyProperties
DeriveProperties(membershipFunction: MembershipFunction | _AnalyticalSource | _LegacyAnalyticalAdapter, universe: ContinuousUniverse | DiscreteUniverse) -> ContinuousFuzzyProperties | DiscreteFuzzyProperties

Выводит точные свойства нечёткого множества для поддерживаемого скалярного универсального множества.

Непрерывным результатам нужна современная MembershipFunction или исторический адаптер MFunction. Точные аналитические сведения копируются из проверенного источника формулы; произвольная функция не доказывает непрерывные поддержку или высоту. На дискретном универсальном множестве результат точен благодаря вычислению каждой объявленной координаты. Для явно приближённого непрерывного запроса используйте SampleProperties.

Parameters:

Name Type Description Default
membershipFunction MembershipFunction | _AnalyticalSource | _LegacyAnalyticalAdapter

Современное аналитическое семейство или поддерживаемый исторический аналитический адаптер.

required
universe ContinuousUniverse | DiscreteUniverse

Анализируемое непрерывное или дискретное скалярное универсальное множество.

required

Returns:

Type Description
ContinuousFuzzyProperties | DiscreteFuzzyProperties

Точные непрерывные аналитические свойства или полные дискретные свойства согласно типу универсального множества.

Raises:

Type Description
TypeError

Один из аргументов имеет неподдерживаемый тип контракта.

ValueError

Аналитическое семейство не поддерживается или вычисление даёт недопустимую степень принадлежности.

Source code in fuzzyroutines/properties.py
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
def DeriveProperties(
    membershipFunction: MembershipFunction | _AnalyticalSource | _LegacyAnalyticalAdapter,
    universe: ContinuousUniverse | DiscreteUniverse,
) -> ContinuousFuzzyProperties | DiscreteFuzzyProperties:
    """Derive exact fuzzy-set properties for a supported scalar universe.

    Continuous results require a modern
    [MembershipFunction][fuzzyroutines.membership.MembershipFunction] or a
    historical [MFunction][fuzzyroutines.FuzzyRoutines.MFunction] adapter.
    Exact analytical evidence is copied from a validated formula source; an
    arbitrary callable does not prove continuous support or height.
    A discrete universe is exact because every declared coordinate is evaluated.
    Use [SampleProperties][fuzzyroutines.properties.SampleProperties] for an
    explicitly approximate continuous query.

    Args:
        membershipFunction: Modern analytical family or supported historical
            analytical adapter.
        universe: Continuous or discrete scalar universe to analyze.

    Returns:
        Exact continuous analytical properties or exhaustive discrete
        properties, matching the universe type.

    Raises:
        TypeError: If either argument has an unsupported contract type.
        ValueError: If the analytical family is unsupported or evaluation
            produces an invalid membership grade.
    """

    source: _AnalyticalSource | _LegacyAnalyticalAdapter | None

    if not (isinstance(universe, DiscreteUniverse) and isinstance(membershipFunction, _LegacyAnalyticalAdapter)):
        source = _GetAnalyticalSource(membershipFunction)

    else:
        source = membershipFunction

    if source is None:
        if isinstance(universe, ContinuousUniverse) and isinstance(membershipFunction, _LegacyAnalyticalAdapter):
            raise InvalidParameterError("exact analytical evidence requires an unchanged registered evaluator")

        raise InvalidParameterTypeError("membershipFunction must be a supported analytical membership source")

    if isinstance(universe, ContinuousUniverse):
        # Continuous inputs always pass through _GetAnalyticalSource above.
        analyticalSource = cast(_AnalyticalSource, source)
        (
            globalPositiveSupport,
            globalCore,
            globalBoundary,
            leftLimit,
            rightLimit,
        ) = _AnalyticalRegions(analyticalSource)
        positiveSupport = _IntersectRegion(globalPositiveSupport, universe)
        supportClosure = _ClosureWithin(positiveSupport, universe)
        core = _IntersectRegion(globalCore, universe)
        boundary = _IntersectRegion(globalBoundary, universe)
        height = _ContinuousHeight(
            analyticalSource,
            core,
            boundary,
            leftLimit,
            rightLimit,
        )
        return ContinuousFuzzyProperties(
            universe,
            positiveSupport,
            supportClosure,
            core,
            boundary,
            height,
        )

    if isinstance(universe, DiscreteUniverse):
        grades = _EvaluateCoordinates(source, universe.points)
        positivePoints = tuple(point for point, grade in zip(universe.points, grades) if grade > 0)
        corePoints = tuple(point for point, grade in zip(universe.points, grades) if grade == 1)
        boundaryPoints = tuple(
            point for point, grade in zip(universe.points, grades) if 0 < grade < 1
        )
        discreteSupport = DiscreteRegion(positivePoints)
        return DiscreteFuzzyProperties(
            universe,
            discreteSupport,
            discreteSupport,
            DiscreteRegion(corePoints),
            DiscreteRegion(boundaryPoints),
            max(grades),
        )

    raise InvalidParameterTypeError("universe must be a ContinuousUniverse or DiscreteUniverse")

SampleProperties

SampleProperties(membershipFunction: MembershipFunction | _AnalyticalSource | _LegacyAnalyticalAdapter, analysisDomain: IntegrationDomain, sampleCount: int = 101) -> SampledFuzzyProperties

Возвращает явно приближённые наблюдения на равномерной конечной сетке.

Parameters:

Name Type Description Default
membershipFunction MembershipFunction | _AnalyticalSource | _LegacyAnalyticalAdapter

Современное аналитическое семейство или исторический аналитический адаптер, значения которого вычисляются в узлах сетки.

required
analysisDomain IntegrationDomain

Конечный замкнутый интервал, покрываемый сеткой.

required
sampleCount int

Число координат равномерной сетки, включая границы.

101

Returns:

Type Description
SampledFuzzyProperties

Выборочные наблюдения нечётких свойств с подробным описанием происхождения.

Raises:

Type Description
TypeError

Аргумент имеет неверный тип контракта.

ValueError

sampleCount меньше двух или наблюдаемая степень вне \([0, 1]\).

Source code in fuzzyroutines/properties.py
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
def SampleProperties(
    membershipFunction: MembershipFunction | _AnalyticalSource | _LegacyAnalyticalAdapter,
    analysisDomain: IntegrationDomain,
    sampleCount: int = 101,
) -> SampledFuzzyProperties:
    """Return explicitly approximate observations on a uniform finite grid.

    Args:
        membershipFunction: Modern analytical family or historical analytical
            adapter whose scalar evaluations are sampled.
        analysisDomain: Closed finite interval covered by the grid.
        sampleCount: Number of uniform-grid coordinates, including endpoints.

    Returns:
        Provenance-rich sampled fuzzy-property observations.

    Raises:
        TypeError: If an argument has the wrong contract type.
        ValueError: If `sampleCount` is less than two or a sampled grade is
            outside $[0, 1]$.
    """

    source: _AnalyticalSource | _LegacyAnalyticalAdapter | None

    if not isinstance(membershipFunction, _LegacyAnalyticalAdapter):
        source = _GetAnalyticalSource(membershipFunction)

    else:
        source = membershipFunction

    if source is None:
        raise InvalidParameterTypeError("membershipFunction must be a supported analytical membership source")

    if not isinstance(analysisDomain, IntegrationDomain):
        raise InvalidParameterTypeError("analysisDomain must be an IntegrationDomain")

    if isinstance(sampleCount, bool) or not isinstance(sampleCount, int):
        raise InvalidParameterTypeError("sampleCount must be an integer")

    if sampleCount < 2:
        raise InvalidParameterError("sampleCount must be at least two")

    step = (cast(float, analysisDomain.right) - cast(float, analysisDomain.left)) / (sampleCount - 1)
    # Preserve the exact declared right endpoint instead of trusting the last
    # rounded multiply-add; see source-algorithm-invariants.md.
    coordinates = tuple(
        analysisDomain.right if sampleIndex == sampleCount - 1 else cast(float, analysisDomain.left) + sampleIndex * step
        for sampleIndex in range(sampleCount)
    )
    grades = _EvaluateCoordinates(source, coordinates)
    positivePoints = tuple(point for point, grade in zip(coordinates, grades) if grade > 0)
    corePoints = tuple(point for point, grade in zip(coordinates, grades) if grade == 1)
    boundaryPoints = tuple(point for point, grade in zip(coordinates, grades) if 0 < grade < 1)
    return SampledFuzzyProperties(
        analysisDomain,
        sampleCount,
        coordinates,
        grades,
        DiscreteRegion(positivePoints),
        DiscreteRegion(corePoints),
        DiscreteRegion(boundaryPoints),
        max(grades),
    )