Add complement

This commit is contained in:
Alexander Ignatov 2021-12-19 01:01:30 +02:00
parent 07943d45dd
commit 67380ab162
8 changed files with 83 additions and 3 deletions

View File

@ -18,6 +18,10 @@ public struct ContinuousFuzzySet: FuzzySet {
public func alphaCut(_ alpha: Grade) -> Self {
.init { max(membershipFunction($0), alpha) }
}
public var complement: Self {
.init { 1 - membershipFunction($0) }
}
}
public extension ContinuousFuzzySet {

View File

@ -38,6 +38,14 @@ public struct DiscreteMutableFuzzySet<Universe: Hashable>: FuzzySet {
let newMap = Dictionary(uniqueKeysWithValues: newGradeTuples)
grades = newMap
}
public var complement: Self {
let newGradeTuples = grades.map {
($0.key, 1 - $0.value)
}
let newMap = Dictionary(uniqueKeysWithValues: newGradeTuples)
return .init(elementToGradeMap: newMap)
}
}
public extension DiscreteMutableFuzzySet {

View File

@ -9,6 +9,8 @@ public protocol FuzzySet {
subscript(_ element: Universe) -> Grade { get }
func alphaCut(_ alpha: Grade) -> Self
var complement: Self { get }
}
public extension FuzzySet {

View File

@ -30,6 +30,12 @@ public struct IterableFuzzySet<Universe: Strideable> {
Swift.max(function($0), alpha)
}
}
public var complement: Self {
.init(range: range) {
1 - function($0)
}
}
}
extension IterableFuzzySet: FuzzySet {

View File

@ -18,4 +18,20 @@ final class ContinuousFuzzySetTests: XCTestCase {
XCTAssertEqual(1.0, peakResult)
XCTAssertEqual(alpha, maxResult)
}
func test_triangular_complement() {
let a = 3.0
let b = 5.0
let c = 8.0
let set = ContinuousFuzzySet(membershipFunction: .triangular(minimum: a, peak: b, maximum: c))
let sut = set.complement
let minResult = sut[a]
let peakResult = sut[b]
let maxResult = sut[c]
XCTAssertEqual(1.0, minResult)
XCTAssertEqual(0.0, peakResult)
XCTAssertEqual(1.0, maxResult)
}
}

View File

@ -111,4 +111,30 @@ final class DiscreteMutableFuzzySetTests: XCTestCase {
assertExpectedGrade(element: element, expectedGrade: grade, sut: sut2)
}
}
func test_complement_gradesAreCorrect() {
let initial = [
"a": 1.0,
"b": 0.88,
"c": 0.69,
"d": 0.42,
"e": 0.001,
"f": 0.0,
]
let expected = [
"a": 0.0,
"b": 0.12,
"c": 0.31,
"d": 0.58,
"e": 0.999,
"f": 1.0,
]
let set = DiscreteMutableFuzzySet(elementToGradeMap: initial)
let sut = set.complement
for (element, grade) in expected {
assertExpectedGrade(element: element, expectedGrade: grade, sut: sut)
}
}
}

View File

@ -1,12 +1,17 @@
import XCTest
import FuzzyKit
func XCTAssertApproximatelyEqual(_ v1: Double, _ v2: Double, tolerance: Double = 0.0001) {
let diff = v1 - v2
XCTAssert(-tolerance <= diff && diff <= +tolerance)
}
func assertExpectedGrade<E, S: FuzzySet>(element: E, expectedGrade: Grade, sut: S)
where S.Universe == E {
let grade1 = sut[element]
let grade2 = sut.grade(forElement: element)
XCTAssertEqual(grade1, grade2)
XCTAssertEqual(expectedGrade, grade1)
XCTAssertEqual(expectedGrade, grade2)
XCTAssertApproximatelyEqual(grade1, grade2)
XCTAssertApproximatelyEqual(expectedGrade, grade1)
XCTAssertApproximatelyEqual(expectedGrade, grade2)
}

View File

@ -57,4 +57,17 @@ class IterableFuzzySetTests: XCTestCase {
let allAreBelowAlpha = grades.allSatisfy { $0 >= alpha }
XCTAssertTrue(allAreBelowAlpha)
}
func test_complementOfTriangular_allValuesAddUpToOne() {
let set = IterableFuzzySet(
range: stride(from: 0.0, through: 100.0, by: 0.5),
membershipFunction: .triangular(minimum: 42.0, peak: 69.0, maximum: 88.88)
)
let sut = set.complement
let sums = zip(set, sut).map { $0.0.grade + $0.1.grade }
sums.forEach { XCTAssertApproximatelyEqual(1.0, $0) }
}
}