Historical-to-Modern API Migration Examples¶
- Status: current
developimplementation boundary - Related Task: #99
- Canonical entry point: compatibility and migration
- Compatibility decision: ADR-0001
- Exact implementation boundary: current status
Migration rule¶
Historical names remain supported. Existing users do not need to rename
MFunction, FuzzySet, FuzzyScale, UniversalFuzzyScale, Defuz, or the
scalar operator functions merely to adopt version 2. Migrate one area at a
time when the focused API already provides the behavior the application
needs.
The current modern API covers explicit domains, immutable scalar fuzzy sets,
set algebra, relations, derived properties, alpha-cuts, exact height-aware
normalization, and typed linguistic-term and ordered-scale representations. A
focused immutable membership-function factory is also available through
fuzzyroutines.membership. Exact and Unicode
case-insensitive typed scale lookup plus explicit fuzzification policies are
available. Explicit-grid coverage, overlap, gap, and partition diagnostics are
also available without changing membership coefficients. Modern centroid defuzzification is available
through an explicit integration domain and numerical policy. The examples
below keep remaining gaps visible instead of inventing future call shapes.
| Area | Historical API remains supported | Preferred path available today |
|---|---|---|
| Operators | FuzzyNOT, TNorm, SCoNorm, and compose functions |
NegationPolicy, TNormPolicy, and SNormPolicy; set operations require policies explicitly |
| Membership functions | MFunction and every protected historical identifier |
Immutable callable factories in fuzzyroutines.membership, including conventional Triangle and Trapezoid |
| Fuzzy sets | Mutable FuzzySet with a legacy supportSet integration interval |
Immutable ScalarFuzzySet with an explicit ContinuousUniverse or DiscreteUniverse |
| Scales | FuzzyScale and UniversalFuzzyScale |
Typed representation, lookup, fuzzification, and sampled diagnostics through LinguisticScale |
| Derived operations | No equivalent unified modern surface | DeriveProperties, AlphaCut, SampleAlphaCut, Height, and Normalize preserve explicit exactness boundaries |
| Defuzzification | FuzzySet.Defuz() and defuzValue |
Centroid() with explicit ScalarFuzzySet, IntegrationDomain, and optional CentroidPolicy |
Operators¶
Historical scalar calls select a family with a string:
from fuzzyroutines.FuzzyRoutines import FuzzyNOT, SCoNorm, TNorm
conjunction = TNorm(0.4, 0.7, normType="algebraic")
disjunction = SCoNorm(0.4, 0.7, normType="logic")
negated = FuzzyNOT(0.4)
The modern scalar and fuzzy-set paths make the selected policy an immutable value:
from fuzzyroutines import NegationPolicy, SNormPolicy, TNormPolicy
conjunction = TNormPolicy("algebraic").Evaluate(0.4, 0.7)
disjunction = SNormPolicy("logic").Evaluate(0.4, 0.7)
negated = NegationPolicy("standard").Evaluate(0.4)
TNormCompose and SCoNormCompose do not yet have focused modern
counterparts. Keep those historical names when n-ary composition is required;
do not replace them with an undocumented API.
Membership functions¶
The historical factory and parameter conventions remain the executable API:
from fuzzyroutines.FuzzyRoutines import MFunction
# Historical order is preserved: a = left foot, c = apex, b = right foot.
membershipFunction = MFunction("triangle", a=0.0, b=1.0, c=0.5)
grade = membershipFunction.mju(0.25)
For new code, use the immutable modern callable directly:
from fuzzyroutines import ContinuousUniverse, ScalarFuzzySet
from fuzzyroutines.membership import Triangle
membershipFunction = Triangle(left=0.0, peak=0.5, right=1.0)
universe = ContinuousUniverse(0.0, 1.0, leftClosed=True, rightClosed=True)
fuzzySet = ScalarFuzzySet(universe, membershipFunction)
Additive registry names such as gaussian, logistic, sShoulder, and
harringtonDesirability are available, but migration does not require
renaming exponential, sigmoidal, parabolic, or desirability. See the
membership-function contract
before changing any identifier because some historical parameter orders are
deliberately preserved.
The modern Triangle(left, peak, right) contract deliberately differs from
historical MFunction("triangle", a=left, b=right, c=peak). Modern
Trapezoid(left, plateauStart, plateauEnd, right) similarly differs from
the historical trapezium keyword mapping. Do not transfer a positional tuple
between the APIs without translating it explicitly. The shared scalar
formulas retain the accepted historical boundaries, including peak == right
for the existing high triangular term.
Earlier v2 development snapshots named the plateau arguments plateau_start
and plateau_end. The canonical names are now plateauStart and plateauEnd
in Bell, Trapezoid, and MembershipFunction's read-only parameter mapping.
Both constructors and direct family construction still accept the old keyword
spellings at runtime; specifying an alias together with its canonical spelling
is rejected. Positional order, parameter meaning and numerical results are
unchanged. New code and static typing use the canonical camelCase names.
Fuzzy sets¶
Historical construction combines a membership object, a mutable name, and a
tuple historically called supportSet:
from fuzzyroutines.FuzzyRoutines import FuzzySet, MFunction
membershipFunction = MFunction("triangle", a=0.0, b=1.0, c=0.5)
fuzzySet = FuzzySet(
membershipFunction,
supportSet=(0.0, 1.0),
linguisticName="Medium",
)
For new set algebra, declare the universe separately and pass a membership callable:
from fuzzyroutines import (
Complement,
ContinuousUniverse,
NegationPolicy,
ScalarFuzzySet,
)
universe = ContinuousUniverse(0.0, 1.0, leftClosed=True, rightClosed=True)
membershipFunction = Triangle(left=0.0, peak=0.5, right=1.0)
fuzzySet = ScalarFuzzySet(universe, membershipFunction)
complement = Complement(fuzzySet, NegationPolicy("standard"))
assert complement.Membership(0.25) == 0.5
ScalarFuzzySet has no linguistic-name field and no numerical integration
interval. IntegrationDomain is a separate operational value and is not
mathematical support.
Scales¶
Continue to use the protected historical classes:
from fuzzyroutines.FuzzyRoutines import UniversalFuzzyScale
scale = UniversalFuzzyScale()
level = scale.Fuzzy(0.5)
assert level["name"] == "Med"
The modern API can represent names, fuzzy sets, and explicit term order without silently inheriting the historical dictionary shape:
from fuzzyroutines import FuzzificationPolicy, LinguisticScale, LinguisticTerm
modernScale = LinguisticScale((LinguisticTerm("Medium", fuzzySet),))
term = modernScale.GetTermByName("medium", exactMatching=False)
result = modernScale.Fuzzify(
0.5,
FuzzificationPolicy(tiePolicy="last", minimumConfidence=0.05),
)
The modern lookup matches only complete names. Its default mode is exact and
case-sensitive; exactMatching=False uses Unicode case-insensitive comparison.
It does not perform fuzzy, prefix, or substring name matching. Modern
Fuzzify() returns all ordered membership scores and the maximum score as
confidence. Its policy makes the no-match threshold, tie tolerance, and
first, last, or all tie selection explicit. Historical callers may keep
FuzzyScale or UniversalFuzzyScale; tiePolicy="last" provides the modern
equivalent of the historical later-winner rule without changing Fuzzy().
Defuzzification¶
Existing code may continue to use the recalculating compatibility entry point:
from fuzzyroutines.FuzzyRoutines import FuzzySet, MFunction
membershipFunction = MFunction("triangle", a=0.0, b=1.0, c=0.5)
fuzzySet = FuzzySet(membershipFunction, supportSet=(0.0, 1.0))
centroid = fuzzySet.Defuz()
Defuz() now uses the modern analytical/adaptive strategy and ignores the
retained compatibility attribute MFunction.accuracy. The historical
supportSet tuple is a finite numerical integration interval, not exact
positive support. New code can express the same operation explicitly:
from fuzzyroutines import Centroid, ContinuousUniverse, IntegrationDomain, ScalarFuzzySet
integrationDomain = IntegrationDomain.FromLegacyInterval(fuzzySet.supportSet)
modernSet = ScalarFuzzySet(ContinuousUniverse(), membershipFunction.mju)
centroid = Centroid(modernSet, integrationDomain)
See Centroid defuzzification for analytical families, adaptive tolerances, zero-area behavior, and convergence failure.
Executable examples¶
Both examples import only public package entry points and contain no source tree path manipulation:
python examples/migration/historical_compatibility.py
python examples/migration/modern_supported.py
historical_compatibility.pyexercises all five historical areas.modern_supported.pyexercises explicit operator policies and immutable fuzzy sets while clearly using the focused immutable membership factory without importing the historical module.
The example tests execute each script from a temporary working directory. The
package workflow independently installs the wheel and source distribution,
removes PYTHONPATH, proves the import origin is inside the clean environment,
and runs the same scripts through the shell-visible entry points. See
Executable Tests, Tools, Benchmarks, and Examples
for the complete artifact and exit-code contract.