Restructure FuzzyLogic module and add rule base DSL
This commit is contained in:
parent
065e729a98
commit
2b6a0516d9
|
@ -12,3 +12,9 @@ public extension BinaryFuzzyRelation {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension FuzzyRule {
|
||||
func asRelation<P, Q>() -> BinaryFuzzyRelation<P, Q> where Input == (P, Q) {
|
||||
.init { (p, q) in self((p, q)) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import FuzzySets
|
||||
import FuzzyRelations
|
||||
|
||||
open class FuzzyLinguisticController<AntecedentUniverse, ConsequentUniverse> {
|
||||
|
||||
public var settings: OperationSettings
|
||||
public var ruleBase: FuzzyRuleBase<(AntecedentUniverse, ConsequentUniverse)>
|
||||
public var aggregatorFuction: (Grade, Grade) -> Grade
|
||||
|
||||
public init(
|
||||
rules: FuzzyRuleBase<(AntecedentUniverse, ConsequentUniverse)> = .init(),
|
||||
settings: OperationSettings = .init()
|
||||
) {
|
||||
self.ruleBase = rules
|
||||
self.settings = settings
|
||||
self.aggregatorFuction = settings.disjunction.function
|
||||
}
|
||||
|
||||
open func consequenceGrade<S: Sequence>(
|
||||
_ value: ConsequentUniverse,
|
||||
usingFact fact: IterableFuzzySet<AntecedentUniverse, S>
|
||||
) -> Grade {
|
||||
ruleBase
|
||||
.map {
|
||||
FuzzySetComposition(set: fact, relation: $0.asRelation())
|
||||
}
|
||||
.map {
|
||||
$0.grade(forElement: value)
|
||||
}
|
||||
.reduce(0, aggregatorFuction)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import FuzzySets
|
||||
|
||||
public protocol FuzzyProposition {
|
||||
associatedtype Input
|
||||
func apply(_ x: Input, settings: OperationSettings) -> Grade
|
||||
}
|
||||
|
||||
public extension FuzzyProposition {
|
||||
func callAsFunction(_ x: Input, settings: OperationSettings = .init()) -> Grade {
|
||||
apply(x, settings: settings)
|
||||
}
|
||||
}
|
||||
|
||||
extension AnyFuzzySet: FuzzyProposition {
|
||||
public func apply(_ x: Universe, settings: OperationSettings) -> Grade {
|
||||
grade(forElement: x)
|
||||
}
|
||||
}
|
||||
|
||||
extension IterableFuzzySet: FuzzyProposition {
|
||||
public func apply(_ x: Universe, settings: OperationSettings) -> Grade {
|
||||
grade(forElement: x)
|
||||
}
|
||||
}
|
||||
|
||||
extension DiscreteMutableFuzzySet: FuzzyProposition {
|
||||
public func apply(_ x: Universe, settings: OperationSettings) -> Grade {
|
||||
grade(forElement: x)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyRuleBase<RuleInput> {
|
||||
|
||||
public typealias Rule = FuzzyRule<RuleInput>
|
||||
|
||||
@resultBuilder
|
||||
public struct FuzzyRuleBaseBuilder {
|
||||
public static func buildBlock() -> [Rule] { [] }
|
||||
|
||||
public static func buildBlock(_ rules: Rule...) -> [Rule] { rules }
|
||||
|
||||
public static func buildOptional(_ component: [Rule]?) -> [Rule] {
|
||||
component ?? []
|
||||
}
|
||||
|
||||
public static func buildEither(first component: [Rule]) -> [Rule] {
|
||||
component
|
||||
}
|
||||
|
||||
public static func buildEither(second component: [Rule]) -> [Rule] {
|
||||
component
|
||||
}
|
||||
|
||||
public static func buildArray(_ components: [[Rule]]) -> [Rule] {
|
||||
components.flatMap { $0 }
|
||||
}
|
||||
}
|
||||
|
||||
public var rules: [Rule]
|
||||
|
||||
public init(_ rules: [Rule] = []) {
|
||||
self.rules = rules
|
||||
}
|
||||
|
||||
public init(@FuzzyRuleBaseBuilder _ rulesBlock: () -> [Rule]) {
|
||||
self.rules = rulesBlock()
|
||||
}
|
||||
}
|
||||
|
||||
extension FuzzyRuleBase: Sequence {
|
||||
public func makeIterator() -> Array<Rule>.Iterator {
|
||||
rules.makeIterator()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyConjunction<Input>: FuzzyProposition {
|
||||
|
||||
private let function: (Input, OperationSettings) -> Grade
|
||||
|
||||
public init<P: FuzzyProposition, Q: FuzzyProposition>(lhs: P, rhs: Q) where Input == (P.Input, Q.Input) {
|
||||
self.function = { (x, settings) -> Grade in
|
||||
settings.conjunction.function(
|
||||
lhs(x.0, settings: settings),
|
||||
rhs(x.1, settings: settings)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func apply(_ values: Input, settings: OperationSettings = .init()) -> Grade {
|
||||
function(values, settings)
|
||||
}
|
||||
}
|
||||
|
||||
public func && <P: FuzzyProposition, Q: FuzzyProposition> (lhs: P, rhs: Q) -> FuzzyConjunction<(P.Input, Q.Input)> {
|
||||
.init(lhs: lhs, rhs: rhs)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyDisjunction<Input>: FuzzyProposition {
|
||||
|
||||
private let function: (Input, OperationSettings) -> Grade
|
||||
|
||||
public init<P: FuzzyProposition, Q: FuzzyProposition>(lhs: P, rhs: Q) where Input == (P.Input, Q.Input) {
|
||||
self.function = { (x, settings) -> Grade in
|
||||
settings.disjunction.function(
|
||||
lhs(x.0, settings: settings),
|
||||
rhs(x.1, settings: settings)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func apply(_ values: Input, settings: OperationSettings = .init()) -> Grade {
|
||||
function(values, settings)
|
||||
}
|
||||
}
|
||||
|
||||
public func || <P: FuzzyProposition, Q: FuzzyProposition> (lhs: P, rhs: Q) -> FuzzyDisjunction<(P.Input, Q.Input)> {
|
||||
.init(lhs: lhs, rhs: rhs)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyNegation<Input>: FuzzyProposition {
|
||||
|
||||
public let function: (Input, OperationSettings) -> Grade
|
||||
|
||||
public init<F: FuzzyProposition>(_ statement: F) where Input == F.Input {
|
||||
self.function = { (input, settings) -> Grade in
|
||||
settings.negation.function(statement(input, settings: settings))
|
||||
}
|
||||
}
|
||||
|
||||
public func apply(_ value: Input, settings: OperationSettings = .init()) -> Grade {
|
||||
function(value, settings)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public prefix func ! <F: FuzzyProposition>(statement: F) -> FuzzyNegation<F.Input> {
|
||||
.init(statement)
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyRule<Input>: FuzzyProposition {
|
||||
|
||||
private let function: (Input, OperationSettings) -> Grade
|
||||
|
||||
public init<P: FuzzyProposition, Q: FuzzyProposition>(antecedent: P, consequent: Q) where Input == (P.Input, Q.Input) {
|
||||
self.function = { (x, settings) -> Grade in
|
||||
settings.implication.function(
|
||||
antecedent(x.0, settings: settings),
|
||||
consequent(x.1, settings: settings)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func apply(_ values: Input, settings: OperationSettings = .init()) -> Grade {
|
||||
function(values, settings)
|
||||
}
|
||||
}
|
||||
|
||||
infix operator -->: TernaryPrecedence // lower than ==, &&, ||, etc
|
||||
public func --> <P: FuzzyProposition, Q: FuzzyProposition> (lhs: P, rhs: Q) -> FuzzyRule<(P.Input, Q.Input)> {
|
||||
.init(antecedent: lhs, consequent: rhs)
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyXOR<Input>: FuzzyProposition {
|
||||
|
||||
private let function: (Input, OperationSettings) -> Grade
|
||||
|
||||
public init<P: FuzzyProposition, Q: FuzzyProposition>(lhs: P, rhs: Q) where Input == (P.Input, Q.Input) {
|
||||
self.function = { (x, settings) -> Grade in
|
||||
settings.xor.function(
|
||||
lhs(x.0, settings: settings),
|
||||
rhs(x.1, settings: settings)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func apply(_ values: Input, settings: OperationSettings = .init()) -> Grade {
|
||||
function(values, settings)
|
||||
}
|
||||
}
|
||||
|
||||
infix operator ^^: ComparisonPrecedence
|
||||
public func ^^ <P: FuzzyProposition, Q: FuzzyProposition> (lhs: P, rhs: Q) -> FuzzyXOR<(P.Input, Q.Input)> {
|
||||
.init(lhs: lhs, rhs: rhs)
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
import FuzzySets
|
||||
|
||||
public protocol FuzzyProposition {
|
||||
associatedtype U
|
||||
func apply(_ u: U, settings: OperationSettings) -> Grade
|
||||
}
|
||||
|
||||
public extension FuzzyProposition {
|
||||
func callAsFunction(_ u: U, settings: OperationSettings = .init()) -> Grade {
|
||||
apply(u, settings: settings)
|
||||
}
|
||||
}
|
||||
|
||||
extension AnyFuzzySet: FuzzyProposition {
|
||||
public func apply(_ u: Universe, settings: OperationSettings) -> Grade {
|
||||
grade(forElement: u)
|
||||
}
|
||||
}
|
||||
|
||||
extension IterableFuzzySet: FuzzyProposition {
|
||||
public func apply(_ u: Universe, settings: OperationSettings) -> Grade {
|
||||
grade(forElement: u)
|
||||
}
|
||||
}
|
||||
|
||||
extension DiscreteMutableFuzzySet: FuzzyProposition {
|
||||
public func apply(_ u: Universe, settings: OperationSettings) -> Grade {
|
||||
grade(forElement: u)
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyConjunction<A: FuzzyProposition, B: FuzzyProposition>: FuzzyProposition {
|
||||
|
||||
public let first: A
|
||||
public let second: B
|
||||
|
||||
public init(_ first: A, _ second: B) {
|
||||
self.first = first
|
||||
self.second = second
|
||||
}
|
||||
|
||||
public func apply(_ values: (A.U, B.U), settings: OperationSettings = .init()) -> Grade {
|
||||
settings.conjunction.function(
|
||||
first(values.0, settings: settings),
|
||||
second(values.1, settings: settings)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func && <A: FuzzyProposition, B: FuzzyProposition>(lhs: A, rhs: B) -> FuzzyConjunction<A, B> {
|
||||
.init(lhs, rhs)
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyDisjunction<A: FuzzyProposition, B: FuzzyProposition>: FuzzyProposition {
|
||||
|
||||
public let first: A
|
||||
public let second: B
|
||||
|
||||
public init(_ first: A, _ second: B) {
|
||||
self.first = first
|
||||
self.second = second
|
||||
}
|
||||
|
||||
public func apply(_ values: (A.U, B.U), settings: OperationSettings = .init()) -> Grade {
|
||||
settings.disjunction.function(
|
||||
first(values.0, settings: settings),
|
||||
second(values.1, settings: settings)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func || <A: FuzzyProposition, B: FuzzyProposition>(lhs: A, rhs: B) -> FuzzyDisjunction<A, B> {
|
||||
.init(lhs, rhs)
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyNegation<FS: FuzzyProposition>: FuzzyProposition {
|
||||
|
||||
public let statement: FS
|
||||
|
||||
public init(_ statement: FS) {
|
||||
self.statement = statement
|
||||
}
|
||||
|
||||
public func apply(_ value: FS.U, settings: OperationSettings = .init()) -> Grade {
|
||||
settings.negation.function(statement(value, settings: settings))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public prefix func ! <FS: FuzzyProposition>(statement: FS) -> FuzzyNegation<FS> {
|
||||
.init(statement)
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyRule<P: FuzzyProposition, Q: FuzzyProposition>: FuzzyProposition {
|
||||
public let antecedent: P
|
||||
public let consequent: Q
|
||||
|
||||
public init(antecedent: P, consequent: Q) {
|
||||
self.antecedent = antecedent
|
||||
self.consequent = consequent
|
||||
}
|
||||
|
||||
public func apply(_ values: (P.U, Q.U), settings: OperationSettings = .init()) -> Grade {
|
||||
settings.implication.function(
|
||||
antecedent(values.0, settings: settings),
|
||||
consequent(values.1, settings: settings)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
infix operator -->: TernaryPrecedence // lower than ==, &&, ||, etc
|
||||
public func --> <P: FuzzyProposition, Q: FuzzyProposition> (lhs: P, rhs: Q) -> FuzzyRule<P, Q> {
|
||||
.init(antecedent: lhs, consequent: rhs)
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import FuzzySets
|
||||
|
||||
public struct FuzzyXOR<A: FuzzyProposition, B: FuzzyProposition>: FuzzyProposition {
|
||||
|
||||
public let first: A
|
||||
public let second: B
|
||||
|
||||
public init(_ first: A, _ second: B) {
|
||||
self.first = first
|
||||
self.second = second
|
||||
}
|
||||
|
||||
public func apply(_ values: (A.U, B.U), settings: OperationSettings = .init()) -> Grade {
|
||||
settings.xor.function(
|
||||
first(values.0, settings: settings),
|
||||
second(values.1, settings: settings)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
infix operator ^^: ComparisonPrecedence
|
||||
public func ^^ <A: FuzzyProposition, B: FuzzyProposition>(lhs: A, rhs: B) -> FuzzyXOR<A, B> {
|
||||
.init(lhs, rhs)
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
import FuzzySets
|
||||
|
||||
open class ReasoningScheme {
|
||||
// TODO
|
||||
}
|
Loading…
Reference in New Issue