summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes 'josch' Schauer <josch@debian.org>2019-01-27 13:56:24 +0100
committerJohannes 'josch' Schauer <josch@debian.org>2019-01-27 13:56:33 +0100
commit6ce553563bc795f389f639a3a8cdfe356de71441 (patch)
treeda4c9ede3087ca534d93bc1ac5a14f044f036600
parentbbefa170378553e5a6e0d72e4d52328b61f3e8ac (diff)
new upstream version 6.0
-rw-r--r--.dockerignore93
-rw-r--r--.gitignore128
-rw-r--r--.travis.yml327
-rw-r--r--CHANGELOG220
-rw-r--r--COPYING53
-rw-r--r--COPYING.LESSER165
-rw-r--r--ChangeLog231
-rw-r--r--Dockerfile22
-rw-r--r--Doxyfile2397
-rw-r--r--LICENSE827
-rw-r--r--LICENSE.FuzzyLite634
-rw-r--r--NEWS321
-rw-r--r--README.md642
-rw-r--r--THANKS22
-rw-r--r--appveyor.yml40
-rw-r--r--documentation/ui/figure.R491
-rw-r--r--documentation/ui/figure/bell.svg260
-rw-r--r--documentation/ui/figure/binary.svg261
-rw-r--r--documentation/ui/figure/concave.svg253
-rw-r--r--documentation/ui/figure/cosine.svg260
-rw-r--r--documentation/ui/figure/discrete.svg310
-rw-r--r--documentation/ui/figure/gaussian.svg260
-rw-r--r--documentation/ui/figure/gaussianProduct.svg264
-rw-r--r--documentation/ui/figure/piShape.svg260
-rw-r--r--documentation/ui/figure/power.svg227
-rw-r--r--documentation/ui/figure/ramp.svg261
-rw-r--r--documentation/ui/figure/rectangle.svg260
-rw-r--r--documentation/ui/figure/sShape.svg260
-rw-r--r--documentation/ui/figure/sigmoid.svg261
-rw-r--r--documentation/ui/figure/sigmoidDifference.svg260
-rw-r--r--documentation/ui/figure/sigmoidProduct.svg252
-rw-r--r--documentation/ui/figure/spike.svg260
-rw-r--r--documentation/ui/figure/terms.svg4955
-rw-r--r--documentation/ui/figure/trapezoid.svg260
-rw-r--r--documentation/ui/figure/triangle.svg260
-rw-r--r--documentation/ui/figure/zShape.svg260
-rw-r--r--documentation/ui/footer.html22
-rw-r--r--documentation/ui/header.html77
-rw-r--r--documentation/ui/image/android-chrome-144x144.pngbin0 -> 6532 bytes
-rw-r--r--documentation/ui/image/android-chrome-192x192.pngbin0 -> 8956 bytes
-rw-r--r--documentation/ui/image/android-chrome-36x36.pngbin0 -> 1735 bytes
-rw-r--r--documentation/ui/image/android-chrome-48x48.pngbin0 -> 2280 bytes
-rw-r--r--documentation/ui/image/android-chrome-72x72.pngbin0 -> 3171 bytes
-rw-r--r--documentation/ui/image/android-chrome-96x96.pngbin0 -> 4447 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-114x114.pngbin0 -> 6890 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-120x120.pngbin0 -> 7417 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-144x144.pngbin0 -> 8862 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-152x152.pngbin0 -> 9766 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-180x180.pngbin0 -> 11090 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-57x57.pngbin0 -> 3699 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-60x60.pngbin0 -> 3861 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-72x72.pngbin0 -> 4563 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-76x76.pngbin0 -> 5054 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon-precomposed.pngbin0 -> 12911 bytes
-rw-r--r--documentation/ui/image/apple-touch-icon.pngbin0 -> 11090 bytes
-rw-r--r--documentation/ui/image/browserconfig.xml12
-rw-r--r--documentation/ui/image/favicon-16x16.pngbin0 -> 813 bytes
-rw-r--r--documentation/ui/image/favicon-32x32.pngbin0 -> 1502 bytes
-rw-r--r--documentation/ui/image/favicon-96x96.pngbin0 -> 4447 bytes
-rw-r--r--documentation/ui/image/favicon.icobin0 -> 15086 bytes
-rw-r--r--documentation/ui/image/manifest.json41
-rw-r--r--documentation/ui/image/mstile-144x144.pngbin0 -> 6557 bytes
-rw-r--r--documentation/ui/image/mstile-150x150.pngbin0 -> 6806 bytes
-rw-r--r--documentation/ui/image/mstile-310x150.pngbin0 -> 7390 bytes
-rw-r--r--documentation/ui/image/mstile-310x310.pngbin0 -> 14321 bytes
-rw-r--r--documentation/ui/image/mstile-70x70.pngbin0 -> 4487 bytes
-rw-r--r--documentation/ui/image/safari-pinned-tab.svg28
-rw-r--r--documentation/ui/stylesheet.css0
-rw-r--r--examples/application/CMakeLists.txt140
-rwxr-xr-xexamples/application/clean.sh1
-rw-r--r--examples/application/compile.bat24
-rwxr-xr-xexamples/application/compile.sh25
-rw-r--r--examples/application/src/main.cpp16
-rw-r--r--examples/examples.R16
-rwxr-xr-xexamples/examples.matbin1062107 -> 0 bytes
-rw-r--r--examples/hybrid/ObstacleAvoidance.R86
-rw-r--r--examples/hybrid/ObstacleAvoidance.cpp75
-rw-r--r--examples/hybrid/ObstacleAvoidance.fcl49
-rw-r--r--examples/hybrid/ObstacleAvoidance.fis43
-rw-r--r--examples/hybrid/ObstacleAvoidance.fld1025
-rw-r--r--examples/hybrid/ObstacleAvoidance.fll43
-rw-r--r--examples/hybrid/ObstacleAvoidance.java86
-rw-r--r--examples/hybrid/ObstacleAvoidance.pdfbin0 -> 45584 bytes
-rw-r--r--examples/hybrid/tipper.R109
-rw-r--r--examples/hybrid/tipper.cpp92
-rw-r--r--examples/hybrid/tipper.fcl66
-rw-r--r--examples/hybrid/tipper.fis57
-rw-r--r--examples/hybrid/tipper.fld1025
-rw-r--r--examples/hybrid/tipper.fll63
-rw-r--r--examples/hybrid/tipper.java103
-rw-r--r--examples/hybrid/tipper.pdfbin0 -> 32309 bytes
-rw-r--r--examples/mamdani/AllTerms.R111
-rw-r--r--examples/mamdani/AllTerms.cpp164
-rw-r--r--examples/mamdani/AllTerms.fcl4
-rw-r--r--examples/mamdani/AllTerms.fis5
-rw-r--r--examples/mamdani/AllTerms.fld2051
-rw-r--r--examples/mamdani/AllTerms.fll10
-rw-r--r--examples/mamdani/AllTerms.java125
-rw-r--r--examples/mamdani/AllTerms.pdfbin0 -> 24280 bytes
-rw-r--r--examples/mamdani/Laundry.R91
-rw-r--r--examples/mamdani/Laundry.cpp105
-rw-r--r--examples/mamdani/Laundry.fcl20
-rw-r--r--examples/mamdani/Laundry.fis51
-rw-r--r--examples/mamdani/Laundry.fld2051
-rw-r--r--examples/mamdani/Laundry.fll31
-rw-r--r--examples/mamdani/Laundry.java106
-rw-r--r--examples/mamdani/Laundry.pdfbin0 -> 30166 bytes
-rw-r--r--examples/mamdani/ObstacleAvoidance.R57
-rw-r--r--examples/mamdani/ObstacleAvoidance.cpp49
-rw-r--r--examples/mamdani/ObstacleAvoidance.fcl34
-rw-r--r--examples/mamdani/ObstacleAvoidance.fis32
-rw-r--r--examples/mamdani/ObstacleAvoidance.fld1025
-rw-r--r--examples/mamdani/ObstacleAvoidance.fll25
-rw-r--r--examples/mamdani/ObstacleAvoidance.java60
-rw-r--r--examples/mamdani/ObstacleAvoidance.pdfbin0 -> 25210 bytes
-rw-r--r--examples/mamdani/SimpleDimmer.R60
-rw-r--r--examples/mamdani/SimpleDimmer.cpp66
-rw-r--r--examples/mamdani/SimpleDimmer.fcl4
-rw-r--r--examples/mamdani/SimpleDimmer.fis9
-rw-r--r--examples/mamdani/SimpleDimmer.fld2051
-rw-r--r--examples/mamdani/SimpleDimmer.fll10
-rw-r--r--examples/mamdani/SimpleDimmer.java57
-rw-r--r--examples/mamdani/SimpleDimmer.pdfbin0 -> 22872 bytes
-rw-r--r--examples/mamdani/SimpleDimmerChained.R85
-rw-r--r--examples/mamdani/SimpleDimmerChained.cpp70
-rw-r--r--examples/mamdani/SimpleDimmerChained.fcl51
-rw-r--r--examples/mamdani/SimpleDimmerChained.fis46
-rw-r--r--examples/mamdani/SimpleDimmerChained.fld1025
-rw-r--r--examples/mamdani/SimpleDimmerChained.fll14
-rw-r--r--examples/mamdani/SimpleDimmerChained.java81
-rw-r--r--examples/mamdani/SimpleDimmerChained.pdfbin0 -> 42431 bytes
-rw-r--r--examples/mamdani/SimpleDimmerInverse.R85
-rw-r--r--examples/mamdani/SimpleDimmerInverse.cpp105
-rw-r--r--examples/mamdani/SimpleDimmerInverse.fcl4
-rw-r--r--examples/mamdani/SimpleDimmerInverse.fis46
-rw-r--r--examples/mamdani/SimpleDimmerInverse.fld2051
-rw-r--r--examples/mamdani/SimpleDimmerInverse.fll14
-rw-r--r--examples/mamdani/SimpleDimmerInverse.java84
-rw-r--r--examples/mamdani/SimpleDimmerInverse.pdfbin0 -> 41795 bytes
-rw-r--r--examples/mamdani/octave/investment_portfolio.R67
-rw-r--r--examples/mamdani/octave/investment_portfolio.cpp84
-rw-r--r--examples/mamdani/octave/investment_portfolio.fcl4
-rw-r--r--examples/mamdani/octave/investment_portfolio.fis5
-rw-r--r--examples/mamdani/octave/investment_portfolio.fld2051
-rw-r--r--examples/mamdani/octave/investment_portfolio.fll11
-rw-r--r--examples/mamdani/octave/investment_portfolio.java77
-rw-r--r--examples/mamdani/octave/investment_portfolio.pdfbin0 -> 19163 bytes
-rw-r--r--examples/mamdani/octave/mamdani_tip_calculator.R90
-rw-r--r--examples/mamdani/octave/mamdani_tip_calculator.cpp105
-rw-r--r--examples/mamdani/octave/mamdani_tip_calculator.fcl4
-rw-r--r--examples/mamdani/octave/mamdani_tip_calculator.fis7
-rw-r--r--examples/mamdani/octave/mamdani_tip_calculator.fld2051
-rw-r--r--examples/mamdani/octave/mamdani_tip_calculator.fll15
-rw-r--r--examples/mamdani/octave/mamdani_tip_calculator.java98
-rw-r--r--examples/mamdani/octave/mamdani_tip_calculator.pdfbin0 -> 31675 bytes
-rw-r--r--examples/original/mamdani/AllTerms.fll9
-rw-r--r--examples/original/mamdani/Laundry.fll9
-rw-r--r--examples/original/mamdani/SimpleDimmer.fll9
-rw-r--r--examples/original/mamdani/SimpleDimmerInverse.fll11
-rw-r--r--examples/original/mamdani/octave/investment_portfolio.fll9
-rw-r--r--examples/original/mamdani/octave/mamdani_tip_calculator.fll11
-rw-r--r--examples/original/takagi-sugeno/SimpleDimmer.fll7
-rw-r--r--examples/original/takagi-sugeno/approximation.fll11
-rw-r--r--examples/original/takagi-sugeno/octave/cubic_approximator.fll7
-rw-r--r--examples/original/takagi-sugeno/octave/heart_disease_risk.fll7
-rw-r--r--examples/original/takagi-sugeno/octave/linear_tip_calculator.fll7
-rw-r--r--examples/original/takagi-sugeno/octave/sugeno_tip_calculator.fll11
-rw-r--r--examples/original/tsukamoto/tsukamoto.fll15
-rw-r--r--examples/takagi-sugeno/ObstacleAvoidance.R57
-rw-r--r--examples/takagi-sugeno/ObstacleAvoidance.cpp49
-rw-r--r--examples/takagi-sugeno/ObstacleAvoidance.fcl33
-rw-r--r--examples/takagi-sugeno/ObstacleAvoidance.fis32
-rw-r--r--examples/takagi-sugeno/ObstacleAvoidance.fld1025
-rw-r--r--examples/takagi-sugeno/ObstacleAvoidance.fll25
-rw-r--r--examples/takagi-sugeno/ObstacleAvoidance.java60
-rw-r--r--examples/takagi-sugeno/ObstacleAvoidance.pdfbin0 -> 25090 bytes
-rw-r--r--examples/takagi-sugeno/SimpleDimmer.R60
-rw-r--r--examples/takagi-sugeno/SimpleDimmer.cpp66
-rw-r--r--examples/takagi-sugeno/SimpleDimmer.fcl4
-rw-r--r--examples/takagi-sugeno/SimpleDimmer.fis13
-rw-r--r--examples/takagi-sugeno/SimpleDimmer.fld2051
-rw-r--r--examples/takagi-sugeno/SimpleDimmer.fll10
-rw-r--r--examples/takagi-sugeno/SimpleDimmer.java57
-rw-r--r--examples/takagi-sugeno/SimpleDimmer.pdfbin0 -> 22975 bytes
-rw-r--r--examples/takagi-sugeno/approximation.R119
-rw-r--r--examples/takagi-sugeno/approximation.cpp146
-rw-r--r--examples/takagi-sugeno/approximation.fcl4
-rw-r--r--examples/takagi-sugeno/approximation.fis15
-rw-r--r--examples/takagi-sugeno/approximation.fld2051
-rw-r--r--examples/takagi-sugeno/approximation.fll18
-rw-r--r--examples/takagi-sugeno/approximation.java127
-rw-r--r--examples/takagi-sugeno/approximation.pdfbin0 -> 65783 bytes
-rw-r--r--examples/takagi-sugeno/octave/cubic_approximator.R84
-rw-r--r--examples/takagi-sugeno/octave/cubic_approximator.cpp110
-rw-r--r--examples/takagi-sugeno/octave/cubic_approximator.fcl4
-rw-r--r--examples/takagi-sugeno/octave/cubic_approximator.fis13
-rw-r--r--examples/takagi-sugeno/octave/cubic_approximator.fld2051
-rw-r--r--examples/takagi-sugeno/octave/cubic_approximator.fll10
-rw-r--r--examples/takagi-sugeno/octave/cubic_approximator.java89
-rw-r--r--examples/takagi-sugeno/octave/cubic_approximator.pdfbin0 -> 24950 bytes
-rw-r--r--examples/takagi-sugeno/octave/heart_disease_risk.R84
-rw-r--r--examples/takagi-sugeno/octave/heart_disease_risk.cpp112
-rw-r--r--examples/takagi-sugeno/octave/heart_disease_risk.fcl4
-rw-r--r--examples/takagi-sugeno/octave/heart_disease_risk.fis11
-rw-r--r--examples/takagi-sugeno/octave/heart_disease_risk.fld2051
-rw-r--r--examples/takagi-sugeno/octave/heart_disease_risk.fll11
-rw-r--r--examples/takagi-sugeno/octave/heart_disease_risk.java83
-rw-r--r--examples/takagi-sugeno/octave/heart_disease_risk.pdfbin0 -> 16865 bytes
-rw-r--r--examples/takagi-sugeno/octave/linear_tip_calculator.R67
-rw-r--r--examples/takagi-sugeno/octave/linear_tip_calculator.cpp84
-rw-r--r--examples/takagi-sugeno/octave/linear_tip_calculator.fcl4
-rw-r--r--examples/takagi-sugeno/octave/linear_tip_calculator.fis11
-rw-r--r--examples/takagi-sugeno/octave/linear_tip_calculator.fld2051
-rw-r--r--examples/takagi-sugeno/octave/linear_tip_calculator.fll11
-rw-r--r--examples/takagi-sugeno/octave/linear_tip_calculator.java77
-rw-r--r--examples/takagi-sugeno/octave/linear_tip_calculator.pdfbin0 -> 18236 bytes
-rw-r--r--examples/takagi-sugeno/octave/sugeno_tip_calculator.R119
-rw-r--r--examples/takagi-sugeno/octave/sugeno_tip_calculator.cpp144
-rw-r--r--examples/takagi-sugeno/octave/sugeno_tip_calculator.fcl4
-rw-r--r--examples/takagi-sugeno/octave/sugeno_tip_calculator.fis11
-rw-r--r--examples/takagi-sugeno/octave/sugeno_tip_calculator.fld2051
-rw-r--r--examples/takagi-sugeno/octave/sugeno_tip_calculator.fll19
-rw-r--r--examples/takagi-sugeno/octave/sugeno_tip_calculator.java125
-rw-r--r--examples/takagi-sugeno/octave/sugeno_tip_calculator.pdfbin0 -> 41451 bytes
-rw-r--r--examples/tsukamoto/tsukamoto.R126
-rw-r--r--examples/tsukamoto/tsukamoto.cpp143
-rw-r--r--examples/tsukamoto/tsukamoto.fcl4
-rw-r--r--examples/tsukamoto/tsukamoto.fis13
-rw-r--r--examples/tsukamoto/tsukamoto.fld2051
-rw-r--r--examples/tsukamoto/tsukamoto.fll22
-rw-r--r--examples/tsukamoto/tsukamoto.java138
-rw-r--r--examples/tsukamoto/tsukamoto.pdfbin0 -> 85574 bytes
-rw-r--r--fuzzylite.pngbin2883 -> 262929 bytes
-rw-r--r--fuzzylite.svg42
-rw-r--r--fuzzylite/CMakeLists.txt163
-rw-r--r--fuzzylite/FL_HEADERS21
-rw-r--r--fuzzylite/FL_SOURCES23
-rw-r--r--fuzzylite/FL_TESTS16
-rw-r--r--fuzzylite/build.bat35
-rwxr-xr-xfuzzylite/build.sh42
-rw-r--r--fuzzylite/fl/Benchmark.h400
-rw-r--r--fuzzylite/fl/Complexity.h297
-rw-r--r--fuzzylite/fl/Console.h143
-rw-r--r--fuzzylite/fl/Engine.h428
-rw-r--r--fuzzylite/fl/Exception.h110
-rw-r--r--fuzzylite/fl/Headers.h49
-rw-r--r--fuzzylite/fl/Operation.h1011
-rw-r--r--fuzzylite/fl/activation/Activation.h95
-rw-r--r--fuzzylite/fl/activation/First.h104
-rw-r--r--fuzzylite/fl/activation/General.h73
-rw-r--r--fuzzylite/fl/activation/Highest.h86
-rw-r--r--fuzzylite/fl/activation/Last.h103
-rw-r--r--fuzzylite/fl/activation/Lowest.h87
-rw-r--r--fuzzylite/fl/activation/Proportional.h71
-rw-r--r--fuzzylite/fl/activation/Threshold.h183
-rw-r--r--fuzzylite/fl/defuzzifier/Bisector.h47
-rw-r--r--fuzzylite/fl/defuzzifier/Centroid.h48
-rw-r--r--fuzzylite/fl/defuzzifier/Defuzzifier.h59
-rw-r--r--fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h62
-rw-r--r--fuzzylite/fl/defuzzifier/LargestOfMaximum.h50
-rw-r--r--fuzzylite/fl/defuzzifier/MeanOfMaximum.h49
-rw-r--r--fuzzylite/fl/defuzzifier/SmallestOfMaximum.h49
-rw-r--r--fuzzylite/fl/defuzzifier/WeightedAverage.h51
-rw-r--r--fuzzylite/fl/defuzzifier/WeightedAverageCustom.h77
-rw-r--r--fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h81
-rw-r--r--fuzzylite/fl/defuzzifier/WeightedSum.h51
-rw-r--r--fuzzylite/fl/defuzzifier/WeightedSumCustom.h78
-rw-r--r--fuzzylite/fl/factory/ActivationFactory.h46
-rw-r--r--fuzzylite/fl/factory/CloningFactory.h198
-rw-r--r--fuzzylite/fl/factory/ConstructionFactory.h180
-rw-r--r--fuzzylite/fl/factory/DefuzzifierFactory.h56
-rw-r--r--fuzzylite/fl/factory/FactoryManager.h131
-rw-r--r--fuzzylite/fl/factory/FunctionFactory.h44
-rw-r--r--fuzzylite/fl/factory/HedgeFactory.h32
-rw-r--r--fuzzylite/fl/factory/SNormFactory.h32
-rw-r--r--fuzzylite/fl/factory/TNormFactory.h32
-rw-r--r--fuzzylite/fl/factory/TermFactory.h32
-rw-r--r--fuzzylite/fl/fuzzylite.h341
-rw-r--r--fuzzylite/fl/hedge/Any.h47
-rw-r--r--fuzzylite/fl/hedge/Extremely.h53
-rw-r--r--fuzzylite/fl/hedge/Hedge.h56
-rw-r--r--fuzzylite/fl/hedge/HedgeFunction.h82
-rw-r--r--fuzzylite/fl/hedge/Not.h43
-rw-r--r--fuzzylite/fl/hedge/Seldom.h48
-rw-r--r--fuzzylite/fl/hedge/Somewhat.h44
-rw-r--r--fuzzylite/fl/hedge/Very.h42
-rw-r--r--fuzzylite/fl/imex/CppExporter.h139
-rw-r--r--fuzzylite/fl/imex/Exporter.h52
-rw-r--r--fuzzylite/fl/imex/FclExporter.h79
-rw-r--r--fuzzylite/fl/imex/FclImporter.h32
-rw-r--r--fuzzylite/fl/imex/FisExporter.h87
-rw-r--r--fuzzylite/fl/imex/FisImporter.h47
-rw-r--r--fuzzylite/fl/imex/FldExporter.h218
-rw-r--r--fuzzylite/fl/imex/FllExporter.h119
-rw-r--r--fuzzylite/fl/imex/FllImporter.h48
-rw-r--r--fuzzylite/fl/imex/Importer.h53
-rw-r--r--fuzzylite/fl/imex/JavaExporter.h124
-rw-r--r--fuzzylite/fl/imex/RScriptExporter.h246
-rw-r--r--fuzzylite/fl/norm/Norm.h56
-rw-r--r--fuzzylite/fl/norm/SNorm.h36
-rw-r--r--fuzzylite/fl/norm/TNorm.h35
-rw-r--r--fuzzylite/fl/norm/s/AlgebraicSum.h49
-rw-r--r--fuzzylite/fl/norm/s/BoundedSum.h45
-rw-r--r--fuzzylite/fl/norm/s/DrasticSum.h50
-rw-r--r--fuzzylite/fl/norm/s/EinsteinSum.h46
-rw-r--r--fuzzylite/fl/norm/s/HamacherSum.h46
-rw-r--r--fuzzylite/fl/norm/s/Maximum.h46
-rw-r--r--fuzzylite/fl/norm/s/NilpotentMaximum.h47
-rw-r--r--fuzzylite/fl/norm/s/NormalizedSum.h44
-rw-r--r--fuzzylite/fl/norm/s/SNormFunction.h81
-rw-r--r--fuzzylite/fl/norm/s/UnboundedSum.h52
-rw-r--r--fuzzylite/fl/norm/t/AlgebraicProduct.h47
-rw-r--r--fuzzylite/fl/norm/t/BoundedDifference.h46
-rw-r--r--fuzzylite/fl/norm/t/DrasticProduct.h50
-rw-r--r--fuzzylite/fl/norm/t/EinsteinProduct.h47
-rw-r--r--fuzzylite/fl/norm/t/HamacherProduct.h46
-rw-r--r--fuzzylite/fl/norm/t/Minimum.h45
-rw-r--r--fuzzylite/fl/norm/t/NilpotentMinimum.h48
-rw-r--r--fuzzylite/fl/norm/t/TNormFunction.h81
-rw-r--r--fuzzylite/fl/rule/Antecedent.h150
-rw-r--r--fuzzylite/fl/rule/Consequent.h116
-rw-r--r--fuzzylite/fl/rule/Expression.h93
-rw-r--r--fuzzylite/fl/rule/Rule.h264
-rw-r--r--fuzzylite/fl/rule/RuleBlock.h194
-rw-r--r--fuzzylite/fl/term/Accumulated.h94
-rw-r--r--fuzzylite/fl/term/Activated.h84
-rw-r--r--fuzzylite/fl/term/Aggregated.h212
-rw-r--r--fuzzylite/fl/term/Bell.h80
-rw-r--r--fuzzylite/fl/term/Binary.h132
-rw-r--r--fuzzylite/fl/term/Concave.h84
-rw-r--r--fuzzylite/fl/term/Constant.h57
-rw-r--r--fuzzylite/fl/term/Cosine.h75
-rw-r--r--fuzzylite/fl/term/Discrete.h245
-rw-r--r--fuzzylite/fl/term/Function.h312
-rw-r--r--fuzzylite/fl/term/Gaussian.h74
-rw-r--r--fuzzylite/fl/term/GaussianProduct.h101
-rw-r--r--fuzzylite/fl/term/Linear.h151
-rw-r--r--fuzzylite/fl/term/PiShape.h105
-rw-r--r--fuzzylite/fl/term/Ramp.h101
-rw-r--r--fuzzylite/fl/term/Rectangle.h74
-rw-r--r--fuzzylite/fl/term/SShape.h81
-rw-r--r--fuzzylite/fl/term/Sigmoid.h88
-rw-r--r--fuzzylite/fl/term/SigmoidDifference.h90
-rw-r--r--fuzzylite/fl/term/SigmoidProduct.h91
-rw-r--r--fuzzylite/fl/term/Spike.h70
-rw-r--r--fuzzylite/fl/term/Term.h136
-rw-r--r--fuzzylite/fl/term/Trapezoid.h94
-rw-r--r--fuzzylite/fl/term/Triangle.h84
-rw-r--r--fuzzylite/fl/term/ZShape.h80
-rw-r--r--fuzzylite/fl/variable/InputVariable.h48
-rw-r--r--fuzzylite/fl/variable/OutputVariable.h214
-rw-r--r--fuzzylite/fl/variable/Variable.h254
-rw-r--r--fuzzylite/fuzzylite.doxygen1781
-rw-r--r--fuzzylite/fuzzylite.pc.in4
-rw-r--r--fuzzylite/src/Benchmark.cpp460
-rw-r--r--fuzzylite/src/Complexity.cpp283
-rw-r--r--fuzzylite/src/Console.cpp809
-rw-r--r--fuzzylite/src/Engine.cpp418
-rw-r--r--fuzzylite/src/Exception.cpp89
-rw-r--r--fuzzylite/src/Operation.cpp477
-rw-r--r--fuzzylite/src/activation/First.cpp122
-rw-r--r--fuzzylite/src/activation/General.cpp77
-rw-r--r--fuzzylite/src/activation/Highest.cpp120
-rw-r--r--fuzzylite/src/activation/Last.cpp121
-rw-r--r--fuzzylite/src/activation/Lowest.cpp122
-rw-r--r--fuzzylite/src/activation/Proportional.cpp91
-rw-r--r--fuzzylite/src/activation/Threshold.cpp170
-rw-r--r--fuzzylite/src/defuzzifier/Bisector.cpp59
-rw-r--r--fuzzylite/src/defuzzifier/Centroid.cpp66
-rw-r--r--fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp31
-rw-r--r--fuzzylite/src/defuzzifier/LargestOfMaximum.cpp48
-rw-r--r--fuzzylite/src/defuzzifier/MeanOfMaximum.cpp53
-rw-r--r--fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp50
-rw-r--r--fuzzylite/src/defuzzifier/WeightedAverage.cpp119
-rw-r--r--fuzzylite/src/defuzzifier/WeightedAverageCustom.cpp117
-rw-r--r--fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp130
-rw-r--r--fuzzylite/src/defuzzifier/WeightedSum.cpp116
-rw-r--r--fuzzylite/src/defuzzifier/WeightedSumCustom.cpp112
-rw-r--r--fuzzylite/src/factory/ActivationFactory.cpp42
-rw-r--r--fuzzylite/src/factory/CloningFactory.cpp135
-rw-r--r--fuzzylite/src/factory/ConstructionFactory.cpp114
-rw-r--r--fuzzylite/src/factory/DefuzzifierFactory.cpp31
-rw-r--r--fuzzylite/src/factory/FactoryManager.cpp72
-rw-r--r--fuzzylite/src/factory/FunctionFactory.cpp129
-rw-r--r--fuzzylite/src/factory/HedgeFactory.cpp27
-rw-r--r--fuzzylite/src/factory/SNormFactory.cpp29
-rw-r--r--fuzzylite/src/factory/TNormFactory.cpp27
-rw-r--r--fuzzylite/src/factory/TermFactory.cpp31
-rw-r--r--fuzzylite/src/fuzzylite.cpp101
-rw-r--r--fuzzylite/src/hedge/Any.cpp35
-rw-r--r--fuzzylite/src/hedge/Extremely.cpp30
-rw-r--r--fuzzylite/src/hedge/HedgeFunction.cpp63
-rw-r--r--fuzzylite/src/hedge/Not.cpp27
-rw-r--r--fuzzylite/src/hedge/Seldom.cpp31
-rw-r--r--fuzzylite/src/hedge/Somewhat.cpp26
-rw-r--r--fuzzylite/src/hedge/Very.cpp26
-rw-r--r--fuzzylite/src/imex/CppExporter.cpp181
-rw-r--r--fuzzylite/src/imex/Exporter.cpp32
-rw-r--r--fuzzylite/src/imex/FclExporter.cpp126
-rw-r--r--fuzzylite/src/imex/FclImporter.cpp164
-rw-r--r--fuzzylite/src/imex/FisExporter.cpp180
-rw-r--r--fuzzylite/src/imex/FisImporter.cpp235
-rw-r--r--fuzzylite/src/imex/FldExporter.cpp246
-rw-r--r--fuzzylite/src/imex/FllExporter.cpp85
-rw-r--r--fuzzylite/src/imex/FllImporter.cpp193
-rw-r--r--fuzzylite/src/imex/Importer.cpp32
-rw-r--r--fuzzylite/src/imex/JavaExporter.cpp157
-rw-r--r--fuzzylite/src/imex/RScriptExporter.cpp234
-rwxr-xr-xfuzzylite/src/m/compare.m60
-rwxr-xr-xfuzzylite/src/m/compare_examples.m45
-rw-r--r--fuzzylite/src/main.cpp73
-rw-r--r--fuzzylite/src/norm/s/AlgebraicSum.cpp26
-rw-r--r--fuzzylite/src/norm/s/BoundedSum.cpp28
-rw-r--r--fuzzylite/src/norm/s/DrasticSum.cpp28
-rw-r--r--fuzzylite/src/norm/s/EinsteinSum.cpp26
-rw-r--r--fuzzylite/src/norm/s/HamacherSum.cpp29
-rw-r--r--fuzzylite/src/norm/s/Maximum.cpp28
-rw-r--r--fuzzylite/src/norm/s/NilpotentMaximum.cpp32
-rw-r--r--fuzzylite/src/norm/s/NormalizedSum.cpp31
-rw-r--r--fuzzylite/src/norm/s/SNormFunction.cpp65
-rw-r--r--fuzzylite/src/norm/s/UnboundedSum.cpp43
-rw-r--r--fuzzylite/src/norm/t/AlgebraicProduct.cpp26
-rw-r--r--fuzzylite/src/norm/t/BoundedDifference.cpp27
-rw-r--r--fuzzylite/src/norm/t/DrasticProduct.cpp28
-rw-r--r--fuzzylite/src/norm/t/EinsteinProduct.cpp26
-rw-r--r--fuzzylite/src/norm/t/HamacherProduct.cpp28
-rw-r--r--fuzzylite/src/norm/t/Minimum.cpp28
-rw-r--r--fuzzylite/src/norm/t/NilpotentMinimum.cpp29
-rw-r--r--fuzzylite/src/norm/t/TNormFunction.cpp66
-rw-r--r--fuzzylite/src/rule/Antecedent.cpp293
-rw-r--r--fuzzylite/src/rule/Consequent.cpp117
-rw-r--r--fuzzylite/src/rule/Expression.cpp48
-rw-r--r--fuzzylite/src/rule/Rule.cpp182
-rw-r--r--fuzzylite/src/rule/RuleBlock.cpp115
-rw-r--r--fuzzylite/src/term/Accumulated.cpp211
-rw-r--r--fuzzylite/src/term/Activated.cpp80
-rw-r--r--fuzzylite/src/term/Aggregated.cpp247
-rw-r--r--fuzzylite/src/term/Bell.cpp40
-rw-r--r--fuzzylite/src/term/Binary.cpp96
-rw-r--r--fuzzylite/src/term/Concave.cpp68
-rw-r--r--fuzzylite/src/term/Constant.cpp34
-rw-r--r--fuzzylite/src/term/Cosine.cpp49
-rw-r--r--fuzzylite/src/term/Discrete.cpp194
-rw-r--r--fuzzylite/src/term/Function.cpp266
-rw-r--r--fuzzylite/src/term/Gaussian.cpp48
-rw-r--r--fuzzylite/src/term/GaussianProduct.cpp59
-rw-r--r--fuzzylite/src/term/Linear.cpp94
-rw-r--r--fuzzylite/src/term/PiShape.cpp78
-rw-r--r--fuzzylite/src/term/Ramp.cpp73
-rw-r--r--fuzzylite/src/term/Rectangle.cpp44
-rw-r--r--fuzzylite/src/term/SShape.cpp74
-rw-r--r--fuzzylite/src/term/Sigmoid.cpp78
-rw-r--r--fuzzylite/src/term/SigmoidDifference.cpp44
-rw-r--r--fuzzylite/src/term/SigmoidProduct.cpp43
-rw-r--r--fuzzylite/src/term/Spike.cpp42
-rw-r--r--fuzzylite/src/term/Term.cpp55
-rw-r--r--fuzzylite/src/term/Trapezoid.cpp56
-rw-r--r--fuzzylite/src/term/Triangle.cpp58
-rw-r--r--fuzzylite/src/term/ZShape.cpp74
-rw-r--r--fuzzylite/src/variable/InputVariable.cpp44
-rw-r--r--fuzzylite/src/variable/OutputVariable.cpp185
-rw-r--r--fuzzylite/src/variable/Variable.cpp175
-rw-r--r--fuzzylite/test/BenchmarkTest.cpp131
-rw-r--r--fuzzylite/test/Catch.License23
-rw-r--r--fuzzylite/test/MainTest.cpp34
-rw-r--r--fuzzylite/test/QuickTest.cpp128
-rw-r--r--fuzzylite/test/activation/ThresholdTest.cpp65
-rw-r--r--fuzzylite/test/catch.hpp11282
-rw-r--r--fuzzylite/test/hedge/HedgeFunctionTest.cpp141
-rw-r--r--fuzzylite/test/imex/FldExporterTest.cpp45
-rw-r--r--fuzzylite/test/imex/FllImporterTest.cpp56
-rw-r--r--fuzzylite/test/imex/RScriptExporterTest.cpp103
-rw-r--r--fuzzylite/test/norm/NormFunctionTest.cpp202
-rw-r--r--fuzzylite/test/term/AggregatedTest.cpp52
-rw-r--r--fuzzylite/test/term/DiscreteTest.cpp125
-rw-r--r--fuzzylite/test/term/FunctionTest.cpp115
-rw-r--r--fuzzylite/test/term/TrapezoidTest.cpp53
-rw-r--r--fuzzylite/test/term/TriangleTest.cpp66
-rw-r--r--fuzzylite/test/variable/VariableTest.cpp74
479 files changed, 68056 insertions, 24771 deletions
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..5d73f37
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,93 @@
+#Ignore documentation to be generated by doxygen
+fuzzylite/release/
+fuzzylite/debug/
+documentation/html/
+documentation/man/
+
+# Created by https://www.gitignore.io/api/git,windows,linux,osx,netbeans,cmake
+
+### Git ###
+*.orig
+
+
+### Windows ###
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+
+### Linux ###
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+
+### OSX ###
+*.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+nbactions.xml
+.nb-gradle/
+
+
+### CMake ###
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Makefile
+cmake_install.cmake
+install_manifest.txt
+CTestTestfile.cmake \ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 0def275..fb98d86 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,83 @@
+# Created by https://www.gitignore.io
+
+### Linux ###
+*~
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+
+### Windows ###
+# Windows image file caches
+Thumbs.db
+ehthumbs.db
+
+# Folder config file
+Desktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+
+### OSX ###
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+
+### C++ ###
# Compiled Object files
*.slo
*.lo
*.o
*.obj
+# Precompiled Headers
+*.gch
+*.pch
+
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
+# Fortran module files
+*.mod
+
# Compiled Static libraries
*.lai
*.la
@@ -19,3 +88,62 @@
*.exe
*.out
*.app
+
+
+### NetBeans ###
+nbproject/
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+nbactions.xml
+nb-configuration.xml
+.nb-gradle/
+
+
+### Eclipse ###
+*.pydevproject
+.metadata
+.gradle
+bin/
+tmp/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+
+# Eclipse Core
+.project
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# CDT-specific
+.cproject
+
+# JDT-specific (Eclipse Java Development Tools)
+.classpath
+
+# PDT-specific
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# TeXlipse plugin
+.texlipse
+
+
+### CMake ###
+CMakeCache.txt
+CMakeFiles
+Makefile
+cmake_install.cmake
+install_manifest.txt
diff --git a/.travis.yml b/.travis.yml
index a22168d..71dbd88 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,144 +1,213 @@
-language: cpp
+language: generic
+dist: trusty
+sudo: required
-os:
- - linux
- - osx
+services:
+ - docker
-before_install:
-
- - if [ "$TRAVIS_OS_NAME" = "linux" ];
- then
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test;
- sudo add-apt-repository --yes ppa:h-rayflood/llvm;
- sudo add-apt-repository --yes ppa:andykimpe/cmake;
- sudo apt-get update -qq;
- sudo apt-get install -qq cmake;
- sudo apt-get install -qq $SUPPORT;
- sudo apt-get install -qq $PACKAGE;
- fi
-
- #setup compiler
- - export CC=${REAL_CC} CXX=${REAL_CXX}
+git:
+ depth: 1
+
+before_script:
+ - docker build -t fuzzylite -f Dockerfile --build-arg CXX_COMPILER=${CXX_COMPILER} .
script:
- - cd fuzzylite
- - mkdir -p $FL_CONF
- - cd $FL_CONF
- - cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=$FL_CONF -DFL_BACKTRACE=ON -DFL_USE_FLOAT=$FL_USE_FLOAT -DFL_CPP11=$FL_CPP11
- - make
+ - docker run -e CXX=${CXX_COMPILER} -e FL_CPP98=${FL_CPP98} -e FL_USE_FLOAT=${FL_USE_FLOAT} -e FL_BUILD_TESTS=ON -t fuzzylite release
+
+ - docker run -e CXX=${CXX_COMPILER} -e FL_CPP98=${FL_CPP98} -e FL_USE_FLOAT=${FL_USE_FLOAT} -e FL_BUILD_TESTS=ON -t fuzzylite debug
-env:
- - ignore=this
+ - docker run -t fuzzylite documentation
matrix:
- exclude:
- - env: ignore=this
include:
-#clang-3.2
-##Debug
- - compiler: clang
- env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=ON
-##Release
- - compiler: clang
- env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=clang-3.2 REAL_CXX=clang++-3.2 PACKAGE=clang-3.2 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=ON
-
-#clang-3.3
-##Debug
- - compiler: clang
- env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=ON
-##Release
- - compiler: clang
- env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=clang-3.3 REAL_CXX=clang++-3.3 PACKAGE=clang-3.3 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=ON
-
-#clang-3.4
-##Debug
- - compiler: clang
- env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8 FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=ON
-##Release
- - compiler: clang
- env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=clang-3.4 REAL_CXX=clang++-3.4 PACKAGE=clang-3.4 SUPPORT=g++-4.8 FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=ON
-
-
-#gcc-4.7
-##Debug
- - compiler: clang
- env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT= FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT= FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT= FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT= FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=ON
-##Release
- - compiler: clang
- env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT= FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT= FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT= FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=gcc-4.7 REAL_CXX=g++-4.7 PACKAGE=g++-4.7 SUPPORT= FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=ON
-
-#gcc-4.8
-##Debug
- - compiler: clang
- env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT= FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT= FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT= FL_CONF=Debug FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT= FL_CONF=Debug FL_USE_FLOAT=ON FL_CPP11=ON
-##Release
- - compiler: clang
- env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT= FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT= FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=OFF
- - compiler: clang
- env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT= FL_CONF=Release FL_USE_FLOAT=OFF FL_CPP11=ON
- - compiler: clang
- env: REAL_CC=gcc-4.8 REAL_CXX=g++-4.8 PACKAGE=g++-4.8 SUPPORT= FL_CONF=Release FL_USE_FLOAT=ON FL_CPP11=ON
+ # - osx:
+
+#g++-6
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-6 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-6 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-6 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-6 FL_CPP98=ON FL_USE_FLOAT=ON
+
+##clang-3.8
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.8 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.8 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.8 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.8 FL_CPP98=ON FL_USE_FLOAT=ON
+
+#g++-5
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-5 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-5 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-5 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-5 FL_CPP98=ON FL_USE_FLOAT=ON
+
+##clang-3.7
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.7 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.7 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.7 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.7 FL_CPP98=ON FL_USE_FLOAT=ON
+
+#g++-4.9
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.9 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.9 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.9 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.9 FL_CPP98=ON FL_USE_FLOAT=ON
+
+##clang-3.6
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.6 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.6 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.6 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.6 FL_CPP98=ON FL_USE_FLOAT=ON
+
+#g++-4.8
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.8 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.8 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.8 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.8 FL_CPP98=ON FL_USE_FLOAT=ON
+
+##clang-3.5
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.5 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.5 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.5 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: clang
+ env: CXX_COMPILER=clang++-3.5 FL_CPP98=ON FL_USE_FLOAT=ON
+
+#g++-4.7
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.7 FL_CPP98=OFF FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.7 FL_CPP98=OFF FL_USE_FLOAT=ON
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.7 FL_CPP98=ON FL_USE_FLOAT=OFF
+ - os: linux
+ compiler: g++
+ env: CXX_COMPILER=g++-4.7 FL_CPP98=ON FL_USE_FLOAT=ON
+
+# #clang-3.4 does not install properly in ubuntu (clang++-3.4 command not found)
+# - os: linux
+# compiler: clang
+# env: CXX_COMPILER=clang++-3.4 FL_CPP98=OFF FL_USE_FLOAT=OFF
+# - os: linux
+# compiler: clang
+# env: CXX_COMPILER=clang++-3.4 FL_CPP98=OFF FL_USE_FLOAT=ON
+# - os: linux
+# compiler: clang
+# env: CXX_COMPILER=clang++-3.4 FL_CPP98=ON FL_USE_FLOAT=OFF
+# - os: linux
+# compiler: clang
+# env: CXX_COMPILER=clang++-3.4 FL_CPP98=ON FL_USE_FLOAT=ON
+
+# #g++-4.6 does not have an installation candidate in ubuntu
+# - os: linux
+# compiler: g++
+# env: CXX_COMPILER=g++-4.6 FL_CPP98=OFF FL_USE_FLOAT=OFF
+# - os: linux
+# compiler: g++
+# env: CXX_COMPILER=g++-4.6 FL_CPP98=OFF FL_USE_FLOAT=ON
+# - os: linux
+# compiler: g++
+# env: CXX_COMPILER=g++-4.6 FL_CPP98=ON FL_USE_FLOAT=OFF
+# - os: linux
+# compiler: g++
+# env: CXX_COMPILER=g++-4.6 FL_CPP98=ON FL_USE_FLOAT=ON
+
+
+# #clang-3.3 does not install properly in ubuntu (clang++-3.4 command not found)
+# - os: linux
+# compiler: clang
+# env: CXX_COMPILER=clang++-3.3 FL_CPP98=OFF FL_USE_FLOAT=OFF
+# - os: linux
+# compiler: clang
+# env: CXX_COMPILER=clang++-3.3 FL_CPP98=OFF FL_USE_FLOAT=ON
+# - os: linux
+# compiler: clang
+# env: CXX_COMPILER=clang++-3.3 FL_CPP98=ON FL_USE_FLOAT=OFF
+# - os: linux
+# compiler: clang
+# env: CXX_COMPILER=clang++-3.3 FL_CPP98=ON FL_USE_FLOAT=ON
+# #g++-4.5 does not have an installation candidate in ubuntu
+# - os: linux
+# compiler: g++
+# env: CXX_COMPILER=g++-4.5 FL_CPP98=OFF FL_USE_FLOAT=OFF
+# - os: linux
+# compiler: g++
+# env: CXX_COMPILER=g++-4.5 FL_CPP98=OFF FL_USE_FLOAT=ON
+# - os: linux
+# compiler: g++
+# env: CXX_COMPILER=g++-4.5 FL_CPP98=ON FL_USE_FLOAT=OFF
+# - os: linux
+# compiler: g++
+# env: CXX_COMPILER=g++-4.5 FL_CPP98=ON FL_USE_FLOAT=ON
notifications:
email:
recipients:
- jcrada@fuzzylite.com
- on_success: change
+ on_success: always
on_failure: always
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..640dacb
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,220 @@
+Version 6.0
+===========
+
+Overview
+--------
+* The FuzzyLite Libraries, namely fuzzylite and jfuzzylite, both in version 6.0, are licensed under the GNU General Public License version 3.
+
+* By default, fuzzylite builds using C++11 instead of C++98.
+
+* Important performance improvements.
+
+* Refactored the following names for the operation of engines: from activation operator to implication operator, from accumulation operator to aggregation operator.
+
+* Renamed the term `Accumulated` to `Aggregated`.
+
+* New activation methods decouple the activation of rules from the rule block and provide different methods for activating rules (see Activation Methods).
+
+* New class `ActivationFactory` provides a factory of activation methods.
+
+* New class `Benchmark` to evaluate the performance and accuracy of engines.
+
+* New class `Complexity` to estimate the computational complexity of an engine.
+
+* New class `RScriptExporter` to export the surfaces of an engine using the `ggplot2` library.
+
+* New class `Binary` term for binary edges.
+
+* New `UnboundedSum` S-Norm in `SNormFactory`.
+
+* New classes `SNormFunction` and `TNormFunction` to create custom functions on any two values using the `Function` class.
+
+* Added description strings to `Engine`, `Variable` and `RuleBlock`
+
+* Privatized previously protected members of classes and subclasses of `Term`, `Variable`, `Rule`, `Defuzzifier`, `[Cloning|Construction]Factory`, `Importer`, `Exporter`, amongst others.
+
+* Improved portability by replacing `int` for `std::size_t` where necessary, thereby additionally removing warnings in Windows 64bit
+
+* Deleted `Operation.cpp` and inlined its methods into `Operation.h`
+
+* Updated `.travis.yml` to use Docker, and build using g++ (versions 6, 5, 4.9, 4.8, 4.7) and clang (versions 3.8, 3.7, 3.6, and 3.5).
+
+* Added `appveyor.yml` to use continuous integration in Windows under Visual Studio 2013 and 2015.
+
+* Added some unit tests and support for future unit tests.
+
+* Bug fixes.
+
+* New example of hybrid engines.
+
+* New example on obstacle avoidance for Mamdani, Takagi-Sugeno, and Hybrid engines.
+
+* New R scripts for each example and its respective surfaces in `pdf` formats.
+
+
+Activation Method
+-----------------
+* New activation methods determine the activation of rules in a rule block. Specifically, the activation methods compute the activation degrees of the rules and the activation order of the rules.
+
+* Seven activation methods available: General, First, Last, Highest, Lowest, Proportional and Threshold.
+
+* If no activation method is supplied, an instance of General will be automatically set.
+
+* New class `General` activates every rule following the insertion order in the rule block.
+
+* New classes `First` and `Last` activate the first and last $n$ rules (following insertion order) whose activation degrees are greater than or equal to a given threshold.
+
+* New classes `Highest` and `Lowest` activate the first and last $n$ rules sorted (descending or ascending) by activation degree.
+
+* New class `Proportional` activates every rule with an activation degree proportional to the activation degrees of the other rules.
+
+* New class `Threshold` activates every rule that satisfies a given comparison operator and a given threshold.
+
+* New class `ActivationFactory` provides a factory of activation methods.
+
+
+
+Defuzzifier
+-----------
+* Overall performance improvements
+* The new default resolution of integral defuzzifiers is 100 (from 200 in previous version)
+* Importantly simplified `WeightedAverage` and `WeightedSum` by not using the implication and aggregation operators.
+* New experimental classes `WeightedAverageCustom` and `WeightedSumCustom` which use the implication and aggregation operators to compute the weighted averages and weighted sums, respectively.
+
+
+Factory
+-------
+* New class `ActivationFactory` to register activation methods.
+* New method `FactoryManager::activation()` to get the activation factory.
+* Inlined methods in [CloningFactory|ConstructionFactory].h
+* Fixed bug in `CloningFactory::deregisterObject()`. Bug: Object was deleted before removing it from the map, leaving an invalid object in the map which would cause a segmentation fault. Solution: Remove the object from the map before deleting it.
+* New `abs` function in `FunctionFactory` to compute the absolute value of a number.
+* New `UnboundedSum` S-Norm in `SNormFactory`.
+
+Hedge
+-----
+* Added `FL_IOVERRIDE` identifiers to hedge Extremely
+* Added `FL_IFINAL` final identifiers to `Hedge` classes (except `Any`).
+
+
+
+Importer and Exporter
+---------------------
+* New `RScriptExporter` generates an R script that uses the `ggplot2` library to produce the surfaces of an engine for each pair of input variables on each output variable.
+
+* Updated `Fll[Importer|Exporter]` to import and export the newly named properties `implication` and `aggregation` (previously known as `activation` and `accumulation`). However, the `FllImporter` has backward compatibility with the previous property names.
+
+* In `Fll[Importer|Exporter]`, added `lock-range` property of input variables, `activation` property for activation methods in rule blocks, and `description` property to `[Input|Output]Variable` and `RuleBlock`.
+
+* Added default option to generate C++ and Java code using the actual names of the input variables, output variables, and rule blocks, instead of the generic `[input|output]Variable` and `ruleBlock` names.
+
+* Updated [Cpp|Java][Import|Export] to generate code using the `description` of an engine if available, the `implication` instead of the `activation`, and the `aggregation` instead of the `accumulation`.
+
+* Removed compatibility between `[Fcl|Fis]Exporter` and `fuzzylite`. In previous versions, these exporters produced additional tags that were only relevant to `fuzzylite`, so that an engine written in these languages could also support the features in `fuzzylite`. However, in doing so, Matlab, Octave and JFuzzyLogic would fail to import the engines written in their own languages because they would not recognize the `fuzzylite` features. Hence, in order to generate code compatible with Matlab, Octave, and JFuzzyLogic, the `fuzzylite` features are removed from the code.
+
+* Refactored methods [Cpp|Java|Fll|Fis|Fcl]Exporter::toString([S|T]Norm*) to take `::toString(Norm*)`.
+
+* Renamed methods FisImporter::extract[SNorm|TNorm|Defuzzifier]() to FisImporter::translate[SNorm|TNorm|Defuzzifier]()
+
+* Fixed bug causing segmentation fault when malformed term in FuzzyLite Language
+
+
+
+Norms
+-----
+* New class `UnboundedSum` to compute sum between any two values and hence reflect Matlab's and Octave's `sum` aggregation operator.
+* New classes `SNormFunction` and `TNormFunction` to create custom functions on any two values using the `Function` class.
+* Fixed bug computing the `NormalizedSum` S-Norm.
+
+
+Rule
+----
+* Added properties `fl::scalar activationDegree`, `bool triggered` and `bool enabled` to a `Rule`. The `activationDegree` property stores the activation degree of the rule in order to avoid recomputing it when requesting it. The `triggered` property indicates whether the rule was triggered (i.e., whether the antecedent modified the consequent). The `enabled` property determines whether the rule can be triggered (by default, a rule is always enabled unless programmatically indicated otherwise).
+
+* Decoupled computing the activation degree and triggering the rule. Previously, the activation degree of a rule was computed and triggered at the same time using `Rule::activate(TNorm* conjunction, SNorm* disjunction, TNorm* implication)`. Currently, there are two methods: `fl::scalar activateWith(TNorm* conjunction, SNorm* disjunction)`, which computes, stores and returns the activation degree of the rule; and `trigger(TNorm* implication)`, which, if the rule is enabled and the activation degree is greater than zero, then the rule is triggered to modify the consequent.
+
+* Renamed `RuleBlock::activation` operator to `RuleBlock::implication` operator, and so its respective getters and setters.
+* Added `RuleBlock::activation` method and respective getters and setters.
+* In `RuleBlock::activate()`, if there is no activation method, the `General` activation method is automatically set in order to have backward compatibility.
+
+* Fixed bug in `RuleBlock` to reset and clone the implication operator. Bug: implication operator is not copied and reset. Fix: copy and reset implication operator when cloning the `RuleBlock`.
+
+* Added identifier `FL_IFINAL` to classes `Proposition` and `Operator`.
+
+Term
+----
+* Performance improvements.
+* `Discrete` term uses binary search instead of linear search, hence significantly improving performance.
+* `Discrete` term can create a `Discrete` term from any other term.
+* New `Binary` edge term.
+* Added method `bool Term::isMonotonic()` to determine whether the term is monotonic (returns true only for `Concave`, `Ramp`, `Sigmoid`, `SShape`, and `ZShape`).
+* Refactored static method `WeightedDefuzzifier::tsukamoto()` into non-static method `Term::tsukamoto()`, which is overriden by each of the terms that can be used for `tsukamoto` controllers.
+* Privatized `Term::name` and the properties of each subclass of `Term`.
+* Inlined generic methods in `[Linear|Discrete].h`
+* Renamed `Activated::activation` operator to `Activated::implication` and its respective getters and setters.
+* Renamed `Accumulated` term to `Aggregated` term, and its `accumulation` operator to `aggregation` operator including getters and setters.
+* For performance improvements, terms of `Aggregated` term are copies of objects in stack memory rather than pointers to objects in heap memory.
+* Refactored static `Term::updateReference()` to non-static being overrided by `Linear`, `Function`.
+* Added enum `[Ramp|Sigmoid]::Direction` to specify the direction of the term.
+* Added `Term::clone()` method to create a copy of any term.
+
+* Fixed bug in `Function` term. Bug: given a formula = "tan(y)" and a map["y"] = 1.0, and executing `Function::load(formula)`, then the map of variables is reset because `load()` calls `unload()` first, causing the deregistration of variable `y`. Solution: Removed method `unload()` from `load()`, thereby causing future `load()` not to reset variables.
+* Fixed bug in `Function` when enclosing variable in double parenthesis.
+
+
+
+Variable
+--------
+* Refactored `[Input|Output]Variable::[get|set][Input|Output]Value()` to a single value in `Variable::[get|set]Value()`.
+* Refactored `OutputVariable::[is|set]LockedOutputValueInRange()` to its parent `Variable::[is|set]LockValueInRange()`.
+* Added option to lock value in range to input variables by refactoring `OutputVariable::lockValueInRange` to `Variable::lockValueInRange`.
+* Renamed `OutputVariable::[is|set]LockedPreviousValue()` to `OutputVariable::[is|set]LockPreviousValue()`.
+* Added wrapping method `OutputVariable::[get|set]Aggregation()`.
+* For performance improvements, added enum `Variable::Type` and methods `Variable::type()` to indicate whether the variable is of `Type::InputVariable` or `Type::OutputVariable`. Thus, it is no longer necessary to `dynamic_cast` variables to find out whether they are input or output variables.
+
+
+
+Benchmark
+---------
+* Benchmark the time it takes your engine to perform a given number of evaluations (available only when building using C++11) over a given number of independent runs.
+* Measure the accuracy of the engine using the mean squared error between the obtained values and the expected values.
+* Export the benchmark results to text.
+
+Complexity
+----------
+* New complexity methods in the components involved in the operation of an engine.
+* Complexity methods are completely decoupled from the operation of an engine, so they do not affect the performance of the engines.
+
+Console
+-------
+* Benchmark engines from the FuzzyLite Console
+* Hybrid example in Console
+
+Engine
+------
+* Description string for Engine
+* Changed signature of `::configure(TNorm* conjunction, SNorm* disjunction, TNorm* activation, SNorm* accumulation, int resolution)` to `::configure(TNorm* conjunction, SNorm* SNorm* disjunction, TNorm* implication, SNorm* aggregation, Activation* activation)`, where `implication` and `aggregation` are better names for activation and accumulation (respectively), and the `activation` refers to an activation method (see Activation Methods)
+
+Exception.h
+-----------
+* Definition FL_BACKTRACE_OFF in Exception.cpp renamed to FL_BACKTRACE, hence functionality is changed.
+
+fuzzylite.h
+-----------
+* Removed definitions FL_VERSION, FL_DATE from fuzzylite.h
+* Renamed fuzzylite::debug() to fuzzylite::isDebugging()
+* Renamed fuzzylite::logging() to fuzzylite::isLogging()
+* Inlined methods of fuzzylite.h
+* Removed definition `FL_CPP11` and replaced it for `FL_CPP98`. By default, `FL_CPP98` is not defined, hence building using `C++11`.
+
+
+Examples
+--------
+* New example of hybrid engines.
+* New example on obstacle avoidance for Mamdani, Takagi-Sugeno, and Hybrid engines.
+* New R scripts for each example and its respective surfaces in `pdf` formats.
+* Updated examples to use the new properties `InputVariable::lock-range`, `Engine::description`, `[Input|Output]Variable::description`, `RuleBlock::description`, `RuleBlock::implication`, `RuleBlock::activation`, and `OutputVariable::aggregation`.
+* Updated C++ and Java examples to reflect variable names instead of generic names.
+
+
+
diff --git a/COPYING b/COPYING
index 94a9ed0..94a0453 100644
--- a/COPYING
+++ b/COPYING
@@ -619,56 +619,3 @@ Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- <program> Copyright (C) <year> <name of author>
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/COPYING.LESSER b/COPYING.LESSER
deleted file mode 100644
index 65c5ca8..0000000
--- a/COPYING.LESSER
+++ /dev/null
@@ -1,165 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index 012623e..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,231 +0,0 @@
-Version 5.1
-* Updated `JavaExporter` to remove boolean from exported `Function.create(String name, String formula, Engine engine, boolean)`
-* Improved CMakeLists to remove errors from warnings, and exclude library rt for benchmarks
-* Moved benchmarks in `Console.cpp` to FL_CPP11 in order to get rid of rt library
-* Made most constructors `explicit`
-* FL_WINDOWS, FL_APPLE and FL_UNIX are automatically defined in `fuzzylite.h`
-* Option to prefix namespace `fl::` in class `CppExporter`
-* New methods `FclExporter::toString([[Input|Output]Variable]|RuleBlock|Norm])`
-* New methods `FclExporter::toString(Norm)`
-* Identifier FL_IOVERRIDE in SNorm and TNorm
-* New private methods `CloningFactory::register[Operators|Functions]`
-* `FisExporter` merges all ruleblocks into one
-* New `Rule::clone()` method
-* Fixed `FclImporter` exception on malformed Term
-* Made sure this version builds successfully with g++5.1
-
-
-Version 5.0
-* Modified Function::Unary and Binary to take scalar instead of double
-* Fixed building using -DFL_USE_FLOAT=ON
-* Added deductive type of Engine with Engine::type()
-* Fixed minor memory leak at RuleBlock (conjunction, disjunction, activation)
-* Fixed minor memory leak at Accumulated (accumulation, thresholded terms)
-* Fixed minor memory leak at OutputVariable (defuzzifier)
-* Fixed minor memory leak at Function::Node
-* Fixed minor memory leak at FactoryManager
-* Improved handling of Exceptions
-* Modified FclExporter and FisExporter to provide backward compatibility with FCL and FIS formats
-* Updated the FIS and FCL examples for backward compatibility
-* Included the original example files
-* Updated FLD examples produced from the engines of the original examples
-* Fixed some original examples of takagi-sugeno to use AlgebraicProduct activation
-* FldExporter no longer restarts the engine
-* Fixed rethrowing of exceptions to provide proper information about errors!
-* Catching std::exceptions where possible to avoid unexpected exceptions
-* FldExporter exports from a custom input dataset
-* Console includes option to read custom input dataset from file
-* Console provides more information about its usage
-* Renamed methods FldExporter::toWriter() to FldExporter::write()
-* Removed variable and methods for property FldExporter::maximum
-* Accuracy improvements importing fis files with large number of decimals
-* Updated FLD examples to reflect accuracy
-* Changed operation for multiple hedges to operate from last to first
-* Fixed OutputVariable to store last valid output value regardless of locks
-* Renamed Op::isNan to Op::isNaN
-* New OutputVariable::(get|set)OutputValue to store value from defuzzification
-* Changed OutputVariable::defuzzify to store its output value
-* Changed return type of scalar OutputVariable::defuzzify to void OutputVariable::defuzzify
-* Renamed OutputVariable::(get|set)LastValidOutput to OutputVariable::(get|set)LastValidOutputValue
-* Removed OutputVariable::defuzzifyNoLocks
-* Removed const from Term* Accumulated::(get|set)Accumulation
-* Added InputVariable::fuzzyInputValue and OutputVariable::fuzzyOutputValue
-* Removed defaults in Engine::configure
-* Added Engine::configure without conjuntion and disjuntion
-* Added parameter string to Engine::type
-* Changed Engine::isReady
-* Correct handling of integral defuzzification with min|max=NaN|Inf
-* Added method Rule::isLoaded to determine whether a rule is to be activated
-* Added method Rule::unload to allow existence of invalid rules
-* Added methods Engine::set((Input|Output)Variables), Engine::setRuleBlocks
-* Added method RuleBlock::setRules
-* Changed visibility of Rule::setText to public
-* Added method Rule::load(const Engine*)
-* Renamed term Thresholded to Activated
-* Renamed Thresholded::(set|get)Threshold to Activated::(set|get)Degree
-* Removed variable Rule::FL_ASSIGNS="=" and method Rule::assignsKeyword()
-* Modified original takagi-sugeno examples to reflect proper activation and accumulation
-* Moved Engine::_hedges (and methods) to Rule::_hedges
-* Renamed Antecedent::(get|set)Root to Antecedent::(get|set)Expression
-* Added (Antecedent|Consequent)::(get|set)Text
-* Added (Antecedent|Consequent)::load|unload
-* Renamed typedef Factory::Creator to Factory::Constructor
-* Added an M-file to compare output values of fuzzylite engines with Matlab
-* Removed const from Norms in RuleBlock::(get|set)(Activation|Conjunction|Disjunction)
-* Deleted method Op::repeat
-* Added built-in functions gt,lt,ge,le,eq and operator !
-* Renamed Term::copy to Term::clone in every Term
-* Added copy constructors and assignment operators to (Input|Output)Variable
-* Added copy constructors and assignment operators to Accumulated
-* Merged Function::Operator and Function::BuiltInFunction into Function::Element
-* Created FunctionFactory for Function::Elements
-* IMPORTANT: Changed starting precedence of Function::Element::Operators to 10 (refer to FunctionFactory)
-* Setters of FactoryManager no longer delete previous factories
-* Renamed Factory<T>::(register|deregister)Class to Factory<T>::(register|deregister)Constructor
-* Renamed Factory<T> to ConstructionFactory<T>
-* Created CloningFactory<T>
-* Moved functions and operators of term Function to a FunctionFactory
-* Added clone methods to Defuzzifiers, Hedges, Norms, and Terms
-* Changed Exception::btCallStack(const int) to Exception::btCallStack(void)
-* Using std::auto_ptr to (T|S)Norms in RuleBlock, SNorm in Accumulated, and Defuzzifier in OutputVariable
-* Added methods Engine::set((Input|Output)Variable) and Engine::setRuleBlock()
-* Added method RuleBlock::reloadRules()
-* Changed Linear pointers to input variables for a pointer to Engine
-* Added support to compare infinity values with fl::Op::isEq and therefore other comparison operators
-* Parameters of all terms are set to fl::nan by default
-* Added methods Engine::(input|output)Variables() and ::ruleBlocks() to return mutable references
-* Added method Variable::terms() to return mutable reference
-* Added method RuleBlock::rules() to return mutable reference
-* Added methods Ramp::direction() and Sigmoid::direction() to represent direction of slope
-* Added method fl::Op::isFinite(x) to check x is not (nan or inf)
-* Changed fl::Op::isEq(a,b) to return true if a = b = NaN
-* Added method Accumulated::terms() to return mutable reference
-* Changed visibility of Linear::coefficients to protected
-* Added methods Linear::coefficients(), Linear::setCoefficients()
-* Removed public variables Discrete::x,y
-* Added in Discrete a typedef to std::pair<scalar, scalar> Pair, and changed signatures of methods and types of their parameters
-* Changed representation of Discrete::(x,y) from std::vector<scalar> to std::vector<Pair>
-* Added methods Discrete::setXY(), Discrete::xy(), ::xy(int) to set and get new representation
-* Added methods Discrete::toPairs(std::vector<scalar>) and Discrete::toVector(std::vector<Pair>)
-* Added method Discrete::formatXY() to get pairs (x,y) nicely formatted
-* Linear term no longer throws exception when inputVariables != |coefficients|
-* Changed visibility of Function::root to protected and renamed it to Function::_root
-* Added method Function::root() to return pointer to Function::_root
-* Added option to prefix the namespace in CppExporter, by default it does not prefix
-* Added method OutputVariable::clear() to restart the output variable
-* Renamed variable OutputVariable::_lastValidOutputValue to ::_previousOutputValue
-* Renamed method OutputVariable::(get|set)LastValidOutputValue to ::(get|set)PreviousOutputValue
-* Renamed variable OutputVariable::_lockOutputRange to ::_lockOutputValueInRange
-* Renamed method OutputVariable::setLockOutputRange() to ::setLockOutputValueInRange
-* Renamed method OutputVariable::isLockingOutputRange() to ::isLockedOutputValueInRange
-* Renamed variable OutputVariable::_lockValidOutput to ::_lockPreviousOutputValue
-* Renamed method OutputVariable::setLockValidOutput() to ::setLockPreviousOutputValue
-* Renamed method OutputVariable::isLockingValidOutput() to ::isLockedPreviousOutputValue
-* Renamed FLL property 'lock-valid' to 'lock-previous'
-* Renamed FIS property 'LockValid' to 'LockPrevious'
-* Renamed FCL property 'LOCK: VALID' to 'LOCK: PREVIOUS'
-* Added method Engine::variables() to retrieve both Input and OutputVariables
-* Added method Term::updateReference(Term*, Engine*) to ensure Linear and Function terms to update references of engines
-* Added method Engine::updateReferences() to update references to the engine in its terms.
-* Added in Discrete a typedef to std::pair<scalar, scalar> Pair, and changed signatures of methods and types of their parameters
-* Added terms: Concave, Cosine and Spike
-* Renamed methods Triangle::(set|get)(A|B|C) to (set|get)(Vertex(A|B|C))
-* Renamed methods Trapezoid::(set|get)(A|B|C|D) to (set|get)(Vertex(A|B|C|D))
-* Removed method fuzzylite::configuration()
-* Renamed MACRO FL_DEBUG to FL_DBG
-* Renamed MACRO (FL_BEGIN_DEBUG_BLOCK and FL_END_DEBUG_BLOCK) to (FL_DEBUG_BEGIN and FL_DEBUG_END)
-* Renamed methods in (Fis|Fcl)Importers::extract? to ::parse?
-* Made defaultResolution a static property of IntegralDefuzzifiers
-* Added method Engine::type(name, reason) to show type and reason why type
-* Added method Engine::clone()
-* Added support for Tsukamoto with Concave terms
-* Changed Accumulated to take Activated* terms instead of const Terms*
-* Deleted class Tsukamoto
-* Created class WeightedDefuzzifier from which Weighted(Average|Sum) derive with options: Automatic|TakagiSugeno|Tsukamoto
-* Added methods WeightedDefuzzifier::tsukamoto() and ::inferType()
-* Added benchmarks for fuzzylite in Linux
-* Created the FuzzyLite Interactive Console
-* Added basic rule chaining such that Output Variables can be utilized as antecedents
-* Added two examples for rule chaining: mamdani/Laundry.fll and mamdani/SimpleDimmerInverse.fll
-* Added Term::(get|set)Height and changed all terms accordingly
-* Renamed method Op::makeValidId to Op::validName, which now returns "unnamed" for empty strings.
-* Converted examples/original/*.fis to examples/original/*.fll
-* Removed Exception Specification from methods in Discrete, Linear and Function terms
-* Changed name of debug libraries to fuzzylited.dll and fuzzylite-staticd.lib
-* Removed method Operation::toScalar(std::string, bool, scalar)
-* Added method Operation::toScalar(std::string) [throws Exception], and ::toScalar(std::string, scalar alternative) throw()
-* Added method ImEx::(from|to)File to import and export engines using files
-* WeightedAverage and WeightedSum without Activation operators have default behaviour, i.e., AlgebraicProduct
-* FactoryManager utilizes smart pointers.
-* Rule utilizes smart pointers for Antecedent and Consequent
-* Exceptions are thrown when Conjunction, Disjunction, Activation and Accumulation operators are NULL when they are required
-* Exception is thrown when Defuzzifier is required and not set.
-* Added support for C++11 utilizing smart pointers, identifiers (override, noexcept), and delete identifiers to DISABLE_COPY(Class)
-* Macros for identifiers are FL_IOVERRIDE, FL_IFINAL, FL_IDEFAULT, FL_IDELETE, and FL_INOEXCEPT (fl/fuzzylite.h)
-* Added macro FL_unique_ptr to refer to std::auto_ptr (C++98) or std::unique_ptr (C++11), and its respective FL_move_ptr(x) to move a smart pointer.
-* Added constant fl::null to refer to 0L (C++98) or nullptr (C++11)
-* Added macros FL_DEFAULT_COPY(Class), FL_DEFAULT_MOVE(Class), and FL_DEFAULT_COPY_AND_MOVE(Class) for default copy and move constructors and operators
-* Added build.sh to build fuzzylite
-* Changed default to fuzzylite::_macheps = 1e-6;
-* Renamed macro FL_EXPORTS to FL_API
-* Added macro FL_SHARED_LIBRARY and FL_STATIC_LIBRARY to be defined when building shared and static libraries
-
-
-Version 4.0
-* FuzzyRule merged with Rule, and FuzzyRule deleted.
-* FuzzyAntecedent merged with Antecedent, and FuzzyAntecedent deleted
-* FuzzyConsequent merged with Consequent, and FuzzyConsequent deleted
-* FuzzyExpression renamed Expression
-* Renamed Rule::get/setUnparsedRule to get/setText
-* Renamed RuleBlock::get/set(Tnorm|Snorm) to get/set(Conjunction|Disjunction)
-* Renamed RuleBlock::fireRules to activate
-* Renamed Rule::fireStrength to activationDegree, fire to activate
-* Renamed Consequent::fire to modify
-* Created IntegralDefuzzifier to extract divisions from Defuzzifier
-* Renamed divisions from IntegralDefuzzifier to resolution, FL_DIVISIONS to FL_RESOLUTION
-* Deleted MaximumDefuzzifier
-* Centroid, Bisector, and Largest/Smallest/Mean Defuzzifiers inherit from IntegralDefuzzifier
-* Changed names of arithmetic operations in fl::Operation
-* Renamed Function::get/set(Infix) to get/set(Formula)
-* Renamed InputVariable::get/set(Input) to get/set(InputValue)
-* Renamed Antecedent::firingStrength to activationDegree
-* Renamed Antecedent::toString/(Prefix,Infix,Postfix) to to/(Prefix,Infix,Postfix)
-* Renamed Rule::FL_ASSIGN to Rule::FL_EQUALS
-* New method restart in Engine
-* New methods Engine::setInputValue(name, value), scalar Engine::getOutputValue(name)
-* Renamed Op::str(vector/varargs) to Op::join(vector/varargs)
-* Refactored associtativity, unary and binary properties in Element within Function
-* Removed unnecessary Hedges creation upon importing engines, now is automatic via Factories
-* Created the JavaExporter
-* Renamed methods within Fis/Fcl/CppExporter to toString(*);
-* Extracted TNorms and SNorms from TNorm.h/cpp and SNorm.h/cpp
-* Created proper Factories with registration of classes and constructors
-* Renamed method Factory::create to Factory::createInstance
-* Added static constructor method to every Defuzzifier, Hedge, TNorm, and SNorm
-* Removed FL_PRECISION, FL_DECIMALS as Macros, and created static variables in fuzzylite.h
-* Renamed FL_PRECISION to macheps, i.e., machine epsilon to differentiate real numbers
-* Removed FL_DEBUG and created a static variable in fuzzylite.h
-* Removed FL_NO_LOG as it is now controlled with fuzzylite::logging(), previously named logEnabled()
-* Libraries and Console application are both built in folder bin/ (previously libraries were at lib/)
-* Removed Engine::toStringFis/Fcl/Cpp to encourage use of Fcl/Fis/CppExporters instead
-* Renamed Op::logical_and to Op::logicalAnd, Op::logical_or to Op::logicalOr
-* Added support to Fis/FclImporters to treat comments (%,#,//,/*) in fis and fcl files
-* Created the Console application instead of previous demo
-* Added Variable::range() to return (maximum - minimum)
-* Removed Variable::isEmpty, use Variable::terms().empty()
-* Removed RuleBlock::isEmpty, use RuleBlock::rules().empty()
-* Created method Op::makeValidId to ensure names are valid
-* Engine, Variable and Term::toString return FllExport::toString
-* Created Term::parameters to return list of parameter values as string separated by spaces
-* Created Term::configure to configure from Term::parameters
-* FclImEx import and export terms using Term::parameters
-* Created the FuzzyLite Language in FllImporter and FllExporter
-* Created the FuzzyLite Dataset FldExporter
-* Added property Enable to Engine, Variable and RuleBlock
-* Extended FCL and FIS to consider Enabled properties
-* Changed Engine::defuzzify() to consider enabled variables
-* Changed Engine::process() to consider enabled rule blocks
-* Changed OutputVariable::output() to OutputVariable::fuzzyOutput()
-* Renamed Rectangle::minimum/maximum to Rectangle::start/end
-* Renamed fuzzylite::shortVersion to fuzzylite::version
-* Improved accuracy of Triangle and Trapezoid
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..99a11d1
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,22 @@
+FROM ubuntu:latest
+MAINTAINER Juan Rada-Vilela <jcrada@fuzzylite.com>
+
+ARG CXX_COMPILER=g++
+ENV CXX_COMPILER ${CXX_COMPILER}
+
+
+#install software-properties-common to use add-apt to add repository for g++-6
+RUN apt-get update && apt-get -y install software-properties-common && \
+ add-apt-repository ppa:ubuntu-toolchain-r/test && \
+ apt-get update && apt-get -y install \
+ ${CXX_COMPILER} \
+ make \
+ cmake \
+ doxygen \
+ graphviz
+
+#Create and copy Docker's context into /build
+RUN mkdir /build
+ADD . /build
+WORKDIR /build/fuzzylite
+ENTRYPOINT [ "/build/fuzzylite/build.sh" ] \ No newline at end of file
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..84978af
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,2397 @@
+# Doxyfile 1.8.11
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "fuzzylite"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = 6.0
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "A Fuzzy Logic Control Library in C++"
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO = fuzzylite.svg
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = documentation/
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = YES
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = YES
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = fuzzylite/fl README.md
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd,
+# *.vhdl, *.ucf, *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.h
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH = examples/mamdani examples/takagi-sugeno examples/tsukamoto
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *.fll *.fld *.cpp *.java *.fis *.fcl *.R
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH = documentation/ui/figure/ documentation/ui/image
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE = README.md
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER = documentation/ui/header.html
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER = documentation/ui/footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET = documentation/ui/stylesheet.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+
+HTML_EXTRA_FILES = README.md \
+ documentation/ui/image/browserconfig.xml \
+ documentation/ui/image/manifest.json \
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "FuzzyLite Documentation"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = com.fuzzylite
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = com.fuzzylite.documentation
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = FuzzyLite Limited
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =fuzzylite-6.0.chm
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE = fuzzylite.qch
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = com.fuzzylite
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = com.fuzzylite.documentation
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 14
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = YES
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest/
+# The path should be set to ./MathJax, but there is no way to use it in Doxygen
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES ={amsmath}
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+#@TODO: YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+#@TODO: YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+#@TODO: YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+#@TODO: YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = YES
+#@TODO: YES
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 15
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = YES
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+#@TODO: YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+#@TODO: YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = YES
+#@TODO: YES
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = YES
+#@TODO: YES
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = svg
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 500
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/LICENSE b/LICENSE
index 65c5ca8..94a9ed0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,165 +1,674 @@
- GNU LESSER GENERAL PUBLIC LICENSE
+ GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/LICENSE.FuzzyLite b/LICENSE.FuzzyLite
new file mode 100644
index 0000000..9477af6
--- /dev/null
+++ b/LICENSE.FuzzyLite
@@ -0,0 +1,634 @@
+FuzzyLite License
+Version 1.0, March 2017
+http://www.fuzzylite.com/license
+
+GENERAL
+=======
+The FuzzyLite Libraries, namely fuzzylite and jfuzzylite, both in version 6.0, are licensed under the GNU General Public License version 3.
+
+GNU General Public License
+--------------------------
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/NEWS b/NEWS
index daa131e..a339cce 100644
--- a/NEWS
+++ b/NEWS
@@ -1,317 +1,52 @@
-Extracted from [README.md](/README.md)
-================================================
+Version 6.0
+===========
+Overview
+--------
+* The FuzzyLite Libraries, namely fuzzylite and jfuzzylite, both in version 6.0, are licensed under the GNU General Public License version 3.
-### <a name="features">Features</a>
+* By default, fuzzylite builds using C++11 instead of C++98.
-**Controllers** *Types* (5) Mamdani, Takagi-Sugeno, Larsen, Tsukamoto, Inverse Tsukamoto
+* Important performance improvements.
-**Linguistic terms** *Basic* (4) triangle, trapezoid, rectangle, discrete. *Extended* (9) bell, cosine, gaussian, gaussian product, pi-shape, sigmoid difference, sigmoid product, spike. *Edges* (4) concave, ramp, sigmoid, s-shape, z-shape. *Functions* (3) constant, linear, function.
+* Refactored the following names for the operation of engines: from activation operator to implication operator, from accumulation operator to aggregation operator.
-**Conjunction and Activation** *T-Norm* (7) minimum, algebraic product, bounded difference, drastic product, einstein product, hamacher product, nilpotent minimum.
+* Renamed the term `Accumulated` to `Aggregated`.
-**Disjunction and Accumulation** *S-Norm* (8) maximum, algebraic sum, bounded sum, normalized sum, drastic sum, einstein sum, hamacher sum, nilpotent maximum.
+* New activation methods decouple the activation of rules from the rule block and provide different methods for activating rules (see Activation Methods).
-**Defuzzifiers** *Integral* (5) centroid, bisector, smallest of maximum, largest of maximum, mean of maximum, *Weighted* (2) weighted average, weighted sum.
+* New class `ActivationFactory` provides a factory of activation methods.
-**Hedges** *Types* (6) any, not, extremely, seldom, somewhat, very.
+* New class `Benchmark` to evaluate the performance and accuracy of engines.
-**Import** *Types* (3) FuzzyLite Language `fll`, Fuzzy Inference System `fis`, Fuzzy Control Language `fcl`.
+* New class `Complexity` to estimate the computational complexity of an engine.
-**Export** *Types* (6) `C++`, `Java`, FuzzyLite Language `fll`, FuzzyLite Dataset `fld`, Fuzzy Inference System `fis`, Fuzzy Control Language `fcl`.
+* New class `RScriptExporter` to export the surfaces of an engine using the `ggplot2` library.
-**Examples** (30+) of Mamdani, Takagi-Sugeno and Tsukamoto controllers from `fuzzylite`, Octave and Matlab, each included in the following formats: `C++`, `Java`, `fll`, `fld`, `fis`, and `fcl`.
+* New class `BinaryTerm` for binary edges.
-***
+* New `UnboundedSum` S-Norm in `SNormFactory`.
-### <a name="example">Example</a>
+* New classes `SNormFunction` and `TNormFunction` to create custom functions on any two values using the `Function` class.
-```cpp
-#include "fl/Headers.h"
+* Added description strings to `Engine`, `Variable` and `RuleBlock`
-int main(int argc, char* argv[]){
- using namespace fl;
- Engine* engine = new Engine("simple-dimmer");
+* Privatized previously protected members of classes and subclasses of `Term`, `Variable`, `Rule`, `Defuzzifier`, `[Cloning|Construction]Factory`, `Importer`, `Exporter`, amongst others.
- InputVariable* ambient = new InputVariable;
- ambient->setName("Ambient");
- ambient->setRange(0.000, 1.000);
- ambient->addTerm(new Triangle("DARK", 0.000, 0.500));
- ambient->addTerm(new Triangle("MEDIUM", 0.250, 0.750));
- ambient->addTerm(new Triangle("BRIGHT", 0.500, 1.000));
- engine->addInputVariable(ambient);
+* Improved portability by replacing `int` for `std::size_t` where necessary, thereby additionally removing warnings in Windows 64bit
- OutputVariable* power = new OutputVariable;
- power->setName("Power");
- power->setRange(0.000, 2.000);
- power->setDefaultValue(fl::nan);
- power->addTerm(new Triangle("LOW", 0.000, 1.000));
- power->addTerm(new Triangle("MEDIUM", 0.500, 1.500));
- power->addTerm(new Triangle("HIGH", 1.000, 2.000));
- engine->addOutputVariable(power);
+* Deleted `Operation.cpp` and inlined its methods into `Operation.h`
- RuleBlock* ruleblock = new RuleBlock;
- ruleblock->addRule(Rule::parse("if Ambient is DARK then Power is HIGH", engine));
- ruleblock->addRule(Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
- ruleblock->addRule(Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
- engine->addRuleBlock(ruleblock);
+* Updated `.travis.yml` to use Docker, and build using g++ (versions 6, 5, 4.9, 4.8, 4.7) and clang (versions 3.8, 3.7, 3.6, and 3.5).
- engine->configure("", "", "Minimum", "Maximum", "Centroid");
+* Added `appveyor.yml` to use continuous integration in Windows under Visual Studio 2013 and 2015.
- std::string status;
- if (not engine->isReady(&status))
- throw Exception("Engine not ready. "
- "The following errors were encountered:\n" + status, FL_AT);
+* Added some unit tests and support for future unit tests.
- for (int i = 0; i < 50; ++i){
- scalar light = ambient->getMinimum() + i * (ambient->range() / 50);
- ambient->setInputValue(light);
- engine->process();
- FL_LOG("Ambient.input = " << Op::str(light) << " -> " <<
- "Power.output = " << Op::str(power->getOutputValue()));
- }
-}
-```
+* Bug fixes.
-***
+* New example of hybrid engines.
-### <a name="whatsnew">What's New?</a>
-The entire `fuzzylite` library has been thoroughly revised, refactored, validated, and significantly improved. The following sections detail the changes and enhancements of version 5.0. Users of previous versions are **strongly** encouraged to carefully read the list before migrating to version 5.0. Important changes and enhancements are marked as **(important)**, **(VERY important)** and **(EXTREMELY important)**.
+* New example on obstacle avoidance for Mamdani, Takagi-Sugeno, and Hybrid engines.
-#### <a name="new-general">General</a>
-+ **(important)** `fuzzylite v5.0` is dual-licensed under the [GNU LGPL v3.0](https://www.gnu.org/licenses/lgpl.html) and a paid commercial license.
-+ Support for both `C++98` and `C++11` using the latest features.
-+ Support for multiple compilers `g++`, `Clang`, `MSVC`.
-+ Refactoring of many classes to improve design and performance.
-+ **(important)** Performance improvements of Takagi-Sugeno controllers by over 55% with respect to v4.0 (estimate based on the average performance on the examples included).
-+ Smart pointers in many classes take care of automatically deleting objects when setting new pointers (`Accumulated`, `FactoryManager`, `Function`, `OutputVariable`, `Rule`, and `RuleBlock`).
-* **(important)** Exceptions are thrown when any of the following `RuleBlock::[conjunction|disjunction|activation]`, `Accumulated::accumulation`, and `OutputVariable::defuzzifier` are required but set to `fl::null`, thereby replacing the operations that would lead to `[signal 11] Segmentation fault` to operations that throw a `fl::Exception` instead.
-+ Automatic build script to build `fuzzylite` in `debug` and `release` mode.
-+ Binaries of debug libraries are renamed to append the letter `d` (e.g.,`fuzzylited.dll`, `libfuzzylited.so`).
-+ **(important)** New file [`fuzzylite/src/m/compare.m`](/fuzzylite/src/m/compare.m) <!---check link--> to compare the output values of your `fuzzylite` engines with the evaluation of the same engine in Octave/Matlab.
-+ **(important)** There is practically no difference between the output values obtained with `fuzzylite` and those obtained with Octave/Matlab. Based on the examples, the average mean square error (MSE) between the output values is less than `7.3e-12` (or `0.0000000000073`) due to negligible differences in floating-point arithmetic. The results and comparison can be found in [`examples/examples.mat`](/examples/examples.mat) <!---check link-->.
-+ **(important)** Source code of applications based on version 4.0 will most likely not compile with version 5.0.
-+ Minor bugs and memory leaks fixed.
-
-####<a name="new-macros">Macros</a>
-* **(important)** Added support for `C++11` with smart pointers, method identifiers, move constructors and move operators as follows. For precise information, refer to file [`fuzzylite/fl/fuzzylite.h`](/fuzzylite/fl/fuzzylite.h). <!---check link-->
-* **(important)** Macros for identifiers are defined as `FL_IOVERRIDE override`, `FL_IFINAL final`, `FL_IDEFAULT = default`, `FL_IDELETE = delete`, `FL_INOEXCEPT noexcept`, `FL_DEFAULT_COPY(Class)`, `FL_DEFAULT_MOVE(Class)`, and `FL_DEFAULT_COPY_AND_MOVE(Class)`.
-* **(important)** Added macro `FL_unique_ptr` to refer to `std::auto_ptr` (`C++98`) or `std::unique_ptr` (`C++11`), and its respective `FL_move_ptr(x)` to move a smart pointer, albeit `FL_move_ptr(x)` is not used within the library as it is not needed.
-* **(important)** Added global variables `const long fl::null = 0L` to refer to the null pointer in `C++98` and `const std::nullptr_t null = nullptr` to refer to the null pointer in `C++11`.
-* **(important)** Renamed macro `FL_DEBUG` to `FL_DBG`.
-* **(important)** Renamed macros `FL_BEGIN_DEBUG_BLOCK` and `FL_END_DEBUG_BLOCK` to `FL_DEBUG_BEGIN` and `FL_DEBUG_END`, respectively.
-* **(important)** Renamed macro `FL_EXPORT` to `FL_API`
-* **(EXTREMELY important)** Added macro definitions `FL_EXPORT_LIBRARY` and `FL_IMPORT_LIBRARY`. If you are building `fuzzylite` as a **shared library**, you need to define `FL_EXPORT_LIBRARY`. If you are building `fuzzylite` **executable** *and* it utilizes the `fuzzylite` **shared library**, you need to define `FL_IMPORT_LIBRARY`. If you are building `fuzzylite` as a **static library** and/or building `fuzzylite` **executable** using the `fuzzylite` **static library**, then you do not need to define either `FL_[IMPORT|EXPORT]_LIBRARY`. Note that the same conditions apply for your application. This is particularly important in Windows platforms, as `FL_IMPORT_LIBRARY` and `FL_EXPORT_LIBRARY` define `FL_API` to `__declspec(dllimport)` and `__declspec(dllexport)`, respectively. If in doubt, please check [`fuzzylite/CMakeLists.txt`](/fuzzylite/CMakeLists.txt)<!---check link-->
-
-#### <a name="new-operation">Operation</a>
-* **(important)** Added method `Operation::toScalar(std::string x, scalar alternative) FL_INOEXCEPT` which returns `alternative` if `x` is not a valid `scalar`, and never throws an exception.
-* **(important)** Added method `Operation::toScalar(std::string x)` that returns the scalar value of `x` or throws a `fl::Exception` if `x` is not a valid `scalar`.
-* **(VERY important)** Marked method (from v4.0) `Operation::toScalar(std::string, bool, scalar) FL_IDELETE;` and removed its implementation such that its usage is prevented at compile time in `C++11` and at linker time in `C++98`. Please, use the appropriate `Op::toScalar` methods mentioned above.
-+ Renamed method `Op::isNan` to `Op::isNaN`.
-* Added method `fl::Op::isFinite(x)` which returns `not (isNaN(x) or isInf(x))`.
-* Changed `fl::Op::isEq(a,b)` to return `true` if `a == b == NaN`.
-* Changed `fl::Op::isEq(a,b)` to return `true` if `a == b == Inf`.
-* Changes to `fl::Op::isEq` affect other comparison methods `fl::Op::is[Lt|LEq|GEq|Gt]`.
-* Added shortcuts of comparisons `fl::Op::[gt,lt,ge,le,eq,neq](scalar a, scalar b)`, mostly to provide binary versions (without `macheps`) for term `Function`.
-* Deleted method `Op::repeat`.
-* Removed method `fuzzylite::configuration()`.
-* Changed default `fuzzylite::_macheps = 1e-6;`.
-* Renamed method `Op::makeValidId` to `Op::validName`, which now returns `"unnamed"` for empty strings.
-
-
-
-####<a name="new-engine">Engine</a>
-* **(VERY important)** Moved `Engine::hedges` (and relevant methods) to `Rule::hedges`.
-* Added enumeration for the type of engine: `enum Engine::Type{Mamdani, Larsen, TakagiSugeno, Tsukamoto, InverseTsukamoto, Hybrid, Unknown}`.
-* Added method `Type Engine::type(std::string* name, std::string* reason)` to infer the type of the engine based on its configuration, additionally provides the name of the type and the inference reasons for its type.
-* **(important)** Changed method `Engine::isReady(std::string)` to satisfy the default operation of controllers. The method `Engine::isReady(std::string)` was initially conceived to provide information before a potential `[signal 11] Segmentation fault` happened due to improper configuration. However, given the improved handling of signals and exceptions mentioned in Section [General](#new-general), using method `Engine::isReady(std::string)` is not necessary except for providing suggestions of what could potentially cause an error.
-* Added methods `Engine::set[Input|Output]Variables(std::vector)` and `Engine::setRuleBlocks(std::vector)`.
-* Added methods `Engine::[input|output]Variables()` and `Engine::ruleBlocks()` to return mutable references.
-* Added method `Engine::variables()` to retrieve a vector (copy) containing the `InputVariables` followed by the `OutputVariables`.
-* Added method `Engine::updateReferences()` to update the references to the engine in all the necessary linguistic terms (i.e., `Linear` and `Function`).
-* Added method `Engine::clone()`.
-* Added copy constructors, assignment operators, and default move constructor to `Engine`.
-
-
-
-####<a name="new-inoutvars">Input Variables and Output Variables</a>
-* **(important)** Added methods `OutputVariable::[get|set]OutputValue()` to [retrieve|store] value from defuzzification
-* **(important)** Changed return type of `scalar OutputVariable::defuzzify()` to `void OutputVariable::defuzzify()` because now it automatically stores the defuzzified output value, and also stores the previous *valid* output value regardless of locks. Like in version 4.0, if `OutputVariable::lockPreviousOutputValue=true`, and the defuzzified output value is not valid (i.e., `[NaN|Inf]`) or no rules were activated, then the defuzzified output value is replaced for the previous valid output value.
-* Removed method `OutputVariable::defuzzifyNoLocks()`.
-* Renamed variable `OutputVariable::lastValidOutputValue` to `OutputVariable::previousOutputValue`.
-* **(important)** Renamed method `OutputVariable::[get|set]LastValidOutput()` to `OutputVariable::[get|set]PreviousOutputValue()`.
-* Renamed variable `OutputVariable::lockValidOutput` to `OutputVariable::lockPreviousOutputValue`.
-* **(important)** Renamed method `OutputVariable::setLockValidOutput()` to `OutputVariable::setLockPreviousOutputValue()`.
-* **(important)** Renamed method `OutputVariable::isLockingValidOutput()` to `OutputVariable::isLockedPreviousOutputValue()`.
-* Renamed variable `OutputVariable::lockOutputRange` to `OutputVariable::lockOutputValueInRange`.
-* **(important)** Renamed method `OutputVariable::setLockOutputRange()` to `OutputVariable::setLockOutputValueInRange()`.
-* **(important)** Renamed method `OutputVariable::isLockingOutputRange()` to `OutputVariable::isLockedOutputValueInRange()`.
-* Added methods `std::string InputVariable::fuzzyInputValue()` and `std::string OutputVariable::fuzzyOutputValue()`.
-* Added method `OutputVariable::clear()` to clear the fuzzy output, and set `OutputVariable::previousOutputValue = fl::nan` and set `OutputVariable::outputValue = fl::nan`.
-* Added copy constructors, assignment operators, move constructors and move operators to [Input|Output]Variable.
-* Added method `Variable::terms()` to return mutable reference.
-* **(important)** Changed `OutputVariable::[defuzzifier|fuzzyOutput]` to smart pointers (`FL_unique_ptr`).
-
-
-#### <a name="new-terms">Linguistic Terms</a>
-* **(VERY important)** Added Term::[get|set]Height to define the height of *integral* terms, and multiply their respective membership functions accordingly.
-* Added copy constructors, assignment operators, move constructors and move operators to every `Term`.
-* **(VERY important)** Parameters of all terms are set by default to `fl::nan`.
-* **(important)** Renamed method `Term::copy()` to `Term::clone()` in every `Term`.
-* Added method `Term::updateReference(Term*, Engine*)` to ensure `Linear` and `Function` terms have updated pointers to the `Engine` (useful when cloning and copy-constructing).
-+ **(important)** Added linguistic terms `Concave`, `Cosine` and `Spike`.
-* **(important)** Changed `Accumulated` to take `Activated*` terms instead of `const Terms*`.
-* Removed `const` from return type of method `SNorm* Accumulated::[get|set]Accumulation()`.
-* Changed `Accumulated::accumulation` to a smart pointer (`FL_unique_ptr`).
-* Added method `Accumulated::terms()` to return mutable reference.
-* **(important)** Renamed methods `Triangle::[set|get][A|B|C]` to `::[set|get]Vertex[A|B|C]`.
-* **(important)** Renamed methods `Trapezoid::[set|get][A|B|C|D]` to `::[set|get]Vertex[A|B|C|D]`.
-* **(important)** Renamed term `Thresholded` to `Activated`.
-* **(important)** Renamed methods `Thresholded::[set|get]Threshold()` to `Activated::[set|get]Degree()`.
-* Added enumeration `[Ramp|Sigmoid]::Direction{ NEGATIVE, ZERO, POSITIVE }` to refer to the slope.
-* Added methods `Ramp::direction()` and `Sigmoid::direction()` to retrieve direction of slope.
-* Removed Exception Specification from methods in `Discrete`, `Linear` and `Function` terms.
-
-#### <a name="new-linear-discrete">Linear and Discrete Terms</a>
-* **(important)** Changed `Linear` from having pointers to the input variables to having a pointer to the `Engine`.
-* Changed visibility of `Linear::coefficients` to `protected`.
-* **(important)** Added methods `Linear::coefficients()`, `Linear::setCoefficients()`.
-* `Linear` term no longer throws exception when `inputVariables != |coefficients|`.
-* **(important)** Removed public vector of variables `Discrete::[x|y]`.
-* **(important)** Added a `typedef std::pair<scalar, scalar> Discrete::Pair`.
-* **(important)** Changed representation of `Discrete::[x|y]` from `std::vector<scalar>` to `std::vector<Discrete::Pair>`.
-* Added methods `Discrete::setXY()` and `Discrete::xy()` to set and get the new representation of pairs.
-* Added methods `Discrete::xy(int index)` to retrieve `Discrete::Pair` at `index`.
-* **(important)** Added methods `Discrete::toPairs(std::vector<scalar>)` which throws an exception if the vector is missing a value (i.e., `std::vector<scalar>.size() % 2 != 0`), and `Discrete::toPairs(std::vector<scalar>, scalar missingValue)` which adds `missingValue` in case `std::vector<scalar>.size() %2 == 1`, hence never throwing an exception.
-* Added method `Discrete::toVector(std::vector<Discrete::Pair>)` to convert `std::vector<Discrete::Pair>` to a `std::vector<scalar>`.
-* Added method `Discrete::formatXY()` to get pairs `(x,y)` nicely formatted.
-
-####<a name="new-function">Function Term</a>
-* **(important)** Merged structs `Function::Operator` and `Function::BuiltInFunction` into a single `struct Function::Element`.
-* **(EXTREMELY important)** Changed the precedence of all built-in instances of `Function::Element` of type `Operator` starting from `100` and decreasing by `10`. The precedence of built-in operators is the following: `(100)` Logical not `[!]` and Negation `[~]`; `(90)` Power `[^]`; `(80)` Multiplication `[*]`, Division `[/]` and Modulo `[%]`; `(70)` Addition `[+]` and Subtraction `[-]`; `(60)` Logical AND `[and]` and Logical OR `[or]`. If you have registered your own operators, please adjust their precedence as required.
-* Added to `Function` built-in comparison functions `gt,lt,ge,le,eq` and operator logical not `!`.
-* Modified typedefs `Function::Unary` and `Function::Binary` to take `scalar` instead of `double`.
-* Changed `public Function::root` to `protected Function::_root` and it is now a smart pointer (`FL_unique_ptr`).
-* Added method `Function::root()` to return pointer to `Function::root`.
-* **(EXTREMELY important)** Moved built-in functions and operators from `Function` to a `FunctionFactory`.
-
-
-#### <a name="new-norms-hedges">[T|S]Norms and Hedges</a>
-+ **(important)** Fixed operation when using multiple hedges to operate from right-most to left-most, e.g. `if Ambient is not very extremely bright`, now evaluates as follows `not(very(extremely(bright)))`.
-+ Added `TNorm` nilpotent minimum and `SNorm` nilpotent maximum.
-* Added clone methods to every `Norm`.
-* Added clone methods to every `Hedge`.
-* **(VERY important)** Moved `Engine::hedges` to `Rule::hedges`.
-
-
-#### <a name="new-rules">Rules</a>
-* **(VERY important)** Moved `Engine::hedges` (and methods) to `Rule::hedges`.
-* Added method `Rule::isLoaded()` to determine whether a rule was properly parsed and thus can be activated.
-* Added method `Rule::unload()` to allow the existence of a rule in an inactive state (useful for invalid rules).
-* **(important)** Removed variable `Rule::FL_ASSIGNS` and method `Rule::assignsKeyword()`, for which the symbol `=` in rules is no longer valid.
-* Changed visibility of method `Rule::setText()` to `public`.
-* Added method `Rule::load(const Engine*)`.
-* Changed `Rule::[antecedent|consequent]` to smart pointers (`FL_unique_ptr`).
-* **(important)** Renamed method `Antecedent::[get|set]Root()` to `Antecedent::[get|set]Expression()`.
-* Added methods `[Antecedent|Consequent]::[get|set]Text()`.
-* **(important)** Added methods `[Antecedent|Consequent]::[load|unload]()`, with the same objective as `Rule::[load|unload]()`.
-
-#### <a name="new-ruleblocks">Rule Blocks</a>
-* Added method `RuleBlock::reloadRules()`.
-* Added method `RuleBlock::setRules(std::vector)`.
-* Added method `RuleBlock::rules()` to return mutable reference.
-* Removed `const` from `TNorm` and `SNorm` in `RuleBlock::[get|set][Conjunction|Disjunction|Activation]()`, respectively.
-* Changed `RuleBlock::[conjunction|disjunction|activation]` to smart pointers (`FL_unique_ptr`).
-* **(VERY important)** Added basic rule chaining such that an `OutputVariable` can be utilized in the `Antecedent` of a `Rule`. For example, considering the rule `if Power is high then InversePower is low`, where `Power` and `InversePower` are both output variables, the activation degree of the `Antecedent` will correspond to the accumulated activation degree of the term `high` in the fuzzy output of `Power`. If `Power::accumulation = none`, the accumulated activation degree of the term `high` will be computed as the regular sum of the activation degrees of term `high` in the fuzzy output of `Power`. Otherwise, the accumulated activation degree is computed utilizing the `Power::accumulation` operator.
-
-
-#### <a name="new-weighted">Weighted Defuzzifiers</a>
-+ **(VERY important)** Performance improvements of Takagi-Sugeno controllers by over 55% (with respect to v4.0) based on the average performance on the examples included.
-* **(important)** Created class `WeightedDefuzzifier` from which classes `Weighted[Average|Sum]` are derived.
-* **(important)** Added enumeration `WeightedDefuzzifier::Type{Automatic, TakagiSugeno, Tsukamoto}` and respective methods `WeightedDefuzzifier::[get|set]Type()` and `WeightedDefuzzifer::getTypeName()`.
-* Added method `WeightedDefuzzifier::inferType(Term*)` to automatically determine the `WeightedDefuzzifier::Type` based on the class of `Term`.
-* **(important)** By default, `WeightedDefuzzifier::type = Automatic`, which automatically infers the type based on the `WeightedDefuzzifier::inferType()`.
-* **(important)** There is a small performance penalty when using `WeightedDefuzzifier::type = Automatic` because `WeightedDefuzzifier::inferType()` performs three `dynamic_cast<>`.
-* **(important)** Deleted class `Tsukamoto`. Its method `static tsukamoto()` was moved to `virtual WeightedDefuzzifier::tsukamoto()`, which allows overriding it
-* Added support for `Tsukamoto` with `Concave` terms.
-+ **(EXTREMELY important)** In version 5.0, the traditional operation of Takagi-Sugeno and Tsukamoto controllers is achieved by setting `OutputVariable::accumulation = none`. Unlike version 4.0, the `RuleBlock::activation` will not have any effect on Takagi-Sugeno nor Tsukamoto controllers, for which `RuleBlock::activation` should also be set to `none`. More information about the roles of the `OutputVariable::accumulation` and `RuleBlock::activation` operators are detailed as follows. Refer to [sciweavers](http://www.sciweavers.org/free-online-latex-equation-editor) to convert LaTeX equations.
-+ **(VERY important)** In version 5.0, the role of the `RuleBlock::activation` `TNorm` on the `Weighted[Average|Sum]` always performs a regular multiplication of the weights and the values (i.e., $w_i \times z_j$) regardless of the `TNorm` chosen. In other words, selecting any `RuleBlock::activation` for `Weighted[Average|Sum]` is irrelevant, and should be set to `none` as every `TNorm` will have the same multiplication effect. This operation is different from `fuzzylite` version 4.0, where the `RuleBlock::activation` operator was utilized to multiply the weights and values (i.e. $w_i \otimes z_j$), and therefore the traditional operation of the `Weighted[Average|Sum]` was achieved when `RuleBlock::activation = AlgebraicProduct;`.
-+ **(VERY important)** In version 5.0, the role of the `OutputVariable::accumulation = none` on the `Weighted[Average|Sum]` results in a regular sum of the multiplied weights and values, i.e., $\dfrac{\sum_i^n w_i \times z_j}{\sum_i^n w_i}$. However, if the `OutputVariable::accumulation != none`, the role of the `SNorm` will be to accumulate the activation degrees of the *repeated* terms in the fuzzy output of the variable. For example, considering the rules `if Ambient is dark then Power is high` and `if Ambient is medium then Power is high`, for any input value of `Ambient` that activates both rules, the fuzzy output of `Power` will have the term `high` activated with the degree from `Rule 1`, and the term `high` activated with the degree from `Rule 2`. Since the term `high` appears twice in the fuzzy output, the role of the accumulation operator will be to accumulate the activation degree of `high` resulting in $\dfrac{(w_1 \oplus w_2) \times z_{high}}{(w_1 \oplus w_2)}$. If another term were activated, the result would be $\dfrac{(w_1 \oplus w_2) \times z_{high} + w_i \times z_j}{(w_1 \oplus w_2) + w_i}$. In version 4.0, the accumulation operator had no effect on the `Weighted[Average|Sum]`.
-
-
-
-#### <a name="new-integral">Integral Defuzzifiers</a>
-* **(important)** Proper handling of indefinite integral defuzzification, that is, returning `fl::nan` when `[minimum|maximum]=[NaN|Inf]`.
-* Default resolution of integration is defined as `static int IntegralDefuzzifier::defaultResolution=200`, and can be changed via `static IntegralDefuzzifier::setDefaultResolution()`.
-+ **(important)** In `fuzzylite`, the accumulation operator has been for several versions associated with the output variables and **not** with the rule blocks, despite that the FCL format and other fuzzy logic control libraries associate the accumulation operator with the rule blocks. The argument for such a decision is that `fuzzylite` provides **coherent** support for multiple rule blocks operating on the same engine and on the same output variables. For example, if multiple rule blocks operate on the same output variables, it only makes sense to have a single accumulation operator associated with each output variable such that the defuzzifier can naturally operate over the accumulated fuzzy output. Differently, if the accumulation operator were associated with the rule block, the possibility of having different accumulation operators in different rule blocks questions (1) **the possibility of having multiple rule blocks operating over the same output variables**; and (2) **the usage of different accumulation operators over the accumulation and defuzzification processes**. Certainly, if (1) is not possible, i.e, different rule blocks only operate on different output variables, then (2) is not a problem because the accumulation process and defuzzification of each variable will only have a single accumulation operator. It is therefore that the association of the accumulation operator with the output variable in `fuzzylite` provides a **better design** and an additional feature that allows having multiple rule blocks operating over the same output variables.
-* Added copy constructors, assignment operators, move constructors and move operators.
-* Added method `Defuzzifier::clone()`.
-
-####<a name="new-imex">Importers and Exporters</a>
-* **(EXTREMELY important)** Since terms have a new `height` property, `[Fll|Fis|Fcl]Exporter` exports terms with an additional `scalar` at the end, which indicates the `height` of the term. However, if `height=1.0`, the additional scalar is not exported.
-* **(EXTREMELY important)** In `[Fll|Fis|Fcl]Importer`, when importing terms, if there is an additional `scalar` it will be assumed as the `height` of the term. For example, `term: high Gaussian 1.0 0.5 0.75` will create a `Gaussian` term with mean `1.0`, standard deviation `0.5` and height `0.75`. This is **extremely important** because there are some examples from Matlab in `fis` format that append a useless `0.0` to some terms.
-* **(EXTREMELY important)** In `FisExporter`, if the Takagi-Sugeno controller has no `activation` or `accumulation` operators (as it should generally be the case), Octave and Matlab will not be able to import the `fis` file. To overcome this issue, you will have to set `ImpMethod="min"` and `AggMethod="max"`, where `ImpMethod` and `AggMethod` are just dummy operators that can be set to any `TNorm` and `SNorm`, respectively.
-+ **(important)** Improved compatibility of the exported code obtained with `[Fis|Fcl]Exporter` by exporting the additional features of `fuzzylite` only when these are different from the default operation. For example, the following features will not be exported given their values: `[Input|Output]Variable::enabled = true;`, `OutputVariable::lock-previous = false;`, `OutputVariable::lock-range = false;`, amongst others.
-* **(important)** Renamed FLL property `'lock-valid'` to `'lock-previous'`.
-* **(important)** Renamed FIS property `'LockValid'` to `'LockPrevious'`.
-* **(important)** Renamed FCL property `'LOCK: VALID'` to `'LOCK: PREVIOUS'`.
-+ **(important)** Export your controllers to files using `[Fll|Fld|Fis|Fcl]Exporter::toFile()`.
-+ **(important)** Import your controllers from files using `[Fll|Fis|Fcl]Importer::fromFile()`.
-+ **(important)** `FldExporter` exports the FuzzyLite Dataset of an engine utilizing the input values of another FuzzyLite Dataset.
-* `FldExporter` no longer restarts the engine when exporting.
-* **(important)** Renamed method `FldExporter::toWriter()` to `FldExporter::write()`.
-* Removed variable and methods for property `int FldExporter::_maximum`.
-* Added option in `CppExporter` to prepend the namespace prefix `fl::` to the classes, and by default it does not prepend prefix.
-* Improvement accuracy of `FisImporter` when importing `fis` files whose scalar values have more than three decimal numbers.
-* Renamed methods in `[Fis|Fcl]Importer::extract*` to `[Fis|Fcl]Importer::parse*`.
-
-
-
-#### <a name="new-factories">Factories</a>
-* Created a generic `CloningFactory<T>` to create clones of objects.
-* **(important)** Created `FunctionFactory` based on `CloningFactory<Function::Element>` where function operators and methods are stored to be cloned as necessary by `Function`. Additional functions and operators can be easily registered.
-* **(VERY important)** Moved built-in functions and operators from `Function` to `FunctionFactory`.
-* Renamed methods `Factory<T>::[register|deregister]Class()` to `Factory<T>::[register|deregister]Constructor()`.
-* **(important)** Renamed `Factory<T>` to `ConstructionFactory<T>`.
-* Renamed `typedef Factory::Creator` to `typedef Factory::Constructor`.
-* Changed pointers of `FactoryManager` to smart pointers (`FL_unique_ptr`).
-
-
-
-#### <a name="new-examples">Examples</a>
-* **(important)** Added two examples for basic rule chaining: `mamdani/SimpleDimmerInverse.fll` and `mamdani/Laundry.fll`.
-* Included the `original` example files in `fis` format.
-* Added conversion of `examples/original/*.fis` to `examples/original/*.fll`.
-* Modified `original/takagi-sugeno` examples to reflect `activation: none; accumulation: none;`.
-* Updated FLD examples produced from the `original` examples.
-+ **(important)** Added file [`fuzzylite/src/m/compare.m`](/fuzzylite/src/m/compare.m) <!---check link--> to compare the output values of your `fuzzylite` engines with the evaluation of the same engine in Octave/Matlab.
-+ **(important)** Added file [`examples/examples.mat`](/examples/examples.mat) <!---check link--> containing the comparison of the output values between `fuzzylite` and Matlab's Fuzzy Logic Toolbox.
-* Added code to perform benchmarks in Linux.
-
-
-#### <a name="new-console">Console</a>
-* **(important)** Console includes option to import custom input dataset from file an export its respective output values.
-* **(important)** Created the FuzzyLite Interactive Console, which can be started by specifying an input file and the output format, e.g., `fuzzylite -i SimpleDimmer.fll -of fld`.
-* Console provides more information about its usage.
-
-
-
-####<a name="new-fixes"> Fixes Bugs and Leaks</a>
-+ **(important)** Fixed operation when using multiple hedges to operate from right-most to left-most, e.g. `if Ambient is not very extremely bright` evaluates as follows `not(very(extremely(bright)))`.
-* **(important)** Fixed membership functions of specific cases of `Triangle` when `a=b` or `b=c`, and `Trapezoid` when `a=b` or `c=d`.
-* Fixed minor memory leak at `~RuleBlock::[conjunction|disjunction|activation]`.
-* Fixed minor memory leak at `~Accumulated::accumulation`.
-* Fixed minor memory leak at `~OutputVariable::defuzzifier`.
-* Fixed minor memory leak at `~Function::Node`.
-* Fixed minor memory leak at `~FactoryManager::[factories]`.
-* Fixed some rethrowing of exceptions to provide proper information about errors. Specifically, changed some rethrown exceptions from `throw ex;` to just `throw;`
-* Fixed building using `-DFL_USE_FLOAT=ON`
-
-
-***
-
-For more information, visit [www.fuzzylite.com](http://www.fuzzylite.com).
-
-fuzzylite&trade; is a trademark of FuzzyLite Limited.
-
-Copyright &#xa9; 2010-2014 FuzzyLite Limited. All rights reserved. \ No newline at end of file
+* New R scripts for each example and its respective surfaces in `pdf` formats. \ No newline at end of file
diff --git a/README.md b/README.md
index 21c873a..0453b8a 100644
--- a/README.md
+++ b/README.md
@@ -1,149 +1,301 @@
-fuzzylite &reg; [![Build Status](https://travis-ci.org/fuzzylite/fuzzylite.svg?branch=v5.x)](https://travis-ci.org/fuzzylite/fuzzylite) <img src="https://github.com/fuzzylite/fuzzylite/raw/v5.x/fuzzylite.png" align="right" alt="fuzzylite">
-===========
+fuzzylite 6.0 &reg;
+=================
+<img src="https://raw.githubusercontent.com/fuzzylite/fuzzylite/release/fuzzylite.png" align="right" alt="fuzzylite">
+
A Fuzzy Logic Control Library in C++
------------------------------------
By: [Juan Rada-Vilela](http://www.fuzzylite.com/jcrada), Ph.D.
+Released: 20/March/2017
+
+[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0)
+[![Build Status](https://travis-ci.org/fuzzylite/fuzzylite.svg?branch=release)](https://travis-ci.org/fuzzylite/fuzzylite)
+[![Build status](https://ci.appveyor.com/api/projects/status/065g596yxdhkt2se/branch/release)](https://ci.appveyor.com/project/jcrada/fuzzylite/branch/release)
+[![Coverity Status](https://scan.coverity.com/projects/5759/badge.svg)](https://scan.coverity.com/projects/5759)
***
### Table of Contents
-[License](#license) &nbsp;
-[Introduction](#introduction) &nbsp;
-[Features](#features) &nbsp;
-[Example](#example) &nbsp;
-[Bulding from source](#building) &nbsp;
-[Binaries](#binaries) &nbsp;
-[What's next](#whatsnext) &nbsp;
-[What's new](#whatsnew) : [General](#new-general), [Macros](#new-macros), [Operation](#new-operation), [Engine](#new-engine), [Input Variables and Output Variables](#new-inoutvars), [Linguistic Terms](#new-terms), [Linear and Discrete Terms](#new-linear-discrete), [Function Term](#new-function), [[T|S]Norms and Hedges](#new-norms-hedges), [Rules](#new-rules), [Rule Blocks](#new-ruleblocks), [Weighted Defuzzifiers](#new-weighted), [Integral Defuzzifiers](#new-integral), [Importers and Exporters](#new-imex), [Examples](#new-examples), [Console](#new-console), [Fixed Bugs and Leaks](#new-fixes)
+[License](#license) <br/>
+[Introduction](#introduction)<br/>
+[Features](#features)<br/>
+[Example](#example) <br/>
+[Compile, Link, and Execute](#compile-build-execute)<br/>
+[Bulding from Source](#building)<br/>
+[Binaries](#binaries) <br/>
+[What's new](#whatsnew)<br/>
+[What's next](#whatsnext) <br/>
-### <a name="license">License</a>
-`fuzzylite` will **always** be free and open source. However, `fuzzylite` is **no** longer released under the Apache License. Since version 5.0, `fuzzylite` is **dual-licensed** under the [**GNU Lesser General Public License (LGPL) v3.0**](https://www.gnu.org/licenses/lgpl.html) and a **paid commercial license**.
-
-In brief, an important restriction the LGPL imposes on your closed-source application is that **you are no longer allowed to statically link** against `fuzzylite`. If your application requires static linking, **you will need to purchase a commercial license** from FuzzyLite Limited. Please, contact [sales@fuzzylite.com](mailto:sales@fuzzylite.com) for commercial licenses, and refer to the [GNU LGPL](https://www.gnu.org/licenses/lgpl.html) for further information on your rights.
-The change of license is an attempt to raise funds in order to be able to work part-time in the development of the `fuzzylite` family of products, namely `fuzzylite` (C++), `jfuzzylite` (Java), `pyfuzzylite` (Python), and `QtFuzzyLite` (Windows/Linux/Mac).
-
-**There are still many things to do!**
+***
-Besides [donations](http://www.fuzzylite.com/donations/), you can significantly contribute by **purchasing a license** of the entirely new [`QtFuzzyLite`](http://www.fuzzylite.com/QtFuzzyLite/) commercial application. In addition, if you require (paid) private support, please contact [jcrada@fuzzylite.com](mailto:jcrada@fuzzylite.com).
+### <a name="license">License</a>
+`fuzzylite 6.0` is licensed under the [**GNU General Public License (GPL) 3.0**](https://www.gnu.org/licenses/gpl.html). You are **strongly** encouraged to support the development of the FuzzyLite Libraries by purchasing a license of [`QtFuzzyLite 6`](http://www.fuzzylite.com/downloads).
+[`QtFuzzyLite 6`](http://www.fuzzylite.com/downloads/) is the new and (very likely) the best graphical user interface available to easily design and directly operate fuzzy logic controllers in real time. Available for Windows, Mac, and Linux, its goal is to significantly **speed up** the design of your fuzzy logic controllers, while providing a very **useful**, **functional** and **beautiful** user interface.
+Please, download it and check it out for free at [www.fuzzylite.com/downloads/](http://www.fuzzylite.com/downloads/).
***
+### <a name="introduction">Introduction</a>
-### <a name="introduction">Introduction</a>
-`fuzzylite` is a free and open-source fuzzy logic control library programmed in C++ for multiple platforms (Windows, Linux, Mac, iOS). Its goal is to allow you to easily create fuzzy logic controllers in a few steps utilizing object-oriented programming without requiring any third-party libraries.
+`fuzzylite` is a free and open-source fuzzy logic control library programmed in C++ for multiple platforms (e.g., Windows, Linux, Mac, iOS). [`jfuzzylite`](https://github.com/fuzzylite/jfuzzylite/) is the equivalent library for Java and Android platforms. Together, they are the FuzzyLite Libraries for Fuzzy Logic Control.
+
+<center>
+```
+The goal of the FuzzyLite Libraries is to easily design and efficiently operate fuzzy logic controllers following an object-oriented programming model without relying on external libraries.
+```
+</center>
#### Reference
-If you are using `fuzzylite`, please cite the following reference in your article:
+If you are using the FuzzyLite Libraries, please cite the following reference in your article:
-Juan Rada-Vilela. fuzzylite: a fuzzy logic control library, 2014. URL http://www.fuzzylite.com.
+Juan Rada-Vilela. fuzzylite: a fuzzy logic control library, 2017. URL http://www.fuzzylite.com/.
```bibtex
@misc{fl::fuzzylite,
author={Juan Rada-Vilela},
title={fuzzylite: a fuzzy logic control library},
- url={http://www.fuzzylite.com},
- year={2014}}
+ url={http://www.fuzzylite.com/},
+ year={2017}}
```
+#### Documentation
+The documentation for the `fuzzylite` library is available at: [www.fuzzylite.com/documentation/](http://www.fuzzylite.com/documentation/).
+
***
### <a name="features">Features</a>
-**Controllers** *Types* (5) Mamdani, Takagi-Sugeno, Larsen, Tsukamoto, Inverse Tsukamoto
+**(6) Controllers**: Mamdani, Takagi-Sugeno, Larsen, Tsukamoto, Inverse Tsukamoto, Hybrids
+
+**(21) Linguistic terms**: (4) *Basic*: triangle, trapezoid, rectangle, discrete.
+(9) *Extended*: bell, cosine, gaussian, gaussian product, pi-shape, sigmoid difference, sigmoid product, spike.
+(5) *Edges*: binary, concave, ramp, sigmoid, s-shape, z-shape.
+(3) *Functions*: constant, linear, function.
+
+**(7) Activation methods**: general, proportional, threshold, first, last, lowest, highest.
-**Linguistic terms** *Basic* (4) triangle, trapezoid, rectangle, discrete. *Extended* (9) bell, cosine, gaussian, gaussian product, pi-shape, sigmoid difference, sigmoid product, spike. *Edges* (4) concave, ramp, sigmoid, s-shape, z-shape. *Functions* (3) constant, linear, function.
+**(8) Conjunction and Implication (T-Norms)**: minimum, algebraic product, bounded difference, drastic product, einstein product, hamacher product, nilpotent minimum, function.
-**Conjunction and Activation** *T-Norm* (7) minimum, algebraic product, bounded difference, drastic product, einstein product, hamacher product, nilpotent minimum.
+**(10) Disjunction and Aggregation (S-Norms)**: maximum, algebraic sum, bounded sum, drastic sum, einstein sum, hamacher sum, nilpotent maximum, normalized sum, unbounded sum, function.
-**Disjunction and Accumulation** *S-Norm* (8) maximum, algebraic sum, bounded sum, normalized sum, drastic sum, einstein sum, hamacher sum, nilpotent maximum.
+**(7) Defuzzifiers**: (5) *Integral*: centroid, bisector, smallest of maximum, largest of maximum, mean of maximum.
+(2) *Weighted*: weighted average, weighted sum.
-**Defuzzifiers** *Integral* (5) centroid, bisector, smallest of maximum, largest of maximum, mean of maximum, *Weighted* (2) weighted average, weighted sum.
+**(7) Hedges**: any, not, extremely, seldom, somewhat, very, function.
-**Hedges** *Types* (6) any, not, extremely, seldom, somewhat, very.
+**(3) Importers**: FuzzyLite Language `fll`, Fuzzy Inference System `fis`, Fuzzy Control Language `fcl`.
+
+**(7) Exporters**: `C++`, `Java`, FuzzyLite Language `fll`, FuzzyLite Dataset `fld`, `R` script, Fuzzy Inference System `fis`, Fuzzy Control Language `fcl`.
+
+**(30+) Examples** of Mamdani, Takagi-Sugeno, Tsukamoto, and Hybrid controllers from `fuzzylite`, Octave, and Matlab, each included in the following formats: `C++`, `Java`, `fll`, `fld`, `R`, `fis`, and `fcl`.
-**Import** *Types* (3) FuzzyLite Language `fll`, Fuzzy Inference System `fis`, Fuzzy Control Language `fcl`.
-**Export** *Types* (6) `C++`, `Java`, FuzzyLite Language `fll`, FuzzyLite Dataset `fld`, Fuzzy Inference System `fis`, Fuzzy Control Language `fcl`.
-**Examples** (30+) of Mamdani, Takagi-Sugeno and Tsukamoto controllers from `fuzzylite`, Octave and Matlab, each included in the following formats: `C++`, `Java`, `fll`, `fld`, `fis`, and `fcl`.
***
### <a name="example">Example</a>
+#### FuzzyLite Language
+```yaml
+#File: ObstacleAvoidance.fll
+Engine: ObstacleAvoidance
+InputVariable: obstacle
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: mSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 100
+ default: nan
+ lock-previous: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+RuleBlock: mamdani
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: AlgebraicProduct
+ activation: General
+ rule: if obstacle is left then mSteer is right
+ rule: if obstacle is right then mSteer is left
+```
+```cpp
+//File: ObstacleAvoidance.cpp
+#include "fl/Headers.h"
+
+int main(int argc, char* argv[]){
+ using namespace fl;
+ Engine* engine = FllImporter().fromFile("ObstacleAvoidance.fll");
+
+ std::string status;
+ if (not engine->isReady(&status))
+ throw Exception("[engine error] engine is not ready:\n" + status, FL_AT);
+
+ InputVariable* obstacle = engine->getInputVariable("obstacle");
+ OutputVariable* steer = engine->getOutputVariable("mSteer");
+
+ for (int i = 0; i <= 50; ++i){
+ scalar location = obstacle->getMinimum() + i * (obstacle->range() / 50);
+ obstacle->setValue(location);
+ engine->process();
+ FL_LOG("obstacle.input = " << Op::str(location) <<
+ " => " << "steer.output = " << Op::str(steer->getValue()));
+ }
+}
+```
+#### C++
```cpp
+//File: ObstacleAvoidance.cpp
#include "fl/Headers.h"
int main(int argc, char* argv[]){
using namespace fl;
- Engine* engine = new Engine("simple-dimmer");
-
- InputVariable* ambient = new InputVariable;
- ambient->setName("Ambient");
- ambient->setRange(0.000, 1.000);
- ambient->addTerm(new Triangle("DARK", 0.000, 0.500));
- ambient->addTerm(new Triangle("MEDIUM", 0.250, 0.750));
- ambient->addTerm(new Triangle("BRIGHT", 0.500, 1.000));
- engine->addInputVariable(ambient);
-
- OutputVariable* power = new OutputVariable;
- power->setName("Power");
- power->setRange(0.000, 2.000);
- power->setDefaultValue(fl::nan);
- power->addTerm(new Triangle("LOW", 0.000, 1.000));
- power->addTerm(new Triangle("MEDIUM", 0.500, 1.500));
- power->addTerm(new Triangle("HIGH", 1.000, 2.000));
- engine->addOutputVariable(power);
-
- RuleBlock* ruleblock = new RuleBlock;
- ruleblock->addRule(Rule::parse("if Ambient is DARK then Power is HIGH", engine));
- ruleblock->addRule(Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
- ruleblock->addRule(Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
- engine->addRuleBlock(ruleblock);
-
- engine->configure("", "", "Minimum", "Maximum", "Centroid");
+ //Code automatically generated with fuzzylite 6.0.
+
+ using namespace fl;
+
+ Engine* engine = new Engine;
+ engine->setName("ObstacleAvoidance");
+ engine->setDescription("");
+
+ InputVariable* obstacle = new InputVariable;
+ obstacle->setName("obstacle");
+ obstacle->setDescription("");
+ obstacle->setEnabled(true);
+ obstacle->setRange(0.000, 1.000);
+ obstacle->setLockValueInRange(false);
+ obstacle->addTerm(new Ramp("left", 1.000, 0.000));
+ obstacle->addTerm(new Ramp("right", 0.000, 1.000));
+ engine->addInputVariable(obstacle);
+
+ OutputVariable* mSteer = new OutputVariable;
+ mSteer->setName("mSteer");
+ mSteer->setDescription("");
+ mSteer->setEnabled(true);
+ mSteer->setRange(0.000, 1.000);
+ mSteer->setLockValueInRange(false);
+ mSteer->setAggregation(new Maximum);
+ mSteer->setDefuzzifier(new Centroid(100));
+ mSteer->setDefaultValue(fl::nan);
+ mSteer->setLockPreviousValue(false);
+ mSteer->addTerm(new Ramp("left", 1.000, 0.000));
+ mSteer->addTerm(new Ramp("right", 0.000, 1.000));
+ engine->addOutputVariable(mSteer);
+
+ RuleBlock* mamdani = new RuleBlock;
+ mamdani->setName("mamdani");
+ mamdani->setDescription("");
+ mamdani->setEnabled(true);
+ mamdani->setConjunction(fl::null);
+ mamdani->setDisjunction(fl::null);
+ mamdani->setImplication(new AlgebraicProduct);
+ mamdani->setActivation(new General);
+ mamdani->addRule(Rule::parse("if obstacle is left then mSteer is right", engine));
+ mamdani->addRule(Rule::parse("if obstacle is right then mSteer is left", engine));
+ engine->addRuleBlock(mamdani);
std::string status;
if (not engine->isReady(&status))
- throw Exception("Engine not ready. "
- "The following errors were encountered:\n" + status, FL_AT);
+ throw Exception("[engine error] engine is not ready:\n" + status, FL_AT);
- for (int i = 0; i < 50; ++i){
- scalar light = ambient->getMinimum() + i * (ambient->range() / 50);
- ambient->setInputValue(light);
+ for (int i = 0; i <= 50; ++i){
+ scalar location = obstacle->getMinimum() + i * (obstacle->range() / 50);
+ obstacle->setValue(location);
engine->process();
- FL_LOG("Ambient.input = " << Op::str(light) << " -> " <<
- "Power.output = " << Op::str(power->getOutputValue()));
+ FL_LOG("obstacle.input = " << Op::str(location) <<
+ " => " << "steer.output = " << Op::str(steer->getValue()));
}
}
```
-***
+### <a name="compile-build-execute">Compile, Link, and Execute</a>
+
+Once you have an engine written in C++, you can compile it to create an executable file which links to the `fuzzylite` library. The linking can be either static or dynamic. Basically, the differences between static and dynamic linking are the following. **Static linking** includes the `fuzzylite` library into your executable file, hence increasing its size, but the executable no longer needs to have access to the `fuzzylite` library files. **Dynamic linking** does not include the `fuzzylite` library into your executable file, hence reducing its size, but the executable needs to have access to the `fuzzylite` shared library file. When using dynamic linking, make sure that the shared library files are either in the same directory as the executable, or are reachable via environmental variables:
+
+```posh
+rem Windows:
+set PATH="\path\to\fuzzylite\release\bin;%PATH%"
+```
+```bash
+#Unix:
+export LD_LIBRARY_PATH="/path/to/fuzzylite/release/bin/:$LD_LIBRARY_PATH"
+```
+
+#### Windows
+The commands to compile your engine in Windows are the following:
+
+C++11 (default)
+```posh
+rem static linking:
+cl.exe ObstacleAvoidance.cpp fuzzylite-static.lib /Ipath/to/fuzzylite /EHsc /MD
+```
+```posh
+rem dynamic linking:
+cl.exe ObstacleAvoidance.cpp fuzzylite.lib /Ipath/to/fuzzylite /DFL_IMPORT_LIBRARY /EHsc /MD
+```
+
+C++98
+```posh
+rem static linking:
+cl.exe ObstacleAvoidance.cpp fuzzylite-static.lib /Ipath/to/fuzzylite /DFL_CPP98=ON /EHsc /MD
+```
+```posh
+rem dynamic linking:
+cl.exe ObstacleAvoidance.cpp fuzzylite.lib /Ipath/to/fuzzylite /DFL_IMPORT_LIBRARY /DFL_CPP98=ON /EHsc /MD
+```
+
+#### Unix
+The commands to compile your engine in Unix are the following:
+
+C++11 (default)
+```bash
+#static linking
+g++ ObstacleAvoidance.cpp -o ObstacleAvoidance -I/path/to/fuzzylite -L/path/to/fuzzylite/release/bin -lfuzzylite-static --std=c++11
+```
+```bash
+#dynamic linking
+g++ ObstacleAvoidance.cpp -o ObstacleAvoidance -I/path/to/fuzzylite -L/path/to/fuzzylite/release/bin -lfuzzylite -Wno-non-literal-null-conversion
+```
+
+C++98
+```bash
+#static linking
+g++ ObstacleAvoidance.cpp -o ObstacleAvoidance -I/path/to/fuzzylite -L/path/to/fuzzylite/release/bin -lfuzzylite-static -DFL_CPP98=ON
+```
+```bash
+#dynamic linking
+g++ ObstacleAvoidance.cpp -o ObstacleAvoidance -I/path/to/fuzzylite -L/path/to/fuzzylite/release/bin -lfuzzylite -DFL_CPP98=ON -Wno-non-literal-null-conversion
+```
+
+#### CMake
+Alternatively, you can use CMake to build your project linking to `fuzzylite`. Please, refer to the example application available at [examples/application]([/examples/application]).
-### <a name="whatsnext">What's Next?</a>
-+ Source code documentation
-+ Type-2 Fuzzy Logic Controllers
-+ Adaptive Neuro-Fuzzy Inference System (ANFIS)
-+ Fuzzy C-means data clustering
***
-### <a name="building">Building from Source</a>
-Building from source requires you to have CMake installed.
-The files [`fuzzylite/build.bat`](/fuzzylite/build.bat) and [`fuzzylite/build.sh`](/fuzzylite/build.sh) are automatic build scripts for Windows and Unix platforms, respectively. The usage of these scripts is presented as follows.
+### <a name="building">Building from Source</a>
+You can build the `fuzzylite` library from source using `CMake` [(cmake.org)](https://cmake.org/).
+
+The files [`fuzzylite/build.bat`](/fuzzylite/build.bat) and [`fuzzylite/build.sh`](/fuzzylite/build.sh) are build scripts for the Windows and Unix platforms, respectively.
+After building from source, the resulting binaries will be located in the sub-folders `fuzzylite/release/bin` and `fuzzylite/debug/bin`. The usage of these scripts is presented as follows.
#### Windows
```bash
@@ -169,26 +321,34 @@ where [options] can be any of the following:
help shows this information
```
-**(important)** After executing the building script, the binaries will be built and stored in the sub-folders `release/bin` and `debug/bin`.
-#### Advanced Building Options
-For more advanced building options, please check the contents of [`fuzzylite/build.bat`](/fuzzylite/build.bat) or [`fuzzylite/build.sh`](/fuzzylite/build.sh), and the contents of [`fuzzylite/CMakeLists.txt`](/fuzzylite/CMakeLists.txt).
-The following building options are available:
+#### Building Options
+For advanced building options, please check the contents of [`fuzzylite/build.bat`](/fuzzylite/build.bat) or [`fuzzylite/build.sh`](/fuzzylite/build.sh), and the contents of [`fuzzylite/CMakeLists.txt`](/fuzzylite/CMakeLists.txt).
+
+The following building options available:
+
+* `-DFL_USE_FLOAT=ON` builds the binaries utilizing the `fl::scalar` data type as a `float` represented in 4 bytes. By default, the binaries are built utilizing `-DFL_USE_FLOAT=OFF` to utilize `fl::scalar` as a `double` represented in 8 bytes and hence providing better accuracy. If `fuzzylite` is built with `-DFL_USE_FLOAT=ON`, then the applications linking to `fuzzylite` also need to specify this compilation flag.
+
+
+* `-DFL_CPP98=ON` builds binaries utilizing `C++98` features. By default, `fuzzylite` is built with `-DFL_CPP98=OFF` to utilize `C++11` features. If compiling for `C++98`, be aware that you will not be able to benchmark the performance of your engine using the `Benchmark` class.
-`-DFL_USE_FLOAT=ON` builds the binaries using `typedef float fl::scalar` instead of `typedef double fl::scalar` (default is OFF, i.e., double is used)
-`-DFL_BACKTRACE=OFF` disables the backtrace information in case of errors (default in Unix platforms is ON, and in Windows platforms is OFF). In Windows, the backtrace information requires the library `dbghelp`, which should be available in your system.
+* `-DFL_BACKTRACE=OFF` disables the backtrace information in case of errors (default is ON). In Windows, the backtrace information requires the external library `dbghelp`, which is generally available in your system.
+
+* `-DCMAKE_BUILD_TYPE=[Debug|Release]` sets the mode of your build. You can only build one mode at a time with a single CMake script.
+
+
+#### Documentation
+The source code of `fuzzylite` is very well documented using [`doxygen`](www.doxygen.org/) formatting, and the documentation is available at [fuzzylite.com/documentation](http://fuzzylite.com/documentation). If you want to generate the documentation locally, you can produce the `html` documentation from the file [Doxyfile](/Doxyfile) using the command line: `doxygen Doxyfile`. The documentation will be created in the [`documentation`](/documentation) folder.
-`-DFL_CPP11=ON` builds `fuzzylite` utilizing `C++11` features (default is OFF, i.e., `C++98`)
-`-DCMAKE_BUILD_TYPE=[Debug|Release]` sets the mode of your build. You can only build one mode at a time with a single CMake script.
***
### <a name="binaries">Binaries</a>
-After building from source, the following are the relevant binaries that will be created in `release` mode. In `debug` mode, binaries will append a `d` at the end of the name (e.g., `fuzzylited.dll`).
+After building from source, the following are the relevant binaries that will be created in `Release` mode. In `Debug` mode, the file names end with `-debug` (e.g., `fuzzylite-debug.exe`).
#### Windows
@@ -200,256 +360,98 @@ After building from source, the following are the relevant binaries that will be
- console application: `fuzzylite`
- shared library: `libfuzzylite.so`
-- static library: `libfuzzylite.a`
+- static library: `libfuzzylite-static.a`
#### Mac
- console application: `fuzzylite`
- shared library: `libfuzzylite.dylib`
-- static library: `libfuzzylite.a`
+- static library: `libfuzzylite-static.a`
+
+#### Console
+The console application of `fuzzylite` allows you to import and export your engines. Its usage can be obtained executing the console binary. In addition, the console can be set in interactive mode. The `FuzzyLite Interactive Console` allows you to evaluate a given controller by manually providing the input values. The interactive console is triggered by specifying an input file and an output format. For example, to interact with the `ObstacleAvoidance` controller, the interactive console is launched as follows:
+
+```bash
+fuzzylite -i ObstacleAvoidance.fll -of fld
+```
-The console application of `fuzzylite` allows you to import and export your controllers. Its usage can be obtained executing the console binary. In addition, the FuzzyLite Interactive Console is activated when exporting to `fld` without providing an output file. The interactive console allows you to evaluate any controller by manually providing the input the values.
***
### <a name="whatsnew">What's New?</a>
-The entire `fuzzylite` library has been thoroughly revised, refactored, validated, and significantly improved. The following sections detail the changes and enhancements of version 5.0. Users of previous versions are **strongly** encouraged to carefully read the list before migrating to version 5.0. Important changes and enhancements are marked as **(important)**, **(VERY important)** and **(EXTREMELY important)**.
-
-#### <a name="new-general">General</a>
-+ **(important)** `fuzzylite v5.0` is dual-licensed under the [GNU LGPL v3.0](https://www.gnu.org/licenses/lgpl.html) and a paid commercial license.
-+ Support for both `C++98` and `C++11` using the latest features.
-+ Support for multiple compilers `g++`, `Clang`, `MSVC`.
-+ Refactoring of many classes to improve design and performance.
-+ **(important)** Performance improvements of Takagi-Sugeno controllers by over 55% with respect to v4.0 (estimate based on the average performance on the examples included).
-+ Smart pointers in many classes take care of automatically deleting objects when setting new pointers (`Accumulated`, `FactoryManager`, `Function`, `OutputVariable`, `Rule`, and `RuleBlock`).
-* **(important)** Exceptions are thrown when any of the following `RuleBlock::[conjunction|disjunction|activation]`, `Accumulated::accumulation`, and `OutputVariable::defuzzifier` are required but set to `fl::null`, thereby replacing the operations that would lead to `[signal 11] Segmentation fault` to operations that throw a `fl::Exception` instead.
-+ Automatic build script to build `fuzzylite` in `debug` and `release` mode.
-+ Binaries of debug libraries are renamed to append the letter `d` (e.g.,`fuzzylited.dll`, `libfuzzylited.so`).
-+ **(important)** New file [`fuzzylite/src/m/compare.m`](/fuzzylite/src/m/compare.m) <!---check link--> to compare the output values of your `fuzzylite` engines with the evaluation of the same engine in Octave/Matlab.
-+ **(important)** There is practically no difference between the output values obtained with `fuzzylite` and those obtained with Octave/Matlab. Based on the examples, the average mean square error (MSE) between the output values is less than `7.3e-12` (or `0.0000000000073`) due to negligible differences in floating-point arithmetic. The results and comparison can be found in [`examples/examples.mat`](/examples/examples.mat) <!---check link-->.
-+ **(important)** Source code of applications based on version 4.0 will most likely not compile with version 5.0.
-+ Minor bugs and memory leaks fixed.
-
-####<a name="new-macros">Macros</a>
-* **(important)** Added support for `C++11` with smart pointers, method identifiers, move constructors and move operators as follows. For precise information, refer to file [`fuzzylite/fl/fuzzylite.h`](/fuzzylite/fl/fuzzylite.h). <!---check link-->
-* **(important)** Macros for identifiers are defined as `FL_IOVERRIDE override`, `FL_IFINAL final`, `FL_IDEFAULT = default`, `FL_IDELETE = delete`, `FL_INOEXCEPT noexcept`, `FL_DEFAULT_COPY(Class)`, `FL_DEFAULT_MOVE(Class)`, and `FL_DEFAULT_COPY_AND_MOVE(Class)`.
-* **(important)** Added macro `FL_unique_ptr` to refer to `std::auto_ptr` (`C++98`) or `std::unique_ptr` (`C++11`), and its respective `FL_move_ptr(x)` to move a smart pointer, albeit `FL_move_ptr(x)` is not used within the library as it is not needed.
-* **(important)** Added global variables `const long fl::null = 0L` to refer to the null pointer in `C++98` and `const std::nullptr_t null = nullptr` to refer to the null pointer in `C++11`.
-* **(important)** Renamed macro `FL_DEBUG` to `FL_DBG`.
-* **(important)** Renamed macros `FL_BEGIN_DEBUG_BLOCK` and `FL_END_DEBUG_BLOCK` to `FL_DEBUG_BEGIN` and `FL_DEBUG_END`, respectively.
-* **(important)** Renamed macro `FL_EXPORT` to `FL_API`
-* **(EXTREMELY important)** Added macro definitions `FL_EXPORT_LIBRARY` and `FL_IMPORT_LIBRARY`. If you are building `fuzzylite` as a **shared library**, you need to define `FL_EXPORT_LIBRARY`. If you are building `fuzzylite` **executable** *and* it utilizes the `fuzzylite` **shared library**, you need to define `FL_IMPORT_LIBRARY`. If you are building `fuzzylite` as a **static library** and/or building `fuzzylite` **executable** using the `fuzzylite` **static library**, then you do not need to define either `FL_[IMPORT|EXPORT]_LIBRARY`. Note that the same conditions apply for your application. This is particularly important in Windows platforms, as `FL_IMPORT_LIBRARY` and `FL_EXPORT_LIBRARY` define `FL_API` to `__declspec(dllimport)` and `__declspec(dllexport)`, respectively. If in doubt, please check [`fuzzylite/CMakeLists.txt`](/fuzzylite/CMakeLists.txt)<!---check link-->
-
-#### <a name="new-operation">Operation</a>
-* **(important)** Added method `Operation::toScalar(std::string x, scalar alternative) FL_INOEXCEPT` which returns `alternative` if `x` is not a valid `scalar`, and never throws an exception.
-* **(important)** Added method `Operation::toScalar(std::string x)` that returns the scalar value of `x` or throws a `fl::Exception` if `x` is not a valid `scalar`.
-* **(VERY important)** Marked method (from v4.0) `Operation::toScalar(std::string, bool, scalar) FL_IDELETE;` and removed its implementation such that its usage is prevented at compile time in `C++11` and at linker time in `C++98`. Please, use the appropriate `Op::toScalar` methods mentioned above.
-+ Renamed method `Op::isNan` to `Op::isNaN`.
-* Added method `fl::Op::isFinite(x)` which returns `not (isNaN(x) or isInf(x))`.
-* Changed `fl::Op::isEq(a,b)` to return `true` if `a == b == NaN`.
-* Changed `fl::Op::isEq(a,b)` to return `true` if `a == b == Inf`.
-* Changes to `fl::Op::isEq` affect other comparison methods `fl::Op::is[Lt|LEq|GEq|Gt]`.
-* Added shortcuts of comparisons `fl::Op::[gt,lt,ge,le,eq,neq](scalar a, scalar b)`, mostly to provide binary versions (without `macheps`) for term `Function`.
-* Deleted method `Op::repeat`.
-* Removed method `fuzzylite::configuration()`.
-* Changed default `fuzzylite::_macheps = 1e-6;`.
-* Renamed method `Op::makeValidId` to `Op::validName`, which now returns `"unnamed"` for empty strings.
-
-
-
-####<a name="new-engine">Engine</a>
-* **(VERY important)** Moved `Engine::hedges` (and relevant methods) to `Rule::hedges`.
-* Added enumeration for the type of engine: `enum Engine::Type{Mamdani, Larsen, TakagiSugeno, Tsukamoto, InverseTsukamoto, Hybrid, Unknown}`.
-* Added method `Type Engine::type(std::string* name, std::string* reason)` to infer the type of the engine based on its configuration, additionally provides the name of the type and the inference reasons for its type.
-* **(important)** Changed method `Engine::isReady(std::string)` to satisfy the default operation of controllers. The method `Engine::isReady(std::string)` was initially conceived to provide information before a potential `[signal 11] Segmentation fault` happened due to improper configuration. However, given the improved handling of signals and exceptions mentioned in Section [General](#new-general), using method `Engine::isReady(std::string)` is not necessary except for providing suggestions of what could potentially cause an error.
-* Added methods `Engine::set[Input|Output]Variables(std::vector)` and `Engine::setRuleBlocks(std::vector)`.
-* Added methods `Engine::[input|output]Variables()` and `Engine::ruleBlocks()` to return mutable references.
-* Added method `Engine::variables()` to retrieve a vector (copy) containing the `InputVariables` followed by the `OutputVariables`.
-* Added method `Engine::updateReferences()` to update the references to the engine in all the necessary linguistic terms (i.e., `Linear` and `Function`).
-* Added method `Engine::clone()`.
-* Added copy constructors, assignment operators, and default move constructor to `Engine`.
-
-
-
-####<a name="new-inoutvars">Input Variables and Output Variables</a>
-* **(important)** Added methods `OutputVariable::[get|set]OutputValue()` to [retrieve|store] value from defuzzification
-* **(important)** Changed return type of `scalar OutputVariable::defuzzify()` to `void OutputVariable::defuzzify()` because now it automatically stores the defuzzified output value, and also stores the previous *valid* output value regardless of locks. Like in version 4.0, if `OutputVariable::lockPreviousOutputValue=true`, and the defuzzified output value is not valid (i.e., `[NaN|Inf]`) or no rules were activated, then the defuzzified output value is replaced for the previous valid output value.
-* Removed method `OutputVariable::defuzzifyNoLocks()`.
-* Renamed variable `OutputVariable::lastValidOutputValue` to `OutputVariable::previousOutputValue`.
-* **(important)** Renamed method `OutputVariable::[get|set]LastValidOutput()` to `OutputVariable::[get|set]PreviousOutputValue()`.
-* Renamed variable `OutputVariable::lockValidOutput` to `OutputVariable::lockPreviousOutputValue`.
-* **(important)** Renamed method `OutputVariable::setLockValidOutput()` to `OutputVariable::setLockPreviousOutputValue()`.
-* **(important)** Renamed method `OutputVariable::isLockingValidOutput()` to `OutputVariable::isLockedPreviousOutputValue()`.
-* Renamed variable `OutputVariable::lockOutputRange` to `OutputVariable::lockOutputValueInRange`.
-* **(important)** Renamed method `OutputVariable::setLockOutputRange()` to `OutputVariable::setLockOutputValueInRange()`.
-* **(important)** Renamed method `OutputVariable::isLockingOutputRange()` to `OutputVariable::isLockedOutputValueInRange()`.
-* Added methods `std::string InputVariable::fuzzyInputValue()` and `std::string OutputVariable::fuzzyOutputValue()`.
-* Added method `OutputVariable::clear()` to clear the fuzzy output, and set `OutputVariable::previousOutputValue = fl::nan` and set `OutputVariable::outputValue = fl::nan`.
-* Added copy constructors, assignment operators, move constructors and move operators to [Input|Output]Variable.
-* Added method `Variable::terms()` to return mutable reference.
-* **(important)** Changed `OutputVariable::[defuzzifier|fuzzyOutput]` to smart pointers (`FL_unique_ptr`).
-
-
-#### <a name="new-terms">Linguistic Terms</a>
-* **(VERY important)** Added Term::[get|set]Height to define the height of *integral* terms, and multiply their respective membership functions accordingly.
-* Added copy constructors, assignment operators, move constructors and move operators to every `Term`.
-* **(VERY important)** Parameters of all terms are set by default to `fl::nan`.
-* **(important)** Renamed method `Term::copy()` to `Term::clone()` in every `Term`.
-* Added method `Term::updateReference(Term*, Engine*)` to ensure `Linear` and `Function` terms have updated pointers to the `Engine` (useful when cloning and copy-constructing).
-+ **(important)** Added linguistic terms `Concave`, `Cosine` and `Spike`.
-* **(important)** Changed `Accumulated` to take `Activated*` terms instead of `const Terms*`.
-* Removed `const` from return type of method `SNorm* Accumulated::[get|set]Accumulation()`.
-* Changed `Accumulated::accumulation` to a smart pointer (`FL_unique_ptr`).
-* Added method `Accumulated::terms()` to return mutable reference.
-* **(important)** Renamed methods `Triangle::[set|get][A|B|C]` to `::[set|get]Vertex[A|B|C]`.
-* **(important)** Renamed methods `Trapezoid::[set|get][A|B|C|D]` to `::[set|get]Vertex[A|B|C|D]`.
-* **(important)** Renamed term `Thresholded` to `Activated`.
-* **(important)** Renamed methods `Thresholded::[set|get]Threshold()` to `Activated::[set|get]Degree()`.
-* Added enumeration `[Ramp|Sigmoid]::Direction{ NEGATIVE, ZERO, POSITIVE }` to refer to the slope.
-* Added methods `Ramp::direction()` and `Sigmoid::direction()` to retrieve direction of slope.
-* Removed Exception Specification from methods in `Discrete`, `Linear` and `Function` terms.
-
-#### <a name="new-linear-discrete">Linear and Discrete Terms</a>
-* **(important)** Changed `Linear` from having pointers to the input variables to having a pointer to the `Engine`.
-* Changed visibility of `Linear::coefficients` to `protected`.
-* **(important)** Added methods `Linear::coefficients()`, `Linear::setCoefficients()`.
-* `Linear` term no longer throws exception when `inputVariables != |coefficients|`.
-* **(important)** Removed public vector of variables `Discrete::[x|y]`.
-* **(important)** Added a `typedef std::pair<scalar, scalar> Discrete::Pair`.
-* **(important)** Changed representation of `Discrete::[x|y]` from `std::vector<scalar>` to `std::vector<Discrete::Pair>`.
-* Added methods `Discrete::setXY()` and `Discrete::xy()` to set and get the new representation of pairs.
-* Added methods `Discrete::xy(int index)` to retrieve `Discrete::Pair` at `index`.
-* **(important)** Added methods `Discrete::toPairs(std::vector<scalar>)` which throws an exception if the vector is missing a value (i.e., `std::vector<scalar>.size() % 2 != 0`), and `Discrete::toPairs(std::vector<scalar>, scalar missingValue)` which adds `missingValue` in case `std::vector<scalar>.size() %2 == 1`, hence never throwing an exception.
-* Added method `Discrete::toVector(std::vector<Discrete::Pair>)` to convert `std::vector<Discrete::Pair>` to a `std::vector<scalar>`.
-* Added method `Discrete::formatXY()` to get pairs `(x,y)` nicely formatted.
-
-####<a name="new-function">Function Term</a>
-* **(important)** Merged structs `Function::Operator` and `Function::BuiltInFunction` into a single `struct Function::Element`.
-* **(EXTREMELY important)** Changed the precedence of all built-in instances of `Function::Element` of type `Operator` starting from `100` and decreasing by `10`. The precedence of built-in operators is the following: `(100)` Logical not `[!]` and Negation `[~]`; `(90)` Power `[^]`; `(80)` Multiplication `[*]`, Division `[/]` and Modulo `[%]`; `(70)` Addition `[+]` and Subtraction `[-]`; `(60)` Logical AND `[and]` and Logical OR `[or]`. If you have registered your own operators, please adjust their precedence as required.
-* Added to `Function` built-in comparison functions `gt,lt,ge,le,eq` and operator logical not `!`.
-* Modified typedefs `Function::Unary` and `Function::Binary` to take `scalar` instead of `double`.
-* Changed `public Function::root` to `protected Function::_root` and it is now a smart pointer (`FL_unique_ptr`).
-* Added method `Function::root()` to return pointer to `Function::root`.
-* **(EXTREMELY important)** Moved built-in functions and operators from `Function` to a `FunctionFactory`.
-
-
-#### <a name="new-norms-hedges">[T|S]Norms and Hedges</a>
-+ **(important)** Fixed operation when using multiple hedges to operate from right-most to left-most, e.g. `if Ambient is not very extremely bright`, now evaluates as follows `not(very(extremely(bright)))`.
-+ Added `TNorm` nilpotent minimum and `SNorm` nilpotent maximum.
-* Added clone methods to every `Norm`.
-* Added clone methods to every `Hedge`.
-* **(VERY important)** Moved `Engine::hedges` to `Rule::hedges`.
-
-
-#### <a name="new-rules">Rules</a>
-* **(VERY important)** Moved `Engine::hedges` (and methods) to `Rule::hedges`.
-* Added method `Rule::isLoaded()` to determine whether a rule was properly parsed and thus can be activated.
-* Added method `Rule::unload()` to allow the existence of a rule in an inactive state (useful for invalid rules).
-* **(important)** Removed variable `Rule::FL_ASSIGNS` and method `Rule::assignsKeyword()`, for which the symbol `=` in rules is no longer valid.
-* Changed visibility of method `Rule::setText()` to `public`.
-* Added method `Rule::load(const Engine*)`.
-* Changed `Rule::[antecedent|consequent]` to smart pointers (`FL_unique_ptr`).
-* **(important)** Renamed method `Antecedent::[get|set]Root()` to `Antecedent::[get|set]Expression()`.
-* Added methods `[Antecedent|Consequent]::[get|set]Text()`.
-* **(important)** Added methods `[Antecedent|Consequent]::[load|unload]()`, with the same objective as `Rule::[load|unload]()`.
-
-#### <a name="new-ruleblocks">Rule Blocks</a>
-* Added method `RuleBlock::reloadRules()`.
-* Added method `RuleBlock::setRules(std::vector)`.
-* Added method `RuleBlock::rules()` to return mutable reference.
-* Removed `const` from `TNorm` and `SNorm` in `RuleBlock::[get|set][Conjunction|Disjunction|Activation]()`, respectively.
-* Changed `RuleBlock::[conjunction|disjunction|activation]` to smart pointers (`FL_unique_ptr`).
-* **(VERY important)** Added basic rule chaining such that an `OutputVariable` can be utilized in the `Antecedent` of a `Rule`. For example, considering the rule `if Power is high then InversePower is low`, where `Power` and `InversePower` are both output variables, the activation degree of the `Antecedent` will correspond to the accumulated activation degree of the term `high` in the fuzzy output of `Power`. If `Power::accumulation = none`, the accumulated activation degree of the term `high` will be computed as the regular sum of the activation degrees of term `high` in the fuzzy output of `Power`. Otherwise, the accumulated activation degree is computed utilizing the `Power::accumulation` operator.
-
-
-#### <a name="new-weighted">Weighted Defuzzifiers</a>
-+ **(VERY important)** Performance improvements of Takagi-Sugeno controllers by over 55% (with respect to v4.0) based on the average performance on the examples included.
-* **(important)** Created class `WeightedDefuzzifier` from which classes `Weighted[Average|Sum]` are derived.
-* **(important)** Added enumeration `WeightedDefuzzifier::Type{Automatic, TakagiSugeno, Tsukamoto}` and respective methods `WeightedDefuzzifier::[get|set]Type()` and `WeightedDefuzzifer::getTypeName()`.
-* Added method `WeightedDefuzzifier::inferType(Term*)` to automatically determine the `WeightedDefuzzifier::Type` based on the class of `Term`.
-* **(important)** By default, `WeightedDefuzzifier::type = Automatic`, which automatically infers the type based on the `WeightedDefuzzifier::inferType()`.
-* **(important)** There is a small performance penalty when using `WeightedDefuzzifier::type = Automatic` because `WeightedDefuzzifier::inferType()` performs three `dynamic_cast<>`.
-* **(important)** Deleted class `Tsukamoto`. Its method `static tsukamoto()` was moved to `virtual WeightedDefuzzifier::tsukamoto()`, which allows overriding it
-* Added support for `Tsukamoto` with `Concave` terms.
-+ **(EXTREMELY important)** In version 5.0, the traditional operation of Takagi-Sugeno and Tsukamoto controllers is achieved by setting `OutputVariable::accumulation = none`. Unlike version 4.0, the `RuleBlock::activation` will not have any effect on Takagi-Sugeno nor Tsukamoto controllers, for which `RuleBlock::activation` should also be set to `none`. More information about the roles of the `OutputVariable::accumulation` and `RuleBlock::activation` operators are detailed as follows. Refer to [sciweavers](http://www.sciweavers.org/free-online-latex-equation-editor) to convert LaTeX equations.
-+ **(VERY important)** In version 5.0, the role of the `RuleBlock::activation` `TNorm` on the `Weighted[Average|Sum]` always performs a regular multiplication of the weights and the values (i.e., $w_i \times z_j$) regardless of the `TNorm` chosen. In other words, selecting any `RuleBlock::activation` for `Weighted[Average|Sum]` is irrelevant, and should be set to `none` as every `TNorm` will have the same multiplication effect. This operation is different from `fuzzylite` version 4.0, where the `RuleBlock::activation` operator was utilized to multiply the weights and values (i.e. $w_i \otimes z_j$), and therefore the traditional operation of the `Weighted[Average|Sum]` was achieved when `RuleBlock::activation = AlgebraicProduct;`.
-+ **(VERY important)** In version 5.0, the role of the `OutputVariable::accumulation = none` on the `Weighted[Average|Sum]` results in a regular sum of the multiplied weights and values, i.e., $\dfrac{\sum_i^n w_i \times z_j}{\sum_i^n w_i}$. However, if the `OutputVariable::accumulation != none`, the role of the `SNorm` will be to accumulate the activation degrees of the *repeated* terms in the fuzzy output of the variable. For example, considering the rules `if Ambient is dark then Power is high` and `if Ambient is medium then Power is high`, for any input value of `Ambient` that activates both rules, the fuzzy output of `Power` will have the term `high` activated with the degree from `Rule 1`, and the term `high` activated with the degree from `Rule 2`. Since the term `high` appears twice in the fuzzy output, the role of the accumulation operator will be to accumulate the activation degree of `high` resulting in $\dfrac{(w_1 \oplus w_2) \times z_{high}}{(w_1 \oplus w_2)}$. If another term were activated, the result would be $\dfrac{(w_1 \oplus w_2) \times z_{high} + w_i \times z_j}{(w_1 \oplus w_2) + w_i}$. In version 4.0, the accumulation operator had no effect on the `Weighted[Average|Sum]`.
-
-
-
-#### <a name="new-integral">Integral Defuzzifiers</a>
-* **(important)** Proper handling of indefinite integral defuzzification, that is, returning `fl::nan` when `[minimum|maximum]=[NaN|Inf]`.
-* Default resolution of integration is defined as `static int IntegralDefuzzifier::defaultResolution=200`, and can be changed via `static IntegralDefuzzifier::setDefaultResolution()`.
-+ **(important)** In `fuzzylite`, the accumulation operator has been for several versions associated with the output variables and **not** with the rule blocks, despite that the FCL format and other fuzzy logic control libraries associate the accumulation operator with the rule blocks. The argument for such a decision is that `fuzzylite` provides **coherent** support for multiple rule blocks operating on the same engine and on the same output variables. For example, if multiple rule blocks operate on the same output variables, it only makes sense to have a single accumulation operator associated with each output variable such that the defuzzifier can naturally operate over the accumulated fuzzy output. Differently, if the accumulation operator were associated with the rule block, the possibility of having different accumulation operators in different rule blocks questions (1) **the possibility of having multiple rule blocks operating over the same output variables**; and (2) **the usage of different accumulation operators over the accumulation and defuzzification processes**. Certainly, if (1) is not possible, i.e, different rule blocks only operate on different output variables, then (2) is not a problem because the accumulation process and defuzzification of each variable will only have a single accumulation operator. It is therefore that the association of the accumulation operator with the output variable in `fuzzylite` provides a **better design** and an additional feature that allows having multiple rule blocks operating over the same output variables.
-* Added copy constructors, assignment operators, move constructors and move operators.
-* Added method `Defuzzifier::clone()`.
-
-####<a name="new-imex">Importers and Exporters</a>
-* **(EXTREMELY important)** Since terms have a new `height` property, `[Fll|Fis|Fcl]Exporter` exports terms with an additional `scalar` at the end, which indicates the `height` of the term. However, if `height=1.0`, the additional scalar is not exported.
-* **(EXTREMELY important)** In `[Fll|Fis|Fcl]Importer`, when importing terms, if there is an additional `scalar` it will be assumed as the `height` of the term. For example, `term: high Gaussian 1.0 0.5 0.75` will create a `Gaussian` term with mean `1.0`, standard deviation `0.5` and height `0.75`. This is **extremely important** because there are some examples from Matlab in `fis` format that append a useless `0.0` to some terms.
-* **(EXTREMELY important)** In `FisExporter`, if the Takagi-Sugeno controller has no `activation` or `accumulation` operators (as it should generally be the case), Octave and Matlab will not be able to import the `fis` file. To overcome this issue, you will have to set `ImpMethod="min"` and `AggMethod="max"`, where `ImpMethod` and `AggMethod` are just dummy operators that can be set to any `TNorm` and `SNorm`, respectively.
-+ **(important)** Improved compatibility of the exported code obtained with `[Fis|Fcl]Exporter` by exporting the additional features of `fuzzylite` only when these are different from the default operation. For example, the following features will not be exported given their values: `[Input|Output]Variable::enabled = true;`, `OutputVariable::lock-previous = false;`, `OutputVariable::lock-range = false;`, amongst others.
-* **(important)** Renamed FLL property `'lock-valid'` to `'lock-previous'`.
-* **(important)** Renamed FIS property `'LockValid'` to `'LockPrevious'`.
-* **(important)** Renamed FCL property `'LOCK: VALID'` to `'LOCK: PREVIOUS'`.
-+ **(important)** Export your controllers to files using `[Fll|Fld|Fis|Fcl]Exporter::toFile()`.
-+ **(important)** Import your controllers from files using `[Fll|Fis|Fcl]Importer::fromFile()`.
-+ **(important)** `FldExporter` exports the FuzzyLite Dataset of an engine utilizing the input values of another FuzzyLite Dataset.
-* `FldExporter` no longer restarts the engine when exporting.
-* **(important)** Renamed method `FldExporter::toWriter()` to `FldExporter::write()`.
-* Removed variable and methods for property `int FldExporter::_maximum`.
-* Added option in `CppExporter` to prepend the namespace prefix `fl::` to the classes, and by default it does not prepend prefix.
-* Improvement accuracy of `FisImporter` when importing `fis` files whose scalar values have more than three decimal numbers.
-* Renamed methods in `[Fis|Fcl]Importer::extract*` to `[Fis|Fcl]Importer::parse*`.
-
-
-
-#### <a name="new-factories">Factories</a>
-* Created a generic `CloningFactory<T>` to create clones of objects.
-* **(important)** Created `FunctionFactory` based on `CloningFactory<Function::Element>` where function operators and methods are stored to be cloned as necessary by `Function`. Additional functions and operators can be easily registered.
-* **(VERY important)** Moved built-in functions and operators from `Function` to `FunctionFactory`.
-* Renamed methods `Factory<T>::[register|deregister]Class()` to `Factory<T>::[register|deregister]Constructor()`.
-* **(important)** Renamed `Factory<T>` to `ConstructionFactory<T>`.
-* Renamed `typedef Factory::Creator` to `typedef Factory::Constructor`.
-* Changed pointers of `FactoryManager` to smart pointers (`FL_unique_ptr`).
-
-
-
-#### <a name="new-examples">Examples</a>
-* **(important)** Added two examples for basic rule chaining: `mamdani/SimpleDimmerInverse.fll` and `mamdani/Laundry.fll`.
-* Included the `original` example files in `fis` format.
-* Added conversion of `examples/original/*.fis` to `examples/original/*.fll`.
-* Modified `original/takagi-sugeno` examples to reflect `activation: none; accumulation: none;`.
-* Updated FLD examples produced from the `original` examples.
-+ **(important)** Added file [`fuzzylite/src/m/compare.m`](/fuzzylite/src/m/compare.m) <!---check link--> to compare the output values of your `fuzzylite` engines with the evaluation of the same engine in Octave/Matlab.
-+ **(important)** Added file [`examples/examples.mat`](/examples/examples.mat) <!---check link--> containing the comparison of the output values between `fuzzylite` and Matlab's Fuzzy Logic Toolbox.
-* Added code to perform benchmarks in Linux.
-
-
-#### <a name="new-console">Console</a>
-* **(important)** Console includes option to import custom input dataset from file an export its respective output values.
-* **(important)** Created the FuzzyLite Interactive Console, which can be started by specifying an input file and the output format, e.g., `fuzzylite -i SimpleDimmer.fll -of fld`.
-* Console provides more information about its usage.
-
-
-
-####<a name="new-fixes"> Fixes Bugs and Leaks</a>
-+ **(important)** Fixed operation when using multiple hedges to operate from right-most to left-most, e.g. `if Ambient is not very extremely bright` evaluates as follows `not(very(extremely(bright)))`.
-* **(important)** Fixed membership functions of specific cases of `Triangle` when `a=b` or `b=c`, and `Trapezoid` when `a=b` or `c=d`.
-* Fixed minor memory leak at `~RuleBlock::[conjunction|disjunction|activation]`.
-* Fixed minor memory leak at `~Accumulated::accumulation`.
-* Fixed minor memory leak at `~OutputVariable::defuzzifier`.
-* Fixed minor memory leak at `~Function::Node`.
-* Fixed minor memory leak at `~FactoryManager::[factories]`.
-* Fixed some rethrowing of exceptions to provide proper information about errors. Specifically, changed some rethrown exceptions from `throw ex;` to just `throw;`
-* Fixed building using `-DFL_USE_FLOAT=ON`
+* The FuzzyLite Libraries, namely fuzzylite and jfuzzylite, both in version 6.0, are dual licensed under the GNU General Public License version 3 and the Apache License version 2.
+
+* By default, fuzzylite builds using C++11 instead of C++98.
+
+* Important performance improvements.
+
+* Refactored the following names for the operation of engines: from activation operator to implication operator, from accumulation operator to aggregation operator.
+
+* Renamed the term `Accumulated` to `Aggregated`.
+
+* New activation methods decouple the activation of rules from the rule block and provide different methods for activating rules (see Activation Methods).
+
+* New class `ActivationFactory` provides a factory of activation methods.
+
+* New class `Benchmark` to evaluate the performance and accuracy of engines.
+
+* New class `Complexity` to estimate the computational complexity of an engine.
+
+* New class `RScriptExporter` to export the surfaces of an engine using the `ggplot2` library.
+
+* New class `Binary` term for binary edges.
+
+* New `UnboundedSum` S-Norm in `SNormFactory`.
+
+* New classes `SNormFunction` and `TNormFunction` to create custom functions on any two values using the `Function` class.
+
+* Added description strings to `Engine`, `Variable` and `RuleBlock`
+
+* Privatized previously protected members of classes and subclasses of `Term`, `Variable`, `Rule`, `Defuzzifier`, `[Cloning|Construction]Factory`, `Importer`, `Exporter`, amongst others.
+
+* Improved portability by replacing `int` for `std::size_t` where necessary, thereby additionally removing warnings in Windows 64bit
+
+* Deleted `Operation.cpp` and inlined its methods into `Operation.h`
+
+* Updated `.travis.yml` to use Docker, and build using g++ (versions 6, 5, 4.9, 4.8, 4.7) and clang (versions 3.8, 3.7, 3.6, and 3.5).
+
+* Added `appveyor.yml` to use continuous integration in Windows under Visual Studio 2013 and 2015.
+
+* Added some unit tests and support for future unit tests.
+
+* Bug fixes.
+
+* New example of hybrid engines.
+
+* New example on obstacle avoidance for Mamdani, Takagi-Sugeno, and Hybrid engines.
+
+* New R scripts for each example and its respective surfaces in `pdf` formats.
+
+#### Bug fixes
+* Fixed bug in `CloningFactory::deregisterObject()`. Bug: Object was deleted before removing it from the map, leaving an invalid object in the map which would cause a segmentation fault. Solution: Remove the object from the map before deleting it.
+* Fixed bug causing segmentation fault when malformed term in FuzzyLite Language
+* Fixed bug computing the `NormalizedSum` S-Norm.
+* Fixed bug in `RuleBlock` to reset and clone the implication operator. Bug: implication operator is not copied and reset. Fix: copy and reset implication operator when cloning the `RuleBlock`.
+* Fixed bug in `Function` term. Bug: given a formula = "tan(y)" and a map["y"] = 1.0, and executing `Function::load(formula)`, then the map of variables is reset because `load()` calls `unload()` first, causing the deregistration of variable `y`. Solution: Removed method `unload()` from `load()`, thereby causing future `load()` not to reset variables.
+* Fixed bug in `Function` when enclosing variable in double parenthesis.
+
+
+***
+
+### <a name="whatsnext">What's Next?</a>
+
++ Optimization of Fuzzy Logic Controllers
++ Type-2 Fuzzy Logic Controllers
++ Adaptive Neuro-Fuzzy Inference System (ANFIS)
++ Fuzzy C-means data clustering
***
-For more information, visit [www.fuzzylite.com](http://www.fuzzylite.com).
+fuzzylite&reg; is a registered trademark of FuzzyLite Limited.<br>
+jfuzzylite&trade; is a trademark of FuzzyLite Limited.<br>
+QtFuzzyLite&trade; is a trademark of FuzzyLite Limited.<br>
-fuzzylite&reg; is a registered trademark of FuzzyLite Limited.
-Copyright &#xa9; 2010-2015 FuzzyLite Limited. All rights reserved.
+Copyright &#xa9; 2010-2017 FuzzyLite Limited. All rights reserved.
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..df56bb0
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,22 @@
+Acknowledgements
+================
+
+Thank you to the community around fuzzylite, whose feedback and support has been of great importance towards improving the libraries.
+
+Thank you to all the users who made generous contributions buying licenses of QtFuzzyLite and making donations.
+
+Thank you to the European Centre for Soft Computing, the Foundation for the Advancement of Soft Computing, Sergio Guadarrama and Luis Magdalena for their support creating the first version of fuzzylite.
+
+Thank you to Dean Morrissey for his feedback on testing the operation of fuzzylite and validating its results; Adrien Cabarbaye for his feedback on discrete terms and feature requests on output variables; Massimo Canonico for his feedback on his experience and usage of fuzzylite in its early stages; Eva Millan for her feedback, ideas, and suggestions on rule chaining; Johannes Schauer for his work making fuzzylite directly available from Debian repositories; and Leonela Gazzano for her suggestions on activation methods.
+
+Thank you to Pablo Cingolani (JFuzzyLogic), Linda Markowsky (Octave Fuzzy Logic Toolkit), Roger Jang (Matlab Fuzzy Logic Toolbox), Edward S. Sazonov (FuzzyEngine), and their respective collaborators for open sourcing their great libraries.
+
+Special thanks to Mengjie Zhang and Mark Johnston (Victoria University of Wellington, New Zealand); Oscar Cordón (European Centre for Soft Computing, Spain); Maritza Bracho, Carlos Lameda, Belkys Lameda, and Rubén Parma (Universidad Centroccidental Lisandro Alvarado, Venezuela); and Yelitza Oviedo, Jorge Rodríguez, Edecio Freitez, Luis Alvarado, Jesús Contreras, and Oswaldo Hernández (Universidad Fermín Toro, Venezuela).
+
+Thank you all very much.
+
+Yours,
+
+Juan Rada-Vilela, Ph.D.
+jcrada@fuzzylite.com
+http://www.fuzzylite.com/jcrada \ No newline at end of file
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..b052265
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,40 @@
+version: '{branch}.{build}'
+branches:
+ only:
+ - master
+ - release
+os:
+- Visual Studio 2015
+- Visual Studio 2013
+configuration:
+- Release
+- Debug
+platform:
+- x64
+- x86
+clone_depth: 1
+clone_folder: C:\projects\fuzzylite
+before_build:
+- cmd: >-
+ cd c:\projects\fuzzylite\fuzzylite
+
+ mkdir build
+
+ cd build
+
+ cmake ..
+
+ echo %cd%
+
+ dir
+build:
+ project: c:\projects\fuzzylite\fuzzylite\build\INSTALL.vcxproj
+ parallel: true
+ verbosity: normal
+notifications:
+- provider: Email
+ to:
+ - jcrada@fuzzylite.com
+ on_build_success: true
+ on_build_failure: true
+ on_build_status_changed: true \ No newline at end of file
diff --git a/documentation/ui/figure.R b/documentation/ui/figure.R
new file mode 100644
index 0000000..88cef79
--- /dev/null
+++ b/documentation/ui/figure.R
@@ -0,0 +1,491 @@
+library('cowplot')
+library('ggplot2')
+
+theme_set(theme_gray())
+
+
+isEq = function(a,b,error=1e-5){
+ abs(a - b) <= error
+}
+
+isLt = function(a,b,error=1e-5){
+ !isEq(a,b,error) & a < b
+}
+
+isGt = function(a,b,error=1e-5){
+ !isEq(a,b,error) & a > b
+}
+
+isLE = function(a,b,error=1e-5){
+ isEq(a,b,error) | a < b
+}
+
+isGE = function(a,b,error=1e-5){
+ isEq(a,b,error) | a > b
+}
+
+#Scale: Scales a number to a different scale
+Scale = function(value, toMin, toMax, fromMin=min(value), fromMax=max(value)){
+ (toMax - toMin) / (fromMax - fromMin) * (value - fromMin) + toMin
+}
+
+#Basic
+
+term.triangle = function(x, a, b, c){
+ if (isLt(x,a) | isGt(x,c))
+ 0.0
+ else if (isEq(x,b))
+ 1.0
+ else if (isLt(x,b))
+ (x - a) / (b - a)
+ else
+ result = (c - x) / (c - b)
+}
+
+term.trapezoid = function(x,a,b,c,d){
+ if (isLt(x, a) | isGt(x, d))
+ 0.0
+ else if (isLE(x, b))
+ min(1.0, (x - a) / (b - a))
+ else if (isLE(x, c))
+ 1.0
+ else if (isLE(x, d))
+ (d - x) / (d - c)
+}
+
+term.rectangle = function(x,a,b){
+ if (isLt(x, a) | isGt(x,b))
+ 0.0
+ else 1.0
+}
+
+term.discrete = function(x, a, b){
+ diff = b-a
+ if (isLt(x,a) | isGt(x,b))
+ 0.0
+ else if (isLt(x,.25 * diff))
+ Scale(x, 0, 1, a, a + diff*.25)
+ else if (isLt(x, .5*diff))
+ Scale(x,1,0.5, a + diff*.25, a + diff*.5)
+ else if (isLt(x, .75*diff))
+ Scale(x,0.5,1,a+diff*.5, a+diff*.75)
+ else if (isLt(x, diff))
+ Scale(x, 1, 0, a+diff*.75, a+diff)
+ else {0.0}
+# else if (isLt(x, a*.5)
+}
+
+
+term.bell = function(x, center, width, slope){
+ 1.0 / (1.0 + abs((x - center) / width)**(2 * slope));
+}
+
+#EXTENDED
+
+term.cosine = function(x, center, width){
+ if (isLt(x, center-width/2.0) || isGt(x, center+width/2.0)){
+ 0.0
+ }else{
+ 0.5 * (1.0 + cos(2.0 / width * pi * (x - center)))
+ }
+}
+
+term.gaussian = function(x, mean, sd){
+ exp((-(x - mean) * (x - mean)) / (2 * sd * sd));
+}
+
+term.gaussianProduct = function(x, meanA, sdA, meanB, sdB){
+ xLEa = isLE(x, meanA)
+ a = exp((-(x - meanA) * (x - meanA)) / (2 * sdA * sdA)) * xLEa + (1 - xLEa)
+ xGEb = isGE(x, meanB)
+ b = exp((-(x - meanB) * (x - meanB)) / (2 * sdB * sdB)) * xGEb + (1 - xGEb)
+ a * b
+}
+
+term.bell = function(x, center, width, slope){
+ 1.0 / (1.0 + abs((x - center) / width)** (2 * slope))
+}
+
+term.piShape = function(x, bottomLeft, topLeft, topRight, bottomRight){
+ a_b_ave = (bottomLeft + topLeft) / 2.0
+ b_minus_a = topLeft - bottomLeft
+ c_d_ave = (topRight + bottomRight) / 2.0
+ d_minus_c = bottomRight - topRight
+
+ if (isLE(x, bottomLeft)) 0.0
+
+ else if (isLE(x, a_b_ave))
+ 2.0 * ((x - bottomLeft) / b_minus_a) ** 2
+
+ else if (isLt(x, topLeft))
+ 1.0 - 2.0 * ((x - topLeft) / b_minus_a)** 2
+
+ else if (isLE(x, topRight))
+ 1.0
+
+ else if (isLE(x, c_d_ave))
+ 1 - 2 * ((x - topRight) / d_minus_c)**2
+
+ else if (isLt(x, bottomRight))
+ 2 * ((x - bottomRight) / d_minus_c)** 2
+
+ else 0.0
+}
+
+term.sigmoidDifference = function(x, left, rising, falling, right){
+ a = 1.0 / (1 + exp(-rising * (x - left)))
+ b = 1.0 / (1 + exp(-falling * (x - right)))
+ abs(a - b)
+}
+
+term.sigmoidProduct = function(x, left, rising, falling, right){
+ a = 1.0 / (1 + exp(-rising * (x - left)))
+ b = 1.0 / (1 + exp(-falling * (x - right)))
+ abs(a * b)
+}
+
+term.spike = function(x, center, width){
+ exp(-abs( 10 / width * (x-center)))
+}
+
+#EDGES
+
+term.binary = function(x, threshold, direction){
+ if (isGE(direction,0.0) && isGE(x, threshold)){
+ 1.0
+ }else if (isLt(direction, 0.0) && isLE(x, threshold)){
+ 1.0
+ }else{
+ 0.0
+ }
+}
+
+term.concave = function(x, inflection, end){
+ if (isLE(inflection, end)){ #Concave increasing
+ if (isLt(x, end)){
+ (end - inflection) / (2 * end - inflection - x)
+ }else{ 1.0 }
+ } else{ #Concave decreasing
+ if (isGt(x, end)){
+ (inflection - end) / (inflection -2 * end + x)
+ }else{ 1.0 }
+ }
+}
+
+
+term.ramp = function(x, start, end){
+ if (isEq(start, end)) 0.0
+
+ else if (isLt(start, end)) {
+ if (isLE(x, start)) 0.0
+ else if (isGE(x, end)) 1.0
+ else (x - start) / (end - start)
+ } else {
+ if (isGE(x, start)) 0.0
+ else if (isLE(x, end)) 1.0
+ else (start - x) / ( start - end)
+ }
+}
+
+term.sigmoid = function(x, inflection, slope){
+ 1.0 / (1.0 + exp(-slope * (x - inflection)))
+}
+
+term.sShape = function(x, start, end){
+ average = (start + end) / 2
+ difference = end - start
+
+ if (isLE(x, start)) 0.0
+
+ else if (isLE(x, average))
+ 2 * ((x - start) / difference) ** 2
+
+ else if (isLt(x, end))
+ 1.0 - 2.0 * ((x - end) / difference) ** 2
+ else 1.0
+}
+
+term.zShape = function(x, start, end){
+ average = (start + end) / 2
+ difference = end - start
+
+ if (isLE(x, start)) 1.0
+
+ else if (isLE(x, average))
+ 1.0 - 2.0 * ((x - start) / difference) ** 2
+
+ else if (isLt(x, end))
+ 2.0 * ((x - end) / difference)** 2
+
+ else 0.0
+}
+
+
+
+
+
+
+
+x = seq(0,1,length=500)
+average = (max(x) + min(x))/2
+diff = (max(x) - min(x))
+
+
+
+
+
+dir.create('figure',showWarnings=F)
+
+
+##################BASIC
+
+triangle.df = data.frame(x, y=sapply(x, term.triangle, min(x), average, max(x)))
+triangle.plot = ggplot(triangle.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/triangle.svg', triangle.plot, width=3, height=3)
+
+
+trapezoid.df = data.frame(x, y=sapply(x, term.trapezoid, min(x), min(x) + .25 * diff, min(x) + .75*diff, max(x)))
+trapezoid.plot = ggplot(trapezoid.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/trapezoid.svg', trapezoid.plot, width=3, height=3)
+
+
+rectangle.df = data.frame(x, y=sapply(x, term.rectangle, min(x) + .25*diff, min(x) + .75*diff))
+rectangle.plot = ggplot(rectangle.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/rectangle.svg', rectangle.plot, width=3, height=3)
+
+
+discrete.x = x[c(1, seq(10, 495, 10), 500)]
+discrete.df = data.frame(x=discrete.x, y=sapply(discrete.x, term.discrete, min(x), max(x)))
+discrete.plot = ggplot(discrete.df, aes(x,y, size=2, lineend='round')) + geom_point() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/discrete.svg', discrete.plot, width=3, height=3)
+
+
+
+#################EXTENDED
+
+cosine.df = data.frame(x, y=sapply(x, term.cosine, average, diff))
+cosine.plot = ggplot(cosine.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/cosine.svg', cosine.plot, width=3, height=3)
+
+
+gaussian.df = data.frame(x, y=sapply(x, term.gaussian, average, .2*diff))
+gaussian.plot = ggplot(gaussian.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/gaussian.svg', gaussian.plot, width=3, height=3)
+
+
+gaussianProduct.df = data.frame(x, y=sapply(x, term.gaussianProduct, average+.1, .2*diff, average-.1, .2*diff))
+gaussianProduct.plot = ggplot(gaussianProduct.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/gaussianProduct.svg', gaussianProduct.plot, width=3, height=3)
+
+
+bell.df = data.frame(x, y=sapply(x, term.bell, average, .25*diff, 3.0))
+bell.plot = ggplot(bell.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/bell.svg', bell.plot, width=3, height=3)
+
+
+piShape.df = data.frame(x, y=sapply(x, term.piShape, min(x), average, average, max(x)))
+piShape.plot = ggplot(piShape.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/piShape.svg', piShape.plot, width=3, height=3)
+
+
+sigmoidDifference.df = data.frame(x, y=sapply(x, term.sigmoidDifference, min(x) + .25*diff, 20/diff, 20/diff, min(x)+.75*diff))
+sigmoidDifference.plot = ggplot(sigmoidDifference.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/sigmoidDifference.svg', sigmoidDifference.plot, width=3, height=3)
+
+
+sigmoidProduct.df = data.frame(x, y=sapply(x, term.sigmoidProduct, min(x) + .25*diff, 10/diff, -10/diff, min(x)+.75*diff))
+sigmoidProduct.plot = ggplot(sigmoidProduct.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/sigmoidProduct.svg', sigmoidProduct.plot, width=3, height=3)
+
+
+spike.df = data.frame(x, y=sapply(x, term.spike, average, diff))
+spike.plot = ggplot(spike.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/spike.svg', spike.plot, width=3, height=3)
+
+
+
+###############EDGE
+
+#Binary
+binary.dfa = data.frame(x, y=sapply(x, term.binary, min(x) + .25*diff, -1))
+binary.dfb = data.frame(x, y=sapply(x, term.binary, min(x) + .75*diff, 1))
+binary.plot = ggplot(binary.dfa, aes(x,y, size=2, lineend='round')) +
+ geom_line(data=binary.dfb, aes(x,y, size=2, lineend='round')) +
+ geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/binary.svg', binary.plot, width=3, height=3)
+
+#Concave
+concave.dfa = data.frame(x, y=sapply(x, term.concave, average, max(x)-.2))
+concave.dfb = data.frame(x, y=sapply(x, term.concave, average, 1-(max(x)-.2)))
+concave.plot = ggplot(concave.dfa, aes(x,y, size=2, lineend='round')) +
+ geom_line(data=concave.dfb, aes(x,y, size=2, lineend='round')) +
+ geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/concave.svg', concave.plot, width=3, height=3)
+
+#RAMP
+ramp.dfa = data.frame(x, y=sapply(x, term.ramp, max(x)-.2, min(x)+.2))
+ramp.dfb = data.frame(x, y=sapply(x, term.ramp, min(x)+.2, max(x)-.2))
+ramp.plot = ggplot(ramp.dfa, aes(x,y, size=2, lineend='round')) +
+ geom_line(data=ramp.dfb, aes(x,y, size=2, lineend='round')) +
+ geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/ramp.svg', ramp.plot, width=3, height=3)
+
+
+sigmoid.dfa = data.frame(x, y=sapply(x, term.sigmoid, average, 20/diff))
+sigmoid.dfb = data.frame(x, y=sapply(x, term.sigmoid, average, -20/diff))
+sigmoid.plot = ggplot(sigmoid.dfa, aes(x,y, size=2, lineend='round')) +
+ geom_line(data=sigmoid.dfb, aes(x,y, size=2, lineend='round')) +
+ geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/sigmoid.svg', sigmoid.plot, width=3, height=3)
+
+
+sShape.df = data.frame(x, y=sapply(x, term.sShape, min(x), max(x)))
+sShape.plot = ggplot(sShape.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/sShape.svg', sShape.plot, width=3, height=3)
+
+
+zShape.df = data.frame(x, y=sapply(x, term.zShape, min(x), max(x)))
+zShape.plot = ggplot(zShape.df, aes(x,y, size=2, lineend='round')) + geom_line() + ylab(expression(mu(x))) + theme(legend.position='none')
+ggsave('figure/zShape.svg', zShape.plot, width=3, height=3)
+
+
+##############Terms
+
+ constant.plot =
+ ggplot(data=data.frame(x=0,y=0)) +
+ geom_point(aes(x=0,y=0), size=0) +
+ ylab(expression(f(x))) + xlab('x') +
+ coord_cartesian(ylim = c(-0.05, 1.05), xlim=c(-0.05,1.05)) +
+ annotate('text', x = .5, y = .5, label = "f(x)==k", parse = T,size=10)
+
+ linear.plot =
+ ggplot(data=data.frame(x=0,y=0)) +
+ geom_point(aes(x=0,y=0), size=0) +
+ ylab(expression(f(x))) + xlab('x') +
+ coord_cartesian(ylim = c(-0.05, 1.05), xlim=c(-0.05,1.05)) +
+ annotate('text', x = .5, y = .5, angle=45, label = "f(x)==sum(paste(c[i],v[i]), i)+k", parse = T,size=10)
+
+ function.plot =
+ ggplot(data=data.frame(x=0,y=0)) +
+ geom_point(aes(x=0,y=0), size=0) +
+ ylab(expression(f(x))) + xlab('x') +
+ coord_cartesian(ylim = c(-0.05, 1.05), xlim=c(-0.05,1.05)) +
+ annotate('text', x = .5, y = .5, label = "f:x %->% f(x)", parse = T,size=10)
+
+
+########## Vertical layout
+ terms.grid = plot_grid(
+
+triangle.plot, bell.plot, piShape.plot,
+trapezoid.plot, cosine.plot, sigmoidDifference.plot,
+rectangle.plot, gaussian.plot, sigmoidProduct.plot,
+discrete.plot, gaussianProduct.plot, spike.plot,
+binary.plot, ramp.plot, sShape.plot,
+concave.plot, sigmoid.plot, zShape.plot,
+function.plot, linear.plot, constant.plot,
+
+ ncol=3, nrow=7, scale=1, label_size=12, vjust=1.25, align='v',
+ #hjust=.5, # align='hv',
+
+ labels=c(
+'Triangle', 'Bell', 'PiShape',
+'Trapezoid', 'Cosine', 'SigmoidDifference',
+'Rectangle', 'Gaussian', 'SigmoidProduct',
+'Discrete', 'GaussianProduct', 'Spike',
+'Binary', 'Ramp', 'SShape',
+'Concave', 'Sigmoid', 'ZShape',
+'Function', 'Linear', 'Constant'
+ )
+ )
+
+ save_plot('figure/terms.svg', terms.grid, ncol=3, nrow=7, scale=.75)
+
+ stop('Script successfully executed')
+
+
+##########Horizontal layout
+ terms.grid = plot_grid(
+
+ triangle.plot, trapezoid.plot, rectangle.plot, discrete.plot, function.plot, binary.plot , concave.plot,
+
+ bell.plot, cosine.plot, gaussian.plot, gaussianProduct.plot, linear.plot, ramp.plot, sigmoid.plot,
+
+ piShape.plot, sigmoidDifference.plot, sigmoidProduct.plot, spike.plot, constant.plot, sShape.plot, zShape.plot,
+
+ ncol=7, nrow=3, scale=1, label_size=12, vjust=1.25, align='v',
+ #hjust=.5, # align='hv',
+
+labels=c(
+'Triangle', 'Trapezoid', 'Rectangle', 'Discrete', 'Function', 'Binary', 'Concave',
+'Bell', 'Cosine', 'Gaussian', 'GaussianProduct', 'Linear', 'Ramp', 'Sigmoid',
+'PiShape', 'SigmoidDifference', 'SigmoidProduct','Spike', 'Constant', 'SShape', 'ZShape')
+)
+
+save_plot('figure/terms.svg', terms.grid, ncol=7, nrow=3, scale=.75)
+
+stop('Script successfully executed')
+
+
+
+
+
+
+
+
+
+
+
+
+# X1234X
+# 123456
+# 7 8
+# 123456
+
+constant.plot =
+ ggplot(data=data.frame(x=0,y=0)) +
+ geom_point(aes(x=0,y=0), size=0) +
+ ylab(expression(mu(x))) + xlab('x') +
+ coord_cartesian(ylim = c(-0.05, 1.05), xlim=c(-0.05,1.05)) +
+ annotate('text', x = .5, y = .5, label = "mu(x)==k", parse = T,size=10)
+
+linear.plot =
+ ggplot(data=data.frame(x=0,y=0)) +
+ geom_point(aes(x=0,y=0), size=0) +
+ ylab(expression(mu(x))) + xlab('x') +
+ coord_cartesian(ylim = c(-0.05, 1.05), xlim=c(-0.05,1.05)) +
+ annotate('text', x = .5, y = .5, angle=45, label = "mu(x)==sum(c[i] %.% x[i], i)+k", parse = T,size=5)
+
+function.plot =
+ ggplot(data=data.frame(x=0,y=0)) +
+ geom_point(aes(x=0,y=0), size=0) +
+ ylab(expression(mu(x))) + xlab('x') +
+ coord_cartesian(ylim = c(-0.05, 1.05), xlim=c(-0.05,1.05)) +
+ annotate('text', x = .5, y = .5, label = "f:x %->% mu(x)", parse = T,size=5)
+
+
+terms.grid = plot_grid(
+
+NULL, triangle.plot, trapezoid.plot, rectangle.plot, discrete.plot, NULL,
+
+bell.plot, cosine.plot, gaussian.plot, gaussianProduct.plot, piShape.plot, sigmoidDifference.plot,
+
+sigmoidProduct.plot, spike.plot, NULL, constant.plot, linear.plot, function.plot,
+
+binary.plot, concave.plot, ramp.plot, sigmoid.plot, sShape.plot, zShape.plot,
+
+nrow=4, ncol=6, scale=1, label_size=12, vjust=1.25,
+#hjust=.5, # align='hv',
+
+labels=c(
+'', 'Triangle', 'Trapezoid', 'Rectangle', 'Discrete', '',
+'Bell', 'Cosine', 'Gaussian', 'GaussianProduct', 'PiShape', 'SigmoidDifference',
+'SigmoidProduct','Spike', '', 'Constant', 'Linear', 'Function',
+'Binary', 'Concave', 'Ramp', 'Sigmoid', 'SShape', 'ZShape')
+)
+
+save_plot('figure/terms.svg', terms.grid,
+ ncol=6, nrow=4, scale=.5)
+
+
+
+
diff --git a/documentation/ui/figure/bell.svg b/documentation/ui/figure/bell.svg
new file mode 100644
index 0000000..9709cf5
--- /dev/null
+++ b/documentation/ui/figure/bell.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 154 L 202 154 L 202 156 L 54.019531 156 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 116 L 202 116 L 202 118 L 54.019531 118 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 78 L 202 78 L 202 80 L 54.019531 80 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 42 L 54.019531 42 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 173 L 202.601562 173 L 202.601562 175 L 54.019531 175 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 135 L 202.601562 135 L 202.601562 137 L 54.019531 137 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 97 L 202.601562 97 L 202.601562 99 L 54.019531 99 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 59 L 202.601562 59 L 202.601562 61 L 54.019531 61 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface216">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 154.882812 L 201.601562 154.882812 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 116.882812 L 201.601562 116.882812 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.882812 L 201.601562 78.882812 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.882812 L 201.601562 40.882812 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 173.882812 L 201.601562 173.882812 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 135.882812 L 201.601562 135.882812 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 97.882812 L 201.601562 97.882812 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.882812 L 201.601562 59.882812 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 60.996094 171.488281 L 61.265625 171.433594 L 61.53125 171.371094 L 61.800781 171.3125 L 62.070312 171.25 L 62.878906 171.050781 L 63.144531 170.980469 L 63.953125 170.757812 L 64.222656 170.679688 L 64.492188 170.597656 L 64.757812 170.515625 L 65.296875 170.34375 L 66.105469 170.0625 L 66.371094 169.964844 L 66.640625 169.863281 L 66.910156 169.757812 L 67.449219 169.539062 L 67.71875 169.421875 L 67.984375 169.304688 L 68.253906 169.183594 L 68.523438 169.058594 L 68.792969 168.929688 L 69.0625 168.796875 L 69.332031 168.660156 L 69.597656 168.515625 L 69.867188 168.371094 L 70.136719 168.222656 L 70.40625 168.066406 L 70.675781 167.90625 L 70.945312 167.742188 L 71.210938 167.574219 L 71.480469 167.398438 L 72.019531 167.03125 L 72.289062 166.839844 L 72.558594 166.640625 L 72.824219 166.433594 L 73.09375 166.222656 L 73.363281 166.007812 L 73.632812 165.78125 L 73.902344 165.550781 L 74.167969 165.308594 L 74.4375 165.0625 L 74.707031 164.808594 L 74.976562 164.542969 L 75.246094 164.273438 L 75.515625 163.992188 L 75.78125 163.699219 L 76.050781 163.402344 L 76.320312 163.09375 L 76.589844 162.773438 L 76.859375 162.445312 L 77.128906 162.101562 L 77.394531 161.75 L 77.664062 161.386719 L 77.933594 161.011719 L 78.203125 160.625 L 78.472656 160.226562 L 78.742188 159.8125 L 79.007812 159.386719 L 79.277344 158.945312 L 79.546875 158.492188 L 79.816406 158.019531 L 80.085938 157.535156 L 80.355469 157.035156 L 80.621094 156.515625 L 80.890625 155.984375 L 81.160156 155.429688 L 81.429688 154.859375 L 81.699219 154.273438 L 81.96875 153.664062 L 82.234375 153.039062 L 82.503906 152.390625 L 82.773438 151.722656 L 83.042969 151.035156 L 83.3125 150.324219 L 83.582031 149.59375 L 83.847656 148.835938 L 84.117188 148.054688 L 84.386719 147.253906 L 84.65625 146.425781 L 84.925781 145.570312 L 85.195312 144.691406 L 85.460938 143.785156 L 85.730469 142.851562 L 86 141.890625 L 86.269531 140.902344 L 86.539062 139.882812 L 86.808594 138.839844 L 87.074219 137.761719 L 87.34375 136.65625 L 87.613281 135.519531 L 87.882812 134.355469 L 88.152344 133.15625 L 88.417969 131.929688 L 88.6875 130.667969 L 88.957031 129.378906 L 89.226562 128.054688 L 89.496094 126.699219 L 89.765625 125.316406 L 90.03125 123.898438 L 90.300781 122.449219 L 90.570312 120.972656 L 90.839844 119.460938 L 91.109375 117.921875 L 91.378906 116.351562 L 91.644531 114.753906 L 91.914062 113.128906 L 92.183594 111.476562 L 92.453125 109.800781 L 92.722656 108.097656 L 92.992188 106.367188 L 93.257812 104.617188 L 93.527344 102.847656 L 93.796875 101.058594 L 94.066406 99.25 L 94.335938 97.425781 L 94.605469 95.589844 L 94.871094 93.738281 L 95.140625 91.878906 L 95.410156 90.007812 L 95.949219 86.257812 L 96.21875 84.378906 L 96.484375 82.5 L 96.753906 80.625 L 97.023438 78.753906 L 97.292969 76.894531 L 97.5625 75.046875 L 97.832031 73.207031 L 98.097656 71.386719 L 98.367188 69.585938 L 98.636719 67.800781 L 98.90625 66.039062 L 99.175781 64.304688 L 99.445312 62.59375 L 99.710938 60.914062 L 99.980469 59.265625 L 100.25 57.648438 L 100.519531 56.0625 L 100.789062 54.515625 L 101.058594 53.003906 L 101.324219 51.53125 L 101.59375 50.097656 L 101.863281 48.703125 L 102.132812 47.351562 L 102.402344 46.039062 L 102.667969 44.769531 L 102.9375 43.542969 L 103.207031 42.359375 L 103.476562 41.21875 L 103.746094 40.125 L 104.015625 39.070312 L 104.28125 38.054688 L 104.550781 37.085938 L 104.820312 36.15625 L 105.089844 35.269531 L 105.359375 34.425781 L 105.628906 33.617188 L 105.894531 32.847656 L 106.164062 32.117188 L 106.433594 31.425781 L 106.703125 30.769531 L 106.972656 30.144531 L 107.242188 29.558594 L 107.507812 29.003906 L 107.777344 28.480469 L 108.046875 27.984375 L 108.316406 27.523438 L 108.585938 27.085938 L 108.855469 26.679688 L 109.121094 26.296875 L 109.390625 25.9375 L 109.660156 25.605469 L 109.929688 25.292969 L 110.199219 25.003906 L 110.46875 24.734375 L 110.734375 24.480469 L 111.003906 24.25 L 111.273438 24.035156 L 111.542969 23.835938 L 111.8125 23.652344 L 112.082031 23.484375 L 112.347656 23.328125 L 112.617188 23.183594 L 112.886719 23.050781 L 113.15625 22.933594 L 113.425781 22.824219 L 113.695312 22.722656 L 113.960938 22.632812 L 114.230469 22.550781 L 114.5 22.472656 L 114.769531 22.40625 L 115.039062 22.34375 L 115.308594 22.289062 L 115.574219 22.238281 L 115.84375 22.195312 L 116.113281 22.15625 L 116.382812 22.121094 L 116.652344 22.089844 L 116.921875 22.0625 L 117.1875 22.035156 L 117.996094 21.976562 L 118.265625 21.964844 L 118.53125 21.949219 L 118.800781 21.941406 L 119.070312 21.929688 L 119.609375 21.914062 L 119.878906 21.910156 L 120.144531 21.90625 L 121.222656 21.890625 L 121.492188 21.890625 L 121.757812 21.886719 L 122.566406 21.886719 L 122.835938 21.882812 L 132.78125 21.882812 L 133.050781 21.886719 L 133.859375 21.886719 L 134.128906 21.890625 L 134.394531 21.890625 L 135.742188 21.910156 L 136.007812 21.914062 L 136.546875 21.929688 L 136.816406 21.941406 L 137.085938 21.949219 L 137.355469 21.964844 L 137.621094 21.976562 L 138.429688 22.035156 L 138.96875 22.089844 L 139.234375 22.121094 L 139.503906 22.15625 L 139.773438 22.195312 L 140.042969 22.238281 L 140.3125 22.289062 L 140.582031 22.34375 L 140.847656 22.40625 L 141.117188 22.472656 L 141.386719 22.550781 L 141.65625 22.632812 L 141.925781 22.722656 L 142.195312 22.824219 L 142.460938 22.933594 L 142.730469 23.050781 L 143 23.183594 L 143.269531 23.328125 L 143.539062 23.484375 L 143.808594 23.652344 L 144.074219 23.835938 L 144.34375 24.035156 L 144.613281 24.25 L 144.882812 24.480469 L 145.152344 24.734375 L 145.421875 25.003906 L 145.6875 25.292969 L 145.957031 25.605469 L 146.226562 25.9375 L 146.496094 26.296875 L 146.765625 26.679688 L 147.03125 27.085938 L 147.300781 27.523438 L 147.570312 27.984375 L 147.839844 28.480469 L 148.109375 29.003906 L 148.378906 29.558594 L 148.644531 30.144531 L 148.914062 30.769531 L 149.183594 31.425781 L 149.453125 32.117188 L 149.722656 32.847656 L 149.992188 33.617188 L 150.257812 34.425781 L 150.527344 35.269531 L 150.796875 36.15625 L 151.066406 37.085938 L 151.335938 38.054688 L 151.605469 39.070312 L 151.871094 40.125 L 152.140625 41.21875 L 152.410156 42.359375 L 152.679688 43.542969 L 152.949219 44.769531 L 153.21875 46.039062 L 153.484375 47.351562 L 153.753906 48.703125 L 154.023438 50.097656 L 154.292969 51.53125 L 154.5625 53.003906 L 154.832031 54.515625 L 155.097656 56.0625 L 155.367188 57.648438 L 155.636719 59.265625 L 155.90625 60.914062 L 156.175781 62.59375 L 156.445312 64.304688 L 156.710938 66.039062 L 156.980469 67.800781 L 157.25 69.585938 L 157.519531 71.386719 L 157.789062 73.207031 L 158.058594 75.046875 L 158.324219 76.894531 L 158.59375 78.753906 L 158.863281 80.625 L 159.132812 82.5 L 159.671875 86.257812 L 159.9375 88.132812 L 160.207031 90.007812 L 160.476562 91.878906 L 160.746094 93.738281 L 161.015625 95.589844 L 161.28125 97.425781 L 161.550781 99.25 L 161.820312 101.058594 L 162.089844 102.847656 L 162.359375 104.617188 L 162.628906 106.367188 L 162.894531 108.097656 L 163.164062 109.800781 L 163.433594 111.476562 L 163.703125 113.128906 L 163.972656 114.753906 L 164.242188 116.351562 L 164.507812 117.921875 L 164.777344 119.460938 L 165.046875 120.972656 L 165.316406 122.449219 L 165.585938 123.898438 L 165.855469 125.316406 L 166.121094 126.699219 L 166.390625 128.054688 L 166.660156 129.378906 L 166.929688 130.667969 L 167.199219 131.929688 L 167.46875 133.15625 L 167.734375 134.355469 L 168.003906 135.519531 L 168.273438 136.65625 L 168.542969 137.761719 L 168.8125 138.839844 L 169.082031 139.882812 L 169.347656 140.902344 L 169.617188 141.890625 L 169.886719 142.851562 L 170.15625 143.785156 L 170.425781 144.691406 L 170.695312 145.570312 L 170.960938 146.425781 L 171.230469 147.253906 L 171.5 148.054688 L 171.769531 148.835938 L 172.039062 149.59375 L 172.308594 150.324219 L 172.574219 151.035156 L 172.84375 151.722656 L 173.113281 152.390625 L 173.382812 153.039062 L 173.652344 153.664062 L 173.921875 154.273438 L 174.1875 154.859375 L 174.457031 155.429688 L 174.726562 155.984375 L 174.996094 156.515625 L 175.265625 157.035156 L 175.535156 157.535156 L 175.800781 158.019531 L 176.070312 158.492188 L 176.339844 158.945312 L 176.609375 159.386719 L 176.878906 159.8125 L 177.144531 160.226562 L 177.414062 160.625 L 177.683594 161.011719 L 177.953125 161.386719 L 178.222656 161.75 L 178.492188 162.101562 L 178.757812 162.445312 L 179.027344 162.773438 L 179.296875 163.09375 L 179.566406 163.402344 L 179.835938 163.699219 L 180.105469 163.992188 L 180.371094 164.273438 L 180.640625 164.542969 L 180.910156 164.808594 L 181.179688 165.0625 L 181.449219 165.308594 L 181.71875 165.550781 L 181.984375 165.78125 L 182.253906 166.007812 L 182.523438 166.222656 L 182.792969 166.433594 L 183.0625 166.640625 L 183.332031 166.839844 L 183.597656 167.03125 L 184.136719 167.398438 L 184.40625 167.574219 L 184.675781 167.742188 L 184.945312 167.90625 L 185.210938 168.066406 L 185.480469 168.222656 L 185.75 168.371094 L 186.289062 168.660156 L 186.558594 168.796875 L 186.824219 168.929688 L 187.09375 169.058594 L 187.363281 169.183594 L 187.632812 169.304688 L 188.171875 169.539062 L 188.4375 169.648438 L 188.707031 169.757812 L 188.976562 169.863281 L 189.246094 169.964844 L 189.515625 170.0625 L 189.785156 170.15625 L 190.050781 170.25 L 190.320312 170.34375 L 190.859375 170.515625 L 191.128906 170.597656 L 191.394531 170.679688 L 191.664062 170.757812 L 192.472656 170.980469 L 192.742188 171.050781 L 193.007812 171.117188 L 193.546875 171.25 L 193.816406 171.3125 L 194.085938 171.371094 L 194.355469 171.433594 L 194.621094 171.488281 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="177.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="177.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="177.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="177.320312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="139.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="139.320312"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="139.320312"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="139.320312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="101.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="101.320312"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="101.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="101.320312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="63.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="63.320312"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="63.320312"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="63.320312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 173.882812 L 54.019531 173.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 135.882812 L 54.019531 135.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 97.882812 L 54.019531 97.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.882812 L 54.019531 59.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/binary.svg b/documentation/ui/figure/binary.svg
new file mode 100644
index 0000000..c6b8575
--- /dev/null
+++ b/documentation/ui/figure/binary.svg
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface241">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.839844 L 201.601562 152.839844 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.421875 L 201.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.007812 L 201.601562 78.007812 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.589844 L 201.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.128906 L 201.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 161.28125 171.546875 L 161.550781 21.882812 L 194.890625 21.882812 "/>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 21.882812 L 94.066406 21.882812 L 94.335938 171.546875 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.128906 L 54.019531 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/concave.svg b/documentation/ui/figure/concave.svg
new file mode 100644
index 0000000..37ef129
--- /dev/null
+++ b/documentation/ui/figure/concave.svg
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 3.171875 -2.375 L 3.171875 -5.421875 L 1.015625 -2.375 Z M 3.1875 0 L 3.1875 -1.640625 L 0.25 -1.640625 L 0.25 -2.46875 L 3.3125 -6.734375 L 4.03125 -6.734375 L 4.03125 -2.375 L 5.015625 -2.375 L 5.015625 -1.640625 L 4.03125 -1.640625 L 4.03125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 2.8125 -6.734375 C 3.5625 -6.734375 4.082031 -6.535156 4.375 -6.140625 C 4.664062 -5.753906 4.8125 -5.359375 4.8125 -4.953125 L 3.984375 -4.953125 C 3.929688 -5.210938 3.851562 -5.421875 3.75 -5.578125 C 3.539062 -5.859375 3.226562 -6 2.8125 -6 C 2.34375 -6 1.96875 -5.78125 1.6875 -5.34375 C 1.414062 -4.90625 1.265625 -4.28125 1.234375 -3.46875 C 1.421875 -3.75 1.664062 -3.960938 1.96875 -4.109375 C 2.226562 -4.234375 2.523438 -4.296875 2.859375 -4.296875 C 3.421875 -4.296875 3.910156 -4.113281 4.328125 -3.75 C 4.742188 -3.394531 4.953125 -2.863281 4.953125 -2.15625 C 4.953125 -1.539062 4.753906 -1 4.359375 -0.53125 C 3.960938 -0.0625 3.398438 0.171875 2.671875 0.171875 C 2.046875 0.171875 1.503906 -0.0625 1.046875 -0.53125 C 0.585938 -1.007812 0.359375 -1.816406 0.359375 -2.953125 C 0.359375 -3.785156 0.460938 -4.488281 0.671875 -5.0625 C 1.054688 -6.175781 1.769531 -6.734375 2.8125 -6.734375 Z M 2.75 -0.578125 C 3.1875 -0.578125 3.515625 -0.722656 3.734375 -1.015625 C 3.960938 -1.316406 4.078125 -1.671875 4.078125 -2.078125 C 4.078125 -2.421875 3.976562 -2.75 3.78125 -3.0625 C 3.582031 -3.375 3.222656 -3.53125 2.703125 -3.53125 C 2.335938 -3.53125 2.019531 -3.410156 1.75 -3.171875 C 1.476562 -2.929688 1.34375 -2.566406 1.34375 -2.078125 C 1.34375 -1.648438 1.460938 -1.289062 1.703125 -1 C 1.953125 -0.71875 2.300781 -0.578125 2.75 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 2.609375 -3.890625 C 2.984375 -3.890625 3.273438 -3.992188 3.484375 -4.203125 C 3.691406 -4.410156 3.796875 -4.660156 3.796875 -4.953125 C 3.796875 -5.203125 3.691406 -5.429688 3.484375 -5.640625 C 3.285156 -5.847656 2.984375 -5.953125 2.578125 -5.953125 C 2.171875 -5.953125 1.875 -5.847656 1.6875 -5.640625 C 1.507812 -5.429688 1.421875 -5.1875 1.421875 -4.90625 C 1.421875 -4.59375 1.535156 -4.34375 1.765625 -4.15625 C 2.003906 -3.976562 2.285156 -3.890625 2.609375 -3.890625 Z M 2.65625 -0.578125 C 3.050781 -0.578125 3.375 -0.679688 3.625 -0.890625 C 3.882812 -1.097656 4.015625 -1.414062 4.015625 -1.84375 C 4.015625 -2.269531 3.878906 -2.59375 3.609375 -2.8125 C 3.347656 -3.039062 3.007812 -3.15625 2.59375 -3.15625 C 2.195312 -3.15625 1.867188 -3.039062 1.609375 -2.8125 C 1.359375 -2.582031 1.234375 -2.265625 1.234375 -1.859375 C 1.234375 -1.515625 1.347656 -1.210938 1.578125 -0.953125 C 1.816406 -0.703125 2.175781 -0.578125 2.65625 -0.578125 Z M 1.46875 -3.578125 C 1.226562 -3.671875 1.039062 -3.785156 0.90625 -3.921875 C 0.664062 -4.171875 0.546875 -4.5 0.546875 -4.90625 C 0.546875 -5.40625 0.722656 -5.832031 1.078125 -6.1875 C 1.441406 -6.550781 1.957031 -6.734375 2.625 -6.734375 C 3.269531 -6.734375 3.773438 -6.5625 4.140625 -6.21875 C 4.503906 -5.875 4.6875 -5.476562 4.6875 -5.03125 C 4.6875 -4.613281 4.582031 -4.273438 4.375 -4.015625 C 4.25 -3.867188 4.0625 -3.722656 3.8125 -3.578125 C 4.09375 -3.453125 4.3125 -3.304688 4.46875 -3.140625 C 4.769531 -2.828125 4.921875 -2.421875 4.921875 -1.921875 C 4.921875 -1.335938 4.722656 -0.835938 4.328125 -0.421875 C 3.929688 -0.015625 3.367188 0.1875 2.640625 0.1875 C 1.984375 0.1875 1.429688 0.0078125 0.984375 -0.34375 C 0.535156 -0.695312 0.3125 -1.210938 0.3125 -1.890625 C 0.3125 -2.285156 0.40625 -2.625 0.59375 -2.90625 C 0.789062 -3.195312 1.082031 -3.421875 1.46875 -3.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-7">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-8">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-9">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 48.683594 14.398438 L 202 14.398438 L 202 180 L 48.683594 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 48.683594 165 L 202 165 L 202 167 L 48.683594 167 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 48.683594 124 L 202 124 L 202 126 L 48.683594 126 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 48.683594 83 L 202 83 L 202 84 L 48.683594 84 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 48.683594 42 L 202 42 L 202 43 L 48.683594 43 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 72 14.398438 L 74 14.398438 L 74 180 L 72 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 107 14.398438 L 109 14.398438 L 109 180 L 107 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 142 14.398438 L 143 14.398438 L 143 180 L 142 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 178 14.398438 L 178 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 48.683594 144 L 202.601562 144 L 202.601562 146 L 48.683594 146 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 48.683594 103 L 202.601562 103 L 202.601562 105 L 48.683594 105 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 48.683594 62 L 202.601562 62 L 202.601562 64 L 48.683594 64 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 48.683594 21 L 202.601562 21 L 202.601562 23 L 48.683594 23 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 55 14.398438 L 57 14.398438 L 57 180 L 55 180 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 89 14.398438 L 91 14.398438 L 91 180 L 89 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 124 14.398438 L 126 14.398438 L 126 180 L 124 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 159 14.398438 L 161 14.398438 L 161 180 L 159 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface246">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 48.683594 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 48.683594 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 165.933594 L 201.601562 165.933594 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 124.777344 L 201.601562 124.777344 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 83.617188 L 201.601562 83.617188 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 42.460938 L 201.601562 42.460938 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 73.011719 179.027344 L 73.011719 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 107.765625 179.027344 L 107.765625 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 142.519531 179.027344 L 142.519531 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 177.273438 179.027344 L 177.273438 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 145.355469 L 201.601562 145.355469 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 104.199219 L 201.601562 104.199219 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 63.039062 L 201.601562 63.039062 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 55.632812 179.027344 L 55.632812 14.398438 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 90.386719 179.027344 L 90.386719 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 125.140625 179.027344 L 125.140625 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 159.894531 179.027344 L 159.894531 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.648438 179.027344 L 194.648438 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 55.632812 21.882812 L 83.214844 21.882812 L 83.492188 22.15625 L 83.769531 23.519531 L 84.050781 24.863281 L 84.328125 26.191406 L 84.605469 27.5 L 84.886719 28.792969 L 85.164062 30.066406 L 85.441406 31.328125 L 85.722656 32.570312 L 86 33.796875 L 86.277344 35.011719 L 86.558594 36.207031 L 86.835938 37.390625 L 87.113281 38.558594 L 87.390625 39.710938 L 87.671875 40.851562 L 87.949219 41.976562 L 88.226562 43.089844 L 88.507812 44.191406 L 88.785156 45.277344 L 89.0625 46.351562 L 89.34375 47.410156 L 89.621094 48.460938 L 89.898438 49.496094 L 90.179688 50.519531 L 90.457031 51.535156 L 90.734375 52.535156 L 91.015625 53.523438 L 91.292969 54.503906 L 91.570312 55.472656 L 91.851562 56.429688 L 92.128906 57.375 L 92.40625 58.3125 L 92.6875 59.238281 L 92.964844 60.152344 L 93.242188 61.058594 L 93.519531 61.957031 L 93.800781 62.84375 L 94.078125 63.71875 L 94.355469 64.585938 L 94.636719 65.445312 L 94.914062 66.296875 L 95.191406 67.136719 L 95.472656 67.96875 L 95.75 68.792969 L 96.027344 69.609375 L 96.308594 70.414062 L 96.585938 71.214844 L 96.863281 72.003906 L 97.144531 72.785156 L 97.421875 73.5625 L 97.699219 74.328125 L 97.980469 75.089844 L 98.257812 75.839844 L 98.535156 76.585938 L 98.816406 77.320312 L 99.09375 78.050781 L 99.371094 78.773438 L 99.652344 79.492188 L 99.929688 80.199219 L 100.207031 80.902344 L 100.484375 81.597656 L 100.765625 82.289062 L 101.042969 82.972656 L 101.320312 83.648438 L 101.601562 84.316406 L 101.878906 84.980469 L 102.15625 85.640625 L 102.4375 86.292969 L 102.714844 86.9375 L 102.992188 87.578125 L 103.273438 88.210938 L 103.550781 88.839844 L 103.828125 89.464844 L 104.109375 90.082031 L 104.386719 90.691406 L 104.664062 91.296875 L 104.945312 91.898438 L 105.222656 92.496094 L 105.5 93.085938 L 105.78125 93.671875 L 106.335938 94.828125 L 106.613281 95.398438 L 106.894531 95.960938 L 107.171875 96.523438 L 107.449219 97.078125 L 107.730469 97.628906 L 108.007812 98.175781 L 108.285156 98.71875 L 108.566406 99.257812 L 109.121094 100.320312 L 109.402344 100.84375 L 109.679688 101.363281 L 109.957031 101.878906 L 110.238281 102.390625 L 110.515625 102.898438 L 110.792969 103.402344 L 111.074219 103.898438 L 111.351562 104.394531 L 111.628906 104.886719 L 111.910156 105.375 L 112.1875 105.859375 L 112.742188 106.8125 L 113.023438 107.285156 L 113.300781 107.753906 L 113.578125 108.21875 L 113.859375 108.679688 L 114.414062 109.59375 L 114.695312 110.042969 L 114.972656 110.492188 L 115.25 110.933594 L 115.53125 111.375 L 115.808594 111.8125 L 116.085938 112.246094 L 116.367188 112.679688 L 116.921875 113.53125 L 117.203125 113.953125 L 117.480469 114.371094 L 117.757812 114.785156 L 118.039062 115.195312 L 118.316406 115.605469 L 118.59375 116.011719 L 118.875 116.414062 L 119.152344 116.816406 L 119.429688 117.214844 L 119.707031 117.609375 L 119.988281 118 L 120.265625 118.390625 L 120.542969 118.773438 L 120.824219 119.160156 L 121.378906 119.917969 L 121.660156 120.292969 L 121.9375 120.667969 L 122.214844 121.035156 L 122.496094 121.40625 L 123.050781 122.132812 L 123.332031 122.492188 L 123.609375 122.851562 L 123.886719 123.207031 L 124.167969 123.558594 L 124.445312 123.910156 L 124.722656 124.257812 L 125.003906 124.605469 L 125.28125 124.949219 L 125.835938 125.628906 L 126.117188 125.964844 L 126.394531 126.300781 L 126.671875 126.632812 L 126.953125 126.960938 L 127.507812 127.617188 L 127.789062 127.941406 L 128.34375 128.582031 L 128.625 128.898438 L 128.902344 129.214844 L 129.179688 129.527344 L 129.460938 129.839844 L 129.738281 130.152344 L 130.015625 130.457031 L 130.296875 130.765625 L 130.574219 131.066406 L 130.851562 131.371094 L 131.132812 131.671875 L 131.6875 132.265625 L 131.964844 132.558594 L 132.246094 132.851562 L 132.523438 133.144531 L 132.800781 133.433594 L 133.082031 133.71875 L 133.636719 134.289062 L 133.917969 134.570312 L 134.195312 134.851562 L 134.472656 135.128906 L 134.753906 135.40625 L 135.03125 135.683594 L 135.308594 135.957031 L 135.589844 136.230469 L 136.144531 136.769531 L 136.425781 137.035156 L 136.980469 137.566406 L 137.261719 137.828125 L 137.816406 138.351562 L 138.09375 138.609375 L 138.375 138.863281 L 138.652344 139.121094 L 138.929688 139.375 L 139.210938 139.625 L 139.488281 139.878906 L 139.765625 140.125 L 140.046875 140.375 L 140.601562 140.867188 L 140.882812 141.109375 L 141.4375 141.59375 L 141.71875 141.835938 L 141.996094 142.074219 L 142.273438 142.308594 L 142.554688 142.546875 L 143.109375 143.015625 L 143.390625 143.246094 L 143.945312 143.707031 L 144.226562 143.933594 L 145.058594 144.613281 L 145.339844 144.835938 L 145.617188 145.058594 L 145.894531 145.277344 L 146.175781 145.496094 L 146.730469 145.933594 L 147.011719 146.148438 L 147.566406 146.578125 L 147.847656 146.792969 L 148.402344 147.214844 L 148.683594 147.425781 L 149.238281 147.839844 L 149.519531 148.046875 L 149.796875 148.25 L 150.074219 148.457031 L 150.355469 148.660156 L 150.632812 148.859375 L 150.910156 149.0625 L 151.1875 149.261719 L 151.46875 149.460938 L 151.746094 149.660156 L 152.023438 149.855469 L 152.304688 150.050781 L 152.859375 150.441406 L 153.140625 150.632812 L 153.417969 150.828125 L 153.695312 151.019531 L 153.976562 151.207031 L 154.253906 151.398438 L 154.53125 151.585938 L 154.8125 151.773438 L 155.089844 151.960938 L 155.367188 152.144531 L 155.648438 152.332031 L 155.925781 152.515625 L 156.203125 152.695312 L 156.484375 152.878906 L 156.761719 153.058594 L 157.039062 153.242188 L 157.316406 153.417969 L 157.597656 153.597656 L 157.875 153.777344 L 158.152344 153.953125 L 158.433594 154.128906 L 158.710938 154.304688 L 158.988281 154.476562 L 159.269531 154.652344 L 159.824219 154.996094 L 160.105469 155.167969 L 160.382812 155.335938 L 160.660156 155.507812 L 160.941406 155.675781 L 161.496094 156.011719 L 161.777344 156.175781 L 162.054688 156.34375 L 162.332031 156.507812 L 162.613281 156.671875 L 162.890625 156.835938 L 163.167969 156.996094 L 163.445312 157.160156 L 163.726562 157.320312 L 164.28125 157.640625 L 164.5625 157.796875 L 164.839844 157.957031 L 165.117188 158.113281 L 165.398438 158.269531 L 165.953125 158.582031 L 166.234375 158.734375 L 166.511719 158.890625 L 166.789062 159.042969 L 167.070312 159.195312 L 167.625 159.5 L 167.90625 159.648438 L 168.183594 159.800781 L 168.460938 159.949219 L 168.742188 160.097656 L 169.019531 160.246094 L 169.296875 160.390625 L 169.578125 160.539062 L 169.855469 160.683594 L 170.132812 160.832031 L 170.410156 160.976562 L 170.691406 161.117188 L 171.246094 161.40625 L 171.527344 161.546875 L 171.804688 161.6875 L 172.082031 161.832031 L 172.363281 161.96875 L 172.917969 162.25 L 173.199219 162.386719 L 173.476562 162.527344 L 173.753906 162.664062 L 174.035156 162.800781 L 174.589844 163.074219 L 174.871094 163.207031 L 175.148438 163.34375 L 175.425781 163.476562 L 175.707031 163.609375 L 176.539062 164.007812 L 176.820312 164.136719 L 177.097656 164.269531 L 177.375 164.398438 L 177.65625 164.527344 L 178.210938 164.785156 L 178.492188 164.914062 L 178.769531 165.042969 L 179.046875 165.167969 L 179.328125 165.296875 L 179.882812 165.546875 L 180.164062 165.671875 L 180.71875 165.921875 L 181 166.042969 L 181.277344 166.167969 L 181.554688 166.289062 L 181.835938 166.414062 L 182.667969 166.777344 L 182.949219 166.894531 L 183.226562 167.015625 L 183.503906 167.132812 L 183.785156 167.253906 L 184.339844 167.488281 L 184.621094 167.605469 L 185.175781 167.839844 L 185.457031 167.957031 L 185.734375 168.070312 L 186.011719 168.1875 L 186.292969 168.300781 L 186.847656 168.527344 L 187.128906 168.640625 L 187.683594 168.867188 L 187.964844 168.980469 L 188.242188 169.089844 L 188.519531 169.203125 L 188.800781 169.3125 L 189.078125 169.421875 L 189.355469 169.535156 L 189.632812 169.644531 L 189.914062 169.753906 L 190.191406 169.859375 L 190.46875 169.96875 L 190.75 170.078125 L 191.027344 170.183594 L 191.304688 170.292969 L 191.585938 170.398438 L 192.140625 170.609375 L 192.421875 170.714844 L 192.976562 170.925781 L 193.257812 171.03125 L 193.535156 171.132812 L 193.8125 171.238281 L 194.09375 171.339844 L 194.371094 171.445312 L 194.648438 171.546875 "/>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 55.632812 171.546875 L 55.910156 171.445312 L 56.191406 171.339844 L 56.46875 171.238281 L 56.746094 171.132812 L 57.027344 171.03125 L 57.582031 170.820312 L 57.863281 170.714844 L 58.417969 170.503906 L 58.699219 170.398438 L 58.976562 170.292969 L 59.253906 170.183594 L 59.535156 170.078125 L 60.089844 169.859375 L 60.371094 169.753906 L 60.925781 169.535156 L 61.207031 169.421875 L 61.761719 169.203125 L 62.039062 169.089844 L 62.320312 168.980469 L 62.875 168.753906 L 63.15625 168.640625 L 63.710938 168.414062 L 63.992188 168.300781 L 64.269531 168.1875 L 64.546875 168.070312 L 64.828125 167.957031 L 65.382812 167.722656 L 65.664062 167.605469 L 66.21875 167.371094 L 66.5 167.253906 L 66.777344 167.132812 L 67.054688 167.015625 L 67.335938 166.894531 L 67.613281 166.777344 L 68.167969 166.535156 L 68.449219 166.414062 L 68.726562 166.289062 L 69.003906 166.167969 L 69.285156 166.042969 L 69.5625 165.921875 L 69.839844 165.796875 L 70.121094 165.671875 L 70.675781 165.421875 L 70.957031 165.296875 L 71.234375 165.167969 L 71.511719 165.042969 L 71.792969 164.914062 L 72.347656 164.65625 L 72.628906 164.527344 L 73.183594 164.269531 L 73.464844 164.136719 L 73.742188 164.007812 L 74.019531 163.875 L 74.300781 163.742188 L 75.132812 163.34375 L 75.414062 163.207031 L 75.691406 163.074219 L 75.96875 162.9375 L 76.25 162.800781 L 76.804688 162.527344 L 77.085938 162.386719 L 77.363281 162.25 L 77.640625 162.109375 L 77.921875 161.96875 L 78.199219 161.832031 L 78.476562 161.6875 L 78.757812 161.546875 L 79.035156 161.40625 L 79.3125 161.261719 L 79.59375 161.117188 L 79.871094 160.976562 L 80.148438 160.832031 L 80.429688 160.683594 L 80.707031 160.539062 L 80.984375 160.390625 L 81.261719 160.246094 L 81.542969 160.097656 L 82.097656 159.800781 L 82.378906 159.648438 L 82.65625 159.5 L 82.933594 159.347656 L 83.214844 159.195312 L 83.769531 158.890625 L 84.050781 158.734375 L 84.328125 158.582031 L 84.605469 158.425781 L 84.886719 158.269531 L 85.441406 157.957031 L 85.722656 157.796875 L 86 157.640625 L 86.277344 157.480469 L 86.558594 157.320312 L 86.835938 157.160156 L 87.113281 156.996094 L 87.390625 156.835938 L 87.671875 156.671875 L 88.226562 156.34375 L 88.507812 156.175781 L 88.785156 156.011719 L 89.0625 155.84375 L 89.34375 155.675781 L 89.621094 155.507812 L 89.898438 155.335938 L 90.179688 155.167969 L 90.734375 154.824219 L 91.015625 154.652344 L 91.292969 154.476562 L 91.570312 154.304688 L 91.851562 154.128906 L 92.40625 153.777344 L 92.6875 153.597656 L 92.964844 153.417969 L 93.242188 153.242188 L 93.519531 153.058594 L 93.800781 152.878906 L 94.078125 152.695312 L 94.355469 152.515625 L 94.636719 152.332031 L 94.914062 152.144531 L 95.191406 151.960938 L 95.472656 151.773438 L 96.027344 151.398438 L 96.308594 151.207031 L 96.585938 151.019531 L 96.863281 150.828125 L 97.144531 150.632812 L 97.421875 150.441406 L 97.699219 150.246094 L 97.980469 150.050781 L 98.535156 149.660156 L 98.816406 149.460938 L 99.371094 149.0625 L 99.652344 148.859375 L 99.929688 148.660156 L 100.207031 148.457031 L 100.484375 148.25 L 100.765625 148.046875 L 101.320312 147.632812 L 101.601562 147.425781 L 102.15625 147.003906 L 102.4375 146.792969 L 102.992188 146.363281 L 103.273438 146.148438 L 103.550781 145.933594 L 103.828125 145.714844 L 104.109375 145.496094 L 104.664062 145.058594 L 104.945312 144.835938 L 105.222656 144.613281 L 105.5 144.386719 L 105.78125 144.160156 L 106.335938 143.707031 L 106.613281 143.476562 L 106.894531 143.246094 L 107.171875 143.015625 L 107.449219 142.78125 L 107.730469 142.546875 L 108.007812 142.308594 L 108.285156 142.074219 L 108.566406 141.835938 L 109.121094 141.351562 L 109.402344 141.109375 L 109.679688 140.867188 L 109.957031 140.621094 L 110.238281 140.375 L 110.515625 140.125 L 110.792969 139.878906 L 111.074219 139.625 L 111.351562 139.375 L 111.628906 139.121094 L 111.910156 138.863281 L 112.1875 138.609375 L 112.464844 138.351562 L 112.742188 138.089844 L 113.023438 137.828125 L 113.300781 137.566406 L 113.578125 137.300781 L 113.859375 137.035156 L 114.136719 136.769531 L 114.414062 136.5 L 114.695312 136.230469 L 115.25 135.683594 L 115.53125 135.40625 L 116.367188 134.570312 L 116.644531 134.289062 L 116.921875 134.003906 L 117.203125 133.71875 L 117.480469 133.433594 L 117.757812 133.144531 L 118.039062 132.851562 L 118.59375 132.265625 L 118.875 131.96875 L 119.152344 131.671875 L 119.429688 131.371094 L 119.707031 131.066406 L 119.988281 130.765625 L 120.265625 130.457031 L 120.542969 130.152344 L 120.824219 129.839844 L 121.378906 129.214844 L 121.660156 128.898438 L 121.9375 128.582031 L 122.214844 128.261719 L 122.496094 127.941406 L 122.773438 127.617188 L 123.050781 127.289062 L 123.332031 126.960938 L 123.609375 126.632812 L 123.886719 126.300781 L 124.167969 125.964844 L 124.445312 125.628906 L 124.722656 125.289062 L 125.003906 124.949219 L 125.28125 124.605469 L 125.835938 123.910156 L 126.117188 123.558594 L 126.394531 123.207031 L 126.671875 122.851562 L 126.953125 122.492188 L 127.230469 122.132812 L 127.507812 121.769531 L 127.789062 121.40625 L 128.066406 121.035156 L 128.34375 120.667969 L 128.625 120.292969 L 128.902344 119.917969 L 129.179688 119.539062 L 129.460938 119.160156 L 129.738281 118.773438 L 130.015625 118.390625 L 130.296875 118 L 130.574219 117.609375 L 130.851562 117.214844 L 131.132812 116.816406 L 131.6875 116.011719 L 131.964844 115.605469 L 132.246094 115.195312 L 132.523438 114.785156 L 132.800781 114.371094 L 133.082031 113.953125 L 133.359375 113.53125 L 133.636719 113.105469 L 133.917969 112.679688 L 134.472656 111.8125 L 134.753906 111.375 L 135.308594 110.492188 L 135.589844 110.042969 L 135.867188 109.59375 L 136.144531 109.136719 L 136.425781 108.679688 L 136.703125 108.21875 L 136.980469 107.753906 L 137.261719 107.285156 L 137.539062 106.8125 L 138.09375 105.859375 L 138.375 105.375 L 138.652344 104.886719 L 138.929688 104.394531 L 139.210938 103.898438 L 139.488281 103.402344 L 139.765625 102.898438 L 140.046875 102.390625 L 140.324219 101.878906 L 140.601562 101.363281 L 140.882812 100.84375 L 141.160156 100.320312 L 141.4375 99.789062 L 141.71875 99.257812 L 141.996094 98.71875 L 142.273438 98.175781 L 142.554688 97.628906 L 142.832031 97.078125 L 143.390625 95.960938 L 143.667969 95.398438 L 143.945312 94.828125 L 144.226562 94.25 L 144.503906 93.671875 L 144.78125 93.085938 L 145.058594 92.496094 L 145.339844 91.898438 L 145.617188 91.296875 L 145.894531 90.691406 L 146.175781 90.082031 L 146.453125 89.464844 L 146.730469 88.839844 L 147.011719 88.210938 L 147.289062 87.578125 L 147.566406 86.9375 L 147.847656 86.292969 L 148.125 85.640625 L 148.402344 84.980469 L 148.683594 84.316406 L 148.960938 83.648438 L 149.238281 82.972656 L 149.519531 82.289062 L 149.796875 81.597656 L 150.074219 80.902344 L 150.355469 80.199219 L 150.632812 79.492188 L 150.910156 78.773438 L 151.1875 78.050781 L 151.46875 77.320312 L 151.746094 76.585938 L 152.023438 75.839844 L 152.304688 75.089844 L 152.582031 74.328125 L 152.859375 73.5625 L 153.140625 72.785156 L 153.417969 72.003906 L 153.695312 71.214844 L 153.976562 70.414062 L 154.253906 69.609375 L 154.53125 68.792969 L 154.8125 67.96875 L 155.089844 67.136719 L 155.367188 66.296875 L 155.648438 65.445312 L 155.925781 64.585938 L 156.203125 63.71875 L 156.484375 62.84375 L 156.761719 61.957031 L 157.039062 61.058594 L 157.316406 60.152344 L 157.597656 59.238281 L 157.875 58.3125 L 158.152344 57.375 L 158.433594 56.429688 L 158.710938 55.472656 L 158.988281 54.503906 L 159.269531 53.523438 L 159.546875 52.535156 L 159.824219 51.535156 L 160.105469 50.519531 L 160.382812 49.496094 L 160.660156 48.460938 L 160.941406 47.410156 L 161.21875 46.351562 L 161.496094 45.277344 L 161.777344 44.191406 L 162.054688 43.089844 L 162.332031 41.976562 L 162.613281 40.851562 L 162.890625 39.710938 L 163.167969 38.558594 L 163.445312 37.390625 L 163.726562 36.207031 L 164.003906 35.011719 L 164.28125 33.796875 L 164.5625 32.570312 L 164.839844 31.328125 L 165.117188 30.066406 L 165.398438 28.792969 L 165.675781 27.5 L 165.953125 26.191406 L 166.234375 24.863281 L 166.511719 23.519531 L 166.789062 22.15625 L 167.070312 21.882812 L 194.648438 21.882812 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="148.792969"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="148.792969"/>
+ <use xlink:href="#glyph0-3" x="36.262756" y="148.792969"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="107.636719"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="107.636719"/>
+ <use xlink:href="#glyph0-4" x="36.262756" y="107.636719"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="66.476562"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="66.476562"/>
+ <use xlink:href="#glyph0-5" x="36.262756" y="66.476562"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.261719" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.262756" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 145.355469 L 48.683594 145.355469 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 104.199219 L 48.683594 104.199219 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 63.039062 L 48.683594 63.039062 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 21.882812 L 48.683594 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 55.632812 183.28125 L 55.632812 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 90.386719 183.28125 L 90.386719 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 125.140625 183.28125 L 125.140625 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 159.894531 183.28125 L 159.894531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.648438 183.28125 L 194.648438 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="46.296875" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="51.632462" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="54.297913" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.633499" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="81.050781" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="86.386368" y="192.992188"/>
+ <use xlink:href="#glyph0-7" x="89.051819" y="192.992188"/>
+ <use xlink:href="#glyph0-8" x="94.387405" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="115.804688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="121.140274" y="192.992188"/>
+ <use xlink:href="#glyph0-8" x="123.805725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="129.141312" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="150.558594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="155.89418" y="192.992188"/>
+ <use xlink:href="#glyph0-9" x="158.559631" y="192.992188"/>
+ <use xlink:href="#glyph0-8" x="163.895218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.3125" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.648087" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.313538" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.649124" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="122.140625" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/cosine.svg b/documentation/ui/figure/cosine.svg
new file mode 100644
index 0000000..ab567c5
--- /dev/null
+++ b/documentation/ui/figure/cosine.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface201">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.835938 L 201.601562 152.835938 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.421875 L 201.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.003906 L 201.601562 78.003906 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.589844 L 201.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.128906 L 201.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 60.996094 171.539062 L 61.265625 171.523438 L 61.53125 171.492188 L 61.800781 171.449219 L 62.070312 171.398438 L 62.339844 171.332031 L 62.609375 171.253906 L 62.878906 171.167969 L 63.144531 171.066406 L 63.414062 170.953125 L 63.683594 170.828125 L 63.953125 170.691406 L 64.222656 170.546875 L 64.492188 170.386719 L 64.757812 170.214844 L 65.027344 170.03125 L 65.296875 169.839844 L 65.566406 169.632812 L 65.835938 169.414062 L 66.105469 169.183594 L 66.371094 168.945312 L 66.640625 168.691406 L 66.910156 168.429688 L 67.179688 168.15625 L 67.449219 167.867188 L 67.71875 167.570312 L 67.984375 167.261719 L 68.253906 166.941406 L 68.523438 166.613281 L 68.792969 166.269531 L 69.0625 165.917969 L 69.332031 165.554688 L 69.597656 165.179688 L 69.867188 164.792969 L 70.136719 164.394531 L 70.40625 163.988281 L 70.675781 163.570312 L 70.945312 163.140625 L 71.210938 162.703125 L 71.480469 162.253906 L 71.75 161.792969 L 72.019531 161.324219 L 72.289062 160.84375 L 72.558594 160.351562 L 72.824219 159.851562 L 73.09375 159.339844 L 73.363281 158.820312 L 73.632812 158.289062 L 73.902344 157.75 L 74.167969 157.199219 L 74.4375 156.640625 L 74.707031 156.070312 L 74.976562 155.492188 L 75.246094 154.902344 L 75.515625 154.308594 L 75.78125 153.699219 L 76.050781 153.085938 L 76.320312 152.460938 L 76.589844 151.828125 L 76.859375 151.1875 L 77.128906 150.535156 L 77.394531 149.878906 L 77.664062 149.210938 L 77.933594 148.535156 L 78.203125 147.851562 L 78.472656 147.160156 L 78.742188 146.457031 L 79.007812 145.75 L 79.277344 145.035156 L 79.546875 144.3125 L 79.816406 143.582031 L 80.085938 142.84375 L 80.355469 142.097656 L 80.621094 141.34375 L 80.890625 140.585938 L 81.160156 139.816406 L 81.429688 139.042969 L 81.699219 138.265625 L 81.96875 137.476562 L 82.234375 136.683594 L 82.503906 135.882812 L 82.773438 135.078125 L 83.042969 134.265625 L 83.3125 133.449219 L 83.582031 132.625 L 83.847656 131.792969 L 84.117188 130.960938 L 84.65625 129.273438 L 84.925781 128.421875 L 85.195312 127.566406 L 85.460938 126.707031 L 85.730469 125.839844 L 86 124.96875 L 86.269531 124.09375 L 86.539062 123.214844 L 86.808594 122.332031 L 87.074219 121.445312 L 87.34375 120.554688 L 87.613281 119.660156 L 87.882812 118.761719 L 88.152344 117.859375 L 88.417969 116.953125 L 88.957031 115.132812 L 89.226562 114.21875 L 89.496094 113.300781 L 89.765625 112.378906 L 90.03125 111.457031 L 90.570312 109.605469 L 91.109375 107.746094 L 91.378906 106.8125 L 91.644531 105.878906 L 92.722656 102.128906 L 92.992188 101.1875 L 93.257812 100.246094 L 94.066406 97.421875 L 94.335938 96.476562 L 94.605469 95.535156 L 94.871094 94.59375 L 95.679688 91.769531 L 95.949219 90.832031 L 96.21875 89.890625 L 96.484375 88.953125 L 96.753906 88.019531 L 97.023438 87.082031 L 97.292969 86.148438 L 97.5625 85.21875 L 97.832031 84.285156 L 98.097656 83.359375 L 98.636719 81.507812 L 98.90625 80.585938 L 99.175781 79.667969 L 99.445312 78.753906 L 99.710938 77.839844 L 99.980469 76.929688 L 100.519531 75.117188 L 101.058594 73.320312 L 101.324219 72.425781 L 101.863281 70.652344 L 102.402344 68.894531 L 102.667969 68.023438 L 102.9375 67.15625 L 103.207031 66.292969 L 103.476562 65.433594 L 103.746094 64.578125 L 104.015625 63.730469 L 104.28125 62.886719 L 104.550781 62.050781 L 104.820312 61.21875 L 105.089844 60.390625 L 105.359375 59.570312 L 105.628906 58.753906 L 105.894531 57.945312 L 106.164062 57.144531 L 106.433594 56.347656 L 106.703125 55.554688 L 106.972656 54.773438 L 107.242188 53.996094 L 107.507812 53.226562 L 107.777344 52.460938 L 108.046875 51.707031 L 108.316406 50.957031 L 108.585938 50.214844 L 108.855469 49.480469 L 109.121094 48.753906 L 109.390625 48.035156 L 109.660156 47.320312 L 109.929688 46.617188 L 110.199219 45.921875 L 110.46875 45.234375 L 110.734375 44.554688 L 111.003906 43.882812 L 111.273438 43.21875 L 111.542969 42.566406 L 111.8125 41.917969 L 112.082031 41.28125 L 112.347656 40.652344 L 112.617188 40.035156 L 112.886719 39.421875 L 113.15625 38.820312 L 113.425781 38.230469 L 113.695312 37.644531 L 113.960938 37.070312 L 114.230469 36.507812 L 114.5 35.953125 L 114.769531 35.40625 L 115.039062 34.871094 L 115.308594 34.347656 L 115.574219 33.832031 L 115.84375 33.324219 L 116.113281 32.828125 L 116.382812 32.34375 L 116.652344 31.867188 L 116.921875 31.402344 L 117.1875 30.949219 L 117.457031 30.503906 L 117.726562 30.070312 L 117.996094 29.648438 L 118.265625 29.234375 L 118.53125 28.832031 L 118.800781 28.441406 L 119.070312 28.0625 L 119.339844 27.691406 L 119.609375 27.332031 L 119.878906 26.984375 L 120.144531 26.648438 L 120.414062 26.324219 L 120.683594 26.007812 L 120.953125 25.707031 L 121.222656 25.414062 L 121.492188 25.132812 L 121.757812 24.863281 L 122.027344 24.605469 L 122.296875 24.359375 L 122.566406 24.125 L 122.835938 23.902344 L 123.105469 23.691406 L 123.371094 23.492188 L 123.640625 23.300781 L 123.910156 23.125 L 124.179688 22.960938 L 124.449219 22.808594 L 124.71875 22.664062 L 124.984375 22.535156 L 125.253906 22.417969 L 125.523438 22.308594 L 125.792969 22.214844 L 126.0625 22.132812 L 126.332031 22.0625 L 126.597656 22 L 126.867188 21.953125 L 127.136719 21.917969 L 127.40625 21.894531 L 127.675781 21.882812 L 127.945312 21.882812 L 128.210938 21.894531 L 128.480469 21.917969 L 128.75 21.953125 L 129.019531 22 L 129.289062 22.0625 L 129.558594 22.132812 L 129.824219 22.214844 L 130.09375 22.308594 L 130.363281 22.417969 L 130.632812 22.535156 L 130.902344 22.664062 L 131.171875 22.808594 L 131.4375 22.960938 L 131.707031 23.125 L 131.976562 23.300781 L 132.246094 23.492188 L 132.515625 23.691406 L 132.78125 23.902344 L 133.050781 24.125 L 133.320312 24.359375 L 133.589844 24.605469 L 133.859375 24.863281 L 134.128906 25.132812 L 134.394531 25.414062 L 134.664062 25.707031 L 134.933594 26.007812 L 135.203125 26.324219 L 135.472656 26.648438 L 135.742188 26.984375 L 136.007812 27.332031 L 136.277344 27.691406 L 136.546875 28.0625 L 136.816406 28.441406 L 137.085938 28.832031 L 137.355469 29.234375 L 137.621094 29.648438 L 137.890625 30.070312 L 138.160156 30.503906 L 138.429688 30.949219 L 138.699219 31.402344 L 138.96875 31.867188 L 139.234375 32.34375 L 139.503906 32.828125 L 139.773438 33.324219 L 140.042969 33.832031 L 140.3125 34.347656 L 140.582031 34.871094 L 140.847656 35.40625 L 141.117188 35.953125 L 141.386719 36.507812 L 141.65625 37.070312 L 141.925781 37.644531 L 142.195312 38.230469 L 142.460938 38.820312 L 142.730469 39.421875 L 143 40.035156 L 143.269531 40.652344 L 143.539062 41.28125 L 143.808594 41.917969 L 144.074219 42.566406 L 144.34375 43.21875 L 144.613281 43.882812 L 144.882812 44.554688 L 145.152344 45.234375 L 145.421875 45.921875 L 145.6875 46.617188 L 145.957031 47.320312 L 146.226562 48.035156 L 146.496094 48.753906 L 146.765625 49.480469 L 147.03125 50.214844 L 147.300781 50.957031 L 147.570312 51.707031 L 147.839844 52.460938 L 148.109375 53.226562 L 148.378906 53.996094 L 148.644531 54.773438 L 148.914062 55.554688 L 149.183594 56.347656 L 149.453125 57.144531 L 149.722656 57.945312 L 149.992188 58.753906 L 150.257812 59.570312 L 150.527344 60.390625 L 150.796875 61.21875 L 151.066406 62.050781 L 151.335938 62.886719 L 151.605469 63.730469 L 151.871094 64.578125 L 152.140625 65.433594 L 152.410156 66.292969 L 152.679688 67.15625 L 152.949219 68.023438 L 153.21875 68.894531 L 153.484375 69.773438 L 153.753906 70.652344 L 154.292969 72.425781 L 154.5625 73.320312 L 154.832031 74.21875 L 155.097656 75.117188 L 155.636719 76.929688 L 155.90625 77.839844 L 156.445312 79.667969 L 156.710938 80.585938 L 156.980469 81.507812 L 157.789062 84.285156 L 158.058594 85.21875 L 158.324219 86.148438 L 158.59375 87.082031 L 158.863281 88.019531 L 159.132812 88.953125 L 159.402344 89.890625 L 159.671875 90.832031 L 159.9375 91.769531 L 161.015625 95.535156 L 161.28125 96.476562 L 161.550781 97.421875 L 162.628906 101.1875 L 162.894531 102.128906 L 163.972656 105.878906 L 164.242188 106.8125 L 164.507812 107.746094 L 165.046875 109.605469 L 165.585938 111.457031 L 165.855469 112.378906 L 166.121094 113.300781 L 166.390625 114.21875 L 166.660156 115.132812 L 167.199219 116.953125 L 167.46875 117.859375 L 167.734375 118.761719 L 168.003906 119.660156 L 168.273438 120.554688 L 168.542969 121.445312 L 168.8125 122.332031 L 169.082031 123.214844 L 169.347656 124.09375 L 169.617188 124.96875 L 169.886719 125.839844 L 170.15625 126.707031 L 170.425781 127.566406 L 170.695312 128.421875 L 170.960938 129.273438 L 171.5 130.960938 L 172.039062 132.625 L 172.308594 133.449219 L 172.574219 134.265625 L 172.84375 135.078125 L 173.113281 135.882812 L 173.382812 136.683594 L 173.652344 137.476562 L 173.921875 138.265625 L 174.1875 139.042969 L 174.457031 139.816406 L 174.726562 140.585938 L 174.996094 141.34375 L 175.265625 142.097656 L 175.535156 142.84375 L 175.800781 143.582031 L 176.070312 144.3125 L 176.339844 145.035156 L 176.609375 145.75 L 176.878906 146.457031 L 177.144531 147.160156 L 177.414062 147.851562 L 177.683594 148.535156 L 177.953125 149.210938 L 178.222656 149.878906 L 178.492188 150.535156 L 178.757812 151.1875 L 179.027344 151.828125 L 179.296875 152.460938 L 179.566406 153.085938 L 179.835938 153.699219 L 180.105469 154.308594 L 180.371094 154.902344 L 180.640625 155.492188 L 180.910156 156.070312 L 181.179688 156.640625 L 181.449219 157.199219 L 181.71875 157.75 L 181.984375 158.289062 L 182.253906 158.820312 L 182.523438 159.339844 L 182.792969 159.851562 L 183.0625 160.351562 L 183.332031 160.84375 L 183.597656 161.324219 L 183.867188 161.792969 L 184.136719 162.253906 L 184.40625 162.703125 L 184.675781 163.140625 L 184.945312 163.570312 L 185.210938 163.988281 L 185.480469 164.394531 L 185.75 164.792969 L 186.019531 165.179688 L 186.289062 165.554688 L 186.558594 165.917969 L 186.824219 166.269531 L 187.09375 166.613281 L 187.363281 166.941406 L 187.632812 167.261719 L 187.902344 167.570312 L 188.171875 167.867188 L 188.4375 168.15625 L 188.707031 168.429688 L 188.976562 168.691406 L 189.246094 168.945312 L 189.515625 169.183594 L 189.785156 169.414062 L 190.050781 169.632812 L 190.320312 169.839844 L 190.589844 170.03125 L 190.859375 170.214844 L 191.128906 170.386719 L 191.394531 170.546875 L 191.664062 170.691406 L 191.933594 170.828125 L 192.203125 170.953125 L 192.472656 171.066406 L 192.742188 171.167969 L 193.007812 171.253906 L 193.277344 171.332031 L 193.546875 171.398438 L 193.816406 171.449219 L 194.085938 171.492188 L 194.355469 171.523438 L 194.621094 171.539062 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.128906 L 54.019531 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/discrete.svg b/documentation/ui/figure/discrete.svg
new file mode 100644
index 0000000..bb24450
--- /dev/null
+++ b/documentation/ui/figure/discrete.svg
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 153 L 54.019531 153 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 114 L 202 114 L 202 115 L 54.019531 115 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 76 L 202 76 L 202 77 L 54.019531 77 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 38 L 202 38 L 202 39 L 54.019531 39 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 132 L 202.601562 132 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 94 L 202.601562 94 L 202.601562 96 L 54.019531 96 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 56 L 202.601562 56 L 202.601562 58 L 54.019531 58 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 18 L 202.601562 18 L 202.601562 20 L 54.019531 20 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface196">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.515625 L 201.601562 152.515625 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 114.449219 L 201.601562 114.449219 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 76.386719 L 201.601562 76.386719 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 38.320312 L 201.601562 38.320312 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 133.480469 L 201.601562 133.480469 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 95.417969 L 201.601562 95.417969 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 57.355469 L 201.601562 57.355469 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 19.289062 L 201.601562 19.289062 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 64.445312 171.546875 C 64.445312 176.507812 57.007812 176.507812 57.007812 171.546875 C 57.007812 166.585938 64.445312 166.585938 64.445312 171.546875 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 66.867188 160.5625 C 66.867188 165.523438 59.425781 165.523438 59.425781 160.5625 C 59.425781 155.601562 66.867188 155.601562 66.867188 160.5625 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 69.554688 148.355469 C 69.554688 153.316406 62.113281 153.316406 62.113281 148.355469 C 62.113281 143.394531 69.554688 143.394531 69.554688 148.355469 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 72.242188 136.152344 C 72.242188 141.113281 64.804688 141.113281 64.804688 136.152344 C 64.804688 131.191406 72.242188 131.191406 72.242188 136.152344 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 74.933594 123.945312 C 74.933594 128.90625 67.492188 128.90625 67.492188 123.945312 C 67.492188 118.984375 74.933594 118.984375 74.933594 123.945312 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 77.621094 111.742188 C 77.621094 116.703125 70.179688 116.703125 70.179688 111.742188 C 70.179688 106.78125 77.621094 106.78125 77.621094 111.742188 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 80.308594 99.535156 C 80.308594 104.496094 72.871094 104.496094 72.871094 99.535156 C 72.871094 94.578125 80.308594 94.578125 80.308594 99.535156 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 83 87.332031 C 83 92.292969 75.558594 92.292969 75.558594 87.332031 C 75.558594 82.371094 83 82.371094 83 87.332031 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 85.6875 75.128906 C 85.6875 80.085938 78.246094 80.085938 78.246094 75.128906 C 78.246094 70.167969 85.6875 70.167969 85.6875 75.128906 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 88.375 62.921875 C 88.375 67.882812 80.933594 67.882812 80.933594 62.921875 C 80.933594 57.960938 88.375 57.960938 88.375 62.921875 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 91.066406 50.71875 C 91.066406 55.679688 83.625 55.679688 83.625 50.71875 C 83.625 45.757812 91.066406 45.757812 91.066406 50.71875 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 93.753906 38.511719 C 93.753906 43.472656 86.3125 43.472656 86.3125 38.511719 C 86.3125 33.550781 93.753906 33.550781 93.753906 38.511719 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 96.441406 26.308594 C 96.441406 31.269531 89 31.269531 89 26.308594 C 89 21.347656 96.441406 21.347656 96.441406 26.308594 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 99.132812 21.882812 C 99.132812 26.84375 91.691406 26.84375 91.691406 21.882812 C 91.691406 16.921875 99.132812 16.921875 99.132812 21.882812 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 101.820312 27.984375 C 101.820312 32.945312 94.378906 32.945312 94.378906 27.984375 C 94.378906 23.023438 101.820312 23.023438 101.820312 27.984375 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 104.507812 34.089844 C 104.507812 39.046875 97.066406 39.046875 97.066406 34.089844 C 97.066406 29.128906 104.507812 29.128906 104.507812 34.089844 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 107.195312 40.191406 C 107.195312 45.152344 99.757812 45.152344 99.757812 40.191406 C 99.757812 35.230469 107.195312 35.230469 107.195312 40.191406 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 109.886719 46.292969 C 109.886719 51.253906 102.445312 51.253906 102.445312 46.292969 C 102.445312 41.332031 109.886719 41.332031 109.886719 46.292969 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 112.574219 52.394531 C 112.574219 57.355469 105.132812 57.355469 105.132812 52.394531 C 105.132812 47.433594 112.574219 47.433594 112.574219 52.394531 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 115.261719 58.496094 C 115.261719 63.457031 107.820312 63.457031 107.820312 58.496094 C 107.820312 53.539062 115.261719 53.539062 115.261719 58.496094 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 117.953125 64.601562 C 117.953125 69.5625 110.511719 69.5625 110.511719 64.601562 C 110.511719 59.640625 117.953125 59.640625 117.953125 64.601562 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 120.640625 70.703125 C 120.640625 75.664062 113.199219 75.664062 113.199219 70.703125 C 113.199219 65.742188 120.640625 65.742188 120.640625 70.703125 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 123.328125 76.804688 C 123.328125 81.765625 115.886719 81.765625 115.886719 76.804688 C 115.886719 71.84375 123.328125 71.84375 123.328125 76.804688 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 126.019531 82.90625 C 126.019531 87.867188 118.578125 87.867188 118.578125 82.90625 C 118.578125 77.945312 126.019531 77.945312 126.019531 82.90625 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 128.707031 89.011719 C 128.707031 93.972656 121.265625 93.972656 121.265625 89.011719 C 121.265625 84.050781 128.707031 84.050781 128.707031 89.011719 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 131.394531 95.113281 C 131.394531 100.074219 123.953125 100.074219 123.953125 95.113281 C 123.953125 90.152344 131.394531 90.152344 131.394531 95.113281 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 134.082031 89.621094 C 134.082031 94.582031 126.644531 94.582031 126.644531 89.621094 C 126.644531 84.660156 134.082031 84.660156 134.082031 89.621094 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 136.773438 83.519531 C 136.773438 88.480469 129.332031 88.480469 129.332031 83.519531 C 129.332031 78.558594 136.773438 78.558594 136.773438 83.519531 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 139.460938 77.414062 C 139.460938 82.375 132.019531 82.375 132.019531 77.414062 C 132.019531 72.453125 139.460938 72.453125 139.460938 77.414062 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 142.148438 71.3125 C 142.148438 76.273438 134.707031 76.273438 134.707031 71.3125 C 134.707031 66.351562 142.148438 66.351562 142.148438 71.3125 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 144.839844 65.210938 C 144.839844 70.171875 137.398438 70.171875 137.398438 65.210938 C 137.398438 60.25 144.839844 60.25 144.839844 65.210938 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 147.527344 59.109375 C 147.527344 64.070312 140.085938 64.070312 140.085938 59.109375 C 140.085938 54.148438 147.527344 54.148438 147.527344 59.109375 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 150.214844 53.003906 C 150.214844 57.964844 142.773438 57.964844 142.773438 53.003906 C 142.773438 48.046875 150.214844 48.046875 150.214844 53.003906 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 152.90625 46.902344 C 152.90625 51.863281 145.464844 51.863281 145.464844 46.902344 C 145.464844 41.941406 152.90625 41.941406 152.90625 46.902344 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 155.59375 40.800781 C 155.59375 45.761719 148.152344 45.761719 148.152344 40.800781 C 148.152344 35.839844 155.59375 35.839844 155.59375 40.800781 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 158.28125 34.699219 C 158.28125 39.660156 150.839844 39.660156 150.839844 34.699219 C 150.839844 29.738281 158.28125 29.738281 158.28125 34.699219 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 160.96875 28.597656 C 160.96875 33.554688 153.53125 33.554688 153.53125 28.597656 C 153.53125 23.636719 160.96875 23.636719 160.96875 28.597656 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 163.660156 22.492188 C 163.660156 27.453125 156.21875 27.453125 156.21875 22.492188 C 156.21875 17.53125 163.660156 17.53125 163.660156 22.492188 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 166.347656 25.085938 C 166.347656 30.046875 158.90625 30.046875 158.90625 25.085938 C 158.90625 20.125 166.347656 20.125 166.347656 25.085938 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 169.035156 37.292969 C 169.035156 42.253906 161.597656 42.253906 161.597656 37.292969 C 161.597656 32.332031 169.035156 32.332031 169.035156 37.292969 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 171.726562 49.496094 C 171.726562 54.457031 164.285156 54.457031 164.285156 49.496094 C 164.285156 44.535156 171.726562 44.535156 171.726562 49.496094 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 174.414062 61.703125 C 174.414062 66.664062 166.972656 66.664062 166.972656 61.703125 C 166.972656 56.742188 174.414062 56.742188 174.414062 61.703125 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 177.101562 73.90625 C 177.101562 78.867188 169.660156 78.867188 169.660156 73.90625 C 169.660156 68.945312 177.101562 68.945312 177.101562 73.90625 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 179.792969 86.113281 C 179.792969 91.070312 172.351562 91.070312 172.351562 86.113281 C 172.351562 81.152344 179.792969 81.152344 179.792969 86.113281 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 182.480469 98.316406 C 182.480469 103.277344 175.039062 103.277344 175.039062 98.316406 C 175.039062 93.355469 182.480469 93.355469 182.480469 98.316406 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 185.167969 110.519531 C 185.167969 115.480469 177.726562 115.480469 177.726562 110.519531 C 177.726562 105.5625 185.167969 105.5625 185.167969 110.519531 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 187.859375 122.726562 C 187.859375 127.6875 180.417969 127.6875 180.417969 122.726562 C 180.417969 117.765625 187.859375 117.765625 187.859375 122.726562 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 190.546875 134.929688 C 190.546875 139.890625 183.105469 139.890625 183.105469 134.929688 C 183.105469 129.96875 190.546875 129.96875 190.546875 134.929688 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 193.234375 147.136719 C 193.234375 152.097656 185.792969 152.097656 185.792969 147.136719 C 185.792969 142.175781 193.234375 142.175781 193.234375 147.136719 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 195.921875 159.339844 C 195.921875 164.300781 188.484375 164.300781 188.484375 159.339844 C 188.484375 154.378906 195.921875 154.378906 195.921875 159.339844 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 198.613281 171.546875 C 198.613281 176.507812 191.171875 176.507812 191.171875 171.546875 C 191.171875 166.585938 198.613281 166.585938 198.613281 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="136.917969"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="136.917969"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="136.917969"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="136.917969"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="98.855469"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="98.855469"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="98.855469"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="98.855469"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="60.792969"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="60.792969"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="60.792969"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="60.792969"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="22.726562"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="22.726562"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="22.726562"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="22.726562"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 133.480469 L 54.019531 133.480469 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 95.417969 L 54.019531 95.417969 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 57.355469 L 54.019531 57.355469 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 19.289062 L 54.019531 19.289062 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/gaussian.svg b/documentation/ui/figure/gaussian.svg
new file mode 100644
index 0000000..3eddc70
--- /dev/null
+++ b/documentation/ui/figure/gaussian.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 158 L 202 158 L 202 160 L 54.019531 160 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 119 L 202 119 L 202 120 L 54.019531 120 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 80 L 202 80 L 202 81 L 54.019531 81 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 41 L 202 41 L 202 42 L 54.019531 42 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 177 L 202.601562 177 L 202.601562 179 L 54.019531 179 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 138 L 202.601562 138 L 202.601562 140 L 54.019531 140 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 99 L 202.601562 99 L 202.601562 101 L 54.019531 101 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 60 L 202.601562 60 L 202.601562 62 L 54.019531 62 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface206">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 158.855469 L 201.601562 158.855469 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 119.71875 L 201.601562 119.71875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 80.585938 L 201.601562 80.585938 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 41.449219 L 201.601562 41.449219 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 178.425781 L 201.601562 178.425781 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 139.289062 L 201.601562 139.289062 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 100.152344 L 201.601562 100.152344 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 61.015625 L 201.601562 61.015625 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 61.265625 171.195312 L 61.53125 171.011719 L 61.800781 170.828125 L 62.339844 170.445312 L 62.878906 170.046875 L 63.144531 169.839844 L 63.414062 169.632812 L 63.683594 169.417969 L 64.222656 168.980469 L 64.492188 168.753906 L 64.757812 168.519531 L 65.027344 168.285156 L 65.296875 168.046875 L 65.566406 167.800781 L 65.835938 167.550781 L 66.105469 167.296875 L 66.371094 167.039062 L 66.640625 166.777344 L 66.910156 166.507812 L 67.179688 166.234375 L 67.449219 165.957031 L 67.71875 165.671875 L 67.984375 165.382812 L 68.253906 165.089844 L 68.523438 164.789062 L 68.792969 164.484375 L 69.0625 164.175781 L 69.332031 163.859375 L 69.597656 163.539062 L 69.867188 163.214844 L 70.136719 162.882812 L 70.40625 162.542969 L 70.675781 162.199219 L 70.945312 161.851562 L 71.210938 161.496094 L 71.480469 161.136719 L 71.75 160.769531 L 72.019531 160.398438 L 72.289062 160.019531 L 72.558594 159.632812 L 72.824219 159.242188 L 73.09375 158.847656 L 73.632812 158.035156 L 73.902344 157.617188 L 74.167969 157.195312 L 74.4375 156.765625 L 74.707031 156.332031 L 74.976562 155.890625 L 75.246094 155.441406 L 75.515625 154.988281 L 75.78125 154.527344 L 76.050781 154.058594 L 76.320312 153.585938 L 76.589844 153.105469 L 76.859375 152.617188 L 77.128906 152.125 L 77.394531 151.621094 L 77.664062 151.113281 L 77.933594 150.597656 L 78.203125 150.078125 L 78.472656 149.550781 L 78.742188 149.015625 L 79.007812 148.472656 L 79.277344 147.921875 L 79.546875 147.367188 L 79.816406 146.804688 L 80.085938 146.234375 L 80.355469 145.65625 L 80.621094 145.070312 L 80.890625 144.480469 L 81.160156 143.882812 L 81.429688 143.277344 L 81.699219 142.664062 L 81.96875 142.046875 L 82.234375 141.417969 L 82.503906 140.785156 L 82.773438 140.144531 L 83.042969 139.5 L 83.3125 138.84375 L 83.582031 138.183594 L 83.847656 137.515625 L 84.117188 136.839844 L 84.386719 136.15625 L 84.65625 135.46875 L 84.925781 134.773438 L 85.195312 134.070312 L 85.460938 133.363281 L 85.730469 132.644531 L 86 131.921875 L 86.269531 131.195312 L 86.539062 130.457031 L 86.808594 129.714844 L 87.074219 128.964844 L 87.34375 128.210938 L 87.613281 127.449219 L 87.882812 126.679688 L 88.152344 125.90625 L 88.417969 125.125 L 88.6875 124.339844 L 88.957031 123.546875 L 89.226562 122.746094 L 89.496094 121.941406 L 89.765625 121.128906 L 90.03125 120.3125 L 90.300781 119.488281 L 90.570312 118.660156 L 90.839844 117.828125 L 91.109375 116.988281 L 91.378906 116.144531 L 91.644531 115.292969 L 91.914062 114.4375 L 92.183594 113.578125 L 92.453125 112.714844 L 92.722656 111.84375 L 92.992188 110.96875 L 93.257812 110.089844 L 93.527344 109.207031 L 94.066406 107.425781 L 94.605469 105.628906 L 94.871094 104.722656 L 95.140625 103.816406 L 95.679688 101.988281 L 95.949219 101.070312 L 96.21875 100.148438 L 96.484375 99.222656 L 97.023438 97.363281 L 97.5625 95.496094 L 97.832031 94.558594 L 98.097656 93.617188 L 98.636719 91.734375 L 98.90625 90.789062 L 99.175781 89.839844 L 99.445312 88.894531 L 99.710938 87.945312 L 99.980469 86.996094 L 100.25 86.042969 L 100.519531 85.09375 L 100.789062 84.140625 L 101.058594 83.191406 L 101.324219 82.238281 L 101.59375 81.289062 L 101.863281 80.335938 L 102.402344 78.4375 L 102.667969 77.492188 L 102.9375 76.542969 L 103.476562 74.652344 L 103.746094 73.710938 L 104.015625 72.773438 L 104.28125 71.835938 L 104.550781 70.898438 L 105.359375 68.109375 L 105.628906 67.1875 L 105.894531 66.269531 L 106.164062 65.351562 L 106.433594 64.441406 L 106.972656 62.628906 L 107.242188 61.730469 L 107.507812 60.835938 L 107.777344 59.949219 L 108.046875 59.066406 L 108.316406 58.1875 L 108.585938 57.316406 L 108.855469 56.449219 L 109.121094 55.589844 L 109.390625 54.734375 L 109.660156 53.886719 L 109.929688 53.046875 L 110.199219 52.210938 L 110.46875 51.386719 L 110.734375 50.566406 L 111.003906 49.757812 L 111.273438 48.953125 L 111.542969 48.15625 L 111.8125 47.371094 L 112.082031 46.589844 L 112.347656 45.820312 L 112.617188 45.0625 L 112.886719 44.308594 L 113.15625 43.566406 L 113.425781 42.832031 L 113.695312 42.109375 L 113.960938 41.394531 L 114.230469 40.691406 L 114.5 40 L 114.769531 39.316406 L 115.039062 38.644531 L 115.308594 37.984375 L 115.574219 37.332031 L 115.84375 36.695312 L 116.113281 36.066406 L 116.382812 35.449219 L 116.652344 34.847656 L 116.921875 34.253906 L 117.1875 33.675781 L 117.457031 33.105469 L 117.726562 32.550781 L 117.996094 32.007812 L 118.265625 31.476562 L 118.53125 30.960938 L 118.800781 30.457031 L 119.070312 29.964844 L 119.339844 29.488281 L 119.609375 29.023438 L 119.878906 28.574219 L 120.144531 28.136719 L 120.414062 27.710938 L 120.683594 27.304688 L 120.953125 26.910156 L 121.222656 26.527344 L 121.492188 26.160156 L 121.757812 25.808594 L 122.027344 25.472656 L 122.296875 25.148438 L 122.566406 24.839844 L 122.835938 24.546875 L 123.105469 24.269531 L 123.371094 24.007812 L 123.640625 23.757812 L 123.910156 23.523438 L 124.179688 23.308594 L 124.449219 23.105469 L 124.71875 22.917969 L 124.984375 22.746094 L 125.253906 22.589844 L 125.523438 22.449219 L 125.792969 22.324219 L 126.0625 22.210938 L 126.332031 22.117188 L 126.597656 22.039062 L 126.867188 21.976562 L 127.136719 21.929688 L 127.40625 21.898438 L 127.675781 21.882812 L 127.945312 21.882812 L 128.210938 21.898438 L 128.480469 21.929688 L 128.75 21.976562 L 129.019531 22.039062 L 129.289062 22.117188 L 129.558594 22.210938 L 129.824219 22.324219 L 130.09375 22.449219 L 130.363281 22.589844 L 130.632812 22.746094 L 130.902344 22.917969 L 131.171875 23.105469 L 131.4375 23.308594 L 131.707031 23.523438 L 131.976562 23.757812 L 132.246094 24.007812 L 132.515625 24.269531 L 132.78125 24.546875 L 133.050781 24.839844 L 133.320312 25.148438 L 133.589844 25.472656 L 133.859375 25.808594 L 134.128906 26.160156 L 134.394531 26.527344 L 134.664062 26.910156 L 134.933594 27.304688 L 135.203125 27.710938 L 135.472656 28.136719 L 135.742188 28.574219 L 136.007812 29.023438 L 136.277344 29.488281 L 136.546875 29.964844 L 136.816406 30.457031 L 137.085938 30.960938 L 137.355469 31.476562 L 137.621094 32.007812 L 137.890625 32.550781 L 138.160156 33.105469 L 138.429688 33.675781 L 138.699219 34.253906 L 138.96875 34.847656 L 139.234375 35.449219 L 139.503906 36.066406 L 139.773438 36.695312 L 140.042969 37.332031 L 140.3125 37.984375 L 140.582031 38.644531 L 140.847656 39.316406 L 141.117188 40 L 141.386719 40.691406 L 141.65625 41.394531 L 141.925781 42.109375 L 142.195312 42.832031 L 142.460938 43.566406 L 142.730469 44.308594 L 143 45.0625 L 143.269531 45.820312 L 143.539062 46.589844 L 143.808594 47.371094 L 144.074219 48.15625 L 144.34375 48.953125 L 144.613281 49.757812 L 144.882812 50.566406 L 145.152344 51.386719 L 145.421875 52.210938 L 145.6875 53.046875 L 145.957031 53.886719 L 146.226562 54.734375 L 146.496094 55.589844 L 146.765625 56.449219 L 147.03125 57.316406 L 147.300781 58.1875 L 147.570312 59.066406 L 147.839844 59.949219 L 148.109375 60.835938 L 148.378906 61.730469 L 148.644531 62.628906 L 149.183594 64.441406 L 149.453125 65.351562 L 149.992188 67.1875 L 150.257812 68.109375 L 151.066406 70.898438 L 151.605469 72.773438 L 151.871094 73.710938 L 152.140625 74.652344 L 152.679688 76.542969 L 152.949219 77.492188 L 153.21875 78.4375 L 153.484375 79.386719 L 153.753906 80.335938 L 154.023438 81.289062 L 154.292969 82.238281 L 154.5625 83.191406 L 154.832031 84.140625 L 155.097656 85.09375 L 155.367188 86.042969 L 155.636719 86.996094 L 156.175781 88.894531 L 156.445312 89.839844 L 156.710938 90.789062 L 156.980469 91.734375 L 157.789062 94.558594 L 158.058594 95.496094 L 158.324219 96.429688 L 158.59375 97.363281 L 159.132812 99.222656 L 159.402344 100.148438 L 159.671875 101.070312 L 159.9375 101.988281 L 160.476562 103.816406 L 161.015625 105.628906 L 161.28125 106.527344 L 161.550781 107.425781 L 162.089844 109.207031 L 162.359375 110.089844 L 162.628906 110.96875 L 162.894531 111.84375 L 163.164062 112.714844 L 163.433594 113.578125 L 163.703125 114.4375 L 163.972656 115.292969 L 164.242188 116.144531 L 164.507812 116.988281 L 164.777344 117.828125 L 165.046875 118.660156 L 165.316406 119.488281 L 165.585938 120.3125 L 165.855469 121.128906 L 166.121094 121.941406 L 166.390625 122.746094 L 166.660156 123.546875 L 166.929688 124.339844 L 167.199219 125.125 L 167.46875 125.90625 L 167.734375 126.679688 L 168.003906 127.449219 L 168.273438 128.210938 L 168.542969 128.964844 L 168.8125 129.714844 L 169.082031 130.457031 L 169.347656 131.195312 L 169.617188 131.921875 L 169.886719 132.644531 L 170.15625 133.363281 L 170.425781 134.070312 L 170.695312 134.773438 L 170.960938 135.46875 L 171.230469 136.15625 L 171.5 136.839844 L 171.769531 137.515625 L 172.039062 138.183594 L 172.308594 138.84375 L 172.574219 139.5 L 172.84375 140.144531 L 173.113281 140.785156 L 173.382812 141.417969 L 173.652344 142.046875 L 173.921875 142.664062 L 174.1875 143.277344 L 174.457031 143.882812 L 174.726562 144.480469 L 174.996094 145.070312 L 175.265625 145.65625 L 175.535156 146.234375 L 175.800781 146.804688 L 176.070312 147.367188 L 176.339844 147.921875 L 176.609375 148.472656 L 176.878906 149.015625 L 177.144531 149.550781 L 177.414062 150.078125 L 177.683594 150.597656 L 177.953125 151.113281 L 178.222656 151.621094 L 178.492188 152.125 L 178.757812 152.617188 L 179.027344 153.105469 L 179.296875 153.585938 L 179.566406 154.058594 L 179.835938 154.527344 L 180.105469 154.988281 L 180.371094 155.441406 L 180.640625 155.890625 L 180.910156 156.332031 L 181.179688 156.765625 L 181.449219 157.195312 L 181.71875 157.617188 L 181.984375 158.035156 L 182.523438 158.847656 L 182.792969 159.242188 L 183.0625 159.632812 L 183.332031 160.019531 L 183.597656 160.398438 L 183.867188 160.769531 L 184.136719 161.136719 L 184.40625 161.496094 L 184.675781 161.851562 L 184.945312 162.199219 L 185.210938 162.542969 L 185.480469 162.882812 L 185.75 163.214844 L 186.019531 163.539062 L 186.289062 163.859375 L 186.558594 164.175781 L 186.824219 164.484375 L 187.09375 164.789062 L 187.363281 165.089844 L 187.632812 165.382812 L 187.902344 165.671875 L 188.171875 165.957031 L 188.4375 166.234375 L 188.707031 166.507812 L 188.976562 166.777344 L 189.246094 167.039062 L 189.515625 167.296875 L 189.785156 167.550781 L 190.050781 167.800781 L 190.320312 168.046875 L 190.589844 168.285156 L 191.128906 168.753906 L 191.394531 168.980469 L 191.933594 169.417969 L 192.203125 169.632812 L 192.742188 170.046875 L 193.007812 170.246094 L 193.277344 170.445312 L 193.816406 170.828125 L 194.355469 171.195312 L 194.621094 171.371094 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="181.863281"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="181.863281"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="181.863281"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="181.863281"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="142.726562"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="142.726562"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="142.726562"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="142.726562"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="103.589844"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="103.589844"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="103.589844"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="103.589844"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="64.453125"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="64.453125"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="64.453125"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="64.453125"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 178.425781 L 54.019531 178.425781 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 139.289062 L 54.019531 139.289062 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 100.152344 L 54.019531 100.152344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 61.015625 L 54.019531 61.015625 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/gaussianProduct.svg b/documentation/ui/figure/gaussianProduct.svg
new file mode 100644
index 0000000..0643bbd
--- /dev/null
+++ b/documentation/ui/figure/gaussianProduct.svg
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 3.171875 -2.375 L 3.171875 -5.421875 L 1.015625 -2.375 Z M 3.1875 0 L 3.1875 -1.640625 L 0.25 -1.640625 L 0.25 -2.46875 L 3.3125 -6.734375 L 4.03125 -6.734375 L 4.03125 -2.375 L 5.015625 -2.375 L 5.015625 -1.640625 L 4.03125 -1.640625 L 4.03125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 2.8125 -6.734375 C 3.5625 -6.734375 4.082031 -6.535156 4.375 -6.140625 C 4.664062 -5.753906 4.8125 -5.359375 4.8125 -4.953125 L 3.984375 -4.953125 C 3.929688 -5.210938 3.851562 -5.421875 3.75 -5.578125 C 3.539062 -5.859375 3.226562 -6 2.8125 -6 C 2.34375 -6 1.96875 -5.78125 1.6875 -5.34375 C 1.414062 -4.90625 1.265625 -4.28125 1.234375 -3.46875 C 1.421875 -3.75 1.664062 -3.960938 1.96875 -4.109375 C 2.226562 -4.234375 2.523438 -4.296875 2.859375 -4.296875 C 3.421875 -4.296875 3.910156 -4.113281 4.328125 -3.75 C 4.742188 -3.394531 4.953125 -2.863281 4.953125 -2.15625 C 4.953125 -1.539062 4.753906 -1 4.359375 -0.53125 C 3.960938 -0.0625 3.398438 0.171875 2.671875 0.171875 C 2.046875 0.171875 1.503906 -0.0625 1.046875 -0.53125 C 0.585938 -1.007812 0.359375 -1.816406 0.359375 -2.953125 C 0.359375 -3.785156 0.460938 -4.488281 0.671875 -5.0625 C 1.054688 -6.175781 1.769531 -6.734375 2.8125 -6.734375 Z M 2.75 -0.578125 C 3.1875 -0.578125 3.515625 -0.722656 3.734375 -1.015625 C 3.960938 -1.316406 4.078125 -1.671875 4.078125 -2.078125 C 4.078125 -2.421875 3.976562 -2.75 3.78125 -3.0625 C 3.582031 -3.375 3.222656 -3.53125 2.703125 -3.53125 C 2.335938 -3.53125 2.019531 -3.410156 1.75 -3.171875 C 1.476562 -2.929688 1.34375 -2.566406 1.34375 -2.078125 C 1.34375 -1.648438 1.460938 -1.289062 1.703125 -1 C 1.953125 -0.71875 2.300781 -0.578125 2.75 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 2.609375 -3.890625 C 2.984375 -3.890625 3.273438 -3.992188 3.484375 -4.203125 C 3.691406 -4.410156 3.796875 -4.660156 3.796875 -4.953125 C 3.796875 -5.203125 3.691406 -5.429688 3.484375 -5.640625 C 3.285156 -5.847656 2.984375 -5.953125 2.578125 -5.953125 C 2.171875 -5.953125 1.875 -5.847656 1.6875 -5.640625 C 1.507812 -5.429688 1.421875 -5.1875 1.421875 -4.90625 C 1.421875 -4.59375 1.535156 -4.34375 1.765625 -4.15625 C 2.003906 -3.976562 2.285156 -3.890625 2.609375 -3.890625 Z M 2.65625 -0.578125 C 3.050781 -0.578125 3.375 -0.679688 3.625 -0.890625 C 3.882812 -1.097656 4.015625 -1.414062 4.015625 -1.84375 C 4.015625 -2.269531 3.878906 -2.59375 3.609375 -2.8125 C 3.347656 -3.039062 3.007812 -3.15625 2.59375 -3.15625 C 2.195312 -3.15625 1.867188 -3.039062 1.609375 -2.8125 C 1.359375 -2.582031 1.234375 -2.265625 1.234375 -1.859375 C 1.234375 -1.515625 1.347656 -1.210938 1.578125 -0.953125 C 1.816406 -0.703125 2.175781 -0.578125 2.65625 -0.578125 Z M 1.46875 -3.578125 C 1.226562 -3.671875 1.039062 -3.785156 0.90625 -3.921875 C 0.664062 -4.171875 0.546875 -4.5 0.546875 -4.90625 C 0.546875 -5.40625 0.722656 -5.832031 1.078125 -6.1875 C 1.441406 -6.550781 1.957031 -6.734375 2.625 -6.734375 C 3.269531 -6.734375 3.773438 -6.5625 4.140625 -6.21875 C 4.503906 -5.875 4.6875 -5.476562 4.6875 -5.03125 C 4.6875 -4.613281 4.582031 -4.273438 4.375 -4.015625 C 4.25 -3.867188 4.0625 -3.722656 3.8125 -3.578125 C 4.09375 -3.453125 4.3125 -3.304688 4.46875 -3.140625 C 4.769531 -2.828125 4.921875 -2.421875 4.921875 -1.921875 C 4.921875 -1.335938 4.722656 -0.835938 4.328125 -0.421875 C 3.929688 -0.015625 3.367188 0.1875 2.640625 0.1875 C 1.984375 0.1875 1.429688 0.0078125 0.984375 -0.34375 C 0.535156 -0.695312 0.3125 -1.210938 0.3125 -1.890625 C 0.3125 -2.285156 0.40625 -2.625 0.59375 -2.90625 C 0.789062 -3.195312 1.082031 -3.421875 1.46875 -3.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-7">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-8">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-9">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 48.683594 14.398438 L 202 14.398438 L 202 180 L 48.683594 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 48.683594 153 L 202 153 L 202 155 L 48.683594 155 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 48.683594 114 L 202 114 L 202 116 L 48.683594 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 48.683594 75 L 202 75 L 202 77 L 48.683594 77 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 48.683594 36 L 202 36 L 202 38 L 48.683594 38 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 72 14.398438 L 74 14.398438 L 74 180 L 72 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 107 14.398438 L 109 14.398438 L 109 180 L 107 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 142 14.398438 L 143 14.398438 L 143 180 L 142 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 178 14.398438 L 178 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 48.683594 173 L 202.601562 173 L 202.601562 175 L 48.683594 175 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 48.683594 134 L 202.601562 134 L 202.601562 136 L 48.683594 136 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 48.683594 95 L 202.601562 95 L 202.601562 97 L 48.683594 97 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 48.683594 56 L 202.601562 56 L 202.601562 58 L 48.683594 58 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 48.683594 17 L 202.601562 17 L 202.601562 19 L 48.683594 19 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 55 14.398438 L 57 14.398438 L 57 180 L 55 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 89 14.398438 L 91 14.398438 L 91 180 L 89 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 124 14.398438 L 126 14.398438 L 126 180 L 124 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 159 14.398438 L 161 14.398438 L 161 180 L 159 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface211">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 48.683594 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 48.683594 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 154.214844 L 201.601562 154.214844 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 115.226562 L 201.601562 115.226562 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 76.234375 L 201.601562 76.234375 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 37.242188 L 201.601562 37.242188 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 73.011719 179.027344 L 73.011719 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 107.765625 179.027344 L 107.765625 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 142.519531 179.027344 L 142.519531 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 177.273438 179.027344 L 177.273438 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 173.710938 L 201.601562 173.710938 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 134.71875 L 201.601562 134.71875 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 95.730469 L 201.601562 95.730469 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 56.738281 L 201.601562 56.738281 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 17.746094 L 201.601562 17.746094 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 55.632812 179.027344 L 55.632812 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 90.386719 179.027344 L 90.386719 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 125.140625 179.027344 L 125.140625 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 159.894531 179.027344 L 159.894531 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.648438 179.027344 L 194.648438 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 55.632812 171.546875 L 55.910156 171.480469 L 56.191406 171.414062 L 56.46875 171.34375 L 56.746094 171.269531 L 57.027344 171.199219 L 57.304688 171.121094 L 57.582031 171.046875 L 57.863281 170.964844 L 58.417969 170.800781 L 58.699219 170.714844 L 58.976562 170.628906 L 59.253906 170.539062 L 59.535156 170.445312 L 59.8125 170.351562 L 60.089844 170.253906 L 60.371094 170.152344 L 60.648438 170.050781 L 60.925781 169.945312 L 61.207031 169.839844 L 61.484375 169.730469 L 61.761719 169.617188 L 62.039062 169.5 L 62.320312 169.382812 L 62.597656 169.261719 L 62.875 169.136719 L 63.15625 169.011719 L 63.710938 168.746094 L 63.992188 168.609375 L 64.269531 168.472656 L 64.546875 168.328125 L 64.828125 168.183594 L 65.382812 167.878906 L 65.664062 167.722656 L 65.941406 167.5625 L 66.21875 167.398438 L 66.5 167.230469 L 67.054688 166.886719 L 67.335938 166.707031 L 67.613281 166.523438 L 67.890625 166.335938 L 68.167969 166.144531 L 68.449219 165.949219 L 68.726562 165.75 L 69.003906 165.546875 L 69.285156 165.335938 L 69.5625 165.125 L 69.839844 164.90625 L 70.121094 164.683594 L 70.398438 164.457031 L 70.675781 164.226562 L 70.957031 163.992188 L 71.234375 163.75 L 71.511719 163.503906 L 71.792969 163.253906 L 72.070312 162.996094 L 72.347656 162.734375 L 72.628906 162.46875 L 72.90625 162.199219 L 73.183594 161.921875 L 73.464844 161.636719 L 73.742188 161.351562 L 74.019531 161.054688 L 74.300781 160.757812 L 74.578125 160.453125 L 74.855469 160.140625 L 75.132812 159.824219 L 75.414062 159.5 L 75.691406 159.171875 L 75.96875 158.835938 L 76.25 158.496094 L 76.527344 158.148438 L 76.804688 157.792969 L 77.085938 157.433594 L 77.363281 157.066406 L 77.640625 156.695312 L 77.921875 156.316406 L 78.199219 155.929688 L 78.476562 155.535156 L 78.757812 155.132812 L 79.035156 154.726562 L 79.3125 154.3125 L 79.59375 153.890625 L 79.871094 153.464844 L 80.148438 153.027344 L 80.429688 152.585938 L 80.707031 152.136719 L 80.984375 151.679688 L 81.261719 151.214844 L 81.542969 150.742188 L 81.820312 150.261719 L 82.097656 149.773438 L 82.378906 149.28125 L 82.65625 148.777344 L 82.933594 148.265625 L 83.214844 147.746094 L 83.492188 147.222656 L 83.769531 146.6875 L 84.050781 146.144531 L 84.328125 145.59375 L 84.605469 145.035156 L 84.886719 144.46875 L 85.164062 143.894531 L 85.441406 143.3125 L 85.722656 142.71875 L 86 142.121094 L 86.277344 141.511719 L 86.558594 140.894531 L 86.835938 140.269531 L 87.113281 139.636719 L 87.390625 138.996094 L 87.671875 138.34375 L 87.949219 137.683594 L 88.226562 137.019531 L 88.507812 136.339844 L 88.785156 135.65625 L 89.0625 134.960938 L 89.34375 134.261719 L 89.621094 133.550781 L 89.898438 132.828125 L 90.179688 132.101562 L 90.457031 131.363281 L 90.734375 130.617188 L 91.015625 129.863281 L 91.292969 129.101562 L 91.570312 128.328125 L 91.851562 127.546875 L 92.128906 126.757812 L 92.40625 125.960938 L 92.6875 125.152344 L 92.964844 124.335938 L 93.242188 123.511719 L 93.519531 122.679688 L 93.800781 121.839844 L 94.078125 120.988281 L 94.355469 120.128906 L 94.636719 119.261719 L 94.914062 118.386719 L 95.191406 117.503906 L 95.472656 116.609375 L 95.75 115.710938 L 96.027344 114.800781 L 96.308594 113.882812 L 96.585938 112.957031 L 96.863281 112.023438 L 97.144531 111.082031 L 97.421875 110.132812 L 97.699219 109.175781 L 97.980469 108.210938 L 98.257812 107.238281 L 98.535156 106.253906 L 98.816406 105.265625 L 99.09375 104.269531 L 99.371094 103.265625 L 99.652344 102.257812 L 99.929688 101.238281 L 100.207031 100.214844 L 100.484375 99.179688 L 100.765625 98.140625 L 101.042969 97.097656 L 101.320312 96.042969 L 101.601562 94.984375 L 101.878906 93.917969 L 102.15625 92.847656 L 102.4375 91.769531 L 102.714844 90.683594 L 102.992188 89.59375 L 103.273438 88.5 L 103.550781 87.398438 L 103.828125 86.292969 L 104.109375 85.179688 L 104.386719 84.0625 L 104.664062 82.941406 L 104.945312 81.8125 L 105.5 79.546875 L 105.78125 78.40625 L 106.058594 77.261719 L 106.335938 76.113281 L 106.613281 74.960938 L 106.894531 73.804688 L 107.171875 72.644531 L 107.449219 71.480469 L 107.730469 70.316406 L 108.007812 69.148438 L 108.285156 67.976562 L 108.566406 66.804688 L 109.121094 64.453125 L 109.402344 63.273438 L 109.679688 62.09375 L 109.957031 60.910156 L 110.238281 59.726562 L 110.792969 57.359375 L 111.074219 56.175781 L 111.351562 54.992188 L 111.628906 53.816406 L 111.910156 52.65625 L 112.1875 51.507812 L 112.464844 50.375 L 112.742188 49.253906 L 113.023438 48.152344 L 113.300781 47.0625 L 113.578125 45.988281 L 113.859375 44.933594 L 114.136719 43.894531 L 114.414062 42.875 L 114.695312 41.871094 L 114.972656 40.886719 L 115.25 39.925781 L 115.53125 38.980469 L 115.808594 38.058594 L 116.085938 37.15625 L 116.367188 36.277344 L 116.644531 35.417969 L 116.921875 34.582031 L 117.203125 33.769531 L 117.480469 32.980469 L 117.757812 32.214844 L 118.039062 31.476562 L 118.316406 30.757812 L 118.59375 30.070312 L 118.875 29.402344 L 119.152344 28.765625 L 119.429688 28.152344 L 119.707031 27.566406 L 119.988281 27.007812 L 120.265625 26.476562 L 120.542969 25.972656 L 120.824219 25.496094 L 121.101562 25.050781 L 121.378906 24.632812 L 121.660156 24.242188 L 121.9375 23.882812 L 122.214844 23.550781 L 122.496094 23.25 L 122.773438 22.976562 L 123.050781 22.734375 L 123.332031 22.523438 L 123.609375 22.339844 L 123.886719 22.1875 L 124.167969 22.066406 L 124.445312 21.972656 L 124.722656 21.914062 L 125.003906 21.882812 L 125.28125 21.882812 L 125.558594 21.914062 L 125.835938 21.972656 L 126.117188 22.066406 L 126.394531 22.1875 L 126.671875 22.339844 L 126.953125 22.523438 L 127.230469 22.734375 L 127.507812 22.976562 L 127.789062 23.25 L 128.066406 23.550781 L 128.34375 23.882812 L 128.625 24.242188 L 128.902344 24.632812 L 129.179688 25.050781 L 129.460938 25.496094 L 129.738281 25.972656 L 130.015625 26.476562 L 130.296875 27.007812 L 130.574219 27.566406 L 130.851562 28.152344 L 131.132812 28.765625 L 131.410156 29.402344 L 131.6875 30.070312 L 131.964844 30.757812 L 132.246094 31.476562 L 132.523438 32.214844 L 132.800781 32.980469 L 133.082031 33.769531 L 133.359375 34.582031 L 133.636719 35.417969 L 133.917969 36.277344 L 134.195312 37.15625 L 134.472656 38.058594 L 134.753906 38.980469 L 135.03125 39.925781 L 135.308594 40.886719 L 135.589844 41.871094 L 135.867188 42.875 L 136.144531 43.894531 L 136.425781 44.933594 L 136.703125 45.988281 L 136.980469 47.0625 L 137.261719 48.152344 L 137.539062 49.253906 L 137.816406 50.375 L 138.09375 51.507812 L 138.375 52.65625 L 138.652344 53.816406 L 138.929688 54.992188 L 139.210938 56.175781 L 139.765625 58.542969 L 140.046875 59.726562 L 140.601562 62.09375 L 140.882812 63.273438 L 141.160156 64.453125 L 141.4375 65.628906 L 141.71875 66.804688 L 142.273438 69.148438 L 142.554688 70.316406 L 143.109375 72.644531 L 143.390625 73.804688 L 143.667969 74.960938 L 143.945312 76.113281 L 144.226562 77.261719 L 144.503906 78.40625 L 144.78125 79.546875 L 145.058594 80.679688 L 145.339844 81.8125 L 145.617188 82.941406 L 145.894531 84.0625 L 146.175781 85.179688 L 146.453125 86.292969 L 146.730469 87.398438 L 147.011719 88.5 L 147.289062 89.59375 L 147.566406 90.683594 L 147.847656 91.769531 L 148.125 92.847656 L 148.402344 93.917969 L 148.683594 94.984375 L 148.960938 96.042969 L 149.238281 97.097656 L 149.519531 98.140625 L 149.796875 99.179688 L 150.074219 100.214844 L 150.355469 101.238281 L 150.632812 102.257812 L 150.910156 103.265625 L 151.1875 104.269531 L 151.46875 105.265625 L 151.746094 106.253906 L 152.023438 107.238281 L 152.304688 108.210938 L 152.582031 109.175781 L 152.859375 110.132812 L 153.140625 111.082031 L 153.417969 112.023438 L 153.695312 112.957031 L 153.976562 113.882812 L 154.253906 114.800781 L 154.53125 115.710938 L 154.8125 116.609375 L 155.089844 117.503906 L 155.367188 118.386719 L 155.648438 119.261719 L 155.925781 120.128906 L 156.203125 120.988281 L 156.484375 121.839844 L 156.761719 122.679688 L 157.039062 123.511719 L 157.316406 124.335938 L 157.597656 125.152344 L 157.875 125.960938 L 158.152344 126.757812 L 158.433594 127.546875 L 158.710938 128.328125 L 158.988281 129.101562 L 159.269531 129.863281 L 159.546875 130.617188 L 159.824219 131.363281 L 160.105469 132.101562 L 160.382812 132.828125 L 160.660156 133.550781 L 160.941406 134.261719 L 161.21875 134.960938 L 161.496094 135.65625 L 161.777344 136.339844 L 162.054688 137.019531 L 162.332031 137.683594 L 162.613281 138.34375 L 162.890625 138.996094 L 163.167969 139.636719 L 163.445312 140.269531 L 163.726562 140.894531 L 164.003906 141.511719 L 164.28125 142.121094 L 164.5625 142.71875 L 164.839844 143.3125 L 165.117188 143.894531 L 165.398438 144.46875 L 165.675781 145.035156 L 165.953125 145.59375 L 166.234375 146.144531 L 166.511719 146.6875 L 166.789062 147.222656 L 167.070312 147.746094 L 167.347656 148.265625 L 167.625 148.777344 L 167.90625 149.28125 L 168.183594 149.773438 L 168.460938 150.261719 L 168.742188 150.742188 L 169.019531 151.214844 L 169.296875 151.679688 L 169.578125 152.136719 L 169.855469 152.585938 L 170.132812 153.027344 L 170.410156 153.464844 L 170.691406 153.890625 L 170.96875 154.3125 L 171.246094 154.726562 L 171.527344 155.132812 L 171.804688 155.535156 L 172.082031 155.929688 L 172.363281 156.316406 L 172.640625 156.695312 L 172.917969 157.066406 L 173.199219 157.433594 L 173.476562 157.792969 L 173.753906 158.148438 L 174.035156 158.496094 L 174.3125 158.835938 L 174.589844 159.171875 L 174.871094 159.5 L 175.148438 159.824219 L 175.425781 160.140625 L 175.707031 160.453125 L 175.984375 160.757812 L 176.539062 161.351562 L 176.820312 161.636719 L 177.097656 161.921875 L 177.375 162.199219 L 177.65625 162.46875 L 177.933594 162.734375 L 178.210938 162.996094 L 178.492188 163.253906 L 178.769531 163.503906 L 179.046875 163.75 L 179.328125 163.992188 L 179.605469 164.226562 L 179.882812 164.457031 L 180.164062 164.683594 L 180.441406 164.90625 L 180.71875 165.125 L 181 165.335938 L 181.277344 165.546875 L 181.554688 165.75 L 181.835938 165.949219 L 182.113281 166.144531 L 182.390625 166.335938 L 182.667969 166.523438 L 182.949219 166.707031 L 183.226562 166.886719 L 183.503906 167.058594 L 183.785156 167.230469 L 184.0625 167.398438 L 184.339844 167.5625 L 184.621094 167.722656 L 184.898438 167.878906 L 185.175781 168.03125 L 185.457031 168.183594 L 186.011719 168.472656 L 186.292969 168.609375 L 186.570312 168.746094 L 186.847656 168.878906 L 187.128906 169.011719 L 187.683594 169.261719 L 187.964844 169.382812 L 188.519531 169.617188 L 188.800781 169.730469 L 189.078125 169.839844 L 189.632812 170.050781 L 189.914062 170.152344 L 190.191406 170.253906 L 190.46875 170.351562 L 190.75 170.445312 L 191.027344 170.539062 L 191.304688 170.628906 L 191.585938 170.714844 L 191.863281 170.800781 L 192.140625 170.882812 L 192.421875 170.964844 L 192.699219 171.046875 L 192.976562 171.121094 L 193.257812 171.199219 L 193.535156 171.269531 L 193.8125 171.34375 L 194.09375 171.414062 L 194.648438 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="177.148438"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="177.148438"/>
+ <use xlink:href="#glyph0-1" x="36.262756" y="177.148438"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="138.15625"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="138.15625"/>
+ <use xlink:href="#glyph0-3" x="36.262756" y="138.15625"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="99.167969"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="99.167969"/>
+ <use xlink:href="#glyph0-4" x="36.262756" y="99.167969"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="60.175781"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="60.175781"/>
+ <use xlink:href="#glyph0-5" x="36.262756" y="60.175781"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="21.183594"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="21.183594"/>
+ <use xlink:href="#glyph0-6" x="36.262756" y="21.183594"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 173.710938 L 48.683594 173.710938 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 134.71875 L 48.683594 134.71875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 95.730469 L 48.683594 95.730469 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 56.738281 L 48.683594 56.738281 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 17.746094 L 48.683594 17.746094 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 55.632812 183.28125 L 55.632812 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 90.386719 183.28125 L 90.386719 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 125.140625 183.28125 L 125.140625 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 159.894531 183.28125 L 159.894531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.648438 183.28125 L 194.648438 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="46.296875" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="51.632462" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="54.297913" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.633499" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="81.050781" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="86.386368" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="89.051819" y="192.992188"/>
+ <use xlink:href="#glyph0-7" x="94.387405" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="115.804688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="121.140274" y="192.992188"/>
+ <use xlink:href="#glyph0-7" x="123.805725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="129.141312" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="150.558594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="155.89418" y="192.992188"/>
+ <use xlink:href="#glyph0-8" x="158.559631" y="192.992188"/>
+ <use xlink:href="#glyph0-7" x="163.895218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-9" x="185.3125" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.648087" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.313538" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.649124" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="122.140625" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/piShape.svg b/documentation/ui/figure/piShape.svg
new file mode 100644
index 0000000..ecf546c
--- /dev/null
+++ b/documentation/ui/figure/piShape.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface221">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.835938 L 201.601562 152.835938 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.421875 L 201.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.007812 L 201.601562 78.007812 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.589844 L 201.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.128906 L 201.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 60.996094 171.542969 L 61.265625 171.527344 L 61.53125 171.503906 L 61.800781 171.46875 L 62.070312 171.425781 L 62.339844 171.371094 L 62.609375 171.308594 L 62.878906 171.238281 L 63.144531 171.15625 L 63.414062 171.066406 L 63.683594 170.964844 L 63.953125 170.851562 L 64.222656 170.734375 L 64.492188 170.601562 L 64.757812 170.464844 L 65.027344 170.316406 L 65.296875 170.15625 L 65.566406 169.988281 L 65.835938 169.808594 L 66.105469 169.621094 L 66.371094 169.425781 L 66.640625 169.21875 L 66.910156 169.003906 L 67.179688 168.777344 L 67.449219 168.539062 L 67.71875 168.296875 L 67.984375 168.039062 L 68.253906 167.777344 L 68.523438 167.503906 L 68.792969 167.21875 L 69.0625 166.925781 L 69.332031 166.621094 L 69.597656 166.308594 L 69.867188 165.988281 L 70.136719 165.65625 L 70.40625 165.3125 L 70.675781 164.964844 L 70.945312 164.601562 L 71.210938 164.230469 L 71.480469 163.851562 L 71.75 163.460938 L 72.019531 163.0625 L 72.289062 162.65625 L 72.558594 162.238281 L 72.824219 161.808594 L 73.09375 161.371094 L 73.363281 160.925781 L 73.632812 160.46875 L 73.902344 160 L 74.167969 159.523438 L 74.4375 159.039062 L 74.707031 158.542969 L 74.976562 158.039062 L 75.246094 157.523438 L 75.515625 157 L 75.78125 156.464844 L 76.050781 155.921875 L 76.320312 155.371094 L 76.589844 154.808594 L 76.859375 154.234375 L 77.128906 153.652344 L 77.394531 153.0625 L 77.664062 152.460938 L 77.933594 151.851562 L 78.203125 151.230469 L 78.472656 150.601562 L 78.742188 149.960938 L 79.007812 149.3125 L 79.277344 148.652344 L 79.546875 147.984375 L 79.816406 147.304688 L 80.085938 146.617188 L 80.355469 145.921875 L 80.621094 145.214844 L 80.890625 144.5 L 81.160156 143.773438 L 81.429688 143.035156 L 81.699219 142.292969 L 81.96875 141.535156 L 82.234375 140.773438 L 82.503906 139.996094 L 82.773438 139.214844 L 83.042969 138.421875 L 83.3125 137.617188 L 83.582031 136.804688 L 83.847656 135.984375 L 84.117188 135.152344 L 84.386719 134.308594 L 84.65625 133.457031 L 84.925781 132.597656 L 85.195312 131.726562 L 85.460938 130.847656 L 85.730469 129.957031 L 86 129.058594 L 86.269531 128.148438 L 86.539062 127.230469 L 86.808594 126.304688 L 87.074219 125.367188 L 87.34375 124.417969 L 87.613281 123.460938 L 87.882812 122.496094 L 88.152344 121.519531 L 88.417969 120.53125 L 88.6875 119.539062 L 88.957031 118.53125 L 89.226562 117.519531 L 89.496094 116.492188 L 89.765625 115.460938 L 90.03125 114.417969 L 90.300781 113.363281 L 90.570312 112.300781 L 90.839844 111.230469 L 91.109375 110.148438 L 91.378906 109.054688 L 91.644531 107.953125 L 91.914062 106.84375 L 92.183594 105.722656 L 92.453125 104.59375 L 92.722656 103.453125 L 92.992188 102.304688 L 93.257812 101.144531 L 93.527344 99.976562 L 93.796875 98.796875 L 94.066406 97.609375 L 94.335938 96.414062 L 94.605469 95.222656 L 94.871094 94.039062 L 95.140625 92.867188 L 95.410156 91.703125 L 95.679688 90.546875 L 95.949219 89.402344 L 96.21875 88.269531 L 96.484375 87.144531 L 96.753906 86.027344 L 97.023438 84.921875 L 97.292969 83.824219 L 97.5625 82.738281 L 97.832031 81.660156 L 98.097656 80.59375 L 98.367188 79.535156 L 98.636719 78.488281 L 98.90625 77.449219 L 99.175781 76.421875 L 99.445312 75.402344 L 99.710938 74.390625 L 99.980469 73.390625 L 100.25 72.402344 L 100.519531 71.417969 L 100.789062 70.449219 L 101.058594 69.488281 L 101.324219 68.535156 L 101.59375 67.59375 L 101.863281 66.660156 L 102.132812 65.734375 L 102.402344 64.824219 L 102.667969 63.917969 L 102.9375 63.023438 L 103.207031 62.140625 L 103.476562 61.265625 L 103.746094 60.398438 L 104.015625 59.542969 L 104.28125 58.695312 L 104.550781 57.859375 L 104.820312 57.03125 L 105.089844 56.214844 L 105.359375 55.40625 L 105.628906 54.609375 L 105.894531 53.820312 L 106.164062 53.042969 L 106.433594 52.273438 L 106.703125 51.511719 L 106.972656 50.761719 L 107.242188 50.023438 L 107.507812 49.292969 L 107.777344 48.570312 L 108.046875 47.859375 L 108.316406 47.15625 L 108.585938 46.464844 L 108.855469 45.78125 L 109.121094 45.109375 L 109.390625 44.445312 L 109.660156 43.789062 L 109.929688 43.144531 L 110.199219 42.511719 L 110.46875 41.886719 L 110.734375 41.269531 L 111.003906 40.664062 L 111.273438 40.070312 L 111.542969 39.480469 L 111.8125 38.90625 L 112.082031 38.335938 L 112.347656 37.78125 L 112.617188 37.230469 L 112.886719 36.691406 L 113.15625 36.164062 L 113.425781 35.644531 L 113.695312 35.136719 L 113.960938 34.636719 L 114.230469 34.144531 L 114.5 33.664062 L 114.769531 33.191406 L 115.039062 32.730469 L 115.308594 32.277344 L 115.574219 31.835938 L 115.84375 31.402344 L 116.113281 30.980469 L 116.382812 30.566406 L 116.652344 30.164062 L 116.921875 29.769531 L 117.1875 29.382812 L 117.457031 29.007812 L 117.726562 28.644531 L 117.996094 28.289062 L 118.265625 27.941406 L 118.53125 27.605469 L 118.800781 27.277344 L 119.070312 26.960938 L 119.339844 26.652344 L 119.609375 26.355469 L 119.878906 26.066406 L 120.144531 25.789062 L 120.414062 25.519531 L 120.683594 25.257812 L 120.953125 25.007812 L 121.222656 24.769531 L 121.492188 24.539062 L 121.757812 24.316406 L 122.027344 24.105469 L 122.296875 23.902344 L 122.566406 23.710938 L 122.835938 23.527344 L 123.105469 23.355469 L 123.371094 23.191406 L 123.640625 23.039062 L 123.910156 22.894531 L 124.179688 22.757812 L 124.449219 22.632812 L 124.71875 22.519531 L 124.984375 22.410156 L 125.253906 22.316406 L 125.523438 22.230469 L 125.792969 22.152344 L 126.0625 22.085938 L 126.332031 22.027344 L 126.597656 21.980469 L 126.867188 21.941406 L 127.136719 21.910156 L 127.40625 21.894531 L 127.675781 21.882812 L 127.945312 21.882812 L 128.210938 21.894531 L 128.480469 21.910156 L 128.75 21.941406 L 129.019531 21.980469 L 129.289062 22.027344 L 129.558594 22.085938 L 129.824219 22.152344 L 130.09375 22.230469 L 130.363281 22.316406 L 130.632812 22.410156 L 130.902344 22.519531 L 131.171875 22.632812 L 131.4375 22.757812 L 131.707031 22.894531 L 131.976562 23.039062 L 132.246094 23.191406 L 132.515625 23.355469 L 132.78125 23.527344 L 133.050781 23.710938 L 133.320312 23.902344 L 133.589844 24.105469 L 133.859375 24.316406 L 134.128906 24.539062 L 134.394531 24.769531 L 134.664062 25.007812 L 134.933594 25.257812 L 135.203125 25.519531 L 135.472656 25.789062 L 135.742188 26.066406 L 136.007812 26.355469 L 136.277344 26.652344 L 136.546875 26.960938 L 136.816406 27.277344 L 137.085938 27.605469 L 137.355469 27.941406 L 137.621094 28.289062 L 137.890625 28.644531 L 138.160156 29.007812 L 138.429688 29.382812 L 138.699219 29.769531 L 138.96875 30.164062 L 139.234375 30.566406 L 139.503906 30.980469 L 139.773438 31.402344 L 140.042969 31.835938 L 140.3125 32.277344 L 140.582031 32.730469 L 140.847656 33.191406 L 141.117188 33.664062 L 141.386719 34.144531 L 141.65625 34.636719 L 141.925781 35.136719 L 142.195312 35.644531 L 142.460938 36.164062 L 142.730469 36.691406 L 143 37.230469 L 143.269531 37.78125 L 143.539062 38.335938 L 143.808594 38.90625 L 144.074219 39.480469 L 144.34375 40.070312 L 144.613281 40.664062 L 144.882812 41.269531 L 145.152344 41.886719 L 145.421875 42.511719 L 145.6875 43.144531 L 145.957031 43.789062 L 146.226562 44.445312 L 146.496094 45.109375 L 146.765625 45.78125 L 147.03125 46.464844 L 147.300781 47.15625 L 147.570312 47.859375 L 147.839844 48.570312 L 148.109375 49.292969 L 148.378906 50.023438 L 148.644531 50.761719 L 148.914062 51.511719 L 149.183594 52.273438 L 149.453125 53.042969 L 149.722656 53.820312 L 149.992188 54.609375 L 150.527344 56.214844 L 150.796875 57.03125 L 151.066406 57.859375 L 151.335938 58.695312 L 151.605469 59.542969 L 151.871094 60.398438 L 152.140625 61.265625 L 152.410156 62.140625 L 152.679688 63.023438 L 152.949219 63.917969 L 153.21875 64.824219 L 153.484375 65.734375 L 153.753906 66.660156 L 154.023438 67.59375 L 154.292969 68.535156 L 154.5625 69.488281 L 154.832031 70.449219 L 155.097656 71.417969 L 155.367188 72.402344 L 155.636719 73.390625 L 155.90625 74.390625 L 156.175781 75.402344 L 156.445312 76.421875 L 156.710938 77.449219 L 156.980469 78.488281 L 157.25 79.535156 L 157.519531 80.59375 L 157.789062 81.660156 L 158.058594 82.738281 L 158.324219 83.824219 L 158.59375 84.921875 L 158.863281 86.027344 L 159.132812 87.144531 L 159.402344 88.269531 L 159.671875 89.402344 L 159.9375 90.546875 L 160.207031 91.703125 L 160.476562 92.867188 L 160.746094 94.039062 L 161.015625 95.222656 L 161.28125 96.414062 L 161.550781 97.609375 L 161.820312 98.796875 L 162.089844 99.976562 L 162.359375 101.144531 L 162.628906 102.304688 L 162.894531 103.453125 L 163.164062 104.59375 L 163.433594 105.722656 L 163.703125 106.84375 L 163.972656 107.953125 L 164.242188 109.054688 L 164.507812 110.148438 L 164.777344 111.230469 L 165.046875 112.300781 L 165.316406 113.363281 L 165.585938 114.417969 L 165.855469 115.460938 L 166.121094 116.492188 L 166.390625 117.519531 L 166.660156 118.53125 L 166.929688 119.539062 L 167.199219 120.53125 L 167.46875 121.519531 L 167.734375 122.496094 L 168.003906 123.460938 L 168.273438 124.417969 L 168.542969 125.367188 L 168.8125 126.304688 L 169.082031 127.230469 L 169.347656 128.148438 L 169.617188 129.058594 L 169.886719 129.957031 L 170.15625 130.847656 L 170.425781 131.726562 L 170.695312 132.597656 L 170.960938 133.457031 L 171.230469 134.308594 L 171.5 135.152344 L 171.769531 135.984375 L 172.039062 136.804688 L 172.308594 137.617188 L 172.574219 138.421875 L 172.84375 139.214844 L 173.113281 139.996094 L 173.382812 140.773438 L 173.652344 141.535156 L 173.921875 142.292969 L 174.1875 143.035156 L 174.457031 143.773438 L 174.726562 144.5 L 174.996094 145.214844 L 175.265625 145.921875 L 175.535156 146.617188 L 175.800781 147.304688 L 176.070312 147.984375 L 176.339844 148.652344 L 176.609375 149.3125 L 176.878906 149.960938 L 177.144531 150.601562 L 177.414062 151.230469 L 177.683594 151.851562 L 177.953125 152.460938 L 178.222656 153.0625 L 178.492188 153.652344 L 178.757812 154.234375 L 179.027344 154.808594 L 179.296875 155.371094 L 179.566406 155.921875 L 179.835938 156.464844 L 180.105469 157 L 180.371094 157.523438 L 180.640625 158.039062 L 180.910156 158.542969 L 181.179688 159.039062 L 181.449219 159.523438 L 181.71875 160 L 181.984375 160.46875 L 182.253906 160.925781 L 182.523438 161.371094 L 182.792969 161.808594 L 183.0625 162.238281 L 183.332031 162.65625 L 183.597656 163.0625 L 183.867188 163.460938 L 184.136719 163.851562 L 184.40625 164.230469 L 184.675781 164.601562 L 184.945312 164.964844 L 185.210938 165.3125 L 185.480469 165.65625 L 185.75 165.988281 L 186.019531 166.308594 L 186.289062 166.621094 L 186.558594 166.925781 L 186.824219 167.21875 L 187.09375 167.503906 L 187.363281 167.777344 L 187.632812 168.039062 L 187.902344 168.296875 L 188.171875 168.539062 L 188.4375 168.777344 L 188.707031 169.003906 L 188.976562 169.21875 L 189.246094 169.425781 L 189.515625 169.621094 L 189.785156 169.808594 L 190.050781 169.988281 L 190.320312 170.15625 L 190.589844 170.316406 L 190.859375 170.464844 L 191.128906 170.601562 L 191.394531 170.734375 L 191.664062 170.851562 L 191.933594 170.964844 L 192.203125 171.066406 L 192.472656 171.15625 L 192.742188 171.238281 L 193.007812 171.308594 L 193.277344 171.371094 L 193.546875 171.425781 L 193.816406 171.46875 L 194.085938 171.503906 L 194.355469 171.527344 L 194.621094 171.542969 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.128906 L 54.019531 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/power.svg b/documentation/ui/figure/power.svg
new file mode 100644
index 0000000..8bb7b3d
--- /dev/null
+++ b/documentation/ui/figure/power.svg
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.421875 0 L 0.421875 -9.46875 L 7.9375 -9.46875 L 7.9375 0 Z M 6.75 -1.1875 L 6.75 -8.28125 L 1.609375 -8.28125 L 1.609375 -1.1875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 3.578125 -9.234375 C 4.765625 -9.234375 5.625 -8.738281 6.15625 -7.75 C 6.570312 -6.988281 6.78125 -5.945312 6.78125 -4.625 C 6.78125 -3.375 6.59375 -2.335938 6.21875 -1.515625 C 5.675781 -0.335938 4.789062 0.25 3.5625 0.25 C 2.457031 0.25 1.632812 -0.226562 1.09375 -1.1875 C 0.632812 -1.988281 0.40625 -3.066406 0.40625 -4.421875 C 0.40625 -5.472656 0.539062 -6.375 0.8125 -7.125 C 1.320312 -8.53125 2.242188 -9.234375 3.578125 -9.234375 Z M 3.5625 -0.8125 C 4.164062 -0.8125 4.644531 -1.078125 5 -1.609375 C 5.351562 -2.140625 5.53125 -3.128906 5.53125 -4.578125 C 5.53125 -5.628906 5.398438 -6.492188 5.140625 -7.171875 C 4.878906 -7.847656 4.378906 -8.1875 3.640625 -8.1875 C 2.960938 -8.1875 2.460938 -7.863281 2.140625 -7.21875 C 1.828125 -6.582031 1.671875 -5.640625 1.671875 -4.390625 C 1.671875 -3.441406 1.769531 -2.679688 1.96875 -2.109375 C 2.28125 -1.242188 2.8125 -0.8125 3.5625 -0.8125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.890625 -9.46875 L 2.046875 -9.46875 L 2.046875 0 L 0.890625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 3.59375 -0.75 C 4.363281 -0.75 4.890625 -1.039062 5.171875 -1.625 C 5.460938 -2.207031 5.609375 -2.851562 5.609375 -3.5625 C 5.609375 -4.207031 5.503906 -4.734375 5.296875 -5.140625 C 4.960938 -5.773438 4.398438 -6.09375 3.609375 -6.09375 C 2.898438 -6.09375 2.382812 -5.820312 2.0625 -5.28125 C 1.738281 -4.738281 1.578125 -4.082031 1.578125 -3.3125 C 1.578125 -2.582031 1.738281 -1.972656 2.0625 -1.484375 C 2.382812 -0.992188 2.894531 -0.75 3.59375 -0.75 Z M 3.640625 -7.109375 C 4.523438 -7.109375 5.273438 -6.8125 5.890625 -6.21875 C 6.503906 -5.625 6.8125 -4.75 6.8125 -3.59375 C 6.8125 -2.476562 6.539062 -1.554688 6 -0.828125 C 5.457031 -0.109375 4.617188 0.25 3.484375 0.25 C 2.535156 0.25 1.78125 -0.0664062 1.21875 -0.703125 C 0.65625 -1.347656 0.375 -2.210938 0.375 -3.296875 C 0.375 -4.460938 0.664062 -5.390625 1.25 -6.078125 C 1.84375 -6.765625 2.640625 -7.109375 3.640625 -7.109375 Z M 3.59375 -7.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.390625 -6.90625 L 2.71875 -1.46875 L 4.0625 -6.90625 L 5.359375 -6.90625 L 6.71875 -1.5 L 8.125 -6.90625 L 9.296875 -6.90625 L 7.28125 0 L 6.078125 0 L 4.671875 -5.34375 L 3.3125 0 L 2.109375 0 L 0.109375 -6.90625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 0.84375 -9.5 L 2.015625 -9.5 L 2.015625 -5.96875 C 2.285156 -6.3125 2.53125 -6.554688 2.75 -6.703125 C 3.125 -6.953125 3.59375 -7.078125 4.15625 -7.078125 C 5.15625 -7.078125 5.832031 -6.722656 6.1875 -6.015625 C 6.382812 -5.640625 6.484375 -5.109375 6.484375 -4.421875 L 6.484375 0 L 5.28125 0 L 5.28125 -4.359375 C 5.28125 -4.859375 5.21875 -5.226562 5.09375 -5.46875 C 4.882812 -5.84375 4.488281 -6.03125 3.90625 -6.03125 C 3.425781 -6.03125 2.988281 -5.863281 2.59375 -5.53125 C 2.207031 -5.207031 2.015625 -4.582031 2.015625 -3.65625 L 2.015625 0 L 0.84375 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.84375 -6.875 L 2.03125 -6.875 L 2.03125 0 L 0.84375 0 Z M 0.84375 -9.46875 L 2.03125 -9.46875 L 2.03125 -8.15625 L 0.84375 -8.15625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-7">
+<path style="stroke:none;" d="M 3.28125 -7.03125 C 3.820312 -7.03125 4.296875 -6.894531 4.703125 -6.625 C 4.921875 -6.476562 5.144531 -6.257812 5.375 -5.96875 L 5.375 -6.84375 L 6.453125 -6.84375 L 6.453125 -0.5625 C 6.453125 0.3125 6.320312 1.003906 6.0625 1.515625 C 5.582031 2.453125 4.671875 2.921875 3.328125 2.921875 C 2.585938 2.921875 1.960938 2.753906 1.453125 2.421875 C 0.953125 2.085938 0.671875 1.566406 0.609375 0.859375 L 1.78125 0.859375 C 1.84375 1.171875 1.957031 1.410156 2.125 1.578125 C 2.382812 1.828125 2.796875 1.953125 3.359375 1.953125 C 4.242188 1.953125 4.828125 1.640625 5.109375 1.015625 C 5.265625 0.648438 5.335938 -0.00390625 5.328125 -0.953125 C 5.097656 -0.609375 4.816406 -0.347656 4.484375 -0.171875 C 4.160156 -0.00390625 3.734375 0.078125 3.203125 0.078125 C 2.453125 0.078125 1.796875 -0.1875 1.234375 -0.71875 C 0.671875 -1.25 0.390625 -2.125 0.390625 -3.34375 C 0.390625 -4.5 0.671875 -5.398438 1.234375 -6.046875 C 1.804688 -6.703125 2.488281 -7.03125 3.28125 -7.03125 Z M 5.375 -3.484375 C 5.375 -4.335938 5.195312 -4.96875 4.84375 -5.375 C 4.488281 -5.789062 4.039062 -6 3.5 -6 C 2.6875 -6 2.128906 -5.617188 1.828125 -4.859375 C 1.660156 -4.441406 1.578125 -3.90625 1.578125 -3.25 C 1.578125 -2.46875 1.734375 -1.875 2.046875 -1.46875 C 2.367188 -1.0625 2.796875 -0.859375 3.328125 -0.859375 C 4.160156 -0.859375 4.75 -1.234375 5.09375 -1.984375 C 5.28125 -2.410156 5.375 -2.910156 5.375 -3.484375 Z M 3.421875 -7.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-8">
+<path style="stroke:none;" d="M 1.265625 -6.53125 L 1.265625 -7.421875 C 2.097656 -7.503906 2.679688 -7.640625 3.015625 -7.828125 C 3.347656 -8.023438 3.597656 -8.476562 3.765625 -9.1875 L 4.671875 -9.1875 L 4.671875 0 L 3.4375 0 L 3.4375 -6.53125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0 -0.421875 L -9.46875 -0.421875 L -9.46875 -7.9375 L 0 -7.9375 Z M -1.1875 -6.75 L -8.28125 -6.75 L -8.28125 -1.609375 L -1.1875 -1.609375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M -9.234375 -3.578125 C -9.234375 -4.765625 -8.738281 -5.625 -7.75 -6.15625 C -6.988281 -6.570312 -5.945312 -6.78125 -4.625 -6.78125 C -3.375 -6.78125 -2.335938 -6.59375 -1.515625 -6.21875 C -0.335938 -5.675781 0.25 -4.789062 0.25 -3.5625 C 0.25 -2.457031 -0.226562 -1.632812 -1.1875 -1.09375 C -1.988281 -0.632812 -3.066406 -0.40625 -4.421875 -0.40625 C -5.472656 -0.40625 -6.375 -0.539062 -7.125 -0.8125 C -8.53125 -1.320312 -9.234375 -2.242188 -9.234375 -3.578125 Z M -0.8125 -3.5625 C -0.8125 -4.164062 -1.078125 -4.644531 -1.609375 -5 C -2.140625 -5.351562 -3.128906 -5.53125 -4.578125 -5.53125 C -5.628906 -5.53125 -6.492188 -5.398438 -7.171875 -5.140625 C -7.847656 -4.878906 -8.1875 -4.378906 -8.1875 -3.640625 C -8.1875 -2.960938 -7.863281 -2.460938 -7.21875 -2.140625 C -6.582031 -1.828125 -5.640625 -1.671875 -4.390625 -1.671875 C -3.441406 -1.671875 -2.679688 -1.769531 -2.109375 -1.96875 C -1.242188 -2.28125 -0.8125 -2.8125 -0.8125 -3.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-2">
+<path style="stroke:none;" d="M -1.40625 -1.125 L -1.40625 -2.46875 L 0 -2.46875 L 0 -1.125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-3">
+<path style="stroke:none;" d="M -2.359375 -1.625 C -1.691406 -1.707031 -1.234375 -2.015625 -0.984375 -2.546875 C -0.847656 -2.828125 -0.78125 -3.144531 -0.78125 -3.5 C -0.78125 -4.1875 -1 -4.695312 -1.4375 -5.03125 C -1.882812 -5.363281 -2.375 -5.53125 -2.90625 -5.53125 C -3.550781 -5.53125 -4.046875 -5.332031 -4.390625 -4.9375 C -4.742188 -4.550781 -4.921875 -4.082031 -4.921875 -3.53125 C -4.921875 -3.125 -4.84375 -2.773438 -4.6875 -2.484375 C -4.539062 -2.203125 -4.328125 -1.960938 -4.046875 -1.765625 L -4.109375 -0.765625 L -9.078125 -1.46875 L -9.078125 -6.265625 L -7.953125 -6.265625 L -7.953125 -2.328125 L -5.390625 -1.9375 C -5.554688 -2.15625 -5.675781 -2.359375 -5.75 -2.546875 C -5.894531 -2.890625 -5.96875 -3.289062 -5.96875 -3.75 C -5.96875 -4.59375 -5.691406 -5.304688 -5.140625 -5.890625 C -4.597656 -6.484375 -3.910156 -6.78125 -3.078125 -6.78125 C -2.203125 -6.78125 -1.429688 -6.507812 -0.765625 -5.96875 C -0.0976562 -5.425781 0.234375 -4.566406 0.234375 -3.390625 C 0.234375 -2.640625 0.0234375 -1.972656 -0.390625 -1.390625 C -0.816406 -0.816406 -1.472656 -0.492188 -2.359375 -0.421875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-4">
+<path style="stroke:none;" d="M -6.53125 -1.265625 L -7.421875 -1.265625 C -7.503906 -2.097656 -7.640625 -2.679688 -7.828125 -3.015625 C -8.023438 -3.347656 -8.476562 -3.597656 -9.1875 -3.765625 L -9.1875 -4.671875 L 0 -4.671875 L 0 -3.4375 L -6.53125 -3.4375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 0.578125 0 L 0.578125 -12.90625 L 10.828125 -12.90625 L 10.828125 0 Z M 9.21875 -1.625 L 9.21875 -11.296875 L 2.203125 -11.296875 L 2.203125 -1.625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M 1.53125 -12.90625 L 7.34375 -12.90625 C 8.5 -12.90625 9.425781 -12.582031 10.125 -11.9375 C 10.832031 -11.289062 11.1875 -10.382812 11.1875 -9.21875 C 11.1875 -8.207031 10.867188 -7.328125 10.234375 -6.578125 C 9.609375 -5.828125 8.644531 -5.453125 7.34375 -5.453125 L 3.28125 -5.453125 L 3.28125 0 L 1.53125 0 Z M 9.40625 -9.203125 C 9.40625 -10.148438 9.054688 -10.796875 8.359375 -11.140625 C 7.972656 -11.316406 7.441406 -11.40625 6.765625 -11.40625 L 3.28125 -11.40625 L 3.28125 -6.9375 L 6.765625 -6.9375 C 7.554688 -6.9375 8.191406 -7.101562 8.671875 -7.4375 C 9.160156 -7.769531 9.40625 -8.359375 9.40625 -9.203125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-2">
+<path style="stroke:none;" d="M 4.890625 -1.015625 C 5.941406 -1.015625 6.660156 -1.410156 7.046875 -2.203125 C 7.441406 -3.003906 7.640625 -3.890625 7.640625 -4.859375 C 7.640625 -5.734375 7.5 -6.445312 7.21875 -7 C 6.769531 -7.875 6 -8.3125 4.90625 -8.3125 C 3.945312 -8.3125 3.242188 -7.941406 2.796875 -7.203125 C 2.359375 -6.460938 2.140625 -5.570312 2.140625 -4.53125 C 2.140625 -3.53125 2.359375 -2.691406 2.796875 -2.015625 C 3.242188 -1.347656 3.941406 -1.015625 4.890625 -1.015625 Z M 4.953125 -9.6875 C 6.171875 -9.6875 7.195312 -9.28125 8.03125 -8.46875 C 8.875 -7.664062 9.296875 -6.476562 9.296875 -4.90625 C 9.296875 -3.382812 8.925781 -2.128906 8.1875 -1.140625 C 7.445312 -0.148438 6.300781 0.34375 4.75 0.34375 C 3.445312 0.34375 2.414062 -0.09375 1.65625 -0.96875 C 0.894531 -1.84375 0.515625 -3.019531 0.515625 -4.5 C 0.515625 -6.082031 0.914062 -7.34375 1.71875 -8.28125 C 2.519531 -9.21875 3.597656 -9.6875 4.953125 -9.6875 Z M 4.90625 -9.640625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-3">
+<path style="stroke:none;" d="M 1.890625 -9.40625 L 3.703125 -2 L 5.53125 -9.40625 L 7.3125 -9.40625 L 9.15625 -2.046875 L 11.078125 -9.40625 L 12.671875 -9.40625 L 9.9375 0 L 8.28125 0 L 6.375 -7.28125 L 4.515625 0 L 2.875 0 L 0.15625 -9.40625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-4">
+<path style="stroke:none;" d="M 5.078125 -9.625 C 5.742188 -9.625 6.390625 -9.46875 7.015625 -9.15625 C 7.648438 -8.84375 8.128906 -8.4375 8.453125 -7.9375 C 8.773438 -7.457031 8.988281 -6.90625 9.09375 -6.28125 C 9.1875 -5.84375 9.234375 -5.148438 9.234375 -4.203125 L 2.328125 -4.203125 C 2.359375 -3.242188 2.582031 -2.472656 3 -1.890625 C 3.425781 -1.316406 4.082031 -1.03125 4.96875 -1.03125 C 5.789062 -1.03125 6.445312 -1.304688 6.9375 -1.859375 C 7.21875 -2.171875 7.421875 -2.535156 7.546875 -2.953125 L 9.09375 -2.953125 C 9.050781 -2.609375 8.914062 -2.222656 8.6875 -1.796875 C 8.457031 -1.367188 8.195312 -1.019531 7.90625 -0.75 C 7.425781 -0.28125 6.832031 0.03125 6.125 0.1875 C 5.75 0.28125 5.316406 0.328125 4.828125 0.328125 C 3.660156 0.328125 2.671875 -0.09375 1.859375 -0.9375 C 1.046875 -1.789062 0.640625 -2.988281 0.640625 -4.53125 C 0.640625 -6.039062 1.046875 -7.265625 1.859375 -8.203125 C 2.679688 -9.148438 3.753906 -9.625 5.078125 -9.625 Z M 7.609375 -5.453125 C 7.535156 -6.140625 7.382812 -6.691406 7.15625 -7.109375 C 6.71875 -7.867188 5.992188 -8.25 4.984375 -8.25 C 4.253906 -8.25 3.644531 -7.984375 3.15625 -7.453125 C 2.664062 -6.929688 2.40625 -6.265625 2.375 -5.453125 Z M 4.9375 -9.640625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-5">
+<path style="stroke:none;" d="M 1.203125 -9.40625 L 2.703125 -9.40625 L 2.703125 -7.78125 C 2.828125 -8.101562 3.128906 -8.488281 3.609375 -8.9375 C 4.085938 -9.394531 4.644531 -9.625 5.28125 -9.625 C 5.300781 -9.625 5.347656 -9.617188 5.421875 -9.609375 C 5.492188 -9.609375 5.613281 -9.597656 5.78125 -9.578125 L 5.78125 -7.90625 C 5.6875 -7.925781 5.597656 -7.9375 5.515625 -7.9375 C 5.441406 -7.945312 5.359375 -7.953125 5.265625 -7.953125 C 4.460938 -7.953125 3.847656 -7.695312 3.421875 -7.1875 C 2.992188 -6.675781 2.78125 -6.085938 2.78125 -5.421875 L 2.78125 0 L 1.203125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 0.484375 0 L 0.484375 -10.765625 L 9.03125 -10.765625 L 9.03125 0 Z M 7.671875 -1.34375 L 7.671875 -9.40625 L 1.828125 -9.40625 L 1.828125 -1.34375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M 5.859375 -7.84375 L 7.328125 -7.84375 C 7.140625 -7.34375 6.726562 -6.195312 6.09375 -4.40625 C 5.613281 -3.050781 5.210938 -1.953125 4.890625 -1.109375 C 4.128906 0.890625 3.59375 2.109375 3.28125 2.546875 C 2.96875 2.992188 2.425781 3.21875 1.65625 3.21875 C 1.476562 3.21875 1.335938 3.207031 1.234375 3.1875 C 1.128906 3.175781 1.003906 3.148438 0.859375 3.109375 L 0.859375 1.90625 C 1.085938 1.96875 1.253906 2.003906 1.359375 2.015625 C 1.460938 2.035156 1.554688 2.046875 1.640625 2.046875 C 1.878906 2.046875 2.054688 2.003906 2.171875 1.921875 C 2.285156 1.847656 2.382812 1.753906 2.46875 1.640625 C 2.488281 1.597656 2.570312 1.394531 2.71875 1.03125 C 2.875 0.664062 2.984375 0.398438 3.046875 0.234375 L 0.15625 -7.84375 L 1.640625 -7.84375 L 3.75 -1.453125 Z M 3.75 -8.03125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -2.296875 -2.484375 C -1.585938 -2.484375 -1.113281 -2.550781 -0.875 -2.6875 C -0.632812 -2.832031 -0.515625 -3.085938 -0.515625 -3.453125 C -0.515625 -4.023438 -0.914062 -4.5 -1.71875 -4.875 C -2.519531 -5.25 -3.539062 -5.4375 -4.78125 -5.4375 L -6.734375 -5.4375 L -6.734375 -6.828125 L -1.8125 -6.828125 C -1.363281 -6.828125 -1.035156 -6.875 -0.828125 -6.96875 C -0.617188 -7.0625 -0.515625 -7.203125 -0.515625 -7.390625 C -0.515625 -7.609375 -0.617188 -7.769531 -0.828125 -7.875 C -1.035156 -7.988281 -1.34375 -8.046875 -1.75 -8.046875 L -1.953125 -8.046875 L -1.953125 -8.359375 C -1.910156 -8.359375 -1.863281 -8.359375 -1.8125 -8.359375 C -1.769531 -8.367188 -1.707031 -8.375 -1.625 -8.375 C -1.0625 -8.375 -0.628906 -8.253906 -0.328125 -8.015625 C -0.0234375 -7.773438 0.125 -7.441406 0.125 -7.015625 C 0.125 -6.515625 -0.0859375 -6.132812 -0.515625 -5.875 C -0.941406 -5.625 -1.585938 -5.5 -2.453125 -5.5 C -1.554688 -5.269531 -0.898438 -4.960938 -0.484375 -4.578125 C -0.078125 -4.191406 0.125 -3.707031 0.125 -3.125 C 0.125 -2.6875 -0.00390625 -2.320312 -0.265625 -2.03125 C -0.523438 -1.738281 -0.90625 -1.535156 -1.40625 -1.421875 C -1.320312 -1.410156 -1.179688 -1.40625 -0.984375 -1.40625 C -0.359375 -1.40625 0.34375 -1.566406 1.125 -1.890625 C 1.90625 -2.210938 2.363281 -2.375 2.5 -2.375 C 2.695312 -2.375 2.851562 -2.316406 2.96875 -2.203125 C 3.082031 -2.085938 3.140625 -1.9375 3.140625 -1.75 C 3.140625 -1.519531 3.054688 -1.351562 2.890625 -1.25 C 2.722656 -1.144531 2.457031 -1.09375 2.09375 -1.09375 C 2 -1.09375 1.707031 -1.101562 1.21875 -1.125 C 0.726562 -1.144531 0.28125 -1.15625 -0.125 -1.15625 C -0.476562 -1.15625 -0.984375 -1.144531 -1.640625 -1.125 C -2.296875 -1.113281 -2.769531 -1.109375 -3.0625 -1.109375 L -6.734375 -1.109375 L -6.734375 -2.484375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-0">
+<path style="stroke:none;" d="M 3.3125 -0.9375 L -13.21875 -0.9375 L -13.21875 -10.3125 L 3.3125 -10.3125 Z M 2.265625 -1.984375 L 2.265625 -9.265625 L -12.171875 -9.265625 L -12.171875 -1.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-1">
+<path style="stroke:none;" d="M -13.1875 -5.359375 C -12.25 -4.328125 -11.160156 -3.585938 -9.921875 -3.140625 C -8.679688 -2.703125 -7.019531 -2.484375 -4.9375 -2.484375 C -2.84375 -2.484375 -1.179688 -2.703125 0.046875 -3.140625 C 1.273438 -3.585938 2.359375 -4.328125 3.296875 -5.359375 L 3.6875 -4.984375 C 2.738281 -3.691406 1.503906 -2.679688 -0.015625 -1.953125 C -1.535156 -1.222656 -3.175781 -0.859375 -4.9375 -0.859375 C -6.695312 -0.859375 -8.335938 -1.222656 -9.859375 -1.953125 C -11.390625 -2.691406 -12.628906 -3.703125 -13.578125 -4.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-2">
+<path style="stroke:none;" d="M -13.1875 -0.875 L -13.578125 -1.234375 C -12.628906 -2.523438 -11.390625 -3.539062 -9.859375 -4.28125 C -8.328125 -5.019531 -6.6875 -5.390625 -4.9375 -5.390625 C -3.1875 -5.390625 -1.546875 -5.019531 -0.015625 -4.28125 C 1.503906 -3.539062 2.738281 -2.523438 3.6875 -1.234375 L 3.296875 -0.875 C 2.367188 -1.914062 1.289062 -2.65625 0.0625 -3.09375 C -1.164062 -3.53125 -2.832031 -3.75 -4.9375 -3.75 C -7.03125 -3.75 -8.691406 -3.53125 -9.921875 -3.09375 C -11.160156 -2.65625 -12.25 -1.914062 -13.1875 -0.875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph6-0">
+<path style="stroke:none;" d="M 0 -0.484375 L -10.765625 -0.484375 L -10.765625 -9.03125 L 0 -9.03125 Z M -1.34375 -7.671875 L -9.40625 -7.671875 L -9.40625 -1.828125 L -1.34375 -1.828125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph6-1">
+<path style="stroke:none;" d="M -7.84375 -5.859375 L -7.84375 -7.328125 C -7.34375 -7.140625 -6.195312 -6.726562 -4.40625 -6.09375 C -3.050781 -5.613281 -1.953125 -5.210938 -1.109375 -4.890625 C 0.890625 -4.128906 2.109375 -3.59375 2.546875 -3.28125 C 2.992188 -2.96875 3.21875 -2.425781 3.21875 -1.65625 C 3.21875 -1.476562 3.207031 -1.335938 3.1875 -1.234375 C 3.175781 -1.128906 3.148438 -1.003906 3.109375 -0.859375 L 1.90625 -0.859375 C 1.96875 -1.085938 2.003906 -1.253906 2.015625 -1.359375 C 2.035156 -1.460938 2.046875 -1.554688 2.046875 -1.640625 C 2.046875 -1.878906 2.003906 -2.054688 1.921875 -2.171875 C 1.847656 -2.285156 1.753906 -2.382812 1.640625 -2.46875 C 1.597656 -2.488281 1.394531 -2.570312 1.03125 -2.71875 C 0.664062 -2.875 0.398438 -2.984375 0.234375 -3.046875 L -7.84375 -0.15625 L -7.84375 -1.640625 L -1.453125 -3.75 Z M -8.03125 -3.75 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 53 17.28125 L 55 17.28125 L 55 179.5625 L 53 179.5625 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 90 17.28125 L 93 17.28125 L 93 179.5625 L 90 179.5625 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 128 17.28125 L 130 17.28125 L 130 179.5625 L 128 179.5625 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 165 17.28125 L 167 17.28125 L 167 179.5625 L 165 179.5625 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 202 17.28125 L 205 17.28125 L 205 179.5625 L 202 179.5625 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 43.199219 172 L 215.558594 172 L 215.558594 174 L 43.199219 174 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 43.199219 134 L 215.558594 134 L 215.558594 136 L 43.199219 136 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 43.199219 97 L 215.558594 97 L 215.558594 99 L 43.199219 99 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 43.199219 60 L 215.558594 60 L 215.558594 62 L 43.199219 62 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 43.199219 22 L 215.558594 22 L 215.558594 24 L 43.199219 24 Z "/>
+</clipPath>
+</defs>
+<g id="surface81">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 43.199219 178.558594 L 214.558594 178.558594 L 214.558594 17.28125 L 43.199219 17.28125 L 43.199219 178.558594 "/>
+<path style="fill:none;stroke-width:9;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.214844 172.585938 L 54.511719 171.390625 L 54.664062 170.792969 L 54.8125 170.191406 L 55.109375 168.996094 L 55.261719 168.398438 L 55.410156 167.796875 L 55.558594 167.199219 L 55.710938 166.601562 L 56.007812 165.40625 L 56.160156 164.804688 L 56.457031 163.609375 L 56.609375 163.011719 L 56.757812 162.410156 L 57.054688 161.214844 L 57.207031 160.617188 L 57.355469 160.015625 L 57.503906 159.417969 L 57.65625 158.820312 L 57.953125 157.625 L 58.105469 157.023438 L 58.550781 155.230469 L 58.703125 154.628906 L 59 153.433594 L 59.152344 152.835938 L 59.300781 152.238281 L 59.449219 151.636719 L 59.601562 151.039062 L 59.898438 149.84375 L 60.050781 149.242188 L 60.496094 147.449219 L 60.648438 146.851562 L 60.796875 146.25 L 60.945312 145.652344 L 61.097656 145.054688 L 61.246094 144.457031 L 61.394531 143.855469 L 61.546875 143.257812 L 61.84375 142.0625 L 61.996094 141.464844 L 62.144531 140.863281 L 62.441406 139.667969 L 62.59375 139.070312 L 62.742188 138.46875 L 62.890625 137.871094 L 63.042969 137.273438 L 63.339844 136.078125 L 63.492188 135.476562 L 63.9375 133.683594 L 64.089844 133.082031 L 64.386719 131.886719 L 64.539062 131.289062 L 64.6875 130.691406 L 64.835938 130.089844 L 64.988281 129.492188 L 65.285156 128.296875 L 65.4375 127.695312 L 65.882812 125.902344 L 66.035156 125.304688 L 66.183594 124.703125 L 66.332031 124.105469 L 66.484375 123.507812 L 66.632812 122.910156 L 66.78125 122.308594 L 66.933594 121.710938 L 67.230469 120.515625 L 67.382812 119.914062 L 67.828125 118.121094 L 67.980469 117.523438 L 68.128906 116.921875 L 68.277344 116.324219 L 68.429688 115.726562 L 68.578125 115.128906 L 68.726562 114.527344 L 68.878906 113.929688 L 69.175781 112.734375 L 69.328125 112.136719 L 69.476562 111.535156 L 69.773438 110.339844 L 69.925781 109.742188 L 70.074219 109.140625 L 70.222656 108.542969 L 70.375 107.945312 L 70.671875 106.75 L 70.824219 106.148438 L 71.269531 104.355469 L 71.421875 103.753906 L 71.71875 102.558594 L 71.871094 101.960938 L 72.019531 101.363281 L 72.167969 100.761719 L 72.320312 100.164062 L 72.617188 98.96875 L 72.769531 98.367188 L 73.214844 96.574219 L 73.367188 95.976562 L 73.515625 95.375 L 73.664062 94.777344 L 73.816406 94.179688 L 73.964844 93.582031 L 74.113281 92.980469 L 74.265625 92.382812 L 74.5625 91.1875 L 74.714844 90.589844 L 74.863281 89.988281 L 75.160156 88.792969 L 75.3125 88.195312 L 75.460938 87.59375 L 75.609375 86.996094 L 75.761719 86.398438 L 76.058594 85.203125 L 76.210938 84.601562 L 76.507812 83.40625 L 76.660156 82.808594 L 76.808594 82.207031 L 77.105469 81.011719 L 77.257812 80.414062 L 77.40625 79.816406 L 77.554688 79.214844 L 77.707031 78.617188 L 78.003906 77.421875 L 78.15625 76.820312 L 78.601562 75.027344 L 78.753906 74.425781 L 79.050781 73.230469 L 79.203125 72.632812 L 79.351562 72.035156 L 79.5 71.433594 L 79.652344 70.835938 L 79.949219 69.640625 L 80.101562 69.039062 L 80.546875 67.246094 L 80.699219 66.648438 L 80.847656 66.046875 L 80.996094 65.449219 L 81.148438 64.851562 L 81.296875 64.253906 L 81.445312 63.652344 L 81.597656 63.054688 L 81.894531 61.859375 L 82.046875 61.261719 L 82.195312 60.660156 L 82.492188 59.464844 L 82.644531 58.867188 L 82.792969 58.265625 L 82.941406 57.667969 L 83.09375 57.070312 L 83.390625 55.875 L 83.542969 55.273438 L 83.988281 53.480469 L 84.140625 52.878906 L 84.4375 51.683594 L 84.589844 51.085938 L 84.738281 50.488281 L 84.886719 49.886719 L 85.039062 49.289062 L 85.335938 48.09375 L 85.488281 47.492188 L 85.933594 45.699219 L 86.085938 45.101562 L 86.234375 44.5 L 86.382812 43.902344 L 86.535156 43.304688 L 86.683594 42.707031 L 86.832031 42.105469 L 86.984375 41.507812 L 87.28125 40.3125 L 87.433594 39.714844 L 87.582031 39.113281 L 87.878906 37.917969 L 88.03125 37.320312 L 88.179688 36.71875 L 88.328125 36.121094 L 88.480469 35.523438 L 88.628906 34.925781 L 88.777344 34.324219 L 88.929688 33.726562 L 89.226562 32.53125 L 89.378906 31.933594 L 89.527344 31.332031 L 89.824219 30.136719 L 89.976562 29.539062 L 90.125 28.9375 L 90.273438 28.339844 L 90.425781 27.742188 L 90.722656 26.546875 L 90.875 25.945312 L 91.320312 24.152344 L 91.472656 23.550781 L 91.621094 23.550781 L 91.769531 24.152344 L 91.921875 24.75 L 92.21875 25.945312 L 92.371094 26.546875 L 92.667969 27.742188 L 92.820312 28.339844 L 92.96875 28.9375 L 93.117188 29.539062 L 93.265625 30.136719 L 93.417969 30.734375 L 93.566406 31.332031 L 93.714844 31.933594 L 93.867188 32.53125 L 94.164062 33.726562 L 94.316406 34.324219 L 94.464844 34.925781 L 94.613281 35.523438 L 94.765625 36.121094 L 94.914062 36.71875 L 95.0625 37.320312 L 95.210938 37.917969 L 95.363281 38.515625 L 95.511719 39.113281 L 95.660156 39.714844 L 95.8125 40.3125 L 96.109375 41.507812 L 96.261719 42.105469 L 96.410156 42.707031 L 96.558594 43.304688 L 96.710938 43.902344 L 96.859375 44.5 L 97.007812 45.101562 L 97.15625 45.699219 L 97.308594 46.296875 L 97.605469 47.492188 L 97.757812 48.09375 L 98.054688 49.289062 L 98.207031 49.886719 L 98.355469 50.488281 L 98.652344 51.683594 L 98.804688 52.28125 L 98.953125 52.878906 L 99.101562 53.480469 L 99.253906 54.078125 L 99.550781 55.273438 L 99.703125 55.875 L 100 57.070312 L 100.152344 57.667969 L 100.300781 58.265625 L 100.449219 58.867188 L 100.597656 59.464844 L 100.75 60.0625 L 100.898438 60.660156 L 101.046875 61.261719 L 101.199219 61.859375 L 101.496094 63.054688 L 101.648438 63.652344 L 101.796875 64.253906 L 101.945312 64.851562 L 102.097656 65.449219 L 102.246094 66.046875 L 102.394531 66.648438 L 102.542969 67.246094 L 102.695312 67.84375 L 102.992188 69.039062 L 103.144531 69.640625 L 103.441406 70.835938 L 103.59375 71.433594 L 103.742188 72.035156 L 104.039062 73.230469 L 104.191406 73.828125 L 104.339844 74.425781 L 104.488281 75.027344 L 104.640625 75.625 L 104.9375 76.820312 L 105.089844 77.421875 L 105.386719 78.617188 L 105.539062 79.214844 L 105.6875 79.816406 L 105.984375 81.011719 L 106.136719 81.609375 L 106.285156 82.207031 L 106.433594 82.808594 L 106.585938 83.40625 L 106.882812 84.601562 L 107.035156 85.203125 L 107.332031 86.398438 L 107.484375 86.996094 L 107.632812 87.59375 L 107.78125 88.195312 L 107.929688 88.792969 L 108.082031 89.390625 L 108.230469 89.988281 L 108.378906 90.589844 L 108.53125 91.1875 L 108.828125 92.382812 L 108.980469 92.980469 L 109.128906 93.582031 L 109.277344 94.179688 L 109.429688 94.777344 L 109.578125 95.375 L 109.726562 95.976562 L 109.875 96.574219 L 110.027344 97.171875 L 110.324219 98.367188 L 110.476562 98.96875 L 110.773438 100.164062 L 110.925781 100.761719 L 111.074219 101.363281 L 111.371094 102.558594 L 111.523438 103.15625 L 111.671875 103.753906 L 111.820312 104.355469 L 111.972656 104.953125 L 112.269531 106.148438 L 112.421875 106.75 L 112.71875 107.945312 L 112.871094 108.542969 L 113.019531 109.140625 L 113.167969 109.742188 L 113.316406 110.339844 L 113.46875 110.9375 L 113.617188 111.535156 L 113.765625 112.136719 L 113.917969 112.734375 L 114.214844 113.929688 L 114.367188 114.527344 L 114.515625 115.128906 L 114.664062 115.726562 L 114.816406 116.324219 L 114.964844 116.921875 L 115.113281 117.523438 L 115.261719 118.121094 L 115.414062 118.71875 L 115.710938 119.914062 L 115.863281 120.515625 L 116.160156 121.710938 L 116.3125 122.308594 L 116.460938 122.910156 L 116.757812 124.105469 L 116.910156 124.703125 L 117.058594 125.304688 L 117.207031 125.902344 L 117.359375 126.5 L 117.65625 127.695312 L 117.808594 128.296875 L 118.105469 129.492188 L 118.257812 130.089844 L 118.40625 130.691406 L 118.703125 131.886719 L 118.855469 132.484375 L 119.003906 133.082031 L 119.152344 133.683594 L 119.304688 134.28125 L 119.601562 135.476562 L 119.753906 136.078125 L 120.050781 137.273438 L 120.203125 137.871094 L 120.351562 138.46875 L 120.5 139.070312 L 120.648438 139.667969 L 120.800781 140.265625 L 120.949219 140.863281 L 121.097656 141.464844 L 121.25 142.0625 L 121.546875 143.257812 L 121.699219 143.855469 L 121.847656 144.457031 L 121.996094 145.054688 L 122.148438 145.652344 L 122.296875 146.25 L 122.445312 146.851562 L 122.59375 147.449219 L 122.746094 148.046875 L 123.042969 149.242188 L 123.195312 149.84375 L 123.492188 151.039062 L 123.644531 151.636719 L 123.792969 152.238281 L 124.089844 153.433594 L 124.242188 154.03125 L 124.390625 154.628906 L 124.539062 155.230469 L 124.691406 155.828125 L 124.988281 157.023438 L 125.140625 157.625 L 125.4375 158.820312 L 125.589844 159.417969 L 125.738281 160.015625 L 125.886719 160.617188 L 126.035156 161.214844 L 126.1875 161.8125 L 126.335938 162.410156 L 126.484375 163.011719 L 126.636719 163.609375 L 126.933594 164.804688 L 127.085938 165.40625 L 127.382812 166.601562 L 127.535156 167.199219 L 127.683594 167.796875 L 127.832031 168.398438 L 127.980469 168.996094 L 128.132812 169.59375 L 128.28125 170.191406 L 128.429688 170.792969 L 128.582031 171.390625 L 128.878906 172.585938 "/>
+<path style="fill:none;stroke-width:9;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 91.546875 172.585938 L 91.695312 171.988281 L 91.847656 171.390625 L 91.996094 170.792969 L 92.144531 170.191406 L 92.292969 169.59375 L 92.445312 168.996094 L 92.59375 168.398438 L 92.742188 167.796875 L 92.894531 167.199219 L 93.191406 166.003906 L 93.34375 165.40625 L 93.492188 164.804688 L 93.640625 164.207031 L 93.792969 163.609375 L 93.941406 163.011719 L 94.089844 162.410156 L 94.238281 161.8125 L 94.390625 161.214844 L 94.539062 160.617188 L 94.6875 160.015625 L 94.839844 159.417969 L 95.136719 158.222656 L 95.289062 157.625 L 95.4375 157.023438 L 95.585938 156.425781 L 95.738281 155.828125 L 95.886719 155.230469 L 96.035156 154.628906 L 96.183594 154.03125 L 96.335938 153.433594 L 96.632812 152.238281 L 96.785156 151.636719 L 97.082031 150.441406 L 97.234375 149.84375 L 97.382812 149.242188 L 97.679688 148.046875 L 97.832031 147.449219 L 97.980469 146.851562 L 98.128906 146.25 L 98.28125 145.652344 L 98.578125 144.457031 L 98.730469 143.855469 L 99.027344 142.660156 L 99.179688 142.0625 L 99.328125 141.464844 L 99.476562 140.863281 L 99.625 140.265625 L 99.777344 139.667969 L 99.925781 139.070312 L 100.074219 138.46875 L 100.226562 137.871094 L 100.523438 136.675781 L 100.675781 136.078125 L 100.824219 135.476562 L 100.972656 134.878906 L 101.125 134.28125 L 101.273438 133.683594 L 101.421875 133.082031 L 101.570312 132.484375 L 101.722656 131.886719 L 102.019531 130.691406 L 102.171875 130.089844 L 102.46875 128.894531 L 102.621094 128.296875 L 102.769531 127.695312 L 102.917969 127.097656 L 103.070312 126.5 L 103.367188 125.304688 L 103.515625 124.703125 L 103.667969 124.105469 L 103.964844 122.910156 L 104.117188 122.308594 L 104.414062 121.113281 L 104.566406 120.515625 L 104.714844 119.914062 L 105.011719 118.71875 L 105.164062 118.121094 L 105.3125 117.523438 L 105.460938 116.921875 L 105.613281 116.324219 L 105.910156 115.128906 L 106.0625 114.527344 L 106.359375 113.332031 L 106.511719 112.734375 L 106.660156 112.136719 L 106.808594 111.535156 L 106.957031 110.9375 L 107.109375 110.339844 L 107.257812 109.742188 L 107.40625 109.140625 L 107.558594 108.542969 L 107.855469 107.347656 L 108.007812 106.75 L 108.15625 106.148438 L 108.304688 105.550781 L 108.457031 104.953125 L 108.605469 104.355469 L 108.753906 103.753906 L 108.902344 103.15625 L 109.054688 102.558594 L 109.351562 101.363281 L 109.503906 100.761719 L 109.800781 99.566406 L 109.953125 98.96875 L 110.101562 98.367188 L 110.398438 97.171875 L 110.550781 96.574219 L 110.699219 95.976562 L 110.847656 95.375 L 111 94.777344 L 111.296875 93.582031 L 111.449219 92.980469 L 111.746094 91.785156 L 111.898438 91.1875 L 112.046875 90.589844 L 112.195312 89.988281 L 112.34375 89.390625 L 112.496094 88.792969 L 112.644531 88.195312 L 112.792969 87.59375 L 112.945312 86.996094 L 113.242188 85.800781 L 113.394531 85.203125 L 113.542969 84.601562 L 113.691406 84.003906 L 113.84375 83.40625 L 113.992188 82.808594 L 114.140625 82.207031 L 114.289062 81.609375 L 114.441406 81.011719 L 114.738281 79.816406 L 114.890625 79.214844 L 115.1875 78.019531 L 115.339844 77.421875 L 115.488281 76.820312 L 115.636719 76.222656 L 115.789062 75.625 L 115.9375 75.027344 L 116.085938 74.425781 L 116.234375 73.828125 L 116.386719 73.230469 L 116.683594 72.035156 L 116.835938 71.433594 L 117.132812 70.238281 L 117.285156 69.640625 L 117.433594 69.039062 L 117.730469 67.84375 L 117.882812 67.246094 L 118.03125 66.648438 L 118.179688 66.046875 L 118.332031 65.449219 L 118.628906 64.253906 L 118.78125 63.652344 L 119.078125 62.457031 L 119.230469 61.859375 L 119.378906 61.261719 L 119.527344 60.660156 L 119.675781 60.0625 L 119.828125 59.464844 L 119.976562 58.867188 L 120.125 58.265625 L 120.277344 57.667969 L 120.574219 56.472656 L 120.726562 55.875 L 120.875 55.273438 L 121.023438 54.675781 L 121.175781 54.078125 L 121.324219 53.480469 L 121.472656 52.878906 L 121.621094 52.28125 L 121.773438 51.683594 L 122.070312 50.488281 L 122.222656 49.886719 L 122.519531 48.691406 L 122.671875 48.09375 L 122.820312 47.492188 L 122.96875 46.894531 L 123.121094 46.296875 L 123.417969 45.101562 L 123.566406 44.5 L 123.71875 43.902344 L 124.015625 42.707031 L 124.167969 42.105469 L 124.464844 40.910156 L 124.617188 40.3125 L 124.765625 39.714844 L 124.914062 39.113281 L 125.0625 38.515625 L 125.214844 37.917969 L 125.363281 37.320312 L 125.511719 36.71875 L 125.664062 36.121094 L 125.960938 34.925781 L 126.113281 34.324219 L 126.410156 33.128906 L 126.5625 32.53125 L 126.710938 31.933594 L 126.859375 31.332031 L 127.007812 30.734375 L 127.160156 30.136719 L 127.308594 29.539062 L 127.457031 28.9375 L 127.609375 28.339844 L 127.90625 27.144531 L 128.058594 26.546875 L 128.207031 25.945312 L 128.355469 25.347656 L 128.507812 24.75 L 128.65625 24.152344 L 128.804688 23.550781 L 128.953125 23.550781 L 129.105469 24.152344 L 129.402344 25.347656 L 129.554688 25.945312 L 129.703125 26.546875 L 129.851562 27.144531 L 130.003906 27.742188 L 130.300781 28.9375 L 130.449219 29.539062 L 130.601562 30.136719 L 130.898438 31.332031 L 131.050781 31.933594 L 131.347656 33.128906 L 131.5 33.726562 L 131.648438 34.324219 L 131.796875 34.925781 L 131.949219 35.523438 L 132.246094 36.71875 L 132.394531 37.320312 L 132.546875 37.917969 L 132.84375 39.113281 L 132.996094 39.714844 L 133.292969 40.910156 L 133.445312 41.507812 L 133.59375 42.105469 L 133.742188 42.707031 L 133.894531 43.304688 L 134.191406 44.5 L 134.339844 45.101562 L 134.492188 45.699219 L 134.789062 46.894531 L 134.941406 47.492188 L 135.089844 48.09375 L 135.238281 48.691406 L 135.390625 49.289062 L 135.539062 49.886719 L 135.6875 50.488281 L 135.839844 51.085938 L 136.285156 52.878906 L 136.4375 53.480469 L 136.734375 54.675781 L 136.886719 55.273438 L 137.035156 55.875 L 137.183594 56.472656 L 137.335938 57.070312 L 137.632812 58.265625 L 137.78125 58.867188 L 137.933594 59.464844 L 138.230469 60.660156 L 138.382812 61.261719 L 138.679688 62.457031 L 138.832031 63.054688 L 138.980469 63.652344 L 139.128906 64.253906 L 139.28125 64.851562 L 139.578125 66.046875 L 139.726562 66.648438 L 139.878906 67.246094 L 140.175781 68.441406 L 140.328125 69.039062 L 140.476562 69.640625 L 140.625 70.238281 L 140.777344 70.835938 L 140.925781 71.433594 L 141.074219 72.035156 L 141.226562 72.632812 L 141.671875 74.425781 L 141.824219 75.027344 L 142.121094 76.222656 L 142.273438 76.820312 L 142.421875 77.421875 L 142.570312 78.019531 L 142.722656 78.617188 L 142.871094 79.214844 L 143.019531 79.816406 L 143.167969 80.414062 L 143.320312 81.011719 L 143.617188 82.207031 L 143.769531 82.808594 L 144.066406 84.003906 L 144.21875 84.601562 L 144.367188 85.203125 L 144.515625 85.800781 L 144.667969 86.398438 L 144.964844 87.59375 L 145.113281 88.195312 L 145.265625 88.792969 L 145.5625 89.988281 L 145.714844 90.589844 L 146.011719 91.785156 L 146.164062 92.382812 L 146.3125 92.980469 L 146.460938 93.582031 L 146.613281 94.179688 L 146.910156 95.375 L 147.058594 95.976562 L 147.210938 96.574219 L 147.507812 97.769531 L 147.660156 98.367188 L 147.808594 98.96875 L 147.957031 99.566406 L 148.109375 100.164062 L 148.257812 100.761719 L 148.40625 101.363281 L 148.558594 101.960938 L 149.003906 103.753906 L 149.15625 104.355469 L 149.453125 105.550781 L 149.605469 106.148438 L 149.753906 106.75 L 149.902344 107.347656 L 150.054688 107.945312 L 150.351562 109.140625 L 150.5 109.742188 L 150.652344 110.339844 L 150.949219 111.535156 L 151.101562 112.136719 L 151.398438 113.332031 L 151.550781 113.929688 L 151.699219 114.527344 L 151.847656 115.128906 L 152 115.726562 L 152.296875 116.921875 L 152.445312 117.523438 L 152.597656 118.121094 L 152.894531 119.316406 L 153.046875 119.914062 L 153.195312 120.515625 L 153.34375 121.113281 L 153.496094 121.710938 L 153.644531 122.308594 L 153.792969 122.910156 L 153.945312 123.507812 L 154.242188 124.703125 L 154.390625 125.304688 L 154.542969 125.902344 L 154.839844 127.097656 L 154.992188 127.695312 L 155.140625 128.296875 L 155.289062 128.894531 L 155.441406 129.492188 L 155.589844 130.089844 L 155.738281 130.691406 L 155.890625 131.289062 L 156.335938 133.082031 L 156.488281 133.683594 L 156.785156 134.878906 L 156.9375 135.476562 L 157.085938 136.078125 L 157.234375 136.675781 L 157.386719 137.273438 L 157.683594 138.46875 L 157.832031 139.070312 L 157.984375 139.667969 L 158.28125 140.863281 L 158.433594 141.464844 L 158.730469 142.660156 L 158.882812 143.257812 L 159.03125 143.855469 L 159.179688 144.457031 L 159.332031 145.054688 L 159.628906 146.25 L 159.777344 146.851562 L 159.929688 147.449219 L 160.226562 148.644531 L 160.378906 149.242188 L 160.527344 149.84375 L 160.675781 150.441406 L 160.828125 151.039062 L 160.976562 151.636719 L 161.125 152.238281 L 161.277344 152.835938 L 161.722656 154.628906 L 161.875 155.230469 L 162.171875 156.425781 L 162.324219 157.023438 L 162.472656 157.625 L 162.621094 158.222656 L 162.773438 158.820312 L 163.070312 160.015625 L 163.21875 160.617188 L 163.371094 161.214844 L 163.667969 162.410156 L 163.820312 163.011719 L 164.117188 164.207031 L 164.269531 164.804688 L 164.417969 165.40625 L 164.566406 166.003906 L 164.71875 166.601562 L 165.015625 167.796875 L 165.164062 168.398438 L 165.316406 168.996094 L 165.613281 170.191406 L 165.765625 170.792969 L 166.0625 171.988281 L 166.214844 172.585938 "/>
+<path style="fill:none;stroke-width:9;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 128.878906 172.585938 L 129.03125 171.988281 L 129.328125 170.792969 L 129.480469 170.191406 L 129.925781 168.398438 L 130.078125 167.796875 L 130.375 166.601562 L 130.527344 166.003906 L 130.675781 165.40625 L 130.824219 164.804688 L 130.976562 164.207031 L 131.273438 163.011719 L 131.421875 162.410156 L 131.574219 161.8125 L 131.871094 160.617188 L 132.023438 160.015625 L 132.320312 158.820312 L 132.472656 158.222656 L 132.621094 157.625 L 132.769531 157.023438 L 132.921875 156.425781 L 133.21875 155.230469 L 133.367188 154.628906 L 133.519531 154.03125 L 133.816406 152.835938 L 133.96875 152.238281 L 134.117188 151.636719 L 134.265625 151.039062 L 134.417969 150.441406 L 134.566406 149.84375 L 134.714844 149.242188 L 134.867188 148.644531 L 135.3125 146.851562 L 135.464844 146.25 L 135.761719 145.054688 L 135.914062 144.457031 L 136.0625 143.855469 L 136.210938 143.257812 L 136.363281 142.660156 L 136.660156 141.464844 L 136.808594 140.863281 L 136.960938 140.265625 L 137.257812 139.070312 L 137.410156 138.46875 L 137.707031 137.273438 L 137.859375 136.675781 L 138.007812 136.078125 L 138.15625 135.476562 L 138.308594 134.878906 L 138.605469 133.683594 L 138.753906 133.082031 L 138.90625 132.484375 L 139.203125 131.289062 L 139.355469 130.691406 L 139.503906 130.089844 L 139.652344 129.492188 L 139.804688 128.894531 L 139.953125 128.296875 L 140.101562 127.695312 L 140.253906 127.097656 L 140.699219 125.304688 L 140.851562 124.703125 L 141.148438 123.507812 L 141.300781 122.910156 L 141.449219 122.308594 L 141.597656 121.710938 L 141.75 121.113281 L 141.898438 120.515625 L 142.046875 119.914062 L 142.199219 119.316406 L 142.644531 117.523438 L 142.796875 116.921875 L 143.09375 115.726562 L 143.246094 115.128906 L 143.394531 114.527344 L 143.542969 113.929688 L 143.695312 113.332031 L 143.992188 112.136719 L 144.140625 111.535156 L 144.292969 110.9375 L 144.589844 109.742188 L 144.742188 109.140625 L 145.039062 107.945312 L 145.191406 107.347656 L 145.339844 106.75 L 145.488281 106.148438 L 145.640625 105.550781 L 145.9375 104.355469 L 146.085938 103.753906 L 146.238281 103.15625 L 146.535156 101.960938 L 146.6875 101.363281 L 146.835938 100.761719 L 146.984375 100.164062 L 147.136719 99.566406 L 147.285156 98.96875 L 147.433594 98.367188 L 147.585938 97.769531 L 148.03125 95.976562 L 148.183594 95.375 L 148.480469 94.179688 L 148.632812 93.582031 L 148.78125 92.980469 L 148.929688 92.382812 L 149.082031 91.785156 L 149.378906 90.589844 L 149.53125 89.988281 L 149.976562 88.195312 L 150.128906 87.59375 L 150.425781 86.398438 L 150.578125 85.800781 L 150.726562 85.203125 L 150.875 84.601562 L 151.027344 84.003906 L 151.324219 82.808594 L 151.472656 82.207031 L 151.625 81.609375 L 151.921875 80.414062 L 152.074219 79.816406 L 152.222656 79.214844 L 152.371094 78.617188 L 152.523438 78.019531 L 152.671875 77.421875 L 152.820312 76.820312 L 152.972656 76.222656 L 153.269531 75.027344 L 153.417969 74.425781 L 153.570312 73.828125 L 153.867188 72.632812 L 154.019531 72.035156 L 154.167969 71.433594 L 154.316406 70.835938 L 154.46875 70.238281 L 154.617188 69.640625 L 154.765625 69.039062 L 154.917969 68.441406 L 155.363281 66.648438 L 155.515625 66.046875 L 155.8125 64.851562 L 155.964844 64.253906 L 156.113281 63.652344 L 156.261719 63.054688 L 156.414062 62.457031 L 156.710938 61.261719 L 156.859375 60.660156 L 157.011719 60.0625 L 157.308594 58.867188 L 157.460938 58.265625 L 157.757812 57.070312 L 157.910156 56.472656 L 158.058594 55.875 L 158.207031 55.273438 L 158.359375 54.675781 L 158.65625 53.480469 L 158.804688 52.878906 L 158.957031 52.28125 L 159.253906 51.085938 L 159.40625 50.488281 L 159.554688 49.886719 L 159.703125 49.289062 L 159.855469 48.691406 L 160.003906 48.09375 L 160.152344 47.492188 L 160.304688 46.894531 L 160.75 45.101562 L 160.902344 44.5 L 161.199219 43.304688 L 161.351562 42.707031 L 161.5 42.105469 L 161.648438 41.507812 L 161.800781 40.910156 L 162.097656 39.714844 L 162.25 39.113281 L 162.695312 37.320312 L 162.847656 36.71875 L 163.144531 35.523438 L 163.296875 34.925781 L 163.445312 34.324219 L 163.59375 33.726562 L 163.746094 33.128906 L 164.042969 31.933594 L 164.191406 31.332031 L 164.34375 30.734375 L 164.640625 29.539062 L 164.792969 28.9375 L 165.089844 27.742188 L 165.242188 27.144531 L 165.390625 26.546875 L 165.539062 25.945312 L 165.691406 25.347656 L 165.988281 24.152344 L 166.136719 23.550781 L 166.289062 23.550781 L 166.4375 24.152344 L 166.585938 24.75 L 166.738281 25.347656 L 166.886719 25.945312 L 167.035156 26.546875 L 167.1875 27.144531 L 167.484375 28.339844 L 167.636719 28.9375 L 167.785156 29.539062 L 168.082031 30.734375 L 168.234375 31.332031 L 168.382812 31.933594 L 168.53125 32.53125 L 168.683594 33.128906 L 168.980469 34.324219 L 169.132812 34.925781 L 169.578125 36.71875 L 169.730469 37.320312 L 170.027344 38.515625 L 170.179688 39.113281 L 170.328125 39.714844 L 170.476562 40.3125 L 170.628906 40.910156 L 170.925781 42.105469 L 171.078125 42.707031 L 171.523438 44.5 L 171.675781 45.101562 L 171.972656 46.296875 L 172.125 46.894531 L 172.273438 47.492188 L 172.421875 48.09375 L 172.574219 48.691406 L 172.871094 49.886719 L 173.023438 50.488281 L 173.46875 52.28125 L 173.621094 52.878906 L 173.769531 53.480469 L 173.917969 54.078125 L 174.070312 54.675781 L 174.21875 55.273438 L 174.367188 55.875 L 174.519531 56.472656 L 174.816406 57.667969 L 174.96875 58.265625 L 175.117188 58.867188 L 175.414062 60.0625 L 175.566406 60.660156 L 175.714844 61.261719 L 175.863281 61.859375 L 176.015625 62.457031 L 176.3125 63.652344 L 176.464844 64.253906 L 176.910156 66.046875 L 177.0625 66.648438 L 177.359375 67.84375 L 177.511719 68.441406 L 177.660156 69.039062 L 177.808594 69.640625 L 177.960938 70.238281 L 178.257812 71.433594 L 178.410156 72.035156 L 178.855469 73.828125 L 179.007812 74.425781 L 179.15625 75.027344 L 179.304688 75.625 L 179.457031 76.222656 L 179.605469 76.820312 L 179.753906 77.421875 L 179.90625 78.019531 L 180.203125 79.214844 L 180.355469 79.816406 L 180.800781 81.609375 L 180.953125 82.207031 L 181.101562 82.808594 L 181.25 83.40625 L 181.402344 84.003906 L 181.550781 84.601562 L 181.699219 85.203125 L 181.851562 85.800781 L 182.148438 86.996094 L 182.300781 87.59375 L 182.449219 88.195312 L 182.746094 89.390625 L 182.898438 89.988281 L 183.046875 90.589844 L 183.195312 91.1875 L 183.347656 91.785156 L 183.644531 92.980469 L 183.796875 93.582031 L 184.242188 95.375 L 184.394531 95.976562 L 184.691406 97.171875 L 184.84375 97.769531 L 184.992188 98.367188 L 185.140625 98.96875 L 185.292969 99.566406 L 185.589844 100.761719 L 185.742188 101.363281 L 186.1875 103.15625 L 186.339844 103.753906 L 186.488281 104.355469 L 186.636719 104.953125 L 186.789062 105.550781 L 186.9375 106.148438 L 187.085938 106.75 L 187.238281 107.347656 L 187.535156 108.542969 L 187.6875 109.140625 L 187.835938 109.742188 L 188.132812 110.9375 L 188.285156 111.535156 L 188.433594 112.136719 L 188.582031 112.734375 L 188.734375 113.332031 L 189.03125 114.527344 L 189.183594 115.128906 L 189.628906 116.921875 L 189.78125 117.523438 L 190.078125 118.71875 L 190.230469 119.316406 L 190.378906 119.914062 L 190.527344 120.515625 L 190.679688 121.113281 L 190.976562 122.308594 L 191.128906 122.910156 L 191.574219 124.703125 L 191.726562 125.304688 L 192.023438 126.5 L 192.175781 127.097656 L 192.324219 127.695312 L 192.472656 128.296875 L 192.625 128.894531 L 192.921875 130.089844 L 193.074219 130.691406 L 193.519531 132.484375 L 193.671875 133.082031 L 193.820312 133.683594 L 193.96875 134.28125 L 194.121094 134.878906 L 194.269531 135.476562 L 194.417969 136.078125 L 194.570312 136.675781 L 194.867188 137.871094 L 195.019531 138.46875 L 195.167969 139.070312 L 195.464844 140.265625 L 195.617188 140.863281 L 195.765625 141.464844 L 195.914062 142.0625 L 196.066406 142.660156 L 196.363281 143.855469 L 196.515625 144.457031 L 196.960938 146.25 L 197.113281 146.851562 L 197.410156 148.046875 L 197.5625 148.644531 L 197.710938 149.242188 L 197.859375 149.84375 L 198.011719 150.441406 L 198.308594 151.636719 L 198.460938 152.238281 L 198.90625 154.03125 L 199.058594 154.628906 L 199.207031 155.230469 L 199.355469 155.828125 L 199.507812 156.425781 L 199.65625 157.023438 L 199.804688 157.625 L 199.957031 158.222656 L 200.253906 159.417969 L 200.40625 160.015625 L 200.554688 160.617188 L 200.851562 161.8125 L 201.003906 162.410156 L 201.152344 163.011719 L 201.300781 163.609375 L 201.453125 164.207031 L 201.601562 164.804688 L 201.75 165.40625 L 201.902344 166.003906 L 202.347656 167.796875 L 202.5 168.398438 L 202.796875 169.59375 L 202.949219 170.191406 L 203.097656 170.792969 L 203.246094 171.390625 L 203.398438 171.988281 L 203.546875 172.585938 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.214844 178.558594 L 203.546875 178.558594 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.214844 178.558594 L 54.214844 185.761719 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 91.546875 178.558594 L 91.546875 185.761719 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 128.878906 178.558594 L 128.878906 185.761719 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 166.214844 178.558594 L 166.214844 185.761719 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 203.546875 178.558594 L 203.546875 185.761719 "/>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="50.542969" y="197.28125"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph0-2" x="81.640625" y="197.28125"/>
+ <use xlink:href="#glyph0-3" x="84.573944" y="197.28125"/>
+ <use xlink:href="#glyph0-4" x="91.916901" y="197.28125"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph0-5" x="153.734375" y="197.28125"/>
+ <use xlink:href="#glyph0-6" x="161.077332" y="197.28125"/>
+ <use xlink:href="#glyph0-7" x="164.010651" y="197.28125"/>
+ <use xlink:href="#glyph0-5" x="171.353607" y="197.28125"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph0-8" x="192.53125" y="197.28125"/>
+ <use xlink:href="#glyph0-1" x="199.874207" y="197.28125"/>
+ <use xlink:href="#glyph0-1" x="207.217163" y="197.28125"/>
+</g>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 43.199219 172.585938 L 43.199219 23.253906 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 43.199219 172.585938 L 36 172.585938 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 43.199219 97.921875 L 36 97.921875 "/>
+<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 43.199219 23.253906 L 36 23.253906 "/>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="33.121094" y="181.761719"/>
+ <use xlink:href="#glyph1-2" x="33.121094" y="174.418762"/>
+ <use xlink:href="#glyph1-1" x="33.121094" y="170.750504"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="33.121094" y="107.097656"/>
+ <use xlink:href="#glyph1-2" x="33.121094" y="99.7547"/>
+ <use xlink:href="#glyph1-3" x="33.121094" y="96.086441"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-4" x="33.121094" y="32.429688"/>
+ <use xlink:href="#glyph1-2" x="33.121094" y="25.086731"/>
+ <use xlink:href="#glyph1-1" x="33.121094" y="21.418472"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="103.367188" y="14.398438"/>
+ <use xlink:href="#glyph2-2" x="115.373047" y="14.398438"/>
+ <use xlink:href="#glyph2-3" x="125.383789" y="14.398438"/>
+ <use xlink:href="#glyph2-4" x="138.382812" y="14.398438"/>
+ <use xlink:href="#glyph2-5" x="148.393555" y="14.398438"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="125.128906" y="211.679688"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="15.03125" y="112.234375"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-1" x="15.03125" y="103.59375"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph6-1" x="15.03125" y="97.347656"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-2" x="15.03125" y="89.847656"/>
+</g>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 54.214844 178.558594 L 54.214844 17.28125 "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 91.546875 178.558594 L 91.546875 17.28125 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 128.878906 178.558594 L 128.878906 17.28125 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 166.214844 178.558594 L 166.214844 17.28125 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 203.546875 178.558594 L 203.546875 17.28125 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 43.199219 172.585938 L 214.558594 172.585938 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 43.199219 135.253906 L 214.558594 135.253906 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 43.199219 97.921875 L 214.558594 97.921875 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 43.199219 60.585938 L 214.558594 60.585938 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.125;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:1.125,3.375;stroke-miterlimit:10;" d="M 43.199219 23.253906 L 214.558594 23.253906 "/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/ramp.svg b/documentation/ui/figure/ramp.svg
new file mode 100644
index 0000000..370fab3
--- /dev/null
+++ b/documentation/ui/figure/ramp.svg
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface251">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.839844 L 201.601562 152.839844 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.421875 L 201.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.007812 L 201.601562 78.007812 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.589844 L 201.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.128906 L 201.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 87.34375 171.546875 L 87.613281 171.445312 L 88.152344 170.445312 L 88.417969 169.945312 L 89.765625 167.445312 L 90.03125 166.945312 L 90.300781 166.445312 L 90.570312 165.949219 L 91.378906 164.449219 L 91.644531 163.949219 L 92.992188 161.449219 L 93.257812 160.949219 L 94.605469 158.449219 L 94.871094 157.949219 L 96.21875 155.449219 L 96.484375 154.949219 L 97.832031 152.449219 L 98.097656 151.949219 L 98.90625 150.449219 L 99.175781 149.953125 L 99.445312 149.453125 L 99.710938 148.953125 L 101.058594 146.453125 L 101.324219 145.953125 L 102.402344 143.953125 L 102.667969 143.453125 L 104.015625 140.953125 L 104.28125 140.453125 L 105.628906 137.953125 L 105.894531 137.453125 L 107.242188 134.953125 L 107.507812 134.457031 L 108.855469 131.957031 L 109.121094 131.457031 L 110.46875 128.957031 L 110.734375 128.457031 L 112.082031 125.957031 L 112.347656 125.457031 L 113.695312 122.957031 L 113.960938 122.457031 L 115.308594 119.957031 L 115.574219 119.457031 L 115.84375 118.957031 L 116.113281 118.460938 L 116.921875 116.960938 L 117.1875 116.460938 L 118.265625 114.460938 L 118.53125 113.960938 L 119.878906 111.460938 L 120.144531 110.960938 L 121.492188 108.460938 L 121.757812 107.960938 L 123.105469 105.460938 L 123.371094 104.960938 L 124.179688 103.460938 L 124.449219 102.964844 L 124.71875 102.464844 L 124.984375 101.964844 L 126.332031 99.464844 L 126.597656 98.964844 L 127.945312 96.464844 L 128.210938 95.964844 L 129.558594 93.464844 L 129.824219 92.964844 L 131.171875 90.464844 L 131.4375 89.964844 L 132.515625 87.964844 L 132.78125 87.46875 L 134.128906 84.96875 L 134.394531 84.46875 L 135.742188 81.96875 L 136.007812 81.46875 L 137.355469 78.96875 L 137.621094 78.46875 L 138.96875 75.96875 L 139.234375 75.46875 L 140.582031 72.96875 L 140.847656 72.46875 L 141.117188 71.96875 L 141.386719 71.472656 L 142.195312 69.972656 L 142.460938 69.472656 L 143.808594 66.972656 L 144.074219 66.472656 L 145.421875 63.972656 L 145.6875 63.472656 L 146.765625 61.472656 L 147.03125 60.972656 L 148.378906 58.472656 L 148.644531 57.972656 L 149.453125 56.472656 L 149.722656 55.976562 L 149.992188 55.476562 L 150.257812 54.976562 L 151.605469 52.476562 L 151.871094 51.976562 L 153.21875 49.476562 L 153.484375 48.976562 L 154.832031 46.476562 L 155.097656 45.976562 L 156.445312 43.476562 L 156.710938 42.976562 L 158.058594 40.476562 L 158.324219 39.980469 L 159.671875 37.480469 L 159.9375 36.980469 L 161.015625 34.980469 L 161.28125 34.480469 L 162.628906 31.980469 L 162.894531 31.480469 L 164.242188 28.980469 L 164.507812 28.480469 L 165.855469 25.980469 L 166.121094 25.480469 L 166.390625 24.980469 L 166.660156 24.484375 L 167.46875 22.984375 L 167.734375 22.484375 L 168.003906 21.984375 L 168.273438 21.882812 L 194.890625 21.882812 "/>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 21.882812 L 87.34375 21.882812 L 87.613281 21.984375 L 88.152344 22.984375 L 88.417969 23.484375 L 88.957031 24.484375 L 89.226562 24.980469 L 89.765625 25.980469 L 90.03125 26.480469 L 91.378906 28.980469 L 91.644531 29.480469 L 92.992188 31.980469 L 93.257812 32.480469 L 94.605469 34.980469 L 94.871094 35.480469 L 96.21875 37.980469 L 96.484375 38.480469 L 97.292969 39.980469 L 97.5625 40.476562 L 97.832031 40.976562 L 98.097656 41.476562 L 99.445312 43.976562 L 99.710938 44.476562 L 101.058594 46.976562 L 101.324219 47.476562 L 102.402344 49.476562 L 102.667969 49.976562 L 104.015625 52.476562 L 104.28125 52.976562 L 105.628906 55.476562 L 105.894531 55.976562 L 106.164062 56.472656 L 107.242188 58.472656 L 107.507812 58.972656 L 108.855469 61.472656 L 109.121094 61.972656 L 110.46875 64.472656 L 110.734375 64.972656 L 112.082031 67.472656 L 112.347656 67.972656 L 113.695312 70.472656 L 113.960938 70.972656 L 114.230469 71.472656 L 114.5 71.96875 L 115.308594 73.46875 L 115.574219 73.96875 L 116.921875 76.46875 L 117.1875 76.96875 L 118.265625 78.96875 L 118.53125 79.46875 L 119.878906 81.96875 L 120.144531 82.46875 L 121.492188 84.96875 L 121.757812 85.46875 L 122.835938 87.46875 L 123.105469 87.964844 L 123.371094 88.464844 L 124.71875 90.964844 L 124.984375 91.464844 L 126.332031 93.964844 L 126.597656 94.464844 L 127.945312 96.964844 L 128.210938 97.464844 L 129.558594 99.964844 L 129.824219 100.464844 L 131.171875 102.964844 L 131.4375 103.460938 L 132.515625 105.460938 L 132.78125 105.960938 L 134.128906 108.460938 L 134.394531 108.960938 L 135.742188 111.460938 L 136.007812 111.960938 L 137.355469 114.460938 L 137.621094 114.960938 L 138.96875 117.460938 L 139.234375 117.960938 L 139.503906 118.460938 L 139.773438 118.957031 L 140.582031 120.457031 L 140.847656 120.957031 L 142.195312 123.457031 L 142.460938 123.957031 L 143.808594 126.457031 L 144.074219 126.957031 L 145.421875 129.457031 L 145.6875 129.957031 L 146.765625 131.957031 L 147.03125 132.457031 L 148.109375 134.457031 L 148.378906 134.953125 L 148.644531 135.453125 L 149.992188 137.953125 L 150.257812 138.453125 L 151.605469 140.953125 L 151.871094 141.453125 L 153.21875 143.953125 L 153.484375 144.453125 L 154.832031 146.953125 L 155.097656 147.453125 L 156.445312 149.953125 L 156.710938 150.449219 L 158.058594 152.949219 L 158.324219 153.449219 L 159.671875 155.949219 L 159.9375 156.449219 L 161.015625 158.449219 L 161.28125 158.949219 L 162.628906 161.449219 L 162.894531 161.949219 L 164.242188 164.449219 L 164.507812 164.949219 L 165.046875 165.949219 L 165.316406 166.445312 L 165.855469 167.445312 L 166.121094 167.945312 L 167.46875 170.445312 L 167.734375 170.945312 L 168.003906 171.445312 L 168.273438 171.546875 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.128906 L 54.019531 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/rectangle.svg b/documentation/ui/figure/rectangle.svg
new file mode 100644
index 0000000..deb6c70
--- /dev/null
+++ b/documentation/ui/figure/rectangle.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface191">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.839844 L 201.601562 152.839844 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.421875 L 201.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.007812 L 201.601562 78.007812 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.589844 L 201.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.128906 L 201.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 94.066406 171.546875 L 94.335938 21.882812 L 161.28125 21.882812 L 161.550781 171.546875 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.128906 L 54.019531 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/sShape.svg b/documentation/ui/figure/sShape.svg
new file mode 100644
index 0000000..3f24ed9
--- /dev/null
+++ b/documentation/ui/figure/sShape.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface261">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.839844 L 201.601562 152.839844 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.421875 L 201.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.007812 L 201.601562 78.007812 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.589844 L 201.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.128906 L 201.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 60.996094 171.542969 L 61.265625 171.542969 L 61.53125 171.535156 L 61.800781 171.527344 L 62.339844 171.503906 L 62.609375 171.488281 L 62.878906 171.46875 L 63.144531 171.449219 L 63.683594 171.402344 L 63.953125 171.371094 L 64.222656 171.34375 L 64.492188 171.308594 L 64.757812 171.277344 L 65.296875 171.199219 L 65.835938 171.113281 L 66.105469 171.066406 L 66.371094 171.015625 L 66.640625 170.964844 L 66.910156 170.910156 L 67.71875 170.734375 L 67.984375 170.667969 L 68.523438 170.535156 L 68.792969 170.464844 L 69.332031 170.316406 L 69.597656 170.238281 L 70.136719 170.074219 L 70.40625 169.988281 L 70.945312 169.808594 L 71.210938 169.71875 L 72.019531 169.425781 L 72.289062 169.324219 L 72.558594 169.21875 L 72.824219 169.113281 L 73.09375 169.003906 L 73.632812 168.777344 L 73.902344 168.660156 L 74.167969 168.539062 L 74.707031 168.296875 L 75.515625 167.910156 L 75.78125 167.777344 L 76.320312 167.503906 L 76.589844 167.363281 L 77.128906 167.074219 L 77.394531 166.925781 L 78.203125 166.46875 L 78.742188 166.148438 L 79.007812 165.988281 L 79.277344 165.824219 L 79.546875 165.65625 L 80.355469 165.140625 L 80.621094 164.964844 L 80.890625 164.785156 L 81.429688 164.417969 L 81.96875 164.042969 L 82.234375 163.851562 L 82.503906 163.660156 L 82.773438 163.464844 L 83.042969 163.265625 L 83.582031 162.859375 L 83.847656 162.65625 L 84.117188 162.445312 L 84.386719 162.238281 L 84.925781 161.808594 L 85.195312 161.589844 L 85.460938 161.371094 L 86 160.925781 L 86.269531 160.695312 L 86.539062 160.46875 L 86.808594 160.234375 L 87.074219 160 L 87.34375 159.765625 L 88.152344 159.039062 L 88.417969 158.792969 L 88.957031 158.292969 L 89.226562 158.039062 L 89.765625 157.523438 L 90.03125 157.261719 L 90.300781 157 L 90.570312 156.734375 L 91.109375 156.195312 L 91.378906 155.921875 L 91.644531 155.648438 L 91.914062 155.371094 L 92.453125 154.808594 L 92.722656 154.523438 L 92.992188 154.234375 L 93.257812 153.945312 L 93.796875 153.359375 L 94.066406 153.0625 L 94.605469 152.460938 L 94.871094 152.15625 L 95.140625 151.851562 L 95.410156 151.542969 L 95.949219 150.917969 L 96.21875 150.601562 L 96.484375 150.28125 L 96.753906 149.960938 L 97.292969 149.3125 L 97.5625 148.984375 L 97.832031 148.652344 L 98.097656 148.320312 L 98.636719 147.648438 L 98.90625 147.304688 L 99.175781 146.964844 L 99.445312 146.617188 L 99.710938 146.273438 L 100.25 145.570312 L 100.789062 144.859375 L 101.058594 144.5 L 101.324219 144.136719 L 101.59375 143.773438 L 101.863281 143.40625 L 102.402344 142.664062 L 102.667969 142.292969 L 103.476562 141.15625 L 103.746094 140.773438 L 104.015625 140.386719 L 104.28125 139.996094 L 104.820312 139.214844 L 105.089844 138.820312 L 105.359375 138.421875 L 105.628906 138.019531 L 105.894531 137.617188 L 106.433594 136.804688 L 106.972656 135.984375 L 107.242188 135.566406 L 107.507812 135.152344 L 108.316406 133.886719 L 108.855469 133.027344 L 109.121094 132.597656 L 109.390625 132.164062 L 109.929688 131.289062 L 110.199219 130.847656 L 110.46875 130.402344 L 110.734375 129.957031 L 111.273438 129.058594 L 111.542969 128.605469 L 112.082031 127.691406 L 112.347656 127.230469 L 112.617188 126.769531 L 112.886719 126.304688 L 113.425781 125.367188 L 113.695312 124.894531 L 113.960938 124.417969 L 114.230469 123.941406 L 114.769531 122.980469 L 115.039062 122.496094 L 115.308594 122.007812 L 115.574219 121.519531 L 116.113281 120.535156 L 116.382812 120.035156 L 116.652344 119.539062 L 116.921875 119.035156 L 117.1875 118.53125 L 117.457031 118.027344 L 117.726562 117.519531 L 118.265625 116.496094 L 118.53125 115.980469 L 119.070312 114.941406 L 119.339844 114.417969 L 119.878906 113.363281 L 120.144531 112.832031 L 120.414062 112.300781 L 120.953125 111.230469 L 121.222656 110.6875 L 121.492188 110.148438 L 121.757812 109.601562 L 122.296875 108.507812 L 123.105469 106.84375 L 123.371094 106.285156 L 123.910156 105.160156 L 124.179688 104.59375 L 124.71875 103.453125 L 124.984375 102.878906 L 125.253906 102.304688 L 125.523438 101.726562 L 126.0625 100.5625 L 126.332031 99.976562 L 126.597656 99.390625 L 126.867188 98.800781 L 127.40625 97.613281 L 127.675781 97.015625 L 127.945312 96.414062 L 128.210938 95.816406 L 128.75 94.628906 L 129.019531 94.039062 L 129.558594 92.867188 L 129.824219 92.285156 L 130.09375 91.703125 L 130.632812 90.546875 L 130.902344 89.976562 L 131.171875 89.402344 L 131.4375 88.835938 L 131.707031 88.269531 L 132.246094 87.144531 L 132.515625 86.585938 L 132.78125 86.027344 L 133.050781 85.472656 L 133.320312 84.921875 L 134.128906 83.28125 L 134.394531 82.738281 L 134.664062 82.199219 L 135.472656 80.59375 L 135.742188 80.066406 L 136.007812 79.539062 L 136.277344 79.011719 L 136.546875 78.488281 L 137.085938 77.449219 L 137.355469 76.933594 L 137.621094 76.421875 L 137.890625 75.910156 L 138.429688 74.894531 L 138.699219 74.390625 L 138.96875 73.890625 L 139.234375 73.390625 L 139.503906 72.894531 L 140.042969 71.910156 L 140.582031 70.933594 L 140.847656 70.449219 L 141.386719 69.488281 L 141.925781 68.535156 L 142.195312 68.0625 L 142.460938 67.59375 L 142.730469 67.125 L 143 66.660156 L 143.808594 65.277344 L 144.074219 64.824219 L 144.613281 63.917969 L 144.882812 63.472656 L 145.152344 63.023438 L 145.421875 62.582031 L 145.6875 62.140625 L 146.226562 61.265625 L 146.765625 60.398438 L 147.03125 59.96875 L 147.300781 59.542969 L 148.109375 58.277344 L 148.378906 57.859375 L 148.644531 57.445312 L 149.453125 56.214844 L 149.992188 55.410156 L 150.257812 55.007812 L 150.527344 54.609375 L 151.066406 53.820312 L 151.335938 53.429688 L 151.605469 53.042969 L 151.871094 52.65625 L 152.410156 51.890625 L 152.679688 51.515625 L 152.949219 51.136719 L 153.21875 50.765625 L 153.484375 50.390625 L 154.023438 49.65625 L 154.5625 48.929688 L 154.832031 48.570312 L 155.097656 48.214844 L 155.367188 47.859375 L 155.90625 47.15625 L 156.175781 46.808594 L 156.445312 46.464844 L 156.710938 46.121094 L 156.980469 45.78125 L 157.519531 45.109375 L 158.058594 44.445312 L 158.324219 44.117188 L 158.863281 43.46875 L 159.402344 42.828125 L 159.671875 42.511719 L 159.9375 42.199219 L 160.207031 41.886719 L 160.476562 41.578125 L 161.015625 40.96875 L 161.28125 40.667969 L 161.550781 40.367188 L 162.089844 39.773438 L 162.628906 39.195312 L 162.894531 38.90625 L 163.164062 38.621094 L 163.703125 38.058594 L 164.242188 37.503906 L 164.507812 37.234375 L 164.777344 36.960938 L 165.585938 36.164062 L 165.855469 35.90625 L 166.121094 35.644531 L 166.660156 35.136719 L 167.199219 34.636719 L 167.46875 34.390625 L 167.734375 34.144531 L 168.003906 33.902344 L 168.273438 33.664062 L 169.082031 32.960938 L 169.347656 32.730469 L 169.617188 32.503906 L 170.425781 31.835938 L 170.695312 31.621094 L 170.960938 31.40625 L 171.230469 31.191406 L 171.5 30.980469 L 172.039062 30.566406 L 172.308594 30.363281 L 172.574219 30.164062 L 172.84375 29.964844 L 173.113281 29.769531 L 173.921875 29.195312 L 174.1875 29.011719 L 174.726562 28.644531 L 174.996094 28.464844 L 175.535156 28.113281 L 175.800781 27.941406 L 176.339844 27.605469 L 176.609375 27.441406 L 176.878906 27.28125 L 177.144531 27.121094 L 177.414062 26.960938 L 177.683594 26.808594 L 177.953125 26.652344 L 178.492188 26.355469 L 178.757812 26.210938 L 179.027344 26.066406 L 179.296875 25.925781 L 179.835938 25.652344 L 180.105469 25.519531 L 180.371094 25.386719 L 180.640625 25.261719 L 180.910156 25.132812 L 181.179688 25.011719 L 181.449219 24.886719 L 181.71875 24.769531 L 181.984375 24.652344 L 182.523438 24.425781 L 182.792969 24.316406 L 183.332031 24.105469 L 183.597656 24.003906 L 183.867188 23.902344 L 184.136719 23.804688 L 184.675781 23.617188 L 184.945312 23.527344 L 185.210938 23.441406 L 185.480469 23.355469 L 186.019531 23.191406 L 186.289062 23.113281 L 186.558594 23.039062 L 186.824219 22.964844 L 187.363281 22.824219 L 187.632812 22.757812 L 188.171875 22.632812 L 188.4375 22.574219 L 188.976562 22.464844 L 189.515625 22.363281 L 189.785156 22.316406 L 190.050781 22.273438 L 190.320312 22.230469 L 190.859375 22.152344 L 191.128906 22.117188 L 191.394531 22.085938 L 191.664062 22.054688 L 191.933594 22.027344 L 192.472656 21.980469 L 192.742188 21.960938 L 193.007812 21.941406 L 193.277344 21.925781 L 193.816406 21.902344 L 194.355469 21.886719 L 194.621094 21.882812 L 194.890625 21.882812 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.128906 L 54.019531 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/sigmoid.svg b/documentation/ui/figure/sigmoid.svg
new file mode 100644
index 0000000..4e58480
--- /dev/null
+++ b/documentation/ui/figure/sigmoid.svg
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface256">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.84375 L 201.601562 152.84375 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.425781 L 201.601562 115.425781 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.003906 L 201.601562 78.003906 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.585938 L 201.601562 40.585938 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.550781 L 201.601562 171.550781 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.132812 L 201.601562 134.132812 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.875 L 201.601562 21.875 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 21.882812 L 62.070312 21.882812 L 62.339844 21.886719 L 64.492188 21.886719 L 64.757812 21.890625 L 66.371094 21.890625 L 66.640625 21.894531 L 67.984375 21.894531 L 68.253906 21.898438 L 69.0625 21.898438 L 69.332031 21.902344 L 70.136719 21.902344 L 70.40625 21.90625 L 70.945312 21.90625 L 71.210938 21.910156 L 71.75 21.910156 L 72.019531 21.914062 L 72.558594 21.914062 L 72.824219 21.917969 L 73.09375 21.917969 L 73.363281 21.921875 L 73.632812 21.921875 L 73.902344 21.925781 L 74.167969 21.925781 L 74.4375 21.929688 L 74.707031 21.929688 L 74.976562 21.933594 L 75.246094 21.933594 L 75.515625 21.9375 L 75.78125 21.941406 L 76.050781 21.941406 L 76.859375 21.953125 L 77.128906 21.953125 L 77.394531 21.957031 L 78.742188 21.976562 L 79.007812 21.980469 L 80.085938 21.996094 L 80.355469 22.003906 L 80.621094 22.007812 L 80.890625 22.011719 L 81.160156 22.019531 L 81.429688 22.023438 L 81.96875 22.039062 L 82.234375 22.042969 L 83.582031 22.082031 L 83.847656 22.089844 L 84.386719 22.105469 L 84.65625 22.117188 L 84.925781 22.125 L 85.195312 22.136719 L 85.460938 22.148438 L 85.730469 22.160156 L 86 22.167969 L 86.269531 22.183594 L 86.808594 22.207031 L 87.074219 22.222656 L 87.34375 22.234375 L 88.152344 22.28125 L 88.417969 22.296875 L 88.6875 22.3125 L 89.765625 22.390625 L 90.03125 22.410156 L 91.378906 22.527344 L 91.644531 22.554688 L 91.914062 22.582031 L 92.183594 22.613281 L 92.453125 22.640625 L 92.722656 22.671875 L 92.992188 22.707031 L 93.257812 22.738281 L 93.527344 22.773438 L 93.796875 22.8125 L 94.066406 22.847656 L 94.335938 22.886719 L 94.605469 22.929688 L 94.871094 22.972656 L 95.140625 23.015625 L 95.679688 23.109375 L 96.21875 23.210938 L 96.484375 23.265625 L 97.292969 23.441406 L 97.5625 23.507812 L 97.832031 23.570312 L 98.097656 23.640625 L 98.367188 23.710938 L 98.636719 23.785156 L 99.175781 23.941406 L 99.445312 24.027344 L 99.710938 24.113281 L 99.980469 24.203125 L 100.25 24.296875 L 100.519531 24.394531 L 100.789062 24.496094 L 101.058594 24.601562 L 101.324219 24.710938 L 101.59375 24.824219 L 101.863281 24.941406 L 102.132812 25.0625 L 102.402344 25.191406 L 102.667969 25.324219 L 102.9375 25.460938 L 103.207031 25.605469 L 103.476562 25.753906 L 103.746094 25.90625 L 104.015625 26.066406 L 104.28125 26.234375 L 104.550781 26.40625 L 104.820312 26.585938 L 105.089844 26.773438 L 105.359375 26.964844 L 105.628906 27.167969 L 105.894531 27.375 L 106.164062 27.589844 L 106.433594 27.816406 L 106.703125 28.046875 L 106.972656 28.289062 L 107.242188 28.539062 L 107.507812 28.800781 L 107.777344 29.070312 L 108.046875 29.351562 L 108.316406 29.640625 L 108.585938 29.941406 L 108.855469 30.25 L 109.121094 30.574219 L 109.390625 30.90625 L 109.660156 31.253906 L 109.929688 31.613281 L 110.199219 31.984375 L 110.46875 32.367188 L 110.734375 32.765625 L 111.003906 33.179688 L 111.273438 33.605469 L 111.542969 34.042969 L 111.8125 34.5 L 112.082031 34.972656 L 112.347656 35.457031 L 112.617188 35.960938 L 112.886719 36.480469 L 113.15625 37.019531 L 113.425781 37.574219 L 113.695312 38.144531 L 113.960938 38.734375 L 114.230469 39.34375 L 114.5 39.972656 L 114.769531 40.617188 L 115.039062 41.285156 L 115.308594 41.972656 L 115.574219 42.679688 L 115.84375 43.410156 L 116.113281 44.160156 L 116.382812 44.929688 L 116.652344 45.722656 L 116.921875 46.535156 L 117.1875 47.375 L 117.457031 48.230469 L 117.726562 49.113281 L 117.996094 50.019531 L 118.265625 50.945312 L 118.53125 51.894531 L 118.800781 52.871094 L 119.070312 53.867188 L 119.339844 54.886719 L 119.609375 55.929688 L 119.878906 56.996094 L 120.144531 58.082031 L 120.414062 59.195312 L 120.683594 60.328125 L 120.953125 61.484375 L 121.222656 62.664062 L 121.492188 63.863281 L 121.757812 65.085938 L 122.027344 66.328125 L 122.296875 67.589844 L 122.566406 68.871094 L 122.835938 70.175781 L 123.105469 71.496094 L 123.371094 72.832031 L 123.640625 74.1875 L 123.910156 75.558594 L 124.179688 76.949219 L 124.449219 78.351562 L 124.71875 79.765625 L 124.984375 81.195312 L 125.253906 82.636719 L 125.523438 84.089844 L 125.792969 85.550781 L 126.0625 87.019531 L 126.332031 88.5 L 126.597656 89.984375 L 126.867188 91.472656 L 127.40625 94.464844 L 127.945312 97.464844 L 128.210938 98.964844 L 128.75 101.957031 L 129.019531 103.445312 L 129.289062 104.929688 L 129.558594 106.40625 L 129.824219 107.878906 L 130.09375 109.339844 L 130.363281 110.792969 L 130.632812 112.234375 L 130.902344 113.664062 L 131.171875 115.078125 L 131.4375 116.480469 L 131.707031 117.867188 L 131.976562 119.242188 L 132.246094 120.597656 L 132.515625 121.933594 L 132.78125 123.253906 L 133.050781 124.558594 L 133.320312 125.839844 L 133.589844 127.101562 L 133.859375 128.34375 L 134.128906 129.566406 L 134.394531 130.765625 L 134.664062 131.945312 L 134.933594 133.101562 L 135.203125 134.234375 L 135.472656 135.347656 L 135.742188 136.433594 L 136.007812 137.5 L 136.277344 138.542969 L 136.546875 139.5625 L 136.816406 140.558594 L 137.085938 141.53125 L 137.355469 142.484375 L 137.621094 143.410156 L 137.890625 144.316406 L 138.160156 145.195312 L 138.429688 146.054688 L 138.699219 146.890625 L 138.96875 147.707031 L 139.234375 148.5 L 139.503906 149.269531 L 139.773438 150.019531 L 140.042969 150.75 L 140.3125 151.457031 L 140.582031 152.144531 L 140.847656 152.808594 L 141.117188 153.457031 L 141.386719 154.085938 L 141.65625 154.695312 L 141.925781 155.285156 L 142.195312 155.855469 L 142.460938 156.410156 L 142.730469 156.949219 L 143 157.46875 L 143.269531 157.972656 L 143.539062 158.457031 L 143.808594 158.929688 L 144.074219 159.382812 L 144.34375 159.824219 L 144.613281 160.25 L 144.882812 160.664062 L 145.152344 161.058594 L 145.421875 161.445312 L 145.6875 161.816406 L 145.957031 162.175781 L 146.226562 162.519531 L 146.496094 162.855469 L 146.765625 163.175781 L 147.03125 163.488281 L 147.300781 163.789062 L 147.570312 164.078125 L 147.839844 164.359375 L 148.109375 164.628906 L 148.378906 164.886719 L 148.644531 165.140625 L 148.914062 165.378906 L 149.183594 165.613281 L 149.453125 165.835938 L 149.722656 166.054688 L 149.992188 166.261719 L 150.257812 166.464844 L 150.527344 166.65625 L 150.796875 166.84375 L 151.066406 167.023438 L 151.335938 167.195312 L 151.605469 167.363281 L 151.871094 167.523438 L 152.140625 167.675781 L 152.410156 167.824219 L 152.679688 167.96875 L 152.949219 168.105469 L 153.21875 168.238281 L 153.484375 168.363281 L 153.753906 168.488281 L 154.023438 168.605469 L 154.292969 168.71875 L 154.5625 168.828125 L 154.832031 168.933594 L 155.097656 169.035156 L 155.367188 169.132812 L 155.636719 169.226562 L 155.90625 169.316406 L 156.175781 169.402344 L 156.445312 169.484375 L 156.710938 169.566406 L 156.980469 169.644531 L 157.25 169.71875 L 157.519531 169.789062 L 158.058594 169.921875 L 158.324219 169.984375 L 158.59375 170.046875 L 158.863281 170.105469 L 159.671875 170.269531 L 159.9375 170.316406 L 160.207031 170.367188 L 160.476562 170.414062 L 161.015625 170.5 L 161.28125 170.539062 L 161.550781 170.582031 L 161.820312 170.617188 L 162.089844 170.65625 L 162.359375 170.691406 L 162.628906 170.722656 L 162.894531 170.757812 L 163.164062 170.789062 L 163.433594 170.816406 L 163.703125 170.847656 L 163.972656 170.875 L 164.242188 170.898438 L 164.507812 170.925781 L 165.585938 171.019531 L 165.855469 171.039062 L 166.121094 171.058594 L 166.660156 171.097656 L 166.929688 171.113281 L 167.199219 171.132812 L 167.46875 171.148438 L 167.734375 171.164062 L 168.273438 171.195312 L 168.542969 171.207031 L 168.8125 171.222656 L 169.082031 171.234375 L 169.347656 171.246094 L 170.425781 171.292969 L 170.695312 171.300781 L 170.960938 171.3125 L 171.230469 171.320312 L 171.5 171.332031 L 172.308594 171.355469 L 172.574219 171.363281 L 173.382812 171.386719 L 173.652344 171.390625 L 173.921875 171.398438 L 174.1875 171.402344 L 174.457031 171.410156 L 174.726562 171.414062 L 174.996094 171.421875 L 175.535156 171.429688 L 175.800781 171.4375 L 176.878906 171.453125 L 177.144531 171.457031 L 178.222656 171.472656 L 178.492188 171.472656 L 178.757812 171.476562 L 179.296875 171.484375 L 179.566406 171.484375 L 180.105469 171.492188 L 180.371094 171.492188 L 180.910156 171.5 L 181.179688 171.5 L 181.449219 171.503906 L 181.71875 171.503906 L 181.984375 171.507812 L 182.523438 171.507812 L 182.792969 171.511719 L 183.0625 171.511719 L 183.332031 171.515625 L 183.867188 171.515625 L 184.136719 171.519531 L 184.40625 171.519531 L 184.675781 171.523438 L 185.480469 171.523438 L 185.75 171.527344 L 186.558594 171.527344 L 186.824219 171.53125 L 187.632812 171.53125 L 187.902344 171.535156 L 189.246094 171.535156 L 189.515625 171.539062 L 191.128906 171.539062 L 191.394531 171.542969 L 193.816406 171.542969 L 194.085938 171.546875 L 194.890625 171.546875 "/>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 61.53125 171.546875 L 61.800781 171.542969 L 64.222656 171.542969 L 64.492188 171.539062 L 66.105469 171.539062 L 66.371094 171.535156 L 67.71875 171.535156 L 67.984375 171.53125 L 68.792969 171.53125 L 69.0625 171.527344 L 69.867188 171.527344 L 70.136719 171.523438 L 70.945312 171.523438 L 71.210938 171.519531 L 71.480469 171.519531 L 71.75 171.515625 L 72.289062 171.515625 L 72.558594 171.511719 L 72.824219 171.511719 L 73.09375 171.507812 L 73.632812 171.507812 L 73.902344 171.503906 L 74.167969 171.503906 L 74.4375 171.5 L 74.707031 171.5 L 75.246094 171.492188 L 75.515625 171.492188 L 75.78125 171.488281 L 76.050781 171.484375 L 76.320312 171.484375 L 77.128906 171.472656 L 77.394531 171.472656 L 78.742188 171.453125 L 79.007812 171.449219 L 79.816406 171.4375 L 80.085938 171.429688 L 80.355469 171.425781 L 80.621094 171.421875 L 80.890625 171.414062 L 81.160156 171.410156 L 81.429688 171.402344 L 81.699219 171.398438 L 81.96875 171.390625 L 82.234375 171.386719 L 83.582031 171.347656 L 83.847656 171.339844 L 84.117188 171.332031 L 84.386719 171.320312 L 84.65625 171.3125 L 84.925781 171.300781 L 85.195312 171.292969 L 85.460938 171.28125 L 86.808594 171.222656 L 87.074219 171.207031 L 87.34375 171.195312 L 88.152344 171.148438 L 88.417969 171.132812 L 88.6875 171.113281 L 88.957031 171.097656 L 89.765625 171.039062 L 90.03125 171.019531 L 91.109375 170.925781 L 91.378906 170.898438 L 91.644531 170.875 L 91.914062 170.847656 L 92.183594 170.816406 L 92.453125 170.789062 L 92.722656 170.757812 L 92.992188 170.722656 L 93.257812 170.691406 L 93.527344 170.65625 L 93.796875 170.617188 L 94.066406 170.582031 L 94.335938 170.539062 L 94.605469 170.5 L 94.871094 170.457031 L 95.140625 170.414062 L 95.410156 170.367188 L 95.679688 170.316406 L 95.949219 170.269531 L 96.21875 170.214844 L 96.484375 170.160156 L 96.753906 170.105469 L 97.023438 170.046875 L 97.5625 169.921875 L 97.832031 169.855469 L 98.097656 169.789062 L 98.367188 169.71875 L 98.636719 169.644531 L 98.90625 169.566406 L 99.445312 169.402344 L 99.710938 169.316406 L 99.980469 169.226562 L 100.25 169.132812 L 100.519531 169.035156 L 100.789062 168.933594 L 101.058594 168.828125 L 101.324219 168.71875 L 101.59375 168.605469 L 101.863281 168.488281 L 102.402344 168.238281 L 102.667969 168.105469 L 102.9375 167.96875 L 103.207031 167.824219 L 103.476562 167.675781 L 103.746094 167.523438 L 104.015625 167.363281 L 104.28125 167.195312 L 104.550781 167.023438 L 104.820312 166.84375 L 105.089844 166.65625 L 105.359375 166.464844 L 105.628906 166.261719 L 105.894531 166.054688 L 106.164062 165.835938 L 106.433594 165.613281 L 106.703125 165.378906 L 106.972656 165.140625 L 107.242188 164.886719 L 107.507812 164.628906 L 107.777344 164.359375 L 108.046875 164.078125 L 108.316406 163.789062 L 108.585938 163.488281 L 108.855469 163.175781 L 109.121094 162.855469 L 109.390625 162.519531 L 109.660156 162.175781 L 109.929688 161.816406 L 110.199219 161.445312 L 110.46875 161.058594 L 110.734375 160.664062 L 111.003906 160.25 L 111.273438 159.824219 L 111.542969 159.382812 L 111.8125 158.929688 L 112.082031 158.457031 L 112.347656 157.972656 L 112.617188 157.46875 L 112.886719 156.949219 L 113.15625 156.410156 L 113.425781 155.855469 L 113.695312 155.285156 L 113.960938 154.695312 L 114.230469 154.085938 L 114.5 153.457031 L 114.769531 152.808594 L 115.039062 152.144531 L 115.308594 151.457031 L 115.574219 150.75 L 115.84375 150.019531 L 116.113281 149.269531 L 116.382812 148.5 L 116.652344 147.707031 L 116.921875 146.890625 L 117.1875 146.054688 L 117.457031 145.195312 L 117.726562 144.316406 L 117.996094 143.410156 L 118.265625 142.484375 L 118.53125 141.53125 L 118.800781 140.558594 L 119.070312 139.5625 L 119.339844 138.542969 L 119.609375 137.5 L 119.878906 136.433594 L 120.144531 135.347656 L 120.414062 134.234375 L 120.683594 133.101562 L 120.953125 131.945312 L 121.222656 130.765625 L 121.492188 129.566406 L 121.757812 128.34375 L 122.027344 127.101562 L 122.296875 125.839844 L 122.566406 124.558594 L 122.835938 123.253906 L 123.105469 121.933594 L 123.371094 120.597656 L 123.640625 119.242188 L 123.910156 117.867188 L 124.179688 116.480469 L 124.449219 115.078125 L 124.71875 113.664062 L 124.984375 112.234375 L 125.253906 110.792969 L 125.523438 109.339844 L 125.792969 107.878906 L 126.0625 106.40625 L 126.332031 104.929688 L 126.597656 103.445312 L 126.867188 101.957031 L 127.40625 98.964844 L 127.945312 95.964844 L 128.210938 94.464844 L 128.75 91.472656 L 129.019531 89.984375 L 129.289062 88.5 L 129.558594 87.019531 L 129.824219 85.550781 L 130.09375 84.089844 L 130.363281 82.636719 L 130.632812 81.195312 L 130.902344 79.765625 L 131.171875 78.351562 L 131.4375 76.949219 L 131.707031 75.558594 L 131.976562 74.1875 L 132.246094 72.832031 L 132.515625 71.496094 L 132.78125 70.175781 L 133.050781 68.871094 L 133.320312 67.589844 L 133.589844 66.328125 L 133.859375 65.085938 L 134.128906 63.863281 L 134.394531 62.664062 L 134.664062 61.484375 L 134.933594 60.328125 L 135.203125 59.195312 L 135.472656 58.082031 L 135.742188 56.996094 L 136.007812 55.929688 L 136.277344 54.886719 L 136.546875 53.867188 L 136.816406 52.871094 L 137.085938 51.894531 L 137.355469 50.945312 L 137.621094 50.019531 L 137.890625 49.113281 L 138.160156 48.230469 L 138.429688 47.375 L 138.699219 46.535156 L 138.96875 45.722656 L 139.234375 44.929688 L 139.503906 44.160156 L 139.773438 43.410156 L 140.042969 42.679688 L 140.3125 41.972656 L 140.582031 41.285156 L 140.847656 40.617188 L 141.117188 39.972656 L 141.386719 39.34375 L 141.65625 38.734375 L 141.925781 38.144531 L 142.195312 37.574219 L 142.460938 37.019531 L 142.730469 36.480469 L 143 35.960938 L 143.269531 35.457031 L 143.539062 34.972656 L 143.808594 34.5 L 144.074219 34.042969 L 144.34375 33.605469 L 144.613281 33.179688 L 144.882812 32.765625 L 145.152344 32.367188 L 145.421875 31.984375 L 145.6875 31.613281 L 145.957031 31.253906 L 146.226562 30.90625 L 146.496094 30.574219 L 146.765625 30.25 L 147.03125 29.941406 L 147.300781 29.640625 L 147.570312 29.351562 L 147.839844 29.070312 L 148.109375 28.800781 L 148.378906 28.539062 L 148.644531 28.289062 L 148.914062 28.046875 L 149.183594 27.816406 L 149.453125 27.589844 L 149.722656 27.375 L 149.992188 27.167969 L 150.257812 26.964844 L 150.527344 26.773438 L 150.796875 26.585938 L 151.066406 26.40625 L 151.335938 26.234375 L 151.605469 26.066406 L 151.871094 25.90625 L 152.140625 25.753906 L 152.410156 25.605469 L 152.679688 25.460938 L 152.949219 25.324219 L 153.21875 25.191406 L 153.484375 25.0625 L 153.753906 24.941406 L 154.023438 24.824219 L 154.292969 24.710938 L 154.5625 24.601562 L 154.832031 24.496094 L 155.097656 24.394531 L 155.367188 24.296875 L 155.636719 24.203125 L 155.90625 24.113281 L 156.445312 23.941406 L 156.710938 23.863281 L 156.980469 23.785156 L 157.25 23.710938 L 157.789062 23.570312 L 158.058594 23.507812 L 158.324219 23.441406 L 159.132812 23.265625 L 159.402344 23.210938 L 159.671875 23.160156 L 159.9375 23.109375 L 160.476562 23.015625 L 161.015625 22.929688 L 161.28125 22.886719 L 161.550781 22.847656 L 161.820312 22.8125 L 162.089844 22.773438 L 162.359375 22.738281 L 162.628906 22.707031 L 162.894531 22.671875 L 163.164062 22.640625 L 163.433594 22.613281 L 163.703125 22.582031 L 164.242188 22.527344 L 164.507812 22.503906 L 165.585938 22.410156 L 165.855469 22.390625 L 166.121094 22.371094 L 166.929688 22.3125 L 167.46875 22.28125 L 167.734375 22.265625 L 168.273438 22.234375 L 168.542969 22.222656 L 168.8125 22.207031 L 169.082031 22.195312 L 169.347656 22.183594 L 169.617188 22.167969 L 169.886719 22.160156 L 170.695312 22.125 L 170.960938 22.117188 L 171.230469 22.105469 L 172.308594 22.074219 L 172.574219 22.066406 L 173.382812 22.042969 L 173.652344 22.039062 L 173.921875 22.03125 L 174.1875 22.023438 L 174.457031 22.019531 L 174.726562 22.011719 L 175.265625 22.003906 L 175.535156 21.996094 L 175.800781 21.992188 L 176.878906 21.976562 L 177.144531 21.972656 L 178.492188 21.953125 L 178.757812 21.953125 L 179.566406 21.941406 L 179.835938 21.941406 L 180.105469 21.9375 L 180.371094 21.933594 L 180.640625 21.933594 L 180.910156 21.929688 L 181.179688 21.929688 L 181.449219 21.925781 L 181.71875 21.925781 L 181.984375 21.921875 L 182.253906 21.921875 L 182.523438 21.917969 L 182.792969 21.917969 L 183.0625 21.914062 L 183.597656 21.914062 L 183.867188 21.910156 L 184.40625 21.910156 L 184.675781 21.90625 L 185.210938 21.90625 L 185.480469 21.902344 L 186.289062 21.902344 L 186.558594 21.898438 L 187.363281 21.898438 L 187.632812 21.894531 L 188.976562 21.894531 L 189.246094 21.890625 L 190.859375 21.890625 L 191.128906 21.886719 L 193.277344 21.886719 L 193.546875 21.882812 L 194.890625 21.882812 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.988281"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.988281"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.988281"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.988281"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.570312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.570312"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.570312"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.570312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.3125"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.3125"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.3125"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.3125"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.550781 L 54.019531 171.550781 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.132812 L 54.019531 134.132812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.875 L 54.019531 21.875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/sigmoidDifference.svg b/documentation/ui/figure/sigmoidDifference.svg
new file mode 100644
index 0000000..ca75ba2
--- /dev/null
+++ b/documentation/ui/figure/sigmoidDifference.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 153 L 202 153 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 76 L 202 76 L 202 78 L 54.019531 78 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 38 L 202 38 L 202 40 L 54.019531 40 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 172 L 202.601562 172 L 202.601562 174 L 54.019531 174 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 95 L 202.601562 95 L 202.601562 97 L 54.019531 97 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 57 L 202.601562 57 L 202.601562 59 L 54.019531 59 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 19 L 202.601562 19 L 202.601562 21 L 54.019531 21 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface226">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 153.476562 L 201.601562 153.476562 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.292969 L 201.601562 115.292969 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 77.113281 L 201.601562 77.113281 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 38.929688 L 201.601562 38.929688 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 172.566406 L 201.601562 172.566406 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.386719 L 201.601562 134.386719 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.203125 L 201.601562 96.203125 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 58.019531 L 201.601562 58.019531 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 19.839844 L 201.601562 19.839844 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 61.265625 171.460938 L 61.53125 171.417969 L 61.800781 171.371094 L 62.609375 171.21875 L 62.878906 171.164062 L 63.144531 171.105469 L 63.414062 171.046875 L 63.953125 170.921875 L 64.222656 170.855469 L 64.492188 170.785156 L 64.757812 170.714844 L 65.027344 170.636719 L 65.296875 170.5625 L 65.566406 170.480469 L 66.105469 170.308594 L 66.371094 170.21875 L 66.910156 170.023438 L 67.179688 169.921875 L 67.449219 169.816406 L 67.71875 169.707031 L 67.984375 169.589844 L 68.253906 169.472656 L 68.523438 169.347656 L 68.792969 169.21875 L 69.0625 169.085938 L 69.332031 168.945312 L 69.597656 168.800781 L 69.867188 168.652344 L 70.136719 168.496094 L 70.40625 168.332031 L 70.675781 168.164062 L 70.945312 167.988281 L 71.210938 167.808594 L 71.480469 167.621094 L 71.75 167.425781 L 72.019531 167.222656 L 72.289062 167.011719 L 72.558594 166.792969 L 72.824219 166.566406 L 73.09375 166.332031 L 73.363281 166.085938 L 73.632812 165.832031 L 73.902344 165.570312 L 74.167969 165.296875 L 74.4375 165.015625 L 74.707031 164.722656 L 74.976562 164.417969 L 75.246094 164.101562 L 75.515625 163.777344 L 75.78125 163.4375 L 76.050781 163.089844 L 76.320312 162.726562 L 76.589844 162.351562 L 76.859375 161.960938 L 77.128906 161.558594 L 77.394531 161.144531 L 77.664062 160.710938 L 77.933594 160.265625 L 78.203125 159.804688 L 78.472656 159.328125 L 78.742188 158.835938 L 79.007812 158.328125 L 79.277344 157.800781 L 79.546875 157.257812 L 79.816406 156.695312 L 80.085938 156.117188 L 80.355469 155.519531 L 80.621094 154.902344 L 80.890625 154.265625 L 81.160156 153.609375 L 81.429688 152.933594 L 81.699219 152.238281 L 81.96875 151.523438 L 82.234375 150.785156 L 82.503906 150.027344 L 82.773438 149.246094 L 83.042969 148.441406 L 83.3125 147.617188 L 83.582031 146.769531 L 83.847656 145.898438 L 84.117188 145.003906 L 84.386719 144.085938 L 84.65625 143.144531 L 84.925781 142.183594 L 85.195312 141.195312 L 85.460938 140.183594 L 85.730469 139.148438 L 86 138.089844 L 86.269531 137.007812 L 86.539062 135.90625 L 86.808594 134.777344 L 87.074219 133.625 L 87.34375 132.449219 L 87.613281 131.253906 L 87.882812 130.035156 L 88.152344 128.792969 L 88.417969 127.53125 L 88.6875 126.25 L 88.957031 124.945312 L 89.226562 123.621094 L 89.496094 122.28125 L 89.765625 120.917969 L 90.03125 119.539062 L 90.300781 118.144531 L 90.570312 116.734375 L 90.839844 115.304688 L 91.109375 113.863281 L 91.378906 112.410156 L 91.644531 110.941406 L 91.914062 109.464844 L 92.183594 107.972656 L 92.453125 106.476562 L 92.722656 104.96875 L 92.992188 103.457031 L 93.257812 101.9375 L 93.527344 100.414062 L 94.066406 97.359375 L 94.605469 94.296875 L 94.871094 92.769531 L 95.410156 89.722656 L 95.679688 88.207031 L 95.949219 86.695312 L 96.21875 85.195312 L 96.484375 83.703125 L 96.753906 82.21875 L 97.023438 80.746094 L 97.292969 79.285156 L 97.5625 77.835938 L 97.832031 76.402344 L 98.097656 74.980469 L 98.367188 73.578125 L 98.636719 72.191406 L 98.90625 70.820312 L 99.175781 69.46875 L 99.445312 68.136719 L 99.710938 66.824219 L 99.980469 65.53125 L 100.25 64.261719 L 100.519531 63.007812 L 100.789062 61.78125 L 101.058594 60.574219 L 101.324219 59.386719 L 101.59375 58.226562 L 101.863281 57.085938 L 102.132812 55.972656 L 102.402344 54.878906 L 102.667969 53.808594 L 102.9375 52.765625 L 103.207031 51.742188 L 103.476562 50.742188 L 103.746094 49.769531 L 104.015625 48.820312 L 104.28125 47.890625 L 104.550781 46.988281 L 104.820312 46.105469 L 105.089844 45.246094 L 105.359375 44.414062 L 105.628906 43.601562 L 105.894531 42.808594 L 106.164062 42.039062 L 106.433594 41.292969 L 106.703125 40.566406 L 106.972656 39.863281 L 107.242188 39.179688 L 107.507812 38.515625 L 107.777344 37.871094 L 108.046875 37.25 L 108.316406 36.644531 L 108.585938 36.058594 L 108.855469 35.488281 L 109.121094 34.941406 L 109.390625 34.40625 L 109.660156 33.894531 L 109.929688 33.394531 L 110.199219 32.914062 L 110.46875 32.445312 L 110.734375 31.996094 L 111.003906 31.5625 L 111.273438 31.140625 L 111.542969 30.734375 L 111.8125 30.34375 L 112.082031 29.964844 L 112.347656 29.601562 L 112.617188 29.25 L 112.886719 28.910156 L 113.15625 28.582031 L 113.425781 28.265625 L 113.695312 27.960938 L 113.960938 27.667969 L 114.230469 27.386719 L 114.5 27.113281 L 114.769531 26.851562 L 115.039062 26.597656 L 115.308594 26.355469 L 115.574219 26.125 L 115.84375 25.898438 L 116.113281 25.683594 L 116.382812 25.476562 L 116.652344 25.277344 L 116.921875 25.085938 L 117.1875 24.902344 L 117.457031 24.726562 L 117.726562 24.558594 L 117.996094 24.394531 L 118.265625 24.238281 L 118.53125 24.089844 L 118.800781 23.949219 L 119.070312 23.8125 L 119.339844 23.679688 L 119.878906 23.4375 L 120.144531 23.324219 L 120.414062 23.214844 L 120.683594 23.113281 L 120.953125 23.015625 L 121.222656 22.921875 L 121.492188 22.832031 L 121.757812 22.75 L 122.027344 22.667969 L 122.296875 22.59375 L 122.566406 22.523438 L 122.835938 22.457031 L 123.105469 22.394531 L 123.371094 22.335938 L 123.640625 22.28125 L 123.910156 22.230469 L 124.179688 22.183594 L 124.71875 22.097656 L 124.984375 22.0625 L 125.523438 22 L 125.792969 21.972656 L 126.0625 21.949219 L 126.332031 21.929688 L 126.597656 21.914062 L 126.867188 21.902344 L 127.40625 21.886719 L 127.675781 21.882812 L 127.945312 21.882812 L 128.210938 21.886719 L 128.75 21.902344 L 129.019531 21.914062 L 129.289062 21.929688 L 129.558594 21.949219 L 129.824219 21.972656 L 130.09375 22 L 130.632812 22.0625 L 130.902344 22.097656 L 131.171875 22.140625 L 131.4375 22.183594 L 131.707031 22.230469 L 131.976562 22.28125 L 132.246094 22.335938 L 132.515625 22.394531 L 132.78125 22.457031 L 133.050781 22.523438 L 133.320312 22.59375 L 133.589844 22.667969 L 134.128906 22.832031 L 134.394531 22.921875 L 134.664062 23.015625 L 134.933594 23.113281 L 135.203125 23.214844 L 135.472656 23.324219 L 135.742188 23.4375 L 136.007812 23.558594 L 136.277344 23.679688 L 136.546875 23.8125 L 136.816406 23.949219 L 137.085938 24.089844 L 137.355469 24.238281 L 137.621094 24.394531 L 137.890625 24.558594 L 138.160156 24.726562 L 138.429688 24.902344 L 138.699219 25.085938 L 138.96875 25.277344 L 139.234375 25.476562 L 139.503906 25.683594 L 139.773438 25.898438 L 140.042969 26.125 L 140.3125 26.355469 L 140.582031 26.597656 L 140.847656 26.851562 L 141.117188 27.113281 L 141.386719 27.386719 L 141.65625 27.667969 L 141.925781 27.960938 L 142.195312 28.265625 L 142.460938 28.582031 L 142.730469 28.910156 L 143 29.25 L 143.269531 29.601562 L 143.539062 29.964844 L 143.808594 30.34375 L 144.074219 30.734375 L 144.34375 31.140625 L 144.613281 31.5625 L 144.882812 31.996094 L 145.152344 32.445312 L 145.421875 32.914062 L 145.6875 33.394531 L 145.957031 33.894531 L 146.226562 34.40625 L 146.496094 34.941406 L 146.765625 35.488281 L 147.03125 36.058594 L 147.300781 36.644531 L 147.570312 37.25 L 147.839844 37.871094 L 148.109375 38.515625 L 148.378906 39.179688 L 148.644531 39.863281 L 148.914062 40.566406 L 149.183594 41.292969 L 149.453125 42.039062 L 149.722656 42.808594 L 149.992188 43.601562 L 150.257812 44.414062 L 150.527344 45.246094 L 150.796875 46.105469 L 151.066406 46.988281 L 151.335938 47.890625 L 151.605469 48.820312 L 151.871094 49.769531 L 152.140625 50.742188 L 152.410156 51.742188 L 152.679688 52.765625 L 152.949219 53.808594 L 153.21875 54.878906 L 153.484375 55.972656 L 153.753906 57.085938 L 154.023438 58.226562 L 154.292969 59.386719 L 154.5625 60.574219 L 154.832031 61.78125 L 155.097656 63.007812 L 155.367188 64.261719 L 155.636719 65.53125 L 155.90625 66.824219 L 156.175781 68.136719 L 156.445312 69.46875 L 156.710938 70.820312 L 156.980469 72.191406 L 157.25 73.578125 L 157.519531 74.980469 L 157.789062 76.402344 L 158.058594 77.835938 L 158.324219 79.285156 L 158.59375 80.746094 L 158.863281 82.21875 L 159.132812 83.703125 L 159.402344 85.195312 L 159.671875 86.695312 L 159.9375 88.207031 L 160.207031 89.722656 L 160.746094 92.769531 L 161.015625 94.296875 L 161.28125 95.828125 L 161.550781 97.359375 L 162.089844 100.414062 L 162.359375 101.9375 L 162.628906 103.457031 L 162.894531 104.96875 L 163.164062 106.476562 L 163.433594 107.972656 L 163.703125 109.464844 L 163.972656 110.941406 L 164.242188 112.410156 L 164.507812 113.863281 L 164.777344 115.304688 L 165.046875 116.734375 L 165.316406 118.144531 L 165.585938 119.539062 L 165.855469 120.917969 L 166.121094 122.28125 L 166.390625 123.621094 L 166.660156 124.945312 L 166.929688 126.25 L 167.199219 127.53125 L 167.46875 128.792969 L 167.734375 130.035156 L 168.003906 131.253906 L 168.273438 132.449219 L 168.542969 133.625 L 168.8125 134.777344 L 169.082031 135.90625 L 169.347656 137.007812 L 169.617188 138.089844 L 169.886719 139.148438 L 170.15625 140.183594 L 170.425781 141.195312 L 170.695312 142.183594 L 170.960938 143.144531 L 171.230469 144.085938 L 171.5 145.003906 L 171.769531 145.898438 L 172.039062 146.769531 L 172.308594 147.617188 L 172.574219 148.441406 L 172.84375 149.246094 L 173.113281 150.027344 L 173.382812 150.785156 L 173.652344 151.523438 L 173.921875 152.238281 L 174.1875 152.933594 L 174.457031 153.609375 L 174.726562 154.265625 L 174.996094 154.902344 L 175.265625 155.519531 L 175.535156 156.117188 L 175.800781 156.695312 L 176.070312 157.257812 L 176.339844 157.800781 L 176.609375 158.328125 L 176.878906 158.835938 L 177.144531 159.328125 L 177.414062 159.804688 L 177.683594 160.265625 L 177.953125 160.710938 L 178.222656 161.144531 L 178.492188 161.558594 L 178.757812 161.960938 L 179.027344 162.351562 L 179.296875 162.726562 L 179.566406 163.089844 L 179.835938 163.4375 L 180.105469 163.777344 L 180.371094 164.101562 L 180.640625 164.417969 L 180.910156 164.722656 L 181.179688 165.015625 L 181.449219 165.296875 L 181.71875 165.570312 L 181.984375 165.832031 L 182.253906 166.085938 L 182.523438 166.332031 L 182.792969 166.566406 L 183.0625 166.792969 L 183.332031 167.011719 L 183.597656 167.222656 L 183.867188 167.425781 L 184.136719 167.621094 L 184.40625 167.808594 L 184.675781 167.988281 L 184.945312 168.164062 L 185.210938 168.332031 L 185.480469 168.496094 L 185.75 168.652344 L 186.019531 168.800781 L 186.289062 168.945312 L 186.558594 169.085938 L 186.824219 169.21875 L 187.09375 169.347656 L 187.363281 169.472656 L 187.902344 169.707031 L 188.171875 169.816406 L 188.4375 169.921875 L 188.707031 170.023438 L 189.246094 170.21875 L 189.515625 170.308594 L 189.785156 170.394531 L 190.050781 170.480469 L 190.320312 170.5625 L 190.589844 170.636719 L 190.859375 170.714844 L 191.128906 170.785156 L 191.394531 170.855469 L 191.664062 170.921875 L 192.203125 171.046875 L 192.742188 171.164062 L 193.007812 171.21875 L 193.816406 171.371094 L 194.085938 171.417969 L 194.355469 171.460938 L 194.621094 171.503906 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="176.003906"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="176.003906"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="176.003906"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="176.003906"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.824219"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.824219"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.824219"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.824219"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="99.640625"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="99.640625"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="99.640625"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="99.640625"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="61.457031"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="61.457031"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="61.457031"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="61.457031"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="23.277344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="23.277344"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="23.277344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="23.277344"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 172.566406 L 54.019531 172.566406 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.386719 L 54.019531 134.386719 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.203125 L 54.019531 96.203125 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 58.019531 L 54.019531 58.019531 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 19.839844 L 54.019531 19.839844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/sigmoidProduct.svg b/documentation/ui/figure/sigmoidProduct.svg
new file mode 100644
index 0000000..61543c9
--- /dev/null
+++ b/documentation/ui/figure/sigmoidProduct.svg
@@ -0,0 +1,252 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 3.171875 -2.375 L 3.171875 -5.421875 L 1.015625 -2.375 Z M 3.1875 0 L 3.1875 -1.640625 L 0.25 -1.640625 L 0.25 -2.46875 L 3.3125 -6.734375 L 4.03125 -6.734375 L 4.03125 -2.375 L 5.015625 -2.375 L 5.015625 -1.640625 L 4.03125 -1.640625 L 4.03125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 2.8125 -6.734375 C 3.5625 -6.734375 4.082031 -6.535156 4.375 -6.140625 C 4.664062 -5.753906 4.8125 -5.359375 4.8125 -4.953125 L 3.984375 -4.953125 C 3.929688 -5.210938 3.851562 -5.421875 3.75 -5.578125 C 3.539062 -5.859375 3.226562 -6 2.8125 -6 C 2.34375 -6 1.96875 -5.78125 1.6875 -5.34375 C 1.414062 -4.90625 1.265625 -4.28125 1.234375 -3.46875 C 1.421875 -3.75 1.664062 -3.960938 1.96875 -4.109375 C 2.226562 -4.234375 2.523438 -4.296875 2.859375 -4.296875 C 3.421875 -4.296875 3.910156 -4.113281 4.328125 -3.75 C 4.742188 -3.394531 4.953125 -2.863281 4.953125 -2.15625 C 4.953125 -1.539062 4.753906 -1 4.359375 -0.53125 C 3.960938 -0.0625 3.398438 0.171875 2.671875 0.171875 C 2.046875 0.171875 1.503906 -0.0625 1.046875 -0.53125 C 0.585938 -1.007812 0.359375 -1.816406 0.359375 -2.953125 C 0.359375 -3.785156 0.460938 -4.488281 0.671875 -5.0625 C 1.054688 -6.175781 1.769531 -6.734375 2.8125 -6.734375 Z M 2.75 -0.578125 C 3.1875 -0.578125 3.515625 -0.722656 3.734375 -1.015625 C 3.960938 -1.316406 4.078125 -1.671875 4.078125 -2.078125 C 4.078125 -2.421875 3.976562 -2.75 3.78125 -3.0625 C 3.582031 -3.375 3.222656 -3.53125 2.703125 -3.53125 C 2.335938 -3.53125 2.019531 -3.410156 1.75 -3.171875 C 1.476562 -2.929688 1.34375 -2.566406 1.34375 -2.078125 C 1.34375 -1.648438 1.460938 -1.289062 1.703125 -1 C 1.953125 -0.71875 2.300781 -0.578125 2.75 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 2.609375 -3.890625 C 2.984375 -3.890625 3.273438 -3.992188 3.484375 -4.203125 C 3.691406 -4.410156 3.796875 -4.660156 3.796875 -4.953125 C 3.796875 -5.203125 3.691406 -5.429688 3.484375 -5.640625 C 3.285156 -5.847656 2.984375 -5.953125 2.578125 -5.953125 C 2.171875 -5.953125 1.875 -5.847656 1.6875 -5.640625 C 1.507812 -5.429688 1.421875 -5.1875 1.421875 -4.90625 C 1.421875 -4.59375 1.535156 -4.34375 1.765625 -4.15625 C 2.003906 -3.976562 2.285156 -3.890625 2.609375 -3.890625 Z M 2.65625 -0.578125 C 3.050781 -0.578125 3.375 -0.679688 3.625 -0.890625 C 3.882812 -1.097656 4.015625 -1.414062 4.015625 -1.84375 C 4.015625 -2.269531 3.878906 -2.59375 3.609375 -2.8125 C 3.347656 -3.039062 3.007812 -3.15625 2.59375 -3.15625 C 2.195312 -3.15625 1.867188 -3.039062 1.609375 -2.8125 C 1.359375 -2.582031 1.234375 -2.265625 1.234375 -1.859375 C 1.234375 -1.515625 1.347656 -1.210938 1.578125 -0.953125 C 1.816406 -0.703125 2.175781 -0.578125 2.65625 -0.578125 Z M 1.46875 -3.578125 C 1.226562 -3.671875 1.039062 -3.785156 0.90625 -3.921875 C 0.664062 -4.171875 0.546875 -4.5 0.546875 -4.90625 C 0.546875 -5.40625 0.722656 -5.832031 1.078125 -6.1875 C 1.441406 -6.550781 1.957031 -6.734375 2.625 -6.734375 C 3.269531 -6.734375 3.773438 -6.5625 4.140625 -6.21875 C 4.503906 -5.875 4.6875 -5.476562 4.6875 -5.03125 C 4.6875 -4.613281 4.582031 -4.273438 4.375 -4.015625 C 4.25 -3.867188 4.0625 -3.722656 3.8125 -3.578125 C 4.09375 -3.453125 4.3125 -3.304688 4.46875 -3.140625 C 4.769531 -2.828125 4.921875 -2.421875 4.921875 -1.921875 C 4.921875 -1.335938 4.722656 -0.835938 4.328125 -0.421875 C 3.929688 -0.015625 3.367188 0.1875 2.640625 0.1875 C 1.984375 0.1875 1.429688 0.0078125 0.984375 -0.34375 C 0.535156 -0.695312 0.3125 -1.210938 0.3125 -1.890625 C 0.3125 -2.285156 0.40625 -2.625 0.59375 -2.90625 C 0.789062 -3.195312 1.082031 -3.421875 1.46875 -3.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-7">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-8">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-9">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 48.683594 14.398438 L 202 14.398438 L 202 180 L 48.683594 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 48.683594 166 L 202 166 L 202 168 L 48.683594 168 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 48.683594 128 L 202 128 L 202 129 L 48.683594 129 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 48.683594 89 L 202 89 L 202 91 L 48.683594 91 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 48.683594 51 L 202 51 L 202 52 L 48.683594 52 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 72 14.398438 L 74 14.398438 L 74 180 L 72 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 107 14.398438 L 109 14.398438 L 109 180 L 107 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 142 14.398438 L 143 14.398438 L 143 180 L 142 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 178 14.398438 L 178 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 48.683594 147 L 202.601562 147 L 202.601562 149 L 48.683594 149 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 48.683594 108 L 202.601562 108 L 202.601562 110 L 48.683594 110 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 48.683594 70 L 202.601562 70 L 202.601562 72 L 48.683594 72 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 48.683594 31 L 202.601562 31 L 202.601562 33 L 48.683594 33 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 55 14.398438 L 57 14.398438 L 57 180 L 55 180 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 89 14.398438 L 91 14.398438 L 91 180 L 89 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 124 14.398438 L 126 14.398438 L 126 180 L 124 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 159 14.398438 L 161 14.398438 L 161 180 L 159 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface231">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 48.683594 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 48.683594 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 166.894531 L 201.601562 166.894531 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 128.433594 L 201.601562 128.433594 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 89.96875 L 201.601562 89.96875 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 51.503906 L 201.601562 51.503906 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 73.011719 179.027344 L 73.011719 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 107.765625 179.027344 L 107.765625 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 142.519531 179.027344 L 142.519531 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 177.273438 179.027344 L 177.273438 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 147.664062 L 201.601562 147.664062 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 109.199219 L 201.601562 109.199219 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 70.738281 L 201.601562 70.738281 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 48.683594 32.273438 L 201.601562 32.273438 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 55.632812 179.027344 L 55.632812 14.398438 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 90.386719 179.027344 L 90.386719 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 125.140625 179.027344 L 125.140625 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 159.894531 179.027344 L 159.894531 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.648438 179.027344 L 194.648438 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 55.632812 171.546875 L 55.910156 171.273438 L 56.191406 170.996094 L 56.46875 170.714844 L 56.746094 170.429688 L 57.027344 170.136719 L 57.304688 169.84375 L 57.582031 169.539062 L 57.863281 169.234375 L 58.140625 168.925781 L 58.417969 168.609375 L 58.699219 168.285156 L 58.976562 167.960938 L 59.253906 167.628906 L 59.535156 167.289062 L 59.8125 166.945312 L 60.089844 166.597656 L 60.371094 166.246094 L 60.925781 165.519531 L 61.207031 165.148438 L 61.484375 164.769531 L 61.761719 164.386719 L 62.039062 164 L 62.320312 163.605469 L 62.597656 163.203125 L 62.875 162.796875 L 63.15625 162.382812 L 63.433594 161.960938 L 63.710938 161.535156 L 63.992188 161.105469 L 64.269531 160.664062 L 64.546875 160.21875 L 64.828125 159.769531 L 65.105469 159.308594 L 65.382812 158.84375 L 65.664062 158.371094 L 65.941406 157.894531 L 66.21875 157.40625 L 66.5 156.914062 L 66.777344 156.417969 L 67.054688 155.910156 L 67.335938 155.398438 L 67.613281 154.878906 L 67.890625 154.351562 L 68.167969 153.816406 L 68.449219 153.273438 L 68.726562 152.726562 L 69.285156 151.609375 L 69.5625 151.039062 L 69.839844 150.460938 L 70.121094 149.875 L 70.398438 149.285156 L 70.675781 148.6875 L 70.957031 148.078125 L 71.234375 147.464844 L 71.511719 146.84375 L 71.792969 146.214844 L 72.070312 145.582031 L 72.347656 144.9375 L 72.628906 144.285156 L 72.90625 143.628906 L 73.183594 142.964844 L 73.464844 142.292969 L 73.742188 141.613281 L 74.019531 140.925781 L 74.300781 140.230469 L 74.578125 139.527344 L 74.855469 138.820312 L 75.132812 138.105469 L 75.414062 137.382812 L 75.691406 136.652344 L 75.96875 135.914062 L 76.25 135.171875 L 76.527344 134.417969 L 76.804688 133.660156 L 77.085938 132.898438 L 77.363281 132.125 L 77.640625 131.347656 L 77.921875 130.5625 L 78.199219 129.773438 L 78.476562 128.976562 L 78.757812 128.171875 L 79.035156 127.359375 L 79.3125 126.542969 L 79.59375 125.722656 L 79.871094 124.894531 L 80.148438 124.058594 L 80.429688 123.21875 L 80.707031 122.375 L 80.984375 121.523438 L 81.261719 120.667969 L 81.542969 119.804688 L 81.820312 118.9375 L 82.097656 118.066406 L 82.378906 117.1875 L 82.65625 116.308594 L 82.933594 115.421875 L 83.214844 114.53125 L 83.492188 113.636719 L 83.769531 112.738281 L 84.050781 111.832031 L 84.328125 110.925781 L 84.605469 110.015625 L 84.886719 109.101562 L 85.164062 108.1875 L 85.441406 107.265625 L 85.722656 106.34375 L 86 105.414062 L 86.277344 104.488281 L 86.558594 103.554688 L 87.113281 101.6875 L 87.390625 100.75 L 87.671875 99.8125 L 88.226562 97.929688 L 88.507812 96.988281 L 88.785156 96.042969 L 89.0625 95.101562 L 89.34375 94.15625 L 89.898438 92.265625 L 90.179688 91.320312 L 90.457031 90.375 L 90.734375 89.433594 L 91.015625 88.488281 L 91.570312 86.605469 L 91.851562 85.667969 L 92.40625 83.792969 L 92.6875 82.859375 L 92.964844 81.925781 L 93.242188 80.996094 L 93.519531 80.070312 L 93.800781 79.144531 L 94.355469 77.308594 L 94.636719 76.390625 L 94.914062 75.480469 L 95.191406 74.574219 L 95.472656 73.671875 L 95.75 72.769531 L 96.027344 71.875 L 96.308594 70.984375 L 96.863281 69.21875 L 97.144531 68.34375 L 97.421875 67.472656 L 97.699219 66.605469 L 97.980469 65.746094 L 98.535156 64.042969 L 98.816406 63.203125 L 99.09375 62.367188 L 99.371094 61.535156 L 99.652344 60.710938 L 99.929688 59.894531 L 100.207031 59.085938 L 100.484375 58.28125 L 100.765625 57.484375 L 101.042969 56.695312 L 101.320312 55.914062 L 101.601562 55.140625 L 101.878906 54.371094 L 102.15625 53.613281 L 102.4375 52.859375 L 102.714844 52.117188 L 102.992188 51.378906 L 103.273438 50.652344 L 103.550781 49.929688 L 103.828125 49.21875 L 104.109375 48.515625 L 104.386719 47.820312 L 104.664062 47.132812 L 104.945312 46.453125 L 105.222656 45.78125 L 105.5 45.121094 L 105.78125 44.46875 L 106.058594 43.824219 L 106.335938 43.191406 L 106.613281 42.5625 L 106.894531 41.945312 L 107.171875 41.335938 L 107.449219 40.738281 L 107.730469 40.148438 L 108.007812 39.566406 L 108.285156 38.996094 L 108.84375 37.878906 L 109.121094 37.335938 L 109.402344 36.800781 L 109.679688 36.273438 L 109.957031 35.757812 L 110.238281 35.25 L 110.515625 34.753906 L 110.792969 34.265625 L 111.074219 33.785156 L 111.351562 33.316406 L 111.628906 32.855469 L 111.910156 32.40625 L 112.1875 31.964844 L 112.464844 31.535156 L 112.742188 31.113281 L 113.023438 30.699219 L 113.300781 30.296875 L 113.578125 29.902344 L 113.859375 29.519531 L 114.136719 29.144531 L 114.414062 28.78125 L 114.695312 28.425781 L 114.972656 28.078125 L 115.25 27.742188 L 115.53125 27.414062 L 115.808594 27.097656 L 116.085938 26.789062 L 116.367188 26.492188 L 116.644531 26.203125 L 116.921875 25.921875 L 117.203125 25.652344 L 117.480469 25.390625 L 117.757812 25.140625 L 118.039062 24.898438 L 118.316406 24.664062 L 118.59375 24.441406 L 118.875 24.230469 L 119.152344 24.023438 L 119.429688 23.828125 L 119.707031 23.644531 L 119.988281 23.46875 L 120.265625 23.300781 L 120.542969 23.144531 L 120.824219 22.996094 L 121.101562 22.855469 L 121.378906 22.726562 L 121.660156 22.605469 L 121.9375 22.492188 L 122.214844 22.390625 L 122.496094 22.300781 L 122.773438 22.214844 L 123.050781 22.140625 L 123.332031 22.078125 L 123.609375 22.023438 L 123.886719 21.976562 L 124.167969 21.9375 L 124.445312 21.910156 L 124.722656 21.890625 L 125.003906 21.882812 L 125.28125 21.882812 L 125.558594 21.890625 L 125.835938 21.910156 L 126.117188 21.9375 L 126.394531 21.976562 L 126.671875 22.023438 L 126.953125 22.078125 L 127.230469 22.140625 L 127.507812 22.214844 L 127.789062 22.300781 L 128.066406 22.390625 L 128.34375 22.492188 L 128.625 22.605469 L 128.902344 22.726562 L 129.179688 22.855469 L 129.460938 22.996094 L 129.738281 23.144531 L 130.015625 23.300781 L 130.296875 23.46875 L 130.574219 23.644531 L 130.851562 23.828125 L 131.132812 24.023438 L 131.410156 24.230469 L 131.6875 24.441406 L 131.964844 24.664062 L 132.246094 24.898438 L 132.523438 25.140625 L 132.800781 25.390625 L 133.082031 25.652344 L 133.359375 25.921875 L 133.636719 26.203125 L 133.917969 26.492188 L 134.195312 26.789062 L 134.472656 27.097656 L 134.753906 27.414062 L 135.03125 27.742188 L 135.308594 28.078125 L 135.589844 28.425781 L 135.867188 28.78125 L 136.144531 29.144531 L 136.425781 29.519531 L 136.703125 29.902344 L 136.980469 30.296875 L 137.261719 30.699219 L 137.539062 31.113281 L 137.816406 31.535156 L 138.09375 31.964844 L 138.375 32.40625 L 138.652344 32.855469 L 138.929688 33.316406 L 139.210938 33.785156 L 139.488281 34.265625 L 139.765625 34.753906 L 140.046875 35.25 L 140.324219 35.757812 L 140.601562 36.273438 L 140.882812 36.800781 L 141.160156 37.335938 L 141.4375 37.878906 L 141.71875 38.433594 L 141.996094 38.996094 L 142.273438 39.566406 L 142.554688 40.148438 L 142.832031 40.738281 L 143.109375 41.335938 L 143.390625 41.945312 L 143.667969 42.5625 L 143.945312 43.191406 L 144.226562 43.824219 L 144.503906 44.46875 L 144.78125 45.121094 L 145.058594 45.78125 L 145.339844 46.453125 L 145.617188 47.132812 L 145.894531 47.820312 L 146.175781 48.515625 L 146.453125 49.21875 L 146.730469 49.929688 L 147.011719 50.652344 L 147.289062 51.378906 L 147.566406 52.117188 L 147.847656 52.859375 L 148.125 53.613281 L 148.402344 54.371094 L 148.683594 55.140625 L 148.960938 55.914062 L 149.238281 56.695312 L 149.519531 57.484375 L 149.796875 58.28125 L 150.074219 59.085938 L 150.355469 59.894531 L 150.632812 60.710938 L 150.910156 61.535156 L 151.1875 62.367188 L 151.46875 63.203125 L 151.746094 64.042969 L 152.023438 64.894531 L 152.304688 65.746094 L 152.582031 66.605469 L 152.859375 67.472656 L 153.140625 68.34375 L 153.417969 69.21875 L 153.695312 70.101562 L 153.976562 70.984375 L 154.253906 71.875 L 154.53125 72.769531 L 154.8125 73.671875 L 155.089844 74.574219 L 155.367188 75.480469 L 155.648438 76.390625 L 156.203125 78.226562 L 156.484375 79.144531 L 157.039062 80.996094 L 157.316406 81.925781 L 157.597656 82.859375 L 157.875 83.792969 L 158.152344 84.730469 L 158.433594 85.667969 L 158.710938 86.605469 L 158.988281 87.546875 L 159.269531 88.488281 L 159.546875 89.433594 L 159.824219 90.375 L 160.105469 91.320312 L 160.660156 93.210938 L 160.941406 94.15625 L 161.21875 95.101562 L 161.496094 96.042969 L 161.777344 96.988281 L 162.332031 98.871094 L 162.613281 99.8125 L 163.167969 101.6875 L 163.445312 102.621094 L 163.726562 103.554688 L 164.003906 104.488281 L 164.28125 105.414062 L 164.5625 106.34375 L 165.117188 108.1875 L 165.398438 109.101562 L 165.675781 110.015625 L 165.953125 110.925781 L 166.234375 111.832031 L 166.511719 112.738281 L 166.789062 113.636719 L 167.070312 114.53125 L 167.347656 115.421875 L 167.625 116.308594 L 167.90625 117.1875 L 168.183594 118.066406 L 168.460938 118.9375 L 168.742188 119.804688 L 169.019531 120.667969 L 169.296875 121.523438 L 169.578125 122.375 L 169.855469 123.21875 L 170.132812 124.058594 L 170.410156 124.894531 L 170.691406 125.722656 L 170.96875 126.542969 L 171.246094 127.359375 L 171.527344 128.171875 L 171.804688 128.976562 L 172.082031 129.773438 L 172.363281 130.5625 L 172.640625 131.347656 L 172.917969 132.125 L 173.199219 132.898438 L 173.476562 133.660156 L 173.753906 134.417969 L 174.035156 135.171875 L 174.3125 135.914062 L 174.589844 136.652344 L 174.871094 137.382812 L 175.148438 138.105469 L 175.425781 138.820312 L 175.707031 139.527344 L 175.984375 140.230469 L 176.261719 140.925781 L 176.539062 141.613281 L 176.820312 142.292969 L 177.097656 142.964844 L 177.375 143.628906 L 177.65625 144.285156 L 177.933594 144.9375 L 178.210938 145.582031 L 178.492188 146.214844 L 178.769531 146.84375 L 179.046875 147.464844 L 179.328125 148.078125 L 179.605469 148.6875 L 179.882812 149.285156 L 180.164062 149.875 L 180.441406 150.460938 L 180.71875 151.039062 L 181 151.609375 L 181.277344 152.171875 L 181.554688 152.726562 L 181.835938 153.273438 L 182.113281 153.816406 L 182.390625 154.351562 L 182.667969 154.878906 L 182.949219 155.398438 L 183.226562 155.910156 L 183.503906 156.417969 L 183.785156 156.914062 L 184.0625 157.40625 L 184.339844 157.894531 L 184.621094 158.371094 L 184.898438 158.84375 L 185.175781 159.308594 L 185.457031 159.769531 L 185.734375 160.21875 L 186.011719 160.664062 L 186.292969 161.105469 L 186.570312 161.535156 L 186.847656 161.960938 L 187.128906 162.382812 L 187.40625 162.796875 L 187.683594 163.203125 L 187.964844 163.605469 L 188.242188 164 L 188.519531 164.386719 L 188.800781 164.769531 L 189.078125 165.148438 L 189.355469 165.519531 L 189.632812 165.882812 L 189.914062 166.246094 L 190.191406 166.597656 L 190.46875 166.945312 L 190.75 167.289062 L 191.027344 167.628906 L 191.304688 167.960938 L 191.585938 168.285156 L 191.863281 168.609375 L 192.140625 168.925781 L 192.421875 169.234375 L 192.976562 169.84375 L 193.257812 170.136719 L 193.535156 170.429688 L 193.8125 170.714844 L 194.371094 171.273438 L 194.648438 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="151.101562"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="151.101562"/>
+ <use xlink:href="#glyph0-3" x="36.262756" y="151.101562"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="112.636719"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="112.636719"/>
+ <use xlink:href="#glyph0-4" x="36.262756" y="112.636719"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="74.175781"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="74.175781"/>
+ <use xlink:href="#glyph0-5" x="36.262756" y="74.175781"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.261719" y="35.710938"/>
+ <use xlink:href="#glyph0-2" x="33.597305" y="35.710938"/>
+ <use xlink:href="#glyph0-6" x="36.262756" y="35.710938"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 147.664062 L 48.683594 147.664062 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 109.199219 L 48.683594 109.199219 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 70.738281 L 48.683594 70.738281 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 44.429688 32.273438 L 48.683594 32.273438 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 55.632812 183.28125 L 55.632812 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 90.386719 183.28125 L 90.386719 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 125.140625 183.28125 L 125.140625 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 159.894531 183.28125 L 159.894531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.648438 183.28125 L 194.648438 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="46.296875" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="51.632462" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="54.297913" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.633499" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="81.050781" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="86.386368" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="89.051819" y="192.992188"/>
+ <use xlink:href="#glyph0-7" x="94.387405" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="115.804688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="121.140274" y="192.992188"/>
+ <use xlink:href="#glyph0-7" x="123.805725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="129.141312" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="150.558594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="155.89418" y="192.992188"/>
+ <use xlink:href="#glyph0-8" x="158.559631" y="192.992188"/>
+ <use xlink:href="#glyph0-7" x="163.895218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-9" x="185.3125" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.648087" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.313538" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.649124" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="122.140625" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/spike.svg b/documentation/ui/figure/spike.svg
new file mode 100644
index 0000000..5bf788b
--- /dev/null
+++ b/documentation/ui/figure/spike.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 153 L 202 153 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 78 L 54.019531 78 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 39 L 202 39 L 202 40 L 54.019531 40 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 172 L 202.601562 172 L 202.601562 174 L 54.019531 174 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 136 L 54.019531 136 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 95 L 202.601562 95 L 202.601562 97 L 54.019531 97 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 57 L 202.601562 57 L 202.601562 59 L 54.019531 59 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 19 L 202.601562 19 L 202.601562 21 L 54.019531 21 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface236">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 153.546875 L 201.601562 153.546875 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.496094 L 201.601562 115.496094 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 77.441406 L 201.601562 77.441406 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 39.390625 L 201.601562 39.390625 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 172.570312 L 201.601562 172.570312 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.519531 L 201.601562 134.519531 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.46875 L 201.601562 96.46875 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 58.417969 L 201.601562 58.417969 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 20.367188 L 201.601562 20.367188 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 60.996094 171.523438 L 61.265625 171.503906 L 61.53125 171.480469 L 61.800781 171.460938 L 62.878906 171.367188 L 63.144531 171.34375 L 63.414062 171.316406 L 63.683594 171.292969 L 63.953125 171.265625 L 64.222656 171.242188 L 64.492188 171.214844 L 64.757812 171.1875 L 65.027344 171.15625 L 65.566406 171.101562 L 66.105469 171.039062 L 66.371094 171.007812 L 67.179688 170.914062 L 67.71875 170.84375 L 67.984375 170.808594 L 68.523438 170.738281 L 68.792969 170.699219 L 69.0625 170.664062 L 69.332031 170.625 L 69.597656 170.585938 L 69.867188 170.542969 L 70.136719 170.503906 L 70.945312 170.375 L 71.210938 170.332031 L 72.289062 170.144531 L 72.558594 170.09375 L 72.824219 170.042969 L 73.363281 169.941406 L 73.902344 169.832031 L 74.167969 169.777344 L 74.4375 169.722656 L 75.246094 169.546875 L 75.515625 169.484375 L 75.78125 169.421875 L 76.050781 169.359375 L 76.859375 169.160156 L 77.128906 169.089844 L 77.394531 169.019531 L 77.664062 168.945312 L 77.933594 168.875 L 78.203125 168.796875 L 78.472656 168.722656 L 78.742188 168.644531 L 79.007812 168.566406 L 79.546875 168.402344 L 80.085938 168.230469 L 80.355469 168.140625 L 80.621094 168.054688 L 81.429688 167.773438 L 81.96875 167.578125 L 82.234375 167.476562 L 83.042969 167.160156 L 83.3125 167.050781 L 83.582031 166.9375 L 83.847656 166.824219 L 84.386719 166.589844 L 84.65625 166.46875 L 85.195312 166.21875 L 85.460938 166.089844 L 86 165.824219 L 86.539062 165.550781 L 86.808594 165.40625 L 87.074219 165.261719 L 87.613281 164.964844 L 88.152344 164.652344 L 88.417969 164.492188 L 88.6875 164.328125 L 89.226562 163.992188 L 89.765625 163.640625 L 90.03125 163.460938 L 90.570312 163.085938 L 90.839844 162.894531 L 91.109375 162.699219 L 91.378906 162.5 L 91.644531 162.296875 L 92.183594 161.875 L 92.453125 161.660156 L 92.722656 161.4375 L 92.992188 161.210938 L 93.257812 160.980469 L 93.527344 160.746094 L 93.796875 160.507812 L 94.066406 160.265625 L 94.335938 160.015625 L 94.605469 159.761719 L 94.871094 159.5 L 95.140625 159.238281 L 95.410156 158.96875 L 95.679688 158.691406 L 95.949219 158.410156 L 96.21875 158.125 L 96.484375 157.832031 L 97.023438 157.230469 L 97.292969 156.917969 L 97.5625 156.601562 L 97.832031 156.277344 L 98.097656 155.949219 L 98.367188 155.613281 L 98.636719 155.269531 L 98.90625 154.917969 L 99.175781 154.5625 L 99.445312 154.195312 L 99.710938 153.824219 L 99.980469 153.445312 L 100.25 153.058594 L 100.519531 152.664062 L 100.789062 152.257812 L 101.058594 151.847656 L 101.324219 151.429688 L 101.59375 151 L 101.863281 150.5625 L 102.132812 150.117188 L 102.402344 149.664062 L 102.667969 149.199219 L 102.9375 148.726562 L 103.207031 148.246094 L 103.476562 147.753906 L 103.746094 147.25 L 104.015625 146.738281 L 104.28125 146.214844 L 104.550781 145.679688 L 104.820312 145.136719 L 105.089844 144.582031 L 105.359375 144.015625 L 105.628906 143.4375 L 105.894531 142.847656 L 106.164062 142.246094 L 106.433594 141.632812 L 106.703125 141.003906 L 106.972656 140.367188 L 107.242188 139.714844 L 107.507812 139.050781 L 107.777344 138.371094 L 108.046875 137.679688 L 108.316406 136.972656 L 108.585938 136.25 L 108.855469 135.515625 L 109.121094 134.765625 L 109.390625 134 L 109.660156 133.21875 L 109.929688 132.421875 L 110.199219 131.609375 L 110.46875 130.78125 L 110.734375 129.9375 L 111.003906 129.074219 L 111.273438 128.191406 L 111.542969 127.292969 L 111.8125 126.378906 L 112.082031 125.441406 L 112.347656 124.488281 L 112.617188 123.515625 L 112.886719 122.523438 L 113.15625 121.507812 L 113.425781 120.476562 L 113.695312 119.421875 L 113.960938 118.34375 L 114.230469 117.246094 L 114.5 116.128906 L 114.769531 114.984375 L 115.039062 113.820312 L 115.308594 112.628906 L 115.574219 111.417969 L 115.84375 110.179688 L 116.113281 108.914062 L 116.382812 107.628906 L 116.652344 106.3125 L 116.921875 104.972656 L 117.1875 103.601562 L 117.457031 102.207031 L 117.726562 100.78125 L 117.996094 99.328125 L 118.265625 97.847656 L 118.53125 96.335938 L 118.800781 94.789062 L 119.070312 93.214844 L 119.339844 91.609375 L 119.609375 89.972656 L 119.878906 88.300781 L 120.144531 86.59375 L 120.414062 84.851562 L 120.683594 83.078125 L 120.953125 81.265625 L 121.222656 79.417969 L 121.492188 77.53125 L 121.757812 75.609375 L 122.027344 73.644531 L 122.296875 71.644531 L 122.566406 69.601562 L 122.835938 67.515625 L 123.105469 65.390625 L 123.371094 63.21875 L 123.640625 61.007812 L 123.910156 58.746094 L 124.179688 56.445312 L 124.449219 54.09375 L 124.71875 51.695312 L 124.984375 49.246094 L 125.253906 46.75 L 125.523438 44.203125 L 125.792969 41.605469 L 126.0625 38.953125 L 126.332031 36.25 L 126.597656 33.492188 L 126.867188 30.675781 L 127.136719 27.804688 L 127.40625 24.871094 L 127.675781 21.882812 L 127.945312 21.882812 L 128.210938 24.871094 L 128.480469 27.804688 L 128.75 30.675781 L 129.019531 33.492188 L 129.289062 36.25 L 129.558594 38.953125 L 129.824219 41.605469 L 130.09375 44.203125 L 130.363281 46.75 L 130.632812 49.246094 L 130.902344 51.695312 L 131.171875 54.09375 L 131.4375 56.445312 L 131.707031 58.746094 L 131.976562 61.007812 L 132.246094 63.21875 L 132.515625 65.390625 L 132.78125 67.515625 L 133.050781 69.601562 L 133.320312 71.644531 L 133.589844 73.644531 L 133.859375 75.609375 L 134.128906 77.53125 L 134.394531 79.417969 L 134.664062 81.265625 L 134.933594 83.078125 L 135.203125 84.851562 L 135.472656 86.59375 L 135.742188 88.300781 L 136.007812 89.972656 L 136.277344 91.609375 L 136.546875 93.214844 L 136.816406 94.789062 L 137.085938 96.335938 L 137.355469 97.847656 L 137.621094 99.328125 L 137.890625 100.78125 L 138.160156 102.207031 L 138.429688 103.601562 L 138.699219 104.972656 L 138.96875 106.3125 L 139.234375 107.628906 L 139.503906 108.914062 L 139.773438 110.179688 L 140.042969 111.417969 L 140.3125 112.628906 L 140.582031 113.820312 L 140.847656 114.984375 L 141.117188 116.128906 L 141.386719 117.246094 L 141.65625 118.34375 L 141.925781 119.421875 L 142.195312 120.476562 L 142.460938 121.507812 L 142.730469 122.523438 L 143 123.515625 L 143.269531 124.488281 L 143.539062 125.441406 L 143.808594 126.378906 L 144.074219 127.292969 L 144.34375 128.191406 L 144.613281 129.074219 L 144.882812 129.9375 L 145.152344 130.78125 L 145.421875 131.609375 L 145.6875 132.421875 L 145.957031 133.21875 L 146.226562 134 L 146.496094 134.765625 L 146.765625 135.515625 L 147.03125 136.25 L 147.300781 136.972656 L 147.570312 137.679688 L 147.839844 138.371094 L 148.109375 139.050781 L 148.378906 139.714844 L 148.644531 140.367188 L 148.914062 141.003906 L 149.183594 141.632812 L 149.453125 142.246094 L 149.722656 142.847656 L 149.992188 143.4375 L 150.257812 144.015625 L 150.527344 144.582031 L 150.796875 145.136719 L 151.066406 145.679688 L 151.335938 146.214844 L 151.605469 146.738281 L 151.871094 147.25 L 152.140625 147.753906 L 152.410156 148.246094 L 152.679688 148.726562 L 152.949219 149.199219 L 153.21875 149.664062 L 153.484375 150.117188 L 153.753906 150.5625 L 154.023438 151 L 154.292969 151.429688 L 154.5625 151.847656 L 154.832031 152.257812 L 155.097656 152.664062 L 155.367188 153.058594 L 155.636719 153.445312 L 155.90625 153.824219 L 156.175781 154.195312 L 156.445312 154.5625 L 156.710938 154.917969 L 156.980469 155.269531 L 157.25 155.613281 L 157.519531 155.949219 L 157.789062 156.277344 L 158.058594 156.601562 L 158.324219 156.917969 L 158.59375 157.230469 L 159.132812 157.832031 L 159.402344 158.125 L 159.671875 158.410156 L 159.9375 158.691406 L 160.207031 158.96875 L 160.476562 159.238281 L 161.015625 159.761719 L 161.28125 160.015625 L 161.550781 160.265625 L 161.820312 160.507812 L 162.089844 160.746094 L 162.359375 160.980469 L 162.628906 161.210938 L 162.894531 161.4375 L 163.164062 161.660156 L 163.433594 161.875 L 163.972656 162.296875 L 164.242188 162.5 L 164.507812 162.699219 L 164.777344 162.894531 L 165.046875 163.085938 L 165.585938 163.460938 L 165.855469 163.640625 L 166.121094 163.816406 L 166.390625 163.992188 L 166.929688 164.328125 L 167.199219 164.492188 L 167.46875 164.652344 L 167.734375 164.808594 L 168.003906 164.964844 L 168.542969 165.261719 L 169.082031 165.550781 L 169.347656 165.6875 L 169.617188 165.824219 L 170.15625 166.089844 L 170.425781 166.21875 L 170.695312 166.34375 L 170.960938 166.46875 L 171.230469 166.589844 L 171.769531 166.824219 L 172.308594 167.050781 L 172.574219 167.160156 L 173.382812 167.476562 L 173.652344 167.578125 L 173.921875 167.675781 L 174.1875 167.773438 L 174.996094 168.054688 L 175.265625 168.140625 L 175.535156 168.230469 L 175.800781 168.316406 L 176.070312 168.402344 L 176.609375 168.566406 L 176.878906 168.644531 L 177.144531 168.722656 L 177.414062 168.796875 L 177.683594 168.875 L 177.953125 168.945312 L 178.222656 169.019531 L 178.492188 169.089844 L 178.757812 169.160156 L 179.566406 169.359375 L 180.105469 169.484375 L 180.371094 169.546875 L 181.179688 169.722656 L 181.71875 169.832031 L 181.984375 169.886719 L 182.253906 169.941406 L 183.332031 170.144531 L 183.597656 170.191406 L 184.40625 170.332031 L 184.945312 170.417969 L 185.210938 170.460938 L 185.480469 170.503906 L 185.75 170.542969 L 186.019531 170.585938 L 186.558594 170.664062 L 186.824219 170.699219 L 187.09375 170.738281 L 188.171875 170.878906 L 188.4375 170.914062 L 189.785156 171.070312 L 190.050781 171.101562 L 190.589844 171.15625 L 190.859375 171.1875 L 191.128906 171.214844 L 191.394531 171.242188 L 191.664062 171.265625 L 191.933594 171.292969 L 192.203125 171.316406 L 192.472656 171.34375 L 192.742188 171.367188 L 193.007812 171.390625 L 193.816406 171.460938 L 194.085938 171.480469 L 194.355469 171.503906 L 194.621094 171.523438 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="176.007812"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="176.007812"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="176.007812"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="176.007812"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.957031"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.957031"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.957031"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.957031"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="99.90625"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="99.90625"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="99.90625"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="99.90625"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="61.855469"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="61.855469"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="61.855469"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="61.855469"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="23.804688"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="23.804688"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="23.804688"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="23.804688"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 172.570312 L 54.019531 172.570312 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.519531 L 54.019531 134.519531 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.46875 L 54.019531 96.46875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 58.417969 L 54.019531 58.417969 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 20.367188 L 54.019531 20.367188 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/terms.svg b/documentation/ui/figure/terms.svg
new file mode 100644
index 0000000..acc306a
--- /dev/null
+++ b/documentation/ui/figure/terms.svg
@@ -0,0 +1,4955 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="712pt" height="1512pt" viewBox="0 0 712 1512" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-7">
+<path style="stroke:none;" d="M 3.171875 -2.375 L 3.171875 -5.421875 L 1.015625 -2.375 Z M 3.1875 0 L 3.1875 -1.640625 L 0.25 -1.640625 L 0.25 -2.46875 L 3.3125 -6.734375 L 4.03125 -6.734375 L 4.03125 -2.375 L 5.015625 -2.375 L 5.015625 -1.640625 L 4.03125 -1.640625 L 4.03125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-8">
+<path style="stroke:none;" d="M 2.8125 -6.734375 C 3.5625 -6.734375 4.082031 -6.535156 4.375 -6.140625 C 4.664062 -5.753906 4.8125 -5.359375 4.8125 -4.953125 L 3.984375 -4.953125 C 3.929688 -5.210938 3.851562 -5.421875 3.75 -5.578125 C 3.539062 -5.859375 3.226562 -6 2.8125 -6 C 2.34375 -6 1.96875 -5.78125 1.6875 -5.34375 C 1.414062 -4.90625 1.265625 -4.28125 1.234375 -3.46875 C 1.421875 -3.75 1.664062 -3.960938 1.96875 -4.109375 C 2.226562 -4.234375 2.523438 -4.296875 2.859375 -4.296875 C 3.421875 -4.296875 3.910156 -4.113281 4.328125 -3.75 C 4.742188 -3.394531 4.953125 -2.863281 4.953125 -2.15625 C 4.953125 -1.539062 4.753906 -1 4.359375 -0.53125 C 3.960938 -0.0625 3.398438 0.171875 2.671875 0.171875 C 2.046875 0.171875 1.503906 -0.0625 1.046875 -0.53125 C 0.585938 -1.007812 0.359375 -1.816406 0.359375 -2.953125 C 0.359375 -3.785156 0.460938 -4.488281 0.671875 -5.0625 C 1.054688 -6.175781 1.769531 -6.734375 2.8125 -6.734375 Z M 2.75 -0.578125 C 3.1875 -0.578125 3.515625 -0.722656 3.734375 -1.015625 C 3.960938 -1.316406 4.078125 -1.671875 4.078125 -2.078125 C 4.078125 -2.421875 3.976562 -2.75 3.78125 -3.0625 C 3.582031 -3.375 3.222656 -3.53125 2.703125 -3.53125 C 2.335938 -3.53125 2.019531 -3.410156 1.75 -3.171875 C 1.476562 -2.929688 1.34375 -2.566406 1.34375 -2.078125 C 1.34375 -1.648438 1.460938 -1.289062 1.703125 -1 C 1.953125 -0.71875 2.300781 -0.578125 2.75 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-9">
+<path style="stroke:none;" d="M 2.609375 -3.890625 C 2.984375 -3.890625 3.273438 -3.992188 3.484375 -4.203125 C 3.691406 -4.410156 3.796875 -4.660156 3.796875 -4.953125 C 3.796875 -5.203125 3.691406 -5.429688 3.484375 -5.640625 C 3.285156 -5.847656 2.984375 -5.953125 2.578125 -5.953125 C 2.171875 -5.953125 1.875 -5.847656 1.6875 -5.640625 C 1.507812 -5.429688 1.421875 -5.1875 1.421875 -4.90625 C 1.421875 -4.59375 1.535156 -4.34375 1.765625 -4.15625 C 2.003906 -3.976562 2.285156 -3.890625 2.609375 -3.890625 Z M 2.65625 -0.578125 C 3.050781 -0.578125 3.375 -0.679688 3.625 -0.890625 C 3.882812 -1.097656 4.015625 -1.414062 4.015625 -1.84375 C 4.015625 -2.269531 3.878906 -2.59375 3.609375 -2.8125 C 3.347656 -3.039062 3.007812 -3.15625 2.59375 -3.15625 C 2.195312 -3.15625 1.867188 -3.039062 1.609375 -2.8125 C 1.359375 -2.582031 1.234375 -2.265625 1.234375 -1.859375 C 1.234375 -1.515625 1.347656 -1.210938 1.578125 -0.953125 C 1.816406 -0.703125 2.175781 -0.578125 2.65625 -0.578125 Z M 1.46875 -3.578125 C 1.226562 -3.671875 1.039062 -3.785156 0.90625 -3.921875 C 0.664062 -4.171875 0.546875 -4.5 0.546875 -4.90625 C 0.546875 -5.40625 0.722656 -5.832031 1.078125 -6.1875 C 1.441406 -6.550781 1.957031 -6.734375 2.625 -6.734375 C 3.269531 -6.734375 3.773438 -6.5625 4.140625 -6.21875 C 4.503906 -5.875 4.6875 -5.476562 4.6875 -5.03125 C 4.6875 -4.613281 4.582031 -4.273438 4.375 -4.015625 C 4.25 -3.867188 4.0625 -3.722656 3.8125 -3.578125 C 4.09375 -3.453125 4.3125 -3.304688 4.46875 -3.140625 C 4.769531 -2.828125 4.921875 -2.421875 4.921875 -1.921875 C 4.921875 -1.335938 4.722656 -0.835938 4.328125 -0.421875 C 3.929688 -0.015625 3.367188 0.1875 2.640625 0.1875 C 1.984375 0.1875 1.429688 0.0078125 0.984375 -0.34375 C 0.535156 -0.695312 0.3125 -1.210938 0.3125 -1.890625 C 0.3125 -2.285156 0.40625 -2.625 0.59375 -2.90625 C 0.789062 -3.195312 1.082031 -3.421875 1.46875 -3.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-2">
+<path style="stroke:none;" d="M -7.234375 -1.03125 C -7.671875 -1.050781 -7.988281 -1.128906 -8.1875 -1.265625 C -8.550781 -1.515625 -8.734375 -1.988281 -8.734375 -2.6875 C -8.734375 -2.757812 -8.726562 -2.828125 -8.71875 -2.890625 C -8.71875 -2.960938 -8.710938 -3.046875 -8.703125 -3.140625 L -7.75 -3.140625 C -7.757812 -3.023438 -7.765625 -2.941406 -7.765625 -2.890625 C -7.765625 -2.847656 -7.765625 -2.804688 -7.765625 -2.765625 C -7.765625 -2.441406 -7.679688 -2.25 -7.515625 -2.1875 C -7.347656 -2.125 -6.925781 -2.09375 -6.25 -2.09375 L -6.25 -3.140625 L -5.421875 -3.140625 L -5.421875 -2.078125 L 0 -2.078125 L 0 -1.03125 L -5.421875 -1.03125 L -5.421875 -0.171875 L -6.25 -0.171875 L -6.25 -1.03125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-0">
+<path style="stroke:none;" d="M 0.90625 0 L 0.90625 -8.640625 L 7.859375 -8.640625 L 7.859375 0 Z M 6.78125 -1.078125 L 6.78125 -7.5625 L 1.984375 -7.5625 L 1.984375 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-1">
+<path style="stroke:none;" d="M 7.1875 -8.640625 L 7.1875 -7.109375 L 4.609375 -7.109375 L 4.609375 0 L 2.796875 0 L 2.796875 -7.109375 L 0.1875 -7.109375 L 0.1875 -8.640625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-2">
+<path style="stroke:none;" d="M 4.25 -6.546875 C 4.28125 -6.546875 4.304688 -6.539062 4.328125 -6.53125 C 4.347656 -6.53125 4.394531 -6.53125 4.46875 -6.53125 L 4.46875 -4.8125 C 4.363281 -4.820312 4.269531 -4.828125 4.1875 -4.828125 C 4.101562 -4.835938 4.035156 -4.84375 3.984375 -4.84375 C 3.316406 -4.84375 2.867188 -4.625 2.640625 -4.1875 C 2.503906 -3.945312 2.4375 -3.566406 2.4375 -3.046875 L 2.4375 0 L 0.765625 0 L 0.765625 -6.390625 L 2.359375 -6.390625 L 2.359375 -5.28125 C 2.617188 -5.695312 2.84375 -5.984375 3.03125 -6.140625 C 3.34375 -6.410156 3.75 -6.546875 4.25 -6.546875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-3">
+<path style="stroke:none;" d="M 2.5 -7.15625 L 0.796875 -7.15625 L 0.796875 -8.6875 L 2.5 -8.6875 Z M 0.796875 -6.390625 L 2.5 -6.390625 L 2.5 0 L 0.796875 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-4">
+<path style="stroke:none;" d="M 4.296875 -3.109375 C 4.191406 -3.035156 4.085938 -2.976562 3.984375 -2.9375 C 3.878906 -2.90625 3.734375 -2.867188 3.546875 -2.828125 L 3.171875 -2.765625 C 2.816406 -2.703125 2.5625 -2.625 2.40625 -2.53125 C 2.144531 -2.375 2.015625 -2.140625 2.015625 -1.828125 C 2.015625 -1.535156 2.09375 -1.328125 2.25 -1.203125 C 2.414062 -1.078125 2.613281 -1.015625 2.84375 -1.015625 C 3.195312 -1.015625 3.523438 -1.117188 3.828125 -1.328125 C 4.128906 -1.535156 4.285156 -1.921875 4.296875 -2.484375 Z M 3.28125 -3.890625 C 3.59375 -3.921875 3.816406 -3.96875 3.953125 -4.03125 C 4.191406 -4.132812 4.3125 -4.289062 4.3125 -4.5 C 4.3125 -4.769531 4.21875 -4.953125 4.03125 -5.046875 C 3.851562 -5.148438 3.585938 -5.203125 3.234375 -5.203125 C 2.835938 -5.203125 2.554688 -5.101562 2.390625 -4.90625 C 2.273438 -4.757812 2.195312 -4.5625 2.15625 -4.3125 L 0.546875 -4.3125 C 0.585938 -4.875 0.742188 -5.335938 1.015625 -5.703125 C 1.460938 -6.265625 2.222656 -6.546875 3.296875 -6.546875 C 3.992188 -6.546875 4.613281 -6.40625 5.15625 -6.125 C 5.695312 -5.84375 5.96875 -5.316406 5.96875 -4.546875 L 5.96875 -1.625 C 5.96875 -1.414062 5.972656 -1.171875 5.984375 -0.890625 C 5.992188 -0.671875 6.023438 -0.519531 6.078125 -0.4375 C 6.140625 -0.363281 6.222656 -0.300781 6.328125 -0.25 L 6.328125 0 L 4.515625 0 C 4.460938 -0.125 4.425781 -0.242188 4.40625 -0.359375 C 4.382812 -0.472656 4.367188 -0.601562 4.359375 -0.75 C 4.128906 -0.5 3.863281 -0.285156 3.5625 -0.109375 C 3.207031 0.0976562 2.800781 0.203125 2.34375 0.203125 C 1.769531 0.203125 1.289062 0.0351562 0.90625 -0.296875 C 0.53125 -0.628906 0.34375 -1.097656 0.34375 -1.703125 C 0.34375 -2.484375 0.644531 -3.050781 1.25 -3.40625 C 1.582031 -3.59375 2.070312 -3.726562 2.71875 -3.8125 Z M 3.375 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-5">
+<path style="stroke:none;" d="M 4.3125 -6.546875 C 4.976562 -6.546875 5.519531 -6.367188 5.9375 -6.015625 C 6.351562 -5.671875 6.5625 -5.097656 6.5625 -4.296875 L 6.5625 0 L 4.859375 0 L 4.859375 -3.890625 C 4.859375 -4.222656 4.8125 -4.476562 4.71875 -4.65625 C 4.5625 -4.988281 4.25 -5.15625 3.78125 -5.15625 C 3.21875 -5.15625 2.832031 -4.914062 2.625 -4.4375 C 2.507812 -4.175781 2.453125 -3.847656 2.453125 -3.453125 L 2.453125 0 L 0.796875 0 L 0.796875 -6.375 L 2.40625 -6.375 L 2.40625 -5.4375 C 2.613281 -5.769531 2.816406 -6.007812 3.015625 -6.15625 C 3.359375 -6.414062 3.789062 -6.546875 4.3125 -6.546875 Z M 3.703125 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-6">
+<path style="stroke:none;" d="M 3.515625 -1.375 C 3.910156 -1.375 4.242188 -1.519531 4.515625 -1.8125 C 4.785156 -2.101562 4.921875 -2.570312 4.921875 -3.21875 C 4.921875 -3.820312 4.789062 -4.28125 4.53125 -4.59375 C 4.28125 -4.914062 3.9375 -5.078125 3.5 -5.078125 C 2.914062 -5.078125 2.515625 -4.800781 2.296875 -4.25 C 2.171875 -3.957031 2.109375 -3.597656 2.109375 -3.171875 C 2.109375 -2.796875 2.171875 -2.46875 2.296875 -2.1875 C 2.523438 -1.644531 2.929688 -1.375 3.515625 -1.375 Z M 3.109375 -6.546875 C 3.429688 -6.546875 3.707031 -6.492188 3.9375 -6.390625 C 4.34375 -6.222656 4.671875 -5.914062 4.921875 -5.46875 L 4.921875 -6.390625 L 6.546875 -6.390625 L 6.546875 -0.328125 C 6.546875 0.492188 6.410156 1.113281 6.140625 1.53125 C 5.660156 2.25 4.742188 2.609375 3.390625 2.609375 C 2.578125 2.609375 1.910156 2.445312 1.390625 2.125 C 0.878906 1.8125 0.597656 1.335938 0.546875 0.703125 L 2.359375 0.703125 C 2.398438 0.890625 2.472656 1.03125 2.578125 1.125 C 2.765625 1.269531 3.070312 1.34375 3.5 1.34375 C 4.09375 1.34375 4.492188 1.144531 4.703125 0.75 C 4.835938 0.488281 4.90625 0.0507812 4.90625 -0.5625 L 4.90625 -0.96875 C 4.738281 -0.695312 4.566406 -0.492188 4.390625 -0.359375 C 4.054688 -0.0976562 3.625 0.03125 3.09375 0.03125 C 2.269531 0.03125 1.613281 -0.253906 1.125 -0.828125 C 0.632812 -1.410156 0.390625 -2.191406 0.390625 -3.171875 C 0.390625 -4.117188 0.625 -4.914062 1.09375 -5.5625 C 1.570312 -6.21875 2.242188 -6.546875 3.109375 -6.546875 Z M 3.640625 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-7">
+<path style="stroke:none;" d="M 2.484375 0 L 0.8125 0 L 0.8125 -8.640625 L 2.484375 -8.640625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-8">
+<path style="stroke:none;" d="M 3.296875 -5.1875 C 2.910156 -5.1875 2.609375 -5.0625 2.390625 -4.8125 C 2.179688 -4.570312 2.050781 -4.242188 2 -3.828125 L 4.59375 -3.828125 C 4.5625 -4.273438 4.425781 -4.613281 4.1875 -4.84375 C 3.945312 -5.070312 3.648438 -5.1875 3.296875 -5.1875 Z M 3.296875 -6.5625 C 3.828125 -6.5625 4.304688 -6.457031 4.734375 -6.25 C 5.160156 -6.050781 5.515625 -5.738281 5.796875 -5.3125 C 6.046875 -4.9375 6.207031 -4.5 6.28125 -4 C 6.320312 -3.707031 6.335938 -3.285156 6.328125 -2.734375 L 1.953125 -2.734375 C 1.984375 -2.085938 2.1875 -1.640625 2.5625 -1.390625 C 2.789062 -1.222656 3.066406 -1.140625 3.390625 -1.140625 C 3.734375 -1.140625 4.015625 -1.238281 4.234375 -1.4375 C 4.347656 -1.539062 4.453125 -1.6875 4.546875 -1.875 L 6.25 -1.875 C 6.207031 -1.5 6.007812 -1.113281 5.65625 -0.71875 C 5.101562 -0.09375 4.335938 0.21875 3.359375 0.21875 C 2.546875 0.21875 1.828125 -0.0390625 1.203125 -0.5625 C 0.585938 -1.09375 0.28125 -1.945312 0.28125 -3.125 C 0.28125 -4.226562 0.554688 -5.078125 1.109375 -5.671875 C 1.671875 -6.265625 2.398438 -6.5625 3.296875 -6.5625 Z M 3.421875 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-9">
+<path style="stroke:none;" d="M 2.671875 -7.140625 L 2.671875 -5.234375 L 4.78125 -5.234375 C 5.164062 -5.234375 5.472656 -5.300781 5.703125 -5.4375 C 5.941406 -5.582031 6.0625 -5.835938 6.0625 -6.203125 C 6.0625 -6.609375 5.90625 -6.875 5.59375 -7 C 5.320312 -7.09375 4.976562 -7.140625 4.5625 -7.140625 Z M 2.671875 -3.796875 L 2.671875 -1.5 L 4.78125 -1.5 C 5.164062 -1.5 5.460938 -1.550781 5.671875 -1.65625 C 6.054688 -1.84375 6.25 -2.203125 6.25 -2.734375 C 6.25 -3.179688 6.0625 -3.488281 5.6875 -3.65625 C 5.476562 -3.75 5.1875 -3.796875 4.8125 -3.796875 Z M 5.140625 -8.640625 C 6.203125 -8.617188 6.953125 -8.3125 7.390625 -7.71875 C 7.648438 -7.351562 7.78125 -6.914062 7.78125 -6.40625 C 7.78125 -5.875 7.648438 -5.445312 7.390625 -5.125 C 7.242188 -4.945312 7.023438 -4.785156 6.734375 -4.640625 C 7.171875 -4.472656 7.5 -4.21875 7.71875 -3.875 C 7.945312 -3.53125 8.0625 -3.109375 8.0625 -2.609375 C 8.0625 -2.097656 7.9375 -1.640625 7.6875 -1.234375 C 7.519531 -0.960938 7.3125 -0.734375 7.0625 -0.546875 C 6.789062 -0.335938 6.460938 -0.191406 6.078125 -0.109375 C 5.703125 -0.0351562 5.296875 0 4.859375 0 L 0.9375 0 L 0.9375 -8.640625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-10">
+<path style="stroke:none;" d="M 5.78125 -5.890625 C 5.78125 -6.335938 5.660156 -6.65625 5.421875 -6.84375 C 5.179688 -7.039062 4.851562 -7.140625 4.4375 -7.140625 L 2.75 -7.140625 L 2.75 -4.59375 L 4.4375 -4.59375 C 4.851562 -4.59375 5.179688 -4.695312 5.421875 -4.90625 C 5.660156 -5.113281 5.78125 -5.441406 5.78125 -5.890625 Z M 7.5625 -5.90625 C 7.5625 -4.882812 7.300781 -4.160156 6.78125 -3.734375 C 6.269531 -3.316406 5.535156 -3.109375 4.578125 -3.109375 L 2.75 -3.109375 L 2.75 0 L 0.953125 0 L 0.953125 -8.640625 L 4.71875 -8.640625 C 5.582031 -8.640625 6.269531 -8.414062 6.78125 -7.96875 C 7.300781 -7.519531 7.5625 -6.832031 7.5625 -5.90625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-11">
+<path style="stroke:none;" d="M 2.21875 -2.671875 C 2.269531 -2.273438 2.378906 -1.976562 2.546875 -1.78125 C 2.835938 -1.425781 3.335938 -1.25 4.046875 -1.25 C 4.472656 -1.25 4.820312 -1.296875 5.09375 -1.390625 C 5.59375 -1.566406 5.84375 -1.898438 5.84375 -2.390625 C 5.84375 -2.671875 5.71875 -2.890625 5.46875 -3.046875 C 5.21875 -3.203125 4.828125 -3.335938 4.296875 -3.453125 L 3.375 -3.65625 C 2.476562 -3.863281 1.859375 -4.085938 1.515625 -4.328125 C 0.929688 -4.722656 0.640625 -5.34375 0.640625 -6.1875 C 0.640625 -6.96875 0.921875 -7.613281 1.484375 -8.125 C 2.046875 -8.632812 2.875 -8.890625 3.96875 -8.890625 C 4.875 -8.890625 5.644531 -8.644531 6.28125 -8.15625 C 6.925781 -7.675781 7.265625 -6.976562 7.296875 -6.0625 L 5.5625 -6.0625 C 5.53125 -6.582031 5.304688 -6.953125 4.890625 -7.171875 C 4.609375 -7.316406 4.257812 -7.390625 3.84375 -7.390625 C 3.375 -7.390625 3 -7.296875 2.71875 -7.109375 C 2.445312 -6.921875 2.3125 -6.660156 2.3125 -6.328125 C 2.3125 -6.015625 2.445312 -5.78125 2.71875 -5.625 C 2.894531 -5.53125 3.269531 -5.414062 3.84375 -5.28125 L 5.328125 -4.921875 C 5.984375 -4.765625 6.476562 -4.554688 6.8125 -4.296875 C 7.320312 -3.890625 7.578125 -3.300781 7.578125 -2.53125 C 7.578125 -1.738281 7.273438 -1.082031 6.671875 -0.5625 C 6.066406 -0.0390625 5.21875 0.21875 4.125 0.21875 C 3 0.21875 2.113281 -0.0351562 1.46875 -0.546875 C 0.820312 -1.054688 0.5 -1.765625 0.5 -2.671875 Z M 3.96875 -8.90625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-12">
+<path style="stroke:none;" d="M 4.296875 -6.546875 C 4.691406 -6.546875 5.050781 -6.476562 5.375 -6.34375 C 5.695312 -6.207031 5.960938 -6 6.171875 -5.71875 C 6.347656 -5.476562 6.453125 -5.234375 6.484375 -4.984375 C 6.523438 -4.734375 6.546875 -4.320312 6.546875 -3.75 L 6.546875 0 L 4.84375 0 L 4.84375 -3.890625 C 4.84375 -4.234375 4.785156 -4.507812 4.671875 -4.71875 C 4.515625 -5.007812 4.222656 -5.15625 3.796875 -5.15625 C 3.359375 -5.15625 3.023438 -5.007812 2.796875 -4.71875 C 2.566406 -4.425781 2.453125 -4.003906 2.453125 -3.453125 L 2.453125 0 L 0.796875 0 L 0.796875 -8.609375 L 2.453125 -8.609375 L 2.453125 -5.5625 C 2.691406 -5.925781 2.972656 -6.179688 3.296875 -6.328125 C 3.617188 -6.472656 3.953125 -6.546875 4.296875 -6.546875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-13">
+<path style="stroke:none;" d="M 5.1875 -3.1875 C 5.1875 -3.6875 5.070312 -4.125 4.84375 -4.5 C 4.613281 -4.875 4.25 -5.0625 3.75 -5.0625 C 3.144531 -5.0625 2.726562 -4.773438 2.5 -4.203125 C 2.382812 -3.898438 2.328125 -3.515625 2.328125 -3.046875 C 2.328125 -2.304688 2.523438 -1.785156 2.921875 -1.484375 C 3.148438 -1.304688 3.425781 -1.21875 3.75 -1.21875 C 4.21875 -1.21875 4.570312 -1.394531 4.8125 -1.75 C 5.0625 -2.113281 5.1875 -2.59375 5.1875 -3.1875 Z M 4.234375 -6.53125 C 4.972656 -6.53125 5.601562 -6.253906 6.125 -5.703125 C 6.644531 -5.148438 6.90625 -4.34375 6.90625 -3.28125 C 6.90625 -2.15625 6.648438 -1.296875 6.140625 -0.703125 C 5.640625 -0.109375 4.988281 0.1875 4.1875 0.1875 C 3.675781 0.1875 3.253906 0.0546875 2.921875 -0.203125 C 2.742188 -0.335938 2.566406 -0.539062 2.390625 -0.8125 L 2.390625 2.515625 L 0.734375 2.515625 L 0.734375 -6.390625 L 2.328125 -6.390625 L 2.328125 -5.4375 C 2.515625 -5.71875 2.707031 -5.9375 2.90625 -6.09375 C 3.28125 -6.382812 3.722656 -6.53125 4.234375 -6.53125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-14">
+<path style="stroke:none;" d="M 0.421875 -5.03125 L 0.421875 -6.390625 L 5.59375 -6.390625 L 5.59375 -5 L 2.359375 -1.375 L 5.703125 -1.375 L 5.703125 0 L 0.1875 0 L 0.1875 -1.296875 L 3.46875 -5.03125 Z M 3 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-15">
+<path style="stroke:none;" d="M 3.640625 -1.171875 C 4.128906 -1.171875 4.503906 -1.34375 4.765625 -1.6875 C 5.023438 -2.039062 5.15625 -2.539062 5.15625 -3.1875 C 5.15625 -3.820312 5.023438 -4.3125 4.765625 -4.65625 C 4.503906 -5.007812 4.128906 -5.1875 3.640625 -5.1875 C 3.148438 -5.1875 2.773438 -5.007812 2.515625 -4.65625 C 2.253906 -4.3125 2.125 -3.820312 2.125 -3.1875 C 2.125 -2.539062 2.253906 -2.039062 2.515625 -1.6875 C 2.773438 -1.34375 3.148438 -1.171875 3.640625 -1.171875 Z M 6.921875 -3.1875 C 6.921875 -2.25 6.648438 -1.445312 6.109375 -0.78125 C 5.566406 -0.113281 4.75 0.21875 3.65625 0.21875 C 2.550781 0.21875 1.726562 -0.113281 1.1875 -0.78125 C 0.65625 -1.445312 0.390625 -2.25 0.390625 -3.1875 C 0.390625 -4.101562 0.65625 -4.898438 1.1875 -5.578125 C 1.726562 -6.253906 2.550781 -6.59375 3.65625 -6.59375 C 4.75 -6.59375 5.566406 -6.253906 6.109375 -5.578125 C 6.648438 -4.898438 6.921875 -4.101562 6.921875 -3.1875 Z M 3.65625 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-16">
+<path style="stroke:none;" d="M 3.140625 -6.546875 C 3.523438 -6.546875 3.867188 -6.457031 4.171875 -6.28125 C 4.472656 -6.113281 4.71875 -5.878906 4.90625 -5.578125 L 4.90625 -8.625 L 6.59375 -8.625 L 6.59375 0 L 4.96875 0 L 4.96875 -0.890625 C 4.726562 -0.503906 4.457031 -0.222656 4.15625 -0.046875 C 3.851562 0.117188 3.472656 0.203125 3.015625 0.203125 C 2.273438 0.203125 1.648438 -0.0976562 1.140625 -0.703125 C 0.628906 -1.304688 0.375 -2.082031 0.375 -3.03125 C 0.375 -4.125 0.625 -4.984375 1.125 -5.609375 C 1.625 -6.234375 2.296875 -6.546875 3.140625 -6.546875 Z M 3.5 -1.203125 C 3.96875 -1.203125 4.328125 -1.378906 4.578125 -1.734375 C 4.828125 -2.085938 4.953125 -2.539062 4.953125 -3.09375 C 4.953125 -3.875 4.753906 -4.4375 4.359375 -4.78125 C 4.109375 -4.976562 3.828125 -5.078125 3.515625 -5.078125 C 3.023438 -5.078125 2.664062 -4.890625 2.4375 -4.515625 C 2.207031 -4.148438 2.09375 -3.695312 2.09375 -3.15625 C 2.09375 -2.5625 2.207031 -2.085938 2.4375 -1.734375 C 2.675781 -1.378906 3.03125 -1.203125 3.5 -1.203125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-17">
+<path style="stroke:none;" d="M 0.546875 -4.25 C 0.546875 -5.757812 0.945312 -6.921875 1.75 -7.734375 C 2.457031 -8.441406 3.351562 -8.796875 4.4375 -8.796875 C 5.882812 -8.796875 6.945312 -8.320312 7.625 -7.375 C 8 -6.832031 8.195312 -6.296875 8.21875 -5.765625 L 6.421875 -5.765625 C 6.296875 -6.171875 6.144531 -6.484375 5.96875 -6.703125 C 5.632812 -7.078125 5.144531 -7.265625 4.5 -7.265625 C 3.84375 -7.265625 3.328125 -7 2.953125 -6.46875 C 2.578125 -5.9375 2.390625 -5.1875 2.390625 -4.21875 C 2.390625 -3.25 2.585938 -2.519531 2.984375 -2.03125 C 3.390625 -1.550781 3.898438 -1.3125 4.515625 -1.3125 C 5.148438 -1.3125 5.628906 -1.519531 5.953125 -1.9375 C 6.140625 -2.164062 6.296875 -2.5 6.421875 -2.9375 L 8.203125 -2.9375 C 8.046875 -2 7.644531 -1.234375 7 -0.640625 C 6.363281 -0.0546875 5.539062 0.234375 4.53125 0.234375 C 3.289062 0.234375 2.316406 -0.160156 1.609375 -0.953125 C 0.898438 -1.753906 0.546875 -2.851562 0.546875 -4.25 Z M 4.390625 -8.90625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-18">
+<path style="stroke:none;" d="M 2.078125 -2.046875 C 2.117188 -1.742188 2.195312 -1.53125 2.3125 -1.40625 C 2.519531 -1.1875 2.898438 -1.078125 3.453125 -1.078125 C 3.785156 -1.078125 4.046875 -1.125 4.234375 -1.21875 C 4.429688 -1.3125 4.53125 -1.457031 4.53125 -1.65625 C 4.53125 -1.84375 4.453125 -1.988281 4.296875 -2.09375 C 4.140625 -2.1875 3.5625 -2.351562 2.5625 -2.59375 C 1.832031 -2.769531 1.320312 -2.992188 1.03125 -3.265625 C 0.726562 -3.523438 0.578125 -3.90625 0.578125 -4.40625 C 0.578125 -5 0.804688 -5.503906 1.265625 -5.921875 C 1.734375 -6.347656 2.390625 -6.5625 3.234375 -6.5625 C 4.023438 -6.5625 4.671875 -6.398438 5.171875 -6.078125 C 5.679688 -5.765625 5.972656 -5.21875 6.046875 -4.4375 L 4.375 -4.4375 C 4.351562 -4.65625 4.289062 -4.828125 4.1875 -4.953125 C 4.007812 -5.179688 3.695312 -5.296875 3.25 -5.296875 C 2.882812 -5.296875 2.625 -5.238281 2.46875 -5.125 C 2.320312 -5.007812 2.25 -4.875 2.25 -4.71875 C 2.25 -4.53125 2.328125 -4.394531 2.484375 -4.3125 C 2.648438 -4.21875 3.234375 -4.0625 4.234375 -3.84375 C 4.898438 -3.6875 5.394531 -3.453125 5.71875 -3.140625 C 6.050781 -2.816406 6.21875 -2.414062 6.21875 -1.9375 C 6.21875 -1.300781 5.984375 -0.78125 5.515625 -0.375 C 5.046875 0.0195312 4.316406 0.21875 3.328125 0.21875 C 2.328125 0.21875 1.585938 0.00390625 1.109375 -0.421875 C 0.628906 -0.847656 0.390625 -1.390625 0.390625 -2.046875 Z M 3.359375 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-19">
+<path style="stroke:none;" d="M 7.921875 -6.53125 C 8.203125 -6.53125 8.476562 -6.472656 8.75 -6.359375 C 9.019531 -6.253906 9.269531 -6.066406 9.5 -5.796875 C 9.675781 -5.566406 9.796875 -5.289062 9.859375 -4.96875 C 9.898438 -4.75 9.921875 -4.4375 9.921875 -4.03125 L 9.90625 0 L 8.1875 0 L 8.1875 -4.0625 C 8.1875 -4.3125 8.148438 -4.515625 8.078125 -4.671875 C 7.929688 -4.960938 7.65625 -5.109375 7.25 -5.109375 C 6.789062 -5.109375 6.472656 -4.914062 6.296875 -4.53125 C 6.210938 -4.332031 6.171875 -4.085938 6.171875 -3.796875 L 6.171875 0 L 4.484375 0 L 4.484375 -3.796875 C 4.484375 -4.179688 4.441406 -4.457031 4.359375 -4.625 C 4.222656 -4.9375 3.953125 -5.09375 3.546875 -5.09375 C 3.066406 -5.09375 2.742188 -4.9375 2.578125 -4.625 C 2.484375 -4.445312 2.4375 -4.1875 2.4375 -3.84375 L 2.4375 0 L 0.75 0 L 0.75 -6.375 L 2.375 -6.375 L 2.375 -5.4375 C 2.582031 -5.769531 2.773438 -6.007812 2.953125 -6.15625 C 3.285156 -6.40625 3.707031 -6.53125 4.21875 -6.53125 C 4.707031 -6.53125 5.101562 -6.421875 5.40625 -6.203125 C 5.644531 -6.003906 5.828125 -5.75 5.953125 -5.4375 C 6.171875 -5.8125 6.441406 -6.085938 6.765625 -6.265625 C 7.109375 -6.441406 7.492188 -6.53125 7.921875 -6.53125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-20">
+<path style="stroke:none;" d="M 2.671875 -7.140625 L 2.671875 -1.5 L 4.328125 -1.5 C 5.179688 -1.5 5.773438 -1.921875 6.109375 -2.765625 C 6.296875 -3.222656 6.390625 -3.769531 6.390625 -4.40625 C 6.390625 -5.28125 6.25 -5.953125 5.96875 -6.421875 C 5.695312 -6.898438 5.148438 -7.140625 4.328125 -7.140625 Z M 4.640625 -8.640625 C 5.171875 -8.628906 5.613281 -8.566406 5.96875 -8.453125 C 6.570312 -8.253906 7.0625 -7.890625 7.4375 -7.359375 C 7.738281 -6.921875 7.941406 -6.453125 8.046875 -5.953125 C 8.160156 -5.453125 8.21875 -4.976562 8.21875 -4.53125 C 8.21875 -3.382812 7.988281 -2.410156 7.53125 -1.609375 C 6.90625 -0.535156 5.941406 0 4.640625 0 L 0.921875 0 L 0.921875 -8.640625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-21">
+<path style="stroke:none;" d="M 3.140625 -8.71875 C 3.242188 -8.71875 3.335938 -8.710938 3.421875 -8.703125 C 3.503906 -8.703125 3.625 -8.695312 3.78125 -8.6875 L 3.78125 -7.328125 C 3.6875 -7.335938 3.523438 -7.34375 3.296875 -7.34375 C 3.078125 -7.351562 2.925781 -7.304688 2.84375 -7.203125 C 2.757812 -7.109375 2.71875 -7 2.71875 -6.875 C 2.71875 -6.75 2.71875 -6.566406 2.71875 -6.328125 L 3.8125 -6.328125 L 3.8125 -5.15625 L 2.71875 -5.15625 L 2.71875 0 L 1.0625 0 L 1.0625 -5.15625 L 0.125 -5.15625 L 0.125 -6.328125 L 1.03125 -6.328125 L 1.03125 -6.734375 C 1.03125 -7.421875 1.148438 -7.894531 1.390625 -8.15625 C 1.628906 -8.53125 2.210938 -8.71875 3.140625 -8.71875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-22">
+<path style="stroke:none;" d="M 4.59375 -4.09375 C 4.5625 -4.332031 4.484375 -4.546875 4.359375 -4.734375 C 4.171875 -4.992188 3.878906 -5.125 3.484375 -5.125 C 2.921875 -5.125 2.535156 -4.847656 2.328125 -4.296875 C 2.210938 -3.992188 2.15625 -3.597656 2.15625 -3.109375 C 2.15625 -2.640625 2.210938 -2.257812 2.328125 -1.96875 C 2.523438 -1.4375 2.898438 -1.171875 3.453125 -1.171875 C 3.835938 -1.171875 4.113281 -1.273438 4.28125 -1.484375 C 4.445312 -1.703125 4.546875 -1.976562 4.578125 -2.3125 L 6.28125 -2.3125 C 6.25 -1.800781 6.066406 -1.320312 5.734375 -0.875 C 5.210938 -0.144531 4.4375 0.21875 3.40625 0.21875 C 2.382812 0.21875 1.628906 -0.0820312 1.140625 -0.6875 C 0.660156 -1.300781 0.421875 -2.09375 0.421875 -3.0625 C 0.421875 -4.164062 0.6875 -5.019531 1.21875 -5.625 C 1.75 -6.238281 2.488281 -6.546875 3.4375 -6.546875 C 4.238281 -6.546875 4.894531 -6.363281 5.40625 -6 C 5.914062 -5.644531 6.21875 -5.007812 6.3125 -4.09375 Z M 3.46875 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-23">
+<path style="stroke:none;" d="M 2.71875 -7.140625 L 2.71875 -4.8125 L 4.765625 -4.8125 C 5.171875 -4.8125 5.472656 -4.859375 5.671875 -4.953125 C 6.035156 -5.117188 6.21875 -5.445312 6.21875 -5.9375 C 6.21875 -6.457031 6.046875 -6.804688 5.703125 -6.984375 C 5.503906 -7.085938 5.207031 -7.140625 4.8125 -7.140625 Z M 5.1875 -8.640625 C 5.789062 -8.628906 6.253906 -8.550781 6.578125 -8.40625 C 6.910156 -8.269531 7.191406 -8.070312 7.421875 -7.8125 C 7.609375 -7.59375 7.753906 -7.347656 7.859375 -7.078125 C 7.972656 -6.816406 8.03125 -6.515625 8.03125 -6.171875 C 8.03125 -5.765625 7.925781 -5.363281 7.71875 -4.96875 C 7.507812 -4.570312 7.164062 -4.289062 6.6875 -4.125 C 7.09375 -3.96875 7.375 -3.738281 7.53125 -3.4375 C 7.695312 -3.144531 7.78125 -2.695312 7.78125 -2.09375 L 7.78125 -1.515625 C 7.78125 -1.117188 7.796875 -0.847656 7.828125 -0.703125 C 7.878906 -0.484375 7.988281 -0.320312 8.15625 -0.21875 L 8.15625 0 L 6.171875 0 C 6.117188 -0.1875 6.082031 -0.34375 6.0625 -0.46875 C 6.007812 -0.707031 5.984375 -0.953125 5.984375 -1.203125 L 5.96875 -2.015625 C 5.957031 -2.566406 5.851562 -2.929688 5.65625 -3.109375 C 5.46875 -3.296875 5.109375 -3.390625 4.578125 -3.390625 L 2.71875 -3.390625 L 2.71875 0 L 0.953125 0 L 0.953125 -8.640625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-24">
+<path style="stroke:none;" d="M 0.125 -5.140625 L 0.125 -6.328125 L 1.015625 -6.328125 L 1.015625 -8.109375 L 2.671875 -8.109375 L 2.671875 -6.328125 L 3.703125 -6.328125 L 3.703125 -5.140625 L 2.671875 -5.140625 L 2.671875 -1.765625 C 2.671875 -1.503906 2.703125 -1.335938 2.765625 -1.265625 C 2.828125 -1.203125 3.03125 -1.171875 3.375 -1.171875 C 3.425781 -1.171875 3.476562 -1.171875 3.53125 -1.171875 C 3.59375 -1.179688 3.648438 -1.1875 3.703125 -1.1875 L 3.703125 0.0625 L 2.90625 0.09375 C 2.125 0.113281 1.585938 -0.0234375 1.296875 -0.328125 C 1.109375 -0.515625 1.015625 -0.804688 1.015625 -1.203125 L 1.015625 -5.140625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-25">
+<path style="stroke:none;" d="M 6.71875 -5.9375 C 6.582031 -6.53125 6.25 -6.941406 5.71875 -7.171875 C 5.425781 -7.304688 5.097656 -7.375 4.734375 -7.375 C 4.035156 -7.375 3.460938 -7.109375 3.015625 -6.578125 C 2.566406 -6.054688 2.34375 -5.269531 2.34375 -4.21875 C 2.34375 -3.15625 2.582031 -2.398438 3.0625 -1.953125 C 3.550781 -1.515625 4.101562 -1.296875 4.71875 -1.296875 C 5.320312 -1.296875 5.816406 -1.46875 6.203125 -1.8125 C 6.597656 -2.164062 6.835938 -2.625 6.921875 -3.1875 L 4.921875 -3.1875 L 4.921875 -4.640625 L 8.53125 -4.640625 L 8.53125 0 L 7.328125 0 L 7.15625 -1.078125 C 6.800781 -0.671875 6.488281 -0.382812 6.21875 -0.21875 C 5.738281 0.0820312 5.148438 0.234375 4.453125 0.234375 C 3.304688 0.234375 2.367188 -0.164062 1.640625 -0.96875 C 0.878906 -1.757812 0.5 -2.847656 0.5 -4.234375 C 0.5 -5.628906 0.882812 -6.75 1.65625 -7.59375 C 2.425781 -8.4375 3.441406 -8.859375 4.703125 -8.859375 C 5.804688 -8.859375 6.6875 -8.578125 7.34375 -8.015625 C 8.007812 -7.460938 8.394531 -6.769531 8.5 -5.9375 Z M 4.703125 -8.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-26">
+<path style="stroke:none;" d="M 2.4375 -6.390625 L 2.4375 -2.53125 C 2.4375 -2.175781 2.484375 -1.90625 2.578125 -1.71875 C 2.722656 -1.394531 3.019531 -1.234375 3.46875 -1.234375 C 4.039062 -1.234375 4.429688 -1.460938 4.640625 -1.921875 C 4.753906 -2.171875 4.8125 -2.5 4.8125 -2.90625 L 4.8125 -6.390625 L 6.5 -6.390625 L 6.5 0 L 4.875 0 L 4.875 -0.90625 C 4.863281 -0.882812 4.828125 -0.820312 4.765625 -0.71875 C 4.703125 -0.625 4.625 -0.539062 4.53125 -0.46875 C 4.269531 -0.238281 4.015625 -0.0820312 3.765625 0 C 3.523438 0.09375 3.242188 0.140625 2.921875 0.140625 C 1.972656 0.140625 1.335938 -0.195312 1.015625 -0.875 C 0.828125 -1.25 0.734375 -1.800781 0.734375 -2.53125 L 0.734375 -6.390625 Z M 3.609375 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-27">
+<path style="stroke:none;" d="M 0.765625 -8.609375 L 2.40625 -8.609375 L 2.40625 -3.953125 L 4.484375 -6.359375 L 6.546875 -6.359375 L 4.3125 -3.921875 L 6.640625 0 L 4.625 0 L 3.09375 -2.734375 L 2.40625 -2.015625 L 2.40625 0 L 0.765625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-28">
+<path style="stroke:none;" d="M 1.03125 1.21875 L 1.25 1.234375 C 1.414062 1.242188 1.570312 1.238281 1.71875 1.21875 C 1.863281 1.195312 1.988281 1.148438 2.09375 1.078125 C 2.1875 1.015625 2.273438 0.878906 2.359375 0.671875 C 2.441406 0.460938 2.476562 0.332031 2.46875 0.28125 L 0.125 -6.390625 L 1.984375 -6.390625 L 3.375 -1.671875 L 4.6875 -6.390625 L 6.46875 -6.390625 L 4.28125 -0.109375 C 3.851562 1.109375 3.515625 1.859375 3.265625 2.140625 C 3.023438 2.429688 2.535156 2.578125 1.796875 2.578125 C 1.648438 2.578125 1.53125 2.578125 1.4375 2.578125 C 1.351562 2.578125 1.21875 2.570312 1.03125 2.5625 Z M 3.296875 -6.5625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-29">
+<path style="stroke:none;" d="M 4.71875 -6.390625 L 6.515625 -6.390625 L 4.203125 0 L 2.4375 0 L 0.15625 -6.390625 L 2.03125 -6.390625 L 3.359375 -1.671875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-30">
+<path style="stroke:none;" d="M 0.3125 -1.53125 L 4.765625 -7.109375 L 0.421875 -7.109375 L 0.421875 -8.640625 L 7.015625 -8.640625 L 7.015625 -7.1875 L 2.5 -1.53125 L 7.03125 -1.53125 L 7.03125 0 L 0.3125 0 Z M 3.71875 -8.640625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-31">
+<path style="stroke:none;" d="M 0.921875 -8.625 L 7.03125 -8.625 L 7.03125 -7.109375 L 2.703125 -7.109375 L 2.703125 -5.125 L 6.5 -5.125 L 6.5 -3.625 L 2.703125 -3.625 L 2.703125 0 L 0.921875 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph5-32">
+<path style="stroke:none;" d="M 0.921875 -8.640625 L 2.71875 -8.640625 L 2.71875 -1.546875 L 7 -1.546875 L 7 0 L 0.921875 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph6-0">
+<path style="stroke:none;" d="M 0.90625 0 L 0.90625 -20.328125 L 17.046875 -20.328125 L 17.046875 0 Z M 14.5 -2.546875 L 14.5 -17.78125 L 3.453125 -17.78125 L 3.453125 -2.546875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph6-1">
+<path style="stroke:none;" d="M 2.453125 -17.078125 C 2.484375 -18.109375 2.660156 -18.863281 2.984375 -19.34375 C 3.566406 -20.195312 4.691406 -20.625 6.359375 -20.625 C 6.515625 -20.625 6.675781 -20.617188 6.84375 -20.609375 C 7.007812 -20.597656 7.195312 -20.582031 7.40625 -20.5625 L 7.40625 -18.296875 C 7.144531 -18.316406 6.957031 -18.328125 6.84375 -18.328125 C 6.726562 -18.335938 6.617188 -18.34375 6.515625 -18.34375 C 5.765625 -18.34375 5.3125 -18.144531 5.15625 -17.75 C 5.007812 -17.351562 4.9375 -16.351562 4.9375 -14.75 L 7.40625 -14.75 L 7.40625 -12.78125 L 4.90625 -12.78125 L 4.90625 0 L 2.453125 0 L 2.453125 -12.78125 L 0.390625 -12.78125 L 0.390625 -14.75 L 2.453125 -14.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph6-2">
+<path style="stroke:none;" d="M 0.421875 -14.828125 L 3.640625 -14.828125 L 7.046875 -9.609375 L 10.484375 -14.828125 L 13.515625 -14.75 L 8.53125 -7.59375 L 13.75 0 L 10.5625 0 L 6.875 -5.5625 L 3.3125 0 L 0.15625 0 L 5.375 -7.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph6-3">
+<path style="stroke:none;" d="M 1.765625 -20.328125 L 4.171875 -20.328125 L 4.171875 -8.53125 L 10.5625 -14.828125 L 13.75 -14.828125 L 8.0625 -9.265625 L 14.0625 0 L 10.875 0 L 6.25 -7.46875 L 4.171875 -5.5625 L 4.171875 0 L 1.765625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph7-0">
+<path style="stroke:none;" d="M 1.40625 5.015625 L 1.40625 -19.984375 L 15.578125 -19.984375 L 15.578125 5.015625 Z M 3 3.4375 L 14 3.4375 L 14 -18.390625 L 3 -18.390625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph7-1">
+<path style="stroke:none;" d="M 5.671875 -11.328125 C 5.671875 -10.878906 5.5 -10.492188 5.15625 -10.171875 C 4.820312 -9.847656 4.414062 -9.6875 3.9375 -9.6875 C 3.457031 -9.6875 3.050781 -9.847656 2.71875 -10.171875 C 2.382812 -10.492188 2.21875 -10.878906 2.21875 -11.328125 C 2.21875 -11.796875 2.382812 -12.1875 2.71875 -12.5 C 3.050781 -12.820312 3.457031 -12.984375 3.9375 -12.984375 C 4.414062 -12.984375 4.820312 -12.820312 5.15625 -12.5 C 5.5 -12.1875 5.671875 -11.796875 5.671875 -11.328125 Z M 5.671875 -1.328125 C 5.671875 -0.878906 5.5 -0.492188 5.15625 -0.171875 C 4.820312 0.148438 4.414062 0.3125 3.9375 0.3125 C 3.457031 0.3125 3.050781 0.148438 2.71875 -0.171875 C 2.382812 -0.492188 2.21875 -0.878906 2.21875 -1.328125 C 2.21875 -1.785156 2.382812 -2.175781 2.71875 -2.5 C 3.050781 -2.832031 3.457031 -3 3.9375 -3 C 4.414062 -3 4.820312 -2.832031 5.15625 -2.5 C 5.5 -2.175781 5.671875 -1.785156 5.671875 -1.328125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph7-2">
+<path style="stroke:none;" d="M 23.265625 -9.390625 L 17.46875 -11.734375 L 18.09375 -13.171875 L 26.390625 -9.65625 L 26.390625 -7.515625 L 18.09375 -4 L 17.46875 -5.4375 L 23.265625 -7.796875 L 1.59375 -7.796875 L 1.59375 -9.390625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph7-3">
+<path style="stroke:none;" d="M 14.359375 -3.859375 L 1.21875 -3.859375 L 1.21875 -5.78125 L 14.359375 -5.78125 Z M 14.359375 -7.59375 L 1.21875 -7.59375 L 1.21875 -9.515625 L 14.359375 -9.515625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph8-0">
+<path style="stroke:none;" d="M 1.765625 6.265625 L 1.765625 -24.984375 L 19.484375 -24.984375 L 19.484375 6.265625 Z M 3.75 4.296875 L 17.515625 4.296875 L 17.515625 -23 L 3.75 -23 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph8-1">
+<path style="stroke:none;" d="M 10.140625 -24.921875 C 8.191406 -23.140625 6.796875 -21.078125 5.953125 -18.734375 C 5.117188 -16.398438 4.703125 -13.265625 4.703125 -9.328125 C 4.703125 -5.378906 5.117188 -2.242188 5.953125 0.078125 C 6.796875 2.410156 8.191406 4.460938 10.140625 6.234375 L 9.4375 6.96875 C 6.988281 5.1875 5.070312 2.859375 3.6875 -0.015625 C 2.3125 -2.898438 1.625 -6.003906 1.625 -9.328125 C 1.625 -12.648438 2.316406 -15.753906 3.703125 -18.640625 C 5.085938 -21.535156 7 -23.875 9.4375 -25.65625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph8-2">
+<path style="stroke:none;" d="M 1.65625 -24.921875 L 2.34375 -25.65625 C 4.78125 -23.875 6.691406 -21.535156 8.078125 -18.640625 C 9.472656 -15.742188 10.171875 -12.640625 10.171875 -9.328125 C 10.171875 -6.015625 9.472656 -2.914062 8.078125 -0.03125 C 6.691406 2.851562 4.78125 5.1875 2.34375 6.96875 L 1.65625 6.234375 C 3.625 4.472656 5.019531 2.429688 5.84375 0.109375 C 6.675781 -2.210938 7.09375 -5.359375 7.09375 -9.328125 C 7.09375 -13.296875 6.675781 -16.441406 5.84375 -18.765625 C 5.019531 -21.097656 3.625 -23.148438 1.65625 -24.921875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph9-0">
+<path style="stroke:none;" d="M 0.640625 -0.640625 L -13.734375 -15.015625 L -2.328125 -26.421875 L 12.046875 -12.046875 Z M 8.453125 -12.046875 L -2.328125 -22.828125 L -10.140625 -15.015625 L 0.640625 -4.234375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph9-1">
+<path style="stroke:none;" d="M -10.34375 -13.8125 C -11.050781 -14.5625 -11.457031 -15.21875 -11.5625 -15.78125 C -11.75 -16.800781 -11.253906 -17.898438 -10.078125 -19.078125 C -9.972656 -19.179688 -9.859375 -19.289062 -9.734375 -19.40625 C -9.609375 -19.519531 -9.46875 -19.644531 -9.3125 -19.78125 L -7.703125 -18.171875 C -7.898438 -17.992188 -8.039062 -17.867188 -8.125 -17.796875 C -8.207031 -17.722656 -8.285156 -17.648438 -8.359375 -17.578125 C -8.890625 -17.046875 -9.066406 -16.582031 -8.890625 -16.1875 C -8.722656 -15.800781 -8.070312 -15.039062 -6.9375 -13.90625 L -5.1875 -15.65625 L -3.796875 -14.265625 L -5.5625 -12.5 L 3.46875 -3.46875 L 1.734375 -1.734375 L -7.296875 -10.765625 L -8.75 -9.3125 L -10.140625 -10.703125 L -8.6875 -12.15625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph9-2">
+<path style="stroke:none;" d="M -10.1875 -10.78125 L -7.90625 -13.0625 L -1.8125 -11.78125 L -3.078125 -17.890625 L -0.859375 -19.984375 L 0.65625 -11.40625 L 9.71875 -9.71875 L 7.46875 -7.46875 L 0.921875 -8.796875 L 2.34375 -2.34375 L 0.109375 -0.109375 L -1.578125 -9.171875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph9-3">
+<path style="stroke:none;" d="M -5.4375 -16.125 C -4.257812 -17.300781 -3.015625 -17.972656 -1.703125 -18.140625 C -0.390625 -18.304688 1.039062 -17.757812 2.59375 -16.5 L 0.875 -14.78125 C 0.125 -15.320312 -0.644531 -15.617188 -1.4375 -15.671875 C -2.238281 -15.734375 -3.046875 -15.359375 -3.859375 -14.546875 C -4.992188 -13.410156 -5.253906 -12.054688 -4.640625 -10.484375 C -4.242188 -9.460938 -3.519531 -8.425781 -2.46875 -7.375 C -1.425781 -6.332031 -0.320312 -5.675781 0.84375 -5.40625 C 2.007812 -5.132812 3.066406 -5.472656 4.015625 -6.421875 C 4.742188 -7.148438 5.097656 -7.953125 5.078125 -8.828125 C 5.054688 -9.703125 4.734375 -10.609375 4.109375 -11.546875 L 5.828125 -13.265625 C 7.035156 -11.679688 7.566406 -10.175781 7.421875 -8.75 C 7.273438 -7.320312 6.59375 -6 5.375 -4.78125 C 4.007812 -3.414062 2.414062 -2.820312 0.59375 -3 C -1.21875 -3.1875 -2.875 -4.03125 -4.375 -5.53125 C -6.21875 -7.375 -7.203125 -9.253906 -7.328125 -11.171875 C -7.453125 -13.085938 -6.820312 -14.738281 -5.4375 -16.125 Z M -5.671875 -15.796875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph9-4">
+<path style="stroke:none;" d="M -8.328125 -12.640625 L 3.015625 -6.890625 L -2.609375 -18.359375 L -0.671875 -20.296875 L 5.859375 -5.859375 L 3.984375 -3.984375 L -10.375 -10.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph9-5">
+<path style="stroke:none;" d="M -13.125 -15.625 L -11.421875 -17.328125 L -3.078125 -8.984375 L -3.015625 -17.953125 L -0.765625 -20.203125 L -0.84375 -12.25 L 9.9375 -9.9375 L 7.6875 -7.6875 L -0.859375 -9.703125 L -0.984375 -6.890625 L 2.953125 -2.953125 L 1.25 -1.25 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph10-0">
+<path style="stroke:none;" d="M 5.6875 3.1875 L -16.421875 -18.921875 L -3.890625 -31.453125 L 18.21875 -9.34375 Z M 5.6875 0.375 L 15.421875 -9.359375 L -3.875 -28.65625 L -13.609375 -18.921875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph10-1">
+<path style="stroke:none;" d="M -10.453125 -24.796875 C -10.566406 -22.160156 -10.09375 -19.71875 -9.03125 -17.46875 C -7.96875 -15.21875 -6.046875 -12.703125 -3.265625 -9.921875 C -0.472656 -7.128906 2.039062 -5.207031 4.28125 -4.15625 C 6.519531 -3.101562 8.953125 -2.640625 11.578125 -2.765625 L 11.59375 -1.75 C 8.601562 -1.28125 5.601562 -1.578125 2.59375 -2.640625 C -0.414062 -3.703125 -3.09375 -5.40625 -5.4375 -7.75 C -7.789062 -10.101562 -9.5 -12.789062 -10.5625 -15.8125 C -11.625 -18.832031 -11.925781 -21.832031 -11.46875 -24.8125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph10-2">
+<path style="stroke:none;" d="M -16.453125 -18.796875 L -16.484375 -19.796875 C -13.492188 -20.265625 -10.484375 -19.960938 -7.453125 -18.890625 C -4.429688 -17.828125 -1.75 -16.125 0.59375 -13.78125 C 2.9375 -11.4375 4.632812 -8.753906 5.6875 -5.734375 C 6.75 -2.722656 7.046875 0.273438 6.578125 3.265625 L 5.578125 3.234375 C 5.734375 0.597656 5.28125 -1.832031 4.21875 -4.0625 C 3.15625 -6.289062 1.222656 -8.804688 -1.578125 -11.609375 C -4.390625 -14.421875 -6.910156 -16.359375 -9.140625 -17.421875 C -11.367188 -18.484375 -13.804688 -18.941406 -16.453125 -18.796875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph10-3">
+<path style="stroke:none;" d="M -0.625 -31.59375 L 2.984375 -28.734375 L 1.890625 -27.640625 C -0.398438 -28.867188 -2.3125 -29.359375 -3.84375 -29.109375 C -5.382812 -28.867188 -7.125 -27.78125 -9.0625 -25.84375 L -12.359375 -22.546875 L 6.3125 -19.65625 L 7.5625 -1.15625 L 12.234375 -5.828125 C 14.265625 -7.859375 15.441406 -9.554688 15.765625 -10.921875 C 16.085938 -12.285156 15.816406 -13.960938 14.953125 -15.953125 L 16.0625 -17.0625 L 18.5625 -13.0625 L 18.6875 -12.8125 C 19.957031 -10.789062 19.859375 -9.046875 18.390625 -7.578125 L 6.3125 4.5 L 4.875 -16.40625 L -17.40625 -19.90625 L -5.890625 -31.421875 C -4.785156 -32.523438 -3.96875 -33.09375 -3.4375 -33.125 C -2.914062 -33.164062 -1.976562 -32.65625 -0.625 -31.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph11-0">
+<path style="stroke:none;" d="M 4.546875 2.546875 L -13.125 -15.125 L -3.109375 -25.140625 L 14.5625 -7.46875 Z M 4.5625 0.3125 L 12.34375 -7.46875 L -3.09375 -22.90625 L -10.875 -15.125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph11-1">
+<path style="stroke:none;" d="M 7.421875 -12.890625 L -1.875 -3.59375 L -3.234375 -4.953125 L 6.0625 -14.25 Z M 4.78125 -15.53125 L -4.515625 -6.234375 L -5.875 -7.59375 L 3.421875 -16.890625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph11-2">
+<path style="stroke:none;" d="M 0.796875 -11.609375 L 4.734375 -15.546875 L 6.078125 -14.203125 L 2.140625 -10.265625 L 6.203125 -6.203125 L 4.84375 -4.84375 L 0.78125 -8.90625 L -3.171875 -4.953125 L -4.515625 -6.296875 L -0.5625 -10.25 L -4.625 -14.3125 L -3.265625 -15.671875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph12-0">
+<path style="stroke:none;" d="M 0.453125 -0.453125 L -9.609375 -10.515625 L -1.625 -18.5 L 8.4375 -8.4375 Z M 5.921875 -8.453125 L -1.625 -16 L -7.09375 -10.53125 L 0.453125 -2.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph12-1">
+<path style="stroke:none;" d="M -6.390625 -8.203125 L -5.140625 -9.453125 L 2.15625 -2.15625 L 0.90625 -0.90625 Z M -9.15625 -10.96875 L -7.90625 -12.21875 L -6.5 -10.8125 L -7.75 -9.5625 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 223 14.398438 L 223 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 223.933594 152 L 223.933594 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 223.933594 115 L 223.933594 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 223.933594 77 L 223.933594 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 223.933594 40 L 223.933594 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 80 14.398438 L 82 14.398438 L 82 180 L 80 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 119 14.398438 L 120 14.398438 L 120 180 L 119 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 157 14.398438 L 158 14.398438 L 158 180 L 157 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 195 14.398438 L 197 14.398438 L 197 180 L 195 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 223.933594 171 L 223.933594 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 223.933594 133 L 223.933594 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 223.933594 96 L 223.933594 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 223.933594 58 L 223.933594 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 223.933594 21 L 223.933594 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 61 14.398438 L 63 14.398438 L 63 180 L 61 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 99 14.398438 L 101 14.398438 L 101 180 L 99 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 137 14.398438 L 140 14.398438 L 140 180 L 137 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 176 14.398438 L 178 14.398438 L 178 180 L 176 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 214 14.398438 L 216 14.398438 L 216 180 L 214 180 Z "/>
+</clipPath>
+<clipPath id="clip20">
+ <path d="M 237.332031 0 L 475 0 L 475 216 L 237.332031 216 Z "/>
+</clipPath>
+<clipPath id="clip21">
+ <path d="M 237.332031 0 L 475.664062 0 L 475.664062 217 L 237.332031 217 Z "/>
+</clipPath>
+<clipPath id="clip22">
+ <path d="M 291.351562 14.398438 L 461 14.398438 L 461 180 L 291.351562 180 Z "/>
+</clipPath>
+<clipPath id="clip23">
+ <path d="M 291.351562 154 L 461 154 L 461 156 L 291.351562 156 Z "/>
+</clipPath>
+<clipPath id="clip24">
+ <path d="M 291.351562 116 L 461 116 L 461 118 L 291.351562 118 Z "/>
+</clipPath>
+<clipPath id="clip25">
+ <path d="M 291.351562 78 L 461 78 L 461 80 L 291.351562 80 Z "/>
+</clipPath>
+<clipPath id="clip26">
+ <path d="M 291.351562 40 L 461 40 L 461 42 L 291.351562 42 Z "/>
+</clipPath>
+<clipPath id="clip27">
+ <path d="M 317 14.398438 L 319 14.398438 L 319 180 L 317 180 Z "/>
+</clipPath>
+<clipPath id="clip28">
+ <path d="M 356 14.398438 L 357 14.398438 L 357 180 L 356 180 Z "/>
+</clipPath>
+<clipPath id="clip29">
+ <path d="M 394 14.398438 L 396 14.398438 L 396 180 L 394 180 Z "/>
+</clipPath>
+<clipPath id="clip30">
+ <path d="M 433 14.398438 L 434 14.398438 L 434 180 L 433 180 Z "/>
+</clipPath>
+<clipPath id="clip31">
+ <path d="M 291.351562 173 L 461 173 L 461 175 L 291.351562 175 Z "/>
+</clipPath>
+<clipPath id="clip32">
+ <path d="M 291.351562 135 L 461 135 L 461 137 L 291.351562 137 Z "/>
+</clipPath>
+<clipPath id="clip33">
+ <path d="M 291.351562 97 L 461 97 L 461 99 L 291.351562 99 Z "/>
+</clipPath>
+<clipPath id="clip34">
+ <path d="M 291.351562 59 L 461 59 L 461 61 L 291.351562 61 Z "/>
+</clipPath>
+<clipPath id="clip35">
+ <path d="M 291.351562 21 L 461 21 L 461 23 L 291.351562 23 Z "/>
+</clipPath>
+<clipPath id="clip36">
+ <path d="M 298 14.398438 L 300 14.398438 L 300 180 L 298 180 Z "/>
+</clipPath>
+<clipPath id="clip37">
+ <path d="M 336 14.398438 L 338 14.398438 L 338 180 L 336 180 Z "/>
+</clipPath>
+<clipPath id="clip38">
+ <path d="M 375 14.398438 L 377 14.398438 L 377 180 L 375 180 Z "/>
+</clipPath>
+<clipPath id="clip39">
+ <path d="M 413 14.398438 L 415 14.398438 L 415 180 L 413 180 Z "/>
+</clipPath>
+<clipPath id="clip40">
+ <path d="M 452 14.398438 L 454 14.398438 L 454 180 L 452 180 Z "/>
+</clipPath>
+<clipPath id="clip41">
+ <path d="M 474.667969 0 L 712 0 L 712 216 L 474.667969 216 Z "/>
+</clipPath>
+<clipPath id="clip42">
+ <path d="M 474.667969 0 L 712 0 L 712 217 L 474.667969 217 Z "/>
+</clipPath>
+<clipPath id="clip43">
+ <path d="M 528.683594 14.398438 L 698 14.398438 L 698 180 L 528.683594 180 Z "/>
+</clipPath>
+<clipPath id="clip44">
+ <path d="M 528.683594 152 L 698 152 L 698 154 L 528.683594 154 Z "/>
+</clipPath>
+<clipPath id="clip45">
+ <path d="M 528.683594 115 L 698 115 L 698 116 L 528.683594 116 Z "/>
+</clipPath>
+<clipPath id="clip46">
+ <path d="M 528.683594 77 L 698 77 L 698 79 L 528.683594 79 Z "/>
+</clipPath>
+<clipPath id="clip47">
+ <path d="M 528.683594 40 L 698 40 L 698 41 L 528.683594 41 Z "/>
+</clipPath>
+<clipPath id="clip48">
+ <path d="M 555 14.398438 L 556 14.398438 L 556 180 L 555 180 Z "/>
+</clipPath>
+<clipPath id="clip49">
+ <path d="M 593 14.398438 L 595 14.398438 L 595 180 L 593 180 Z "/>
+</clipPath>
+<clipPath id="clip50">
+ <path d="M 632 14.398438 L 633 14.398438 L 633 180 L 632 180 Z "/>
+</clipPath>
+<clipPath id="clip51">
+ <path d="M 670 14.398438 L 671 14.398438 L 671 180 L 670 180 Z "/>
+</clipPath>
+<clipPath id="clip52">
+ <path d="M 528.683594 171 L 698.597656 171 L 698.597656 173 L 528.683594 173 Z "/>
+</clipPath>
+<clipPath id="clip53">
+ <path d="M 528.683594 133 L 698.597656 133 L 698.597656 135 L 528.683594 135 Z "/>
+</clipPath>
+<clipPath id="clip54">
+ <path d="M 528.683594 96 L 698.597656 96 L 698.597656 98 L 528.683594 98 Z "/>
+</clipPath>
+<clipPath id="clip55">
+ <path d="M 528.683594 58 L 698.597656 58 L 698.597656 60 L 528.683594 60 Z "/>
+</clipPath>
+<clipPath id="clip56">
+ <path d="M 528.683594 21 L 698.597656 21 L 698.597656 23 L 528.683594 23 Z "/>
+</clipPath>
+<clipPath id="clip57">
+ <path d="M 535 14.398438 L 537 14.398438 L 537 180 L 535 180 Z "/>
+</clipPath>
+<clipPath id="clip58">
+ <path d="M 574 14.398438 L 576 14.398438 L 576 180 L 574 180 Z "/>
+</clipPath>
+<clipPath id="clip59">
+ <path d="M 612 14.398438 L 614 14.398438 L 614 180 L 612 180 Z "/>
+</clipPath>
+<clipPath id="clip60">
+ <path d="M 651 14.398438 L 653 14.398438 L 653 180 L 651 180 Z "/>
+</clipPath>
+<clipPath id="clip61">
+ <path d="M 689 14.398438 L 691 14.398438 L 691 180 L 689 180 Z "/>
+</clipPath>
+<clipPath id="clip62">
+ <path d="M 0 216 L 238 216 L 238 433 L 0 433 Z "/>
+</clipPath>
+<clipPath id="clip63">
+ <path d="M 54.019531 230.398438 L 223 230.398438 L 223 396 L 54.019531 396 Z "/>
+</clipPath>
+<clipPath id="clip64">
+ <path d="M 54.019531 368 L 223.933594 368 L 223.933594 370 L 54.019531 370 Z "/>
+</clipPath>
+<clipPath id="clip65">
+ <path d="M 54.019531 331 L 223.933594 331 L 223.933594 332 L 54.019531 332 Z "/>
+</clipPath>
+<clipPath id="clip66">
+ <path d="M 54.019531 293 L 223.933594 293 L 223.933594 295 L 54.019531 295 Z "/>
+</clipPath>
+<clipPath id="clip67">
+ <path d="M 54.019531 256 L 223.933594 256 L 223.933594 257 L 54.019531 257 Z "/>
+</clipPath>
+<clipPath id="clip68">
+ <path d="M 80 230.398438 L 82 230.398438 L 82 396 L 80 396 Z "/>
+</clipPath>
+<clipPath id="clip69">
+ <path d="M 119 230.398438 L 120 230.398438 L 120 396 L 119 396 Z "/>
+</clipPath>
+<clipPath id="clip70">
+ <path d="M 157 230.398438 L 158 230.398438 L 158 396 L 157 396 Z "/>
+</clipPath>
+<clipPath id="clip71">
+ <path d="M 195 230.398438 L 197 230.398438 L 197 396 L 195 396 Z "/>
+</clipPath>
+<clipPath id="clip72">
+ <path d="M 54.019531 387 L 223.933594 387 L 223.933594 389 L 54.019531 389 Z "/>
+</clipPath>
+<clipPath id="clip73">
+ <path d="M 54.019531 349 L 223.933594 349 L 223.933594 351 L 54.019531 351 Z "/>
+</clipPath>
+<clipPath id="clip74">
+ <path d="M 54.019531 312 L 223.933594 312 L 223.933594 314 L 54.019531 314 Z "/>
+</clipPath>
+<clipPath id="clip75">
+ <path d="M 54.019531 274 L 223.933594 274 L 223.933594 276 L 54.019531 276 Z "/>
+</clipPath>
+<clipPath id="clip76">
+ <path d="M 54.019531 237 L 223.933594 237 L 223.933594 239 L 54.019531 239 Z "/>
+</clipPath>
+<clipPath id="clip77">
+ <path d="M 61 230.398438 L 63 230.398438 L 63 396 L 61 396 Z "/>
+</clipPath>
+<clipPath id="clip78">
+ <path d="M 99 230.398438 L 101 230.398438 L 101 396 L 99 396 Z "/>
+</clipPath>
+<clipPath id="clip79">
+ <path d="M 137 230.398438 L 140 230.398438 L 140 396 L 137 396 Z "/>
+</clipPath>
+<clipPath id="clip80">
+ <path d="M 176 230.398438 L 178 230.398438 L 178 396 L 176 396 Z "/>
+</clipPath>
+<clipPath id="clip81">
+ <path d="M 214 230.398438 L 216 230.398438 L 216 396 L 214 396 Z "/>
+</clipPath>
+<clipPath id="clip82">
+ <path d="M 237.332031 216 L 475 216 L 475 432 L 237.332031 432 Z "/>
+</clipPath>
+<clipPath id="clip83">
+ <path d="M 237.332031 216 L 475.664062 216 L 475.664062 433 L 237.332031 433 Z "/>
+</clipPath>
+<clipPath id="clip84">
+ <path d="M 291.351562 230.398438 L 461 230.398438 L 461 396 L 291.351562 396 Z "/>
+</clipPath>
+<clipPath id="clip85">
+ <path d="M 291.351562 368 L 461 368 L 461 370 L 291.351562 370 Z "/>
+</clipPath>
+<clipPath id="clip86">
+ <path d="M 291.351562 331 L 461 331 L 461 332 L 291.351562 332 Z "/>
+</clipPath>
+<clipPath id="clip87">
+ <path d="M 291.351562 293 L 461 293 L 461 295 L 291.351562 295 Z "/>
+</clipPath>
+<clipPath id="clip88">
+ <path d="M 291.351562 256 L 461 256 L 461 257 L 291.351562 257 Z "/>
+</clipPath>
+<clipPath id="clip89">
+ <path d="M 317 230.398438 L 319 230.398438 L 319 396 L 317 396 Z "/>
+</clipPath>
+<clipPath id="clip90">
+ <path d="M 356 230.398438 L 357 230.398438 L 357 396 L 356 396 Z "/>
+</clipPath>
+<clipPath id="clip91">
+ <path d="M 394 230.398438 L 396 230.398438 L 396 396 L 394 396 Z "/>
+</clipPath>
+<clipPath id="clip92">
+ <path d="M 433 230.398438 L 434 230.398438 L 434 396 L 433 396 Z "/>
+</clipPath>
+<clipPath id="clip93">
+ <path d="M 291.351562 387 L 461 387 L 461 389 L 291.351562 389 Z "/>
+</clipPath>
+<clipPath id="clip94">
+ <path d="M 291.351562 349 L 461 349 L 461 351 L 291.351562 351 Z "/>
+</clipPath>
+<clipPath id="clip95">
+ <path d="M 291.351562 312 L 461 312 L 461 314 L 291.351562 314 Z "/>
+</clipPath>
+<clipPath id="clip96">
+ <path d="M 291.351562 274 L 461 274 L 461 276 L 291.351562 276 Z "/>
+</clipPath>
+<clipPath id="clip97">
+ <path d="M 291.351562 237 L 461 237 L 461 239 L 291.351562 239 Z "/>
+</clipPath>
+<clipPath id="clip98">
+ <path d="M 298 230.398438 L 300 230.398438 L 300 396 L 298 396 Z "/>
+</clipPath>
+<clipPath id="clip99">
+ <path d="M 336 230.398438 L 338 230.398438 L 338 396 L 336 396 Z "/>
+</clipPath>
+<clipPath id="clip100">
+ <path d="M 375 230.398438 L 377 230.398438 L 377 396 L 375 396 Z "/>
+</clipPath>
+<clipPath id="clip101">
+ <path d="M 413 230.398438 L 415 230.398438 L 415 396 L 413 396 Z "/>
+</clipPath>
+<clipPath id="clip102">
+ <path d="M 452 230.398438 L 454 230.398438 L 454 396 L 452 396 Z "/>
+</clipPath>
+<clipPath id="clip103">
+ <path d="M 474.667969 216 L 712 216 L 712 432 L 474.667969 432 Z "/>
+</clipPath>
+<clipPath id="clip104">
+ <path d="M 474.667969 216 L 712 216 L 712 433 L 474.667969 433 Z "/>
+</clipPath>
+<clipPath id="clip105">
+ <path d="M 528.683594 230.398438 L 698 230.398438 L 698 396 L 528.683594 396 Z "/>
+</clipPath>
+<clipPath id="clip106">
+ <path d="M 528.683594 369 L 698 369 L 698 370 L 528.683594 370 Z "/>
+</clipPath>
+<clipPath id="clip107">
+ <path d="M 528.683594 331 L 698 331 L 698 332 L 528.683594 332 Z "/>
+</clipPath>
+<clipPath id="clip108">
+ <path d="M 528.683594 292 L 698 292 L 698 294 L 528.683594 294 Z "/>
+</clipPath>
+<clipPath id="clip109">
+ <path d="M 528.683594 254 L 698 254 L 698 256 L 528.683594 256 Z "/>
+</clipPath>
+<clipPath id="clip110">
+ <path d="M 555 230.398438 L 556 230.398438 L 556 396 L 555 396 Z "/>
+</clipPath>
+<clipPath id="clip111">
+ <path d="M 593 230.398438 L 595 230.398438 L 595 396 L 593 396 Z "/>
+</clipPath>
+<clipPath id="clip112">
+ <path d="M 632 230.398438 L 633 230.398438 L 633 396 L 632 396 Z "/>
+</clipPath>
+<clipPath id="clip113">
+ <path d="M 670 230.398438 L 671 230.398438 L 671 396 L 670 396 Z "/>
+</clipPath>
+<clipPath id="clip114">
+ <path d="M 528.683594 388 L 698.597656 388 L 698.597656 390 L 528.683594 390 Z "/>
+</clipPath>
+<clipPath id="clip115">
+ <path d="M 528.683594 349 L 698.597656 349 L 698.597656 351 L 528.683594 351 Z "/>
+</clipPath>
+<clipPath id="clip116">
+ <path d="M 528.683594 311 L 698.597656 311 L 698.597656 313 L 528.683594 313 Z "/>
+</clipPath>
+<clipPath id="clip117">
+ <path d="M 528.683594 273 L 698.597656 273 L 698.597656 275 L 528.683594 275 Z "/>
+</clipPath>
+<clipPath id="clip118">
+ <path d="M 528.683594 235 L 698.597656 235 L 698.597656 237 L 528.683594 237 Z "/>
+</clipPath>
+<clipPath id="clip119">
+ <path d="M 535 230.398438 L 537 230.398438 L 537 396 L 535 396 Z "/>
+</clipPath>
+<clipPath id="clip120">
+ <path d="M 574 230.398438 L 576 230.398438 L 576 396 L 574 396 Z "/>
+</clipPath>
+<clipPath id="clip121">
+ <path d="M 612 230.398438 L 614 230.398438 L 614 396 L 612 396 Z "/>
+</clipPath>
+<clipPath id="clip122">
+ <path d="M 651 230.398438 L 653 230.398438 L 653 396 L 651 396 Z "/>
+</clipPath>
+<clipPath id="clip123">
+ <path d="M 689 230.398438 L 691 230.398438 L 691 396 L 689 396 Z "/>
+</clipPath>
+<clipPath id="clip124">
+ <path d="M 0 432 L 238 432 L 238 649 L 0 649 Z "/>
+</clipPath>
+<clipPath id="clip125">
+ <path d="M 54.019531 446.398438 L 223 446.398438 L 223 612 L 54.019531 612 Z "/>
+</clipPath>
+<clipPath id="clip126">
+ <path d="M 54.019531 584 L 223.933594 584 L 223.933594 586 L 54.019531 586 Z "/>
+</clipPath>
+<clipPath id="clip127">
+ <path d="M 54.019531 547 L 223.933594 547 L 223.933594 548 L 54.019531 548 Z "/>
+</clipPath>
+<clipPath id="clip128">
+ <path d="M 54.019531 509 L 223.933594 509 L 223.933594 511 L 54.019531 511 Z "/>
+</clipPath>
+<clipPath id="clip129">
+ <path d="M 54.019531 472 L 223.933594 472 L 223.933594 473 L 54.019531 473 Z "/>
+</clipPath>
+<clipPath id="clip130">
+ <path d="M 80 446.398438 L 82 446.398438 L 82 612 L 80 612 Z "/>
+</clipPath>
+<clipPath id="clip131">
+ <path d="M 119 446.398438 L 120 446.398438 L 120 612 L 119 612 Z "/>
+</clipPath>
+<clipPath id="clip132">
+ <path d="M 157 446.398438 L 158 446.398438 L 158 612 L 157 612 Z "/>
+</clipPath>
+<clipPath id="clip133">
+ <path d="M 195 446.398438 L 197 446.398438 L 197 612 L 195 612 Z "/>
+</clipPath>
+<clipPath id="clip134">
+ <path d="M 54.019531 603 L 223.933594 603 L 223.933594 605 L 54.019531 605 Z "/>
+</clipPath>
+<clipPath id="clip135">
+ <path d="M 54.019531 565 L 223.933594 565 L 223.933594 567 L 54.019531 567 Z "/>
+</clipPath>
+<clipPath id="clip136">
+ <path d="M 54.019531 528 L 223.933594 528 L 223.933594 530 L 54.019531 530 Z "/>
+</clipPath>
+<clipPath id="clip137">
+ <path d="M 54.019531 490 L 223.933594 490 L 223.933594 492 L 54.019531 492 Z "/>
+</clipPath>
+<clipPath id="clip138">
+ <path d="M 54.019531 453 L 223.933594 453 L 223.933594 455 L 54.019531 455 Z "/>
+</clipPath>
+<clipPath id="clip139">
+ <path d="M 61 446.398438 L 63 446.398438 L 63 612 L 61 612 Z "/>
+</clipPath>
+<clipPath id="clip140">
+ <path d="M 99 446.398438 L 101 446.398438 L 101 612 L 99 612 Z "/>
+</clipPath>
+<clipPath id="clip141">
+ <path d="M 137 446.398438 L 140 446.398438 L 140 612 L 137 612 Z "/>
+</clipPath>
+<clipPath id="clip142">
+ <path d="M 176 446.398438 L 178 446.398438 L 178 612 L 176 612 Z "/>
+</clipPath>
+<clipPath id="clip143">
+ <path d="M 214 446.398438 L 216 446.398438 L 216 612 L 214 612 Z "/>
+</clipPath>
+<clipPath id="clip144">
+ <path d="M 237.332031 432 L 475 432 L 475 648 L 237.332031 648 Z "/>
+</clipPath>
+<clipPath id="clip145">
+ <path d="M 237.332031 432 L 475.664062 432 L 475.664062 649 L 237.332031 649 Z "/>
+</clipPath>
+<clipPath id="clip146">
+ <path d="M 291.351562 446.398438 L 461 446.398438 L 461 612 L 291.351562 612 Z "/>
+</clipPath>
+<clipPath id="clip147">
+ <path d="M 291.351562 590 L 461 590 L 461 592 L 291.351562 592 Z "/>
+</clipPath>
+<clipPath id="clip148">
+ <path d="M 291.351562 551 L 461 551 L 461 552 L 291.351562 552 Z "/>
+</clipPath>
+<clipPath id="clip149">
+ <path d="M 291.351562 512 L 461 512 L 461 513 L 291.351562 513 Z "/>
+</clipPath>
+<clipPath id="clip150">
+ <path d="M 291.351562 473 L 461 473 L 461 474 L 291.351562 474 Z "/>
+</clipPath>
+<clipPath id="clip151">
+ <path d="M 317 446.398438 L 319 446.398438 L 319 612 L 317 612 Z "/>
+</clipPath>
+<clipPath id="clip152">
+ <path d="M 356 446.398438 L 357 446.398438 L 357 612 L 356 612 Z "/>
+</clipPath>
+<clipPath id="clip153">
+ <path d="M 394 446.398438 L 396 446.398438 L 396 612 L 394 612 Z "/>
+</clipPath>
+<clipPath id="clip154">
+ <path d="M 433 446.398438 L 434 446.398438 L 434 612 L 433 612 Z "/>
+</clipPath>
+<clipPath id="clip155">
+ <path d="M 291.351562 609 L 461 609 L 461 611 L 291.351562 611 Z "/>
+</clipPath>
+<clipPath id="clip156">
+ <path d="M 291.351562 570 L 461 570 L 461 572 L 291.351562 572 Z "/>
+</clipPath>
+<clipPath id="clip157">
+ <path d="M 291.351562 531 L 461 531 L 461 533 L 291.351562 533 Z "/>
+</clipPath>
+<clipPath id="clip158">
+ <path d="M 291.351562 492 L 461 492 L 461 494 L 291.351562 494 Z "/>
+</clipPath>
+<clipPath id="clip159">
+ <path d="M 291.351562 453 L 461 453 L 461 455 L 291.351562 455 Z "/>
+</clipPath>
+<clipPath id="clip160">
+ <path d="M 298 446.398438 L 300 446.398438 L 300 612 L 298 612 Z "/>
+</clipPath>
+<clipPath id="clip161">
+ <path d="M 336 446.398438 L 338 446.398438 L 338 612 L 336 612 Z "/>
+</clipPath>
+<clipPath id="clip162">
+ <path d="M 375 446.398438 L 377 446.398438 L 377 612 L 375 612 Z "/>
+</clipPath>
+<clipPath id="clip163">
+ <path d="M 413 446.398438 L 415 446.398438 L 415 612 L 413 612 Z "/>
+</clipPath>
+<clipPath id="clip164">
+ <path d="M 452 446.398438 L 454 446.398438 L 454 612 L 452 612 Z "/>
+</clipPath>
+<clipPath id="clip165">
+ <path d="M 474.667969 432 L 712 432 L 712 648 L 474.667969 648 Z "/>
+</clipPath>
+<clipPath id="clip166">
+ <path d="M 474.667969 432 L 712 432 L 712 649 L 474.667969 649 Z "/>
+</clipPath>
+<clipPath id="clip167">
+ <path d="M 528.683594 446.398438 L 698 446.398438 L 698 612 L 528.683594 612 Z "/>
+</clipPath>
+<clipPath id="clip168">
+ <path d="M 528.683594 598 L 698 598 L 698 600 L 528.683594 600 Z "/>
+</clipPath>
+<clipPath id="clip169">
+ <path d="M 528.683594 560 L 698 560 L 698 561 L 528.683594 561 Z "/>
+</clipPath>
+<clipPath id="clip170">
+ <path d="M 528.683594 521 L 698 521 L 698 523 L 528.683594 523 Z "/>
+</clipPath>
+<clipPath id="clip171">
+ <path d="M 528.683594 483 L 698 483 L 698 484 L 528.683594 484 Z "/>
+</clipPath>
+<clipPath id="clip172">
+ <path d="M 555 446.398438 L 556 446.398438 L 556 612 L 555 612 Z "/>
+</clipPath>
+<clipPath id="clip173">
+ <path d="M 593 446.398438 L 595 446.398438 L 595 612 L 593 612 Z "/>
+</clipPath>
+<clipPath id="clip174">
+ <path d="M 632 446.398438 L 633 446.398438 L 633 612 L 632 612 Z "/>
+</clipPath>
+<clipPath id="clip175">
+ <path d="M 670 446.398438 L 671 446.398438 L 671 612 L 670 612 Z "/>
+</clipPath>
+<clipPath id="clip176">
+ <path d="M 528.683594 579 L 698.597656 579 L 698.597656 581 L 528.683594 581 Z "/>
+</clipPath>
+<clipPath id="clip177">
+ <path d="M 528.683594 540 L 698.597656 540 L 698.597656 542 L 528.683594 542 Z "/>
+</clipPath>
+<clipPath id="clip178">
+ <path d="M 528.683594 502 L 698.597656 502 L 698.597656 504 L 528.683594 504 Z "/>
+</clipPath>
+<clipPath id="clip179">
+ <path d="M 528.683594 463 L 698.597656 463 L 698.597656 465 L 528.683594 465 Z "/>
+</clipPath>
+<clipPath id="clip180">
+ <path d="M 535 446.398438 L 537 446.398438 L 537 612 L 535 612 Z "/>
+</clipPath>
+<clipPath id="clip181">
+ <path d="M 574 446.398438 L 576 446.398438 L 576 612 L 574 612 Z "/>
+</clipPath>
+<clipPath id="clip182">
+ <path d="M 612 446.398438 L 614 446.398438 L 614 612 L 612 612 Z "/>
+</clipPath>
+<clipPath id="clip183">
+ <path d="M 651 446.398438 L 653 446.398438 L 653 612 L 651 612 Z "/>
+</clipPath>
+<clipPath id="clip184">
+ <path d="M 689 446.398438 L 691 446.398438 L 691 612 L 689 612 Z "/>
+</clipPath>
+<clipPath id="clip185">
+ <path d="M 0 648 L 238 648 L 238 865 L 0 865 Z "/>
+</clipPath>
+<clipPath id="clip186">
+ <path d="M 54.019531 662.398438 L 223 662.398438 L 223 828 L 54.019531 828 Z "/>
+</clipPath>
+<clipPath id="clip187">
+ <path d="M 54.019531 800 L 223.933594 800 L 223.933594 801 L 54.019531 801 Z "/>
+</clipPath>
+<clipPath id="clip188">
+ <path d="M 54.019531 762 L 223.933594 762 L 223.933594 763 L 54.019531 763 Z "/>
+</clipPath>
+<clipPath id="clip189">
+ <path d="M 54.019531 724 L 223.933594 724 L 223.933594 725 L 54.019531 725 Z "/>
+</clipPath>
+<clipPath id="clip190">
+ <path d="M 54.019531 686 L 223.933594 686 L 223.933594 687 L 54.019531 687 Z "/>
+</clipPath>
+<clipPath id="clip191">
+ <path d="M 80 662.398438 L 82 662.398438 L 82 828 L 80 828 Z "/>
+</clipPath>
+<clipPath id="clip192">
+ <path d="M 119 662.398438 L 120 662.398438 L 120 828 L 119 828 Z "/>
+</clipPath>
+<clipPath id="clip193">
+ <path d="M 157 662.398438 L 158 662.398438 L 158 828 L 157 828 Z "/>
+</clipPath>
+<clipPath id="clip194">
+ <path d="M 195 662.398438 L 197 662.398438 L 197 828 L 195 828 Z "/>
+</clipPath>
+<clipPath id="clip195">
+ <path d="M 54.019531 819 L 223.933594 819 L 223.933594 821 L 54.019531 821 Z "/>
+</clipPath>
+<clipPath id="clip196">
+ <path d="M 54.019531 780 L 223.933594 780 L 223.933594 783 L 54.019531 783 Z "/>
+</clipPath>
+<clipPath id="clip197">
+ <path d="M 54.019531 742 L 223.933594 742 L 223.933594 744 L 54.019531 744 Z "/>
+</clipPath>
+<clipPath id="clip198">
+ <path d="M 54.019531 704 L 223.933594 704 L 223.933594 706 L 54.019531 706 Z "/>
+</clipPath>
+<clipPath id="clip199">
+ <path d="M 54.019531 666 L 223.933594 666 L 223.933594 668 L 54.019531 668 Z "/>
+</clipPath>
+<clipPath id="clip200">
+ <path d="M 61 662.398438 L 63 662.398438 L 63 828 L 61 828 Z "/>
+</clipPath>
+<clipPath id="clip201">
+ <path d="M 99 662.398438 L 101 662.398438 L 101 828 L 99 828 Z "/>
+</clipPath>
+<clipPath id="clip202">
+ <path d="M 137 662.398438 L 140 662.398438 L 140 828 L 137 828 Z "/>
+</clipPath>
+<clipPath id="clip203">
+ <path d="M 176 662.398438 L 178 662.398438 L 178 828 L 176 828 Z "/>
+</clipPath>
+<clipPath id="clip204">
+ <path d="M 214 662.398438 L 216 662.398438 L 216 828 L 214 828 Z "/>
+</clipPath>
+<clipPath id="clip205">
+ <path d="M 237.332031 648 L 475 648 L 475 864 L 237.332031 864 Z "/>
+</clipPath>
+<clipPath id="clip206">
+ <path d="M 237.332031 648 L 475.664062 648 L 475.664062 865 L 237.332031 865 Z "/>
+</clipPath>
+<clipPath id="clip207">
+ <path d="M 291.351562 662.398438 L 461 662.398438 L 461 828 L 291.351562 828 Z "/>
+</clipPath>
+<clipPath id="clip208">
+ <path d="M 291.351562 801 L 461 801 L 461 803 L 291.351562 803 Z "/>
+</clipPath>
+<clipPath id="clip209">
+ <path d="M 291.351562 762 L 461 762 L 461 764 L 291.351562 764 Z "/>
+</clipPath>
+<clipPath id="clip210">
+ <path d="M 291.351562 723 L 461 723 L 461 725 L 291.351562 725 Z "/>
+</clipPath>
+<clipPath id="clip211">
+ <path d="M 291.351562 684 L 461 684 L 461 686 L 291.351562 686 Z "/>
+</clipPath>
+<clipPath id="clip212">
+ <path d="M 317 662.398438 L 319 662.398438 L 319 828 L 317 828 Z "/>
+</clipPath>
+<clipPath id="clip213">
+ <path d="M 356 662.398438 L 357 662.398438 L 357 828 L 356 828 Z "/>
+</clipPath>
+<clipPath id="clip214">
+ <path d="M 394 662.398438 L 396 662.398438 L 396 828 L 394 828 Z "/>
+</clipPath>
+<clipPath id="clip215">
+ <path d="M 433 662.398438 L 434 662.398438 L 434 828 L 433 828 Z "/>
+</clipPath>
+<clipPath id="clip216">
+ <path d="M 291.351562 821 L 461 821 L 461 823 L 291.351562 823 Z "/>
+</clipPath>
+<clipPath id="clip217">
+ <path d="M 291.351562 782 L 461 782 L 461 784 L 291.351562 784 Z "/>
+</clipPath>
+<clipPath id="clip218">
+ <path d="M 291.351562 743 L 461 743 L 461 745 L 291.351562 745 Z "/>
+</clipPath>
+<clipPath id="clip219">
+ <path d="M 291.351562 704 L 461 704 L 461 706 L 291.351562 706 Z "/>
+</clipPath>
+<clipPath id="clip220">
+ <path d="M 291.351562 665 L 461 665 L 461 667 L 291.351562 667 Z "/>
+</clipPath>
+<clipPath id="clip221">
+ <path d="M 298 662.398438 L 300 662.398438 L 300 828 L 298 828 Z "/>
+</clipPath>
+<clipPath id="clip222">
+ <path d="M 336 662.398438 L 338 662.398438 L 338 828 L 336 828 Z "/>
+</clipPath>
+<clipPath id="clip223">
+ <path d="M 375 662.398438 L 377 662.398438 L 377 828 L 375 828 Z "/>
+</clipPath>
+<clipPath id="clip224">
+ <path d="M 413 662.398438 L 415 662.398438 L 415 828 L 413 828 Z "/>
+</clipPath>
+<clipPath id="clip225">
+ <path d="M 452 662.398438 L 454 662.398438 L 454 828 L 452 828 Z "/>
+</clipPath>
+<clipPath id="clip226">
+ <path d="M 474.667969 648 L 712 648 L 712 864 L 474.667969 864 Z "/>
+</clipPath>
+<clipPath id="clip227">
+ <path d="M 474.667969 648 L 712 648 L 712 865 L 474.667969 865 Z "/>
+</clipPath>
+<clipPath id="clip228">
+ <path d="M 528.683594 662.398438 L 698 662.398438 L 698 828 L 528.683594 828 Z "/>
+</clipPath>
+<clipPath id="clip229">
+ <path d="M 528.683594 801 L 698 801 L 698 802 L 528.683594 802 Z "/>
+</clipPath>
+<clipPath id="clip230">
+ <path d="M 528.683594 763 L 698 763 L 698 764 L 528.683594 764 Z "/>
+</clipPath>
+<clipPath id="clip231">
+ <path d="M 528.683594 725 L 698 725 L 698 726 L 528.683594 726 Z "/>
+</clipPath>
+<clipPath id="clip232">
+ <path d="M 528.683594 687 L 698 687 L 698 688 L 528.683594 688 Z "/>
+</clipPath>
+<clipPath id="clip233">
+ <path d="M 555 662.398438 L 556 662.398438 L 556 828 L 555 828 Z "/>
+</clipPath>
+<clipPath id="clip234">
+ <path d="M 593 662.398438 L 595 662.398438 L 595 828 L 593 828 Z "/>
+</clipPath>
+<clipPath id="clip235">
+ <path d="M 632 662.398438 L 633 662.398438 L 633 828 L 632 828 Z "/>
+</clipPath>
+<clipPath id="clip236">
+ <path d="M 670 662.398438 L 671 662.398438 L 671 828 L 670 828 Z "/>
+</clipPath>
+<clipPath id="clip237">
+ <path d="M 528.683594 820 L 698.597656 820 L 698.597656 822 L 528.683594 822 Z "/>
+</clipPath>
+<clipPath id="clip238">
+ <path d="M 528.683594 781 L 698.597656 781 L 698.597656 784 L 528.683594 784 Z "/>
+</clipPath>
+<clipPath id="clip239">
+ <path d="M 528.683594 743 L 698.597656 743 L 698.597656 745 L 528.683594 745 Z "/>
+</clipPath>
+<clipPath id="clip240">
+ <path d="M 528.683594 705 L 698.597656 705 L 698.597656 707 L 528.683594 707 Z "/>
+</clipPath>
+<clipPath id="clip241">
+ <path d="M 528.683594 667 L 698.597656 667 L 698.597656 669 L 528.683594 669 Z "/>
+</clipPath>
+<clipPath id="clip242">
+ <path d="M 535 662.398438 L 537 662.398438 L 537 828 L 535 828 Z "/>
+</clipPath>
+<clipPath id="clip243">
+ <path d="M 574 662.398438 L 576 662.398438 L 576 828 L 574 828 Z "/>
+</clipPath>
+<clipPath id="clip244">
+ <path d="M 612 662.398438 L 614 662.398438 L 614 828 L 612 828 Z "/>
+</clipPath>
+<clipPath id="clip245">
+ <path d="M 651 662.398438 L 653 662.398438 L 653 828 L 651 828 Z "/>
+</clipPath>
+<clipPath id="clip246">
+ <path d="M 689 662.398438 L 691 662.398438 L 691 828 L 689 828 Z "/>
+</clipPath>
+<clipPath id="clip247">
+ <path d="M 0 864 L 238 864 L 238 1081 L 0 1081 Z "/>
+</clipPath>
+<clipPath id="clip248">
+ <path d="M 54.019531 878.398438 L 223 878.398438 L 223 1044 L 54.019531 1044 Z "/>
+</clipPath>
+<clipPath id="clip249">
+ <path d="M 54.019531 1016 L 223.933594 1016 L 223.933594 1018 L 54.019531 1018 Z "/>
+</clipPath>
+<clipPath id="clip250">
+ <path d="M 54.019531 979 L 223.933594 979 L 223.933594 980 L 54.019531 980 Z "/>
+</clipPath>
+<clipPath id="clip251">
+ <path d="M 54.019531 941 L 223.933594 941 L 223.933594 943 L 54.019531 943 Z "/>
+</clipPath>
+<clipPath id="clip252">
+ <path d="M 54.019531 904 L 223.933594 904 L 223.933594 905 L 54.019531 905 Z "/>
+</clipPath>
+<clipPath id="clip253">
+ <path d="M 80 878.398438 L 82 878.398438 L 82 1044 L 80 1044 Z "/>
+</clipPath>
+<clipPath id="clip254">
+ <path d="M 119 878.398438 L 120 878.398438 L 120 1044 L 119 1044 Z "/>
+</clipPath>
+<clipPath id="clip255">
+ <path d="M 157 878.398438 L 158 878.398438 L 158 1044 L 157 1044 Z "/>
+</clipPath>
+<clipPath id="clip256">
+ <path d="M 195 878.398438 L 197 878.398438 L 197 1044 L 195 1044 Z "/>
+</clipPath>
+<clipPath id="clip257">
+ <path d="M 54.019531 1035 L 223.933594 1035 L 223.933594 1037 L 54.019531 1037 Z "/>
+</clipPath>
+<clipPath id="clip258">
+ <path d="M 54.019531 997 L 223.933594 997 L 223.933594 999 L 54.019531 999 Z "/>
+</clipPath>
+<clipPath id="clip259">
+ <path d="M 54.019531 960 L 223.933594 960 L 223.933594 962 L 54.019531 962 Z "/>
+</clipPath>
+<clipPath id="clip260">
+ <path d="M 54.019531 922 L 223.933594 922 L 223.933594 924 L 54.019531 924 Z "/>
+</clipPath>
+<clipPath id="clip261">
+ <path d="M 54.019531 885 L 223.933594 885 L 223.933594 887 L 54.019531 887 Z "/>
+</clipPath>
+<clipPath id="clip262">
+ <path d="M 61 878.398438 L 63 878.398438 L 63 1044 L 61 1044 Z "/>
+</clipPath>
+<clipPath id="clip263">
+ <path d="M 99 878.398438 L 101 878.398438 L 101 1044 L 99 1044 Z "/>
+</clipPath>
+<clipPath id="clip264">
+ <path d="M 137 878.398438 L 140 878.398438 L 140 1044 L 137 1044 Z "/>
+</clipPath>
+<clipPath id="clip265">
+ <path d="M 176 878.398438 L 178 878.398438 L 178 1044 L 176 1044 Z "/>
+</clipPath>
+<clipPath id="clip266">
+ <path d="M 214 878.398438 L 216 878.398438 L 216 1044 L 214 1044 Z "/>
+</clipPath>
+<clipPath id="clip267">
+ <path d="M 237.332031 864 L 475 864 L 475 1080 L 237.332031 1080 Z "/>
+</clipPath>
+<clipPath id="clip268">
+ <path d="M 237.332031 864 L 475.664062 864 L 475.664062 1081 L 237.332031 1081 Z "/>
+</clipPath>
+<clipPath id="clip269">
+ <path d="M 291.351562 878.398438 L 461 878.398438 L 461 1044 L 291.351562 1044 Z "/>
+</clipPath>
+<clipPath id="clip270">
+ <path d="M 291.351562 1016 L 461 1016 L 461 1018 L 291.351562 1018 Z "/>
+</clipPath>
+<clipPath id="clip271">
+ <path d="M 291.351562 979 L 461 979 L 461 980 L 291.351562 980 Z "/>
+</clipPath>
+<clipPath id="clip272">
+ <path d="M 291.351562 941 L 461 941 L 461 943 L 291.351562 943 Z "/>
+</clipPath>
+<clipPath id="clip273">
+ <path d="M 291.351562 904 L 461 904 L 461 905 L 291.351562 905 Z "/>
+</clipPath>
+<clipPath id="clip274">
+ <path d="M 317 878.398438 L 319 878.398438 L 319 1044 L 317 1044 Z "/>
+</clipPath>
+<clipPath id="clip275">
+ <path d="M 356 878.398438 L 357 878.398438 L 357 1044 L 356 1044 Z "/>
+</clipPath>
+<clipPath id="clip276">
+ <path d="M 394 878.398438 L 396 878.398438 L 396 1044 L 394 1044 Z "/>
+</clipPath>
+<clipPath id="clip277">
+ <path d="M 433 878.398438 L 434 878.398438 L 434 1044 L 433 1044 Z "/>
+</clipPath>
+<clipPath id="clip278">
+ <path d="M 291.351562 1035 L 461 1035 L 461 1037 L 291.351562 1037 Z "/>
+</clipPath>
+<clipPath id="clip279">
+ <path d="M 291.351562 997 L 461 997 L 461 999 L 291.351562 999 Z "/>
+</clipPath>
+<clipPath id="clip280">
+ <path d="M 291.351562 960 L 461 960 L 461 962 L 291.351562 962 Z "/>
+</clipPath>
+<clipPath id="clip281">
+ <path d="M 291.351562 922 L 461 922 L 461 924 L 291.351562 924 Z "/>
+</clipPath>
+<clipPath id="clip282">
+ <path d="M 291.351562 885 L 461 885 L 461 887 L 291.351562 887 Z "/>
+</clipPath>
+<clipPath id="clip283">
+ <path d="M 298 878.398438 L 300 878.398438 L 300 1044 L 298 1044 Z "/>
+</clipPath>
+<clipPath id="clip284">
+ <path d="M 336 878.398438 L 338 878.398438 L 338 1044 L 336 1044 Z "/>
+</clipPath>
+<clipPath id="clip285">
+ <path d="M 375 878.398438 L 377 878.398438 L 377 1044 L 375 1044 Z "/>
+</clipPath>
+<clipPath id="clip286">
+ <path d="M 413 878.398438 L 415 878.398438 L 415 1044 L 413 1044 Z "/>
+</clipPath>
+<clipPath id="clip287">
+ <path d="M 452 878.398438 L 454 878.398438 L 454 1044 L 452 1044 Z "/>
+</clipPath>
+<clipPath id="clip288">
+ <path d="M 474.667969 864 L 712 864 L 712 1080 L 474.667969 1080 Z "/>
+</clipPath>
+<clipPath id="clip289">
+ <path d="M 474.667969 864 L 712 864 L 712 1081 L 474.667969 1081 Z "/>
+</clipPath>
+<clipPath id="clip290">
+ <path d="M 528.683594 878.398438 L 698 878.398438 L 698 1044 L 528.683594 1044 Z "/>
+</clipPath>
+<clipPath id="clip291">
+ <path d="M 528.683594 1016 L 698 1016 L 698 1018 L 528.683594 1018 Z "/>
+</clipPath>
+<clipPath id="clip292">
+ <path d="M 528.683594 979 L 698 979 L 698 980 L 528.683594 980 Z "/>
+</clipPath>
+<clipPath id="clip293">
+ <path d="M 528.683594 941 L 698 941 L 698 943 L 528.683594 943 Z "/>
+</clipPath>
+<clipPath id="clip294">
+ <path d="M 528.683594 904 L 698 904 L 698 905 L 528.683594 905 Z "/>
+</clipPath>
+<clipPath id="clip295">
+ <path d="M 555 878.398438 L 556 878.398438 L 556 1044 L 555 1044 Z "/>
+</clipPath>
+<clipPath id="clip296">
+ <path d="M 593 878.398438 L 595 878.398438 L 595 1044 L 593 1044 Z "/>
+</clipPath>
+<clipPath id="clip297">
+ <path d="M 632 878.398438 L 633 878.398438 L 633 1044 L 632 1044 Z "/>
+</clipPath>
+<clipPath id="clip298">
+ <path d="M 670 878.398438 L 671 878.398438 L 671 1044 L 670 1044 Z "/>
+</clipPath>
+<clipPath id="clip299">
+ <path d="M 528.683594 1035 L 698.597656 1035 L 698.597656 1037 L 528.683594 1037 Z "/>
+</clipPath>
+<clipPath id="clip300">
+ <path d="M 528.683594 997 L 698.597656 997 L 698.597656 999 L 528.683594 999 Z "/>
+</clipPath>
+<clipPath id="clip301">
+ <path d="M 528.683594 960 L 698.597656 960 L 698.597656 962 L 528.683594 962 Z "/>
+</clipPath>
+<clipPath id="clip302">
+ <path d="M 528.683594 922 L 698.597656 922 L 698.597656 924 L 528.683594 924 Z "/>
+</clipPath>
+<clipPath id="clip303">
+ <path d="M 528.683594 885 L 698.597656 885 L 698.597656 887 L 528.683594 887 Z "/>
+</clipPath>
+<clipPath id="clip304">
+ <path d="M 535 878.398438 L 537 878.398438 L 537 1044 L 535 1044 Z "/>
+</clipPath>
+<clipPath id="clip305">
+ <path d="M 574 878.398438 L 576 878.398438 L 576 1044 L 574 1044 Z "/>
+</clipPath>
+<clipPath id="clip306">
+ <path d="M 612 878.398438 L 614 878.398438 L 614 1044 L 612 1044 Z "/>
+</clipPath>
+<clipPath id="clip307">
+ <path d="M 651 878.398438 L 653 878.398438 L 653 1044 L 651 1044 Z "/>
+</clipPath>
+<clipPath id="clip308">
+ <path d="M 689 878.398438 L 691 878.398438 L 691 1044 L 689 1044 Z "/>
+</clipPath>
+<clipPath id="clip309">
+ <path d="M 0 1080 L 238 1080 L 238 1297 L 0 1297 Z "/>
+</clipPath>
+<clipPath id="clip310">
+ <path d="M 54.019531 1094.398438 L 223 1094.398438 L 223 1260 L 54.019531 1260 Z "/>
+</clipPath>
+<clipPath id="clip311">
+ <path d="M 54.019531 1245 L 223.933594 1245 L 223.933594 1247 L 54.019531 1247 Z "/>
+</clipPath>
+<clipPath id="clip312">
+ <path d="M 54.019531 1204 L 223.933594 1204 L 223.933594 1206 L 54.019531 1206 Z "/>
+</clipPath>
+<clipPath id="clip313">
+ <path d="M 54.019531 1163 L 223.933594 1163 L 223.933594 1164 L 54.019531 1164 Z "/>
+</clipPath>
+<clipPath id="clip314">
+ <path d="M 54.019531 1122 L 223.933594 1122 L 223.933594 1123 L 54.019531 1123 Z "/>
+</clipPath>
+<clipPath id="clip315">
+ <path d="M 80 1094.398438 L 82 1094.398438 L 82 1260 L 80 1260 Z "/>
+</clipPath>
+<clipPath id="clip316">
+ <path d="M 119 1094.398438 L 120 1094.398438 L 120 1260 L 119 1260 Z "/>
+</clipPath>
+<clipPath id="clip317">
+ <path d="M 157 1094.398438 L 158 1094.398438 L 158 1260 L 157 1260 Z "/>
+</clipPath>
+<clipPath id="clip318">
+ <path d="M 195 1094.398438 L 197 1094.398438 L 197 1260 L 195 1260 Z "/>
+</clipPath>
+<clipPath id="clip319">
+ <path d="M 54.019531 1224 L 223.933594 1224 L 223.933594 1226 L 54.019531 1226 Z "/>
+</clipPath>
+<clipPath id="clip320">
+ <path d="M 54.019531 1183 L 223.933594 1183 L 223.933594 1185 L 54.019531 1185 Z "/>
+</clipPath>
+<clipPath id="clip321">
+ <path d="M 54.019531 1142 L 223.933594 1142 L 223.933594 1144 L 54.019531 1144 Z "/>
+</clipPath>
+<clipPath id="clip322">
+ <path d="M 54.019531 1101 L 223.933594 1101 L 223.933594 1103 L 54.019531 1103 Z "/>
+</clipPath>
+<clipPath id="clip323">
+ <path d="M 61 1094.398438 L 63 1094.398438 L 63 1260 L 61 1260 Z "/>
+</clipPath>
+<clipPath id="clip324">
+ <path d="M 99 1094.398438 L 101 1094.398438 L 101 1260 L 99 1260 Z "/>
+</clipPath>
+<clipPath id="clip325">
+ <path d="M 137 1094.398438 L 140 1094.398438 L 140 1260 L 137 1260 Z "/>
+</clipPath>
+<clipPath id="clip326">
+ <path d="M 176 1094.398438 L 178 1094.398438 L 178 1260 L 176 1260 Z "/>
+</clipPath>
+<clipPath id="clip327">
+ <path d="M 214 1094.398438 L 216 1094.398438 L 216 1260 L 214 1260 Z "/>
+</clipPath>
+<clipPath id="clip328">
+ <path d="M 237.332031 1080 L 475 1080 L 475 1296 L 237.332031 1296 Z "/>
+</clipPath>
+<clipPath id="clip329">
+ <path d="M 237.332031 1080 L 475.664062 1080 L 475.664062 1297 L 237.332031 1297 Z "/>
+</clipPath>
+<clipPath id="clip330">
+ <path d="M 291.351562 1094.398438 L 461 1094.398438 L 461 1260 L 291.351562 1260 Z "/>
+</clipPath>
+<clipPath id="clip331">
+ <path d="M 291.351562 1232 L 461 1232 L 461 1234 L 291.351562 1234 Z "/>
+</clipPath>
+<clipPath id="clip332">
+ <path d="M 291.351562 1195 L 461 1195 L 461 1196 L 291.351562 1196 Z "/>
+</clipPath>
+<clipPath id="clip333">
+ <path d="M 291.351562 1157 L 461 1157 L 461 1159 L 291.351562 1159 Z "/>
+</clipPath>
+<clipPath id="clip334">
+ <path d="M 291.351562 1120 L 461 1120 L 461 1121 L 291.351562 1121 Z "/>
+</clipPath>
+<clipPath id="clip335">
+ <path d="M 317 1094.398438 L 319 1094.398438 L 319 1260 L 317 1260 Z "/>
+</clipPath>
+<clipPath id="clip336">
+ <path d="M 356 1094.398438 L 357 1094.398438 L 357 1260 L 356 1260 Z "/>
+</clipPath>
+<clipPath id="clip337">
+ <path d="M 394 1094.398438 L 396 1094.398438 L 396 1260 L 394 1260 Z "/>
+</clipPath>
+<clipPath id="clip338">
+ <path d="M 433 1094.398438 L 434 1094.398438 L 434 1260 L 433 1260 Z "/>
+</clipPath>
+<clipPath id="clip339">
+ <path d="M 291.351562 1251 L 461 1251 L 461 1253 L 291.351562 1253 Z "/>
+</clipPath>
+<clipPath id="clip340">
+ <path d="M 291.351562 1213 L 461 1213 L 461 1215 L 291.351562 1215 Z "/>
+</clipPath>
+<clipPath id="clip341">
+ <path d="M 291.351562 1176 L 461 1176 L 461 1178 L 291.351562 1178 Z "/>
+</clipPath>
+<clipPath id="clip342">
+ <path d="M 291.351562 1138 L 461 1138 L 461 1140 L 291.351562 1140 Z "/>
+</clipPath>
+<clipPath id="clip343">
+ <path d="M 291.351562 1101 L 461 1101 L 461 1103 L 291.351562 1103 Z "/>
+</clipPath>
+<clipPath id="clip344">
+ <path d="M 298 1094.398438 L 300 1094.398438 L 300 1260 L 298 1260 Z "/>
+</clipPath>
+<clipPath id="clip345">
+ <path d="M 336 1094.398438 L 338 1094.398438 L 338 1260 L 336 1260 Z "/>
+</clipPath>
+<clipPath id="clip346">
+ <path d="M 375 1094.398438 L 377 1094.398438 L 377 1260 L 375 1260 Z "/>
+</clipPath>
+<clipPath id="clip347">
+ <path d="M 413 1094.398438 L 415 1094.398438 L 415 1260 L 413 1260 Z "/>
+</clipPath>
+<clipPath id="clip348">
+ <path d="M 452 1094.398438 L 454 1094.398438 L 454 1260 L 452 1260 Z "/>
+</clipPath>
+<clipPath id="clip349">
+ <path d="M 474.667969 1080 L 712 1080 L 712 1296 L 474.667969 1296 Z "/>
+</clipPath>
+<clipPath id="clip350">
+ <path d="M 474.667969 1080 L 712 1080 L 712 1297 L 474.667969 1297 Z "/>
+</clipPath>
+<clipPath id="clip351">
+ <path d="M 528.683594 1094.398438 L 698 1094.398438 L 698 1260 L 528.683594 1260 Z "/>
+</clipPath>
+<clipPath id="clip352">
+ <path d="M 528.683594 1232 L 698 1232 L 698 1234 L 528.683594 1234 Z "/>
+</clipPath>
+<clipPath id="clip353">
+ <path d="M 528.683594 1195 L 698 1195 L 698 1196 L 528.683594 1196 Z "/>
+</clipPath>
+<clipPath id="clip354">
+ <path d="M 528.683594 1157 L 698 1157 L 698 1159 L 528.683594 1159 Z "/>
+</clipPath>
+<clipPath id="clip355">
+ <path d="M 528.683594 1120 L 698 1120 L 698 1121 L 528.683594 1121 Z "/>
+</clipPath>
+<clipPath id="clip356">
+ <path d="M 555 1094.398438 L 556 1094.398438 L 556 1260 L 555 1260 Z "/>
+</clipPath>
+<clipPath id="clip357">
+ <path d="M 593 1094.398438 L 595 1094.398438 L 595 1260 L 593 1260 Z "/>
+</clipPath>
+<clipPath id="clip358">
+ <path d="M 632 1094.398438 L 633 1094.398438 L 633 1260 L 632 1260 Z "/>
+</clipPath>
+<clipPath id="clip359">
+ <path d="M 670 1094.398438 L 671 1094.398438 L 671 1260 L 670 1260 Z "/>
+</clipPath>
+<clipPath id="clip360">
+ <path d="M 528.683594 1251 L 698.597656 1251 L 698.597656 1253 L 528.683594 1253 Z "/>
+</clipPath>
+<clipPath id="clip361">
+ <path d="M 528.683594 1213 L 698.597656 1213 L 698.597656 1215 L 528.683594 1215 Z "/>
+</clipPath>
+<clipPath id="clip362">
+ <path d="M 528.683594 1176 L 698.597656 1176 L 698.597656 1178 L 528.683594 1178 Z "/>
+</clipPath>
+<clipPath id="clip363">
+ <path d="M 528.683594 1138 L 698.597656 1138 L 698.597656 1140 L 528.683594 1140 Z "/>
+</clipPath>
+<clipPath id="clip364">
+ <path d="M 528.683594 1101 L 698.597656 1101 L 698.597656 1103 L 528.683594 1103 Z "/>
+</clipPath>
+<clipPath id="clip365">
+ <path d="M 535 1094.398438 L 537 1094.398438 L 537 1260 L 535 1260 Z "/>
+</clipPath>
+<clipPath id="clip366">
+ <path d="M 574 1094.398438 L 576 1094.398438 L 576 1260 L 574 1260 Z "/>
+</clipPath>
+<clipPath id="clip367">
+ <path d="M 612 1094.398438 L 614 1094.398438 L 614 1260 L 612 1260 Z "/>
+</clipPath>
+<clipPath id="clip368">
+ <path d="M 651 1094.398438 L 653 1094.398438 L 653 1260 L 651 1260 Z "/>
+</clipPath>
+<clipPath id="clip369">
+ <path d="M 689 1094.398438 L 691 1094.398438 L 691 1260 L 689 1260 Z "/>
+</clipPath>
+<clipPath id="clip370">
+ <path d="M 0 1296 L 238 1296 L 238 1512 L 0 1512 Z "/>
+</clipPath>
+<clipPath id="clip371">
+ <path d="M 54.019531 1310.398438 L 223 1310.398438 L 223 1476 L 54.019531 1476 Z "/>
+</clipPath>
+<clipPath id="clip372">
+ <path d="M 54.019531 1448 L 223.933594 1448 L 223.933594 1450 L 54.019531 1450 Z "/>
+</clipPath>
+<clipPath id="clip373">
+ <path d="M 54.019531 1411 L 223.933594 1411 L 223.933594 1412 L 54.019531 1412 Z "/>
+</clipPath>
+<clipPath id="clip374">
+ <path d="M 54.019531 1373 L 223.933594 1373 L 223.933594 1375 L 54.019531 1375 Z "/>
+</clipPath>
+<clipPath id="clip375">
+ <path d="M 54.019531 1336 L 223.933594 1336 L 223.933594 1337 L 54.019531 1337 Z "/>
+</clipPath>
+<clipPath id="clip376">
+ <path d="M 80 1310.398438 L 82 1310.398438 L 82 1476 L 80 1476 Z "/>
+</clipPath>
+<clipPath id="clip377">
+ <path d="M 119 1310.398438 L 120 1310.398438 L 120 1476 L 119 1476 Z "/>
+</clipPath>
+<clipPath id="clip378">
+ <path d="M 157 1310.398438 L 158 1310.398438 L 158 1476 L 157 1476 Z "/>
+</clipPath>
+<clipPath id="clip379">
+ <path d="M 195 1310.398438 L 197 1310.398438 L 197 1476 L 195 1476 Z "/>
+</clipPath>
+<clipPath id="clip380">
+ <path d="M 54.019531 1467 L 223.933594 1467 L 223.933594 1469 L 54.019531 1469 Z "/>
+</clipPath>
+<clipPath id="clip381">
+ <path d="M 54.019531 1429 L 223.933594 1429 L 223.933594 1431 L 54.019531 1431 Z "/>
+</clipPath>
+<clipPath id="clip382">
+ <path d="M 54.019531 1392 L 223.933594 1392 L 223.933594 1394 L 54.019531 1394 Z "/>
+</clipPath>
+<clipPath id="clip383">
+ <path d="M 54.019531 1354 L 223.933594 1354 L 223.933594 1356 L 54.019531 1356 Z "/>
+</clipPath>
+<clipPath id="clip384">
+ <path d="M 54.019531 1317 L 223.933594 1317 L 223.933594 1319 L 54.019531 1319 Z "/>
+</clipPath>
+<clipPath id="clip385">
+ <path d="M 61 1310.398438 L 63 1310.398438 L 63 1476 L 61 1476 Z "/>
+</clipPath>
+<clipPath id="clip386">
+ <path d="M 99 1310.398438 L 101 1310.398438 L 101 1476 L 99 1476 Z "/>
+</clipPath>
+<clipPath id="clip387">
+ <path d="M 137 1310.398438 L 140 1310.398438 L 140 1476 L 137 1476 Z "/>
+</clipPath>
+<clipPath id="clip388">
+ <path d="M 176 1310.398438 L 178 1310.398438 L 178 1476 L 176 1476 Z "/>
+</clipPath>
+<clipPath id="clip389">
+ <path d="M 214 1310.398438 L 216 1310.398438 L 216 1476 L 214 1476 Z "/>
+</clipPath>
+<clipPath id="clip390">
+ <path d="M 237.332031 1296 L 475 1296 L 475 1512 L 237.332031 1512 Z "/>
+</clipPath>
+<clipPath id="clip391">
+ <path d="M 237.332031 1296 L 475.664062 1296 L 475.664062 1512 L 237.332031 1512 Z "/>
+</clipPath>
+<clipPath id="clip392">
+ <path d="M 291.351562 1310.398438 L 461 1310.398438 L 461 1476 L 291.351562 1476 Z "/>
+</clipPath>
+<clipPath id="clip393">
+ <path d="M 291.351562 1448 L 461 1448 L 461 1450 L 291.351562 1450 Z "/>
+</clipPath>
+<clipPath id="clip394">
+ <path d="M 291.351562 1411 L 461 1411 L 461 1412 L 291.351562 1412 Z "/>
+</clipPath>
+<clipPath id="clip395">
+ <path d="M 291.351562 1373 L 461 1373 L 461 1375 L 291.351562 1375 Z "/>
+</clipPath>
+<clipPath id="clip396">
+ <path d="M 291.351562 1336 L 461 1336 L 461 1337 L 291.351562 1337 Z "/>
+</clipPath>
+<clipPath id="clip397">
+ <path d="M 317 1310.398438 L 319 1310.398438 L 319 1476 L 317 1476 Z "/>
+</clipPath>
+<clipPath id="clip398">
+ <path d="M 356 1310.398438 L 357 1310.398438 L 357 1476 L 356 1476 Z "/>
+</clipPath>
+<clipPath id="clip399">
+ <path d="M 394 1310.398438 L 396 1310.398438 L 396 1476 L 394 1476 Z "/>
+</clipPath>
+<clipPath id="clip400">
+ <path d="M 433 1310.398438 L 434 1310.398438 L 434 1476 L 433 1476 Z "/>
+</clipPath>
+<clipPath id="clip401">
+ <path d="M 291.351562 1467 L 461 1467 L 461 1469 L 291.351562 1469 Z "/>
+</clipPath>
+<clipPath id="clip402">
+ <path d="M 291.351562 1429 L 461 1429 L 461 1431 L 291.351562 1431 Z "/>
+</clipPath>
+<clipPath id="clip403">
+ <path d="M 291.351562 1392 L 461 1392 L 461 1394 L 291.351562 1394 Z "/>
+</clipPath>
+<clipPath id="clip404">
+ <path d="M 291.351562 1354 L 461 1354 L 461 1356 L 291.351562 1356 Z "/>
+</clipPath>
+<clipPath id="clip405">
+ <path d="M 291.351562 1317 L 461 1317 L 461 1319 L 291.351562 1319 Z "/>
+</clipPath>
+<clipPath id="clip406">
+ <path d="M 298 1310.398438 L 300 1310.398438 L 300 1476 L 298 1476 Z "/>
+</clipPath>
+<clipPath id="clip407">
+ <path d="M 336 1310.398438 L 338 1310.398438 L 338 1476 L 336 1476 Z "/>
+</clipPath>
+<clipPath id="clip408">
+ <path d="M 375 1310.398438 L 377 1310.398438 L 377 1476 L 375 1476 Z "/>
+</clipPath>
+<clipPath id="clip409">
+ <path d="M 413 1310.398438 L 415 1310.398438 L 415 1476 L 413 1476 Z "/>
+</clipPath>
+<clipPath id="clip410">
+ <path d="M 452 1310.398438 L 454 1310.398438 L 454 1476 L 452 1476 Z "/>
+</clipPath>
+<clipPath id="clip411">
+ <path d="M 474.667969 1296 L 712 1296 L 712 1512 L 474.667969 1512 Z "/>
+</clipPath>
+<clipPath id="clip412">
+ <path d="M 528.683594 1310.398438 L 698 1310.398438 L 698 1476 L 528.683594 1476 Z "/>
+</clipPath>
+<clipPath id="clip413">
+ <path d="M 528.683594 1448 L 698 1448 L 698 1450 L 528.683594 1450 Z "/>
+</clipPath>
+<clipPath id="clip414">
+ <path d="M 528.683594 1411 L 698 1411 L 698 1412 L 528.683594 1412 Z "/>
+</clipPath>
+<clipPath id="clip415">
+ <path d="M 528.683594 1373 L 698 1373 L 698 1375 L 528.683594 1375 Z "/>
+</clipPath>
+<clipPath id="clip416">
+ <path d="M 528.683594 1336 L 698 1336 L 698 1337 L 528.683594 1337 Z "/>
+</clipPath>
+<clipPath id="clip417">
+ <path d="M 555 1310.398438 L 556 1310.398438 L 556 1476 L 555 1476 Z "/>
+</clipPath>
+<clipPath id="clip418">
+ <path d="M 593 1310.398438 L 595 1310.398438 L 595 1476 L 593 1476 Z "/>
+</clipPath>
+<clipPath id="clip419">
+ <path d="M 632 1310.398438 L 633 1310.398438 L 633 1476 L 632 1476 Z "/>
+</clipPath>
+<clipPath id="clip420">
+ <path d="M 670 1310.398438 L 671 1310.398438 L 671 1476 L 670 1476 Z "/>
+</clipPath>
+<clipPath id="clip421">
+ <path d="M 528.683594 1467 L 698.597656 1467 L 698.597656 1469 L 528.683594 1469 Z "/>
+</clipPath>
+<clipPath id="clip422">
+ <path d="M 528.683594 1429 L 698.597656 1429 L 698.597656 1431 L 528.683594 1431 Z "/>
+</clipPath>
+<clipPath id="clip423">
+ <path d="M 528.683594 1392 L 698.597656 1392 L 698.597656 1394 L 528.683594 1394 Z "/>
+</clipPath>
+<clipPath id="clip424">
+ <path d="M 528.683594 1354 L 698.597656 1354 L 698.597656 1356 L 528.683594 1356 Z "/>
+</clipPath>
+<clipPath id="clip425">
+ <path d="M 528.683594 1317 L 698.597656 1317 L 698.597656 1319 L 528.683594 1319 Z "/>
+</clipPath>
+<clipPath id="clip426">
+ <path d="M 535 1310.398438 L 537 1310.398438 L 537 1476 L 535 1476 Z "/>
+</clipPath>
+<clipPath id="clip427">
+ <path d="M 574 1310.398438 L 576 1310.398438 L 576 1476 L 574 1476 Z "/>
+</clipPath>
+<clipPath id="clip428">
+ <path d="M 612 1310.398438 L 614 1310.398438 L 614 1476 L 612 1476 Z "/>
+</clipPath>
+<clipPath id="clip429">
+ <path d="M 651 1310.398438 L 653 1310.398438 L 653 1476 L 651 1476 Z "/>
+</clipPath>
+<clipPath id="clip430">
+ <path d="M 689 1310.398438 L 691 1310.398438 L 691 1476 L 689 1476 Z "/>
+</clipPath>
+</defs>
+<g id="surface1191">
+<rect x="0" y="0" width="712" height="1512" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 237.332031 216 L 237.332031 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 222.933594 179.027344 L 222.933594 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.800781 L 222.933594 152.800781 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.308594 L 222.933594 115.308594 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 77.820312 L 222.933594 77.820312 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.328125 L 222.933594 40.328125 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 80.890625 179.027344 L 80.890625 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 119.28125 179.027344 L 119.28125 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.671875 179.027344 L 157.671875 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 196.058594 179.027344 L 196.058594 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 222.933594 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.054688 L 222.933594 134.054688 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.5625 L 222.933594 96.5625 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.074219 L 222.933594 59.074219 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.582031 L 222.933594 21.582031 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 179.027344 L 61.695312 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 179.027344 L 100.085938 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 179.027344 L 138.476562 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 179.027344 L 176.867188 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 179.027344 L 215.253906 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 61.695312 171.546875 L 62.621094 169.742188 L 62.925781 169.140625 L 63.234375 168.539062 L 63.542969 167.941406 L 63.851562 167.339844 L 64.15625 166.738281 L 65.390625 164.332031 L 65.695312 163.730469 L 66.003906 163.132812 L 66.621094 161.929688 L 66.925781 161.328125 L 68.160156 158.921875 L 68.464844 158.324219 L 69.390625 156.519531 L 69.695312 155.917969 L 70.3125 154.714844 L 70.621094 154.117188 L 70.929688 153.515625 L 71.234375 152.914062 L 72.46875 150.507812 L 72.773438 149.90625 L 73.082031 149.308594 L 73.699219 148.105469 L 74.003906 147.503906 L 75.238281 145.097656 L 75.542969 144.5 L 76.46875 142.695312 L 76.773438 142.09375 L 77.699219 140.289062 L 78.007812 139.691406 L 78.3125 139.089844 L 79.238281 137.285156 L 79.542969 136.683594 L 79.851562 136.082031 L 80.160156 135.484375 L 80.777344 134.28125 L 81.082031 133.679688 L 82.007812 131.875 L 82.3125 131.273438 L 82.621094 130.675781 L 83.546875 128.871094 L 83.851562 128.269531 L 84.777344 126.464844 L 85.082031 125.867188 L 86.316406 123.460938 L 86.621094 122.859375 L 86.929688 122.257812 L 87.238281 121.660156 L 87.855469 120.457031 L 88.160156 119.855469 L 89.085938 118.050781 L 89.390625 117.449219 L 89.699219 116.851562 L 90.625 115.046875 L 90.929688 114.445312 L 91.855469 112.640625 L 92.160156 112.042969 L 93.394531 109.636719 L 93.699219 109.035156 L 94.007812 108.433594 L 94.316406 107.835938 L 94.625 107.234375 L 94.929688 106.632812 L 96.164062 104.226562 L 96.46875 103.625 L 96.777344 103.027344 L 97.394531 101.824219 L 97.699219 101.222656 L 98.933594 98.816406 L 99.238281 98.21875 L 100.164062 96.414062 L 100.46875 95.8125 L 101.394531 94.007812 L 101.703125 93.410156 L 102.007812 92.808594 L 103.242188 90.402344 L 103.546875 89.800781 L 103.855469 89.203125 L 104.472656 88 L 104.777344 87.398438 L 106.011719 84.992188 L 106.316406 84.394531 L 107.242188 82.589844 L 107.546875 81.988281 L 108.472656 80.183594 L 108.78125 79.585938 L 109.085938 78.984375 L 110.011719 77.179688 L 110.316406 76.578125 L 110.625 75.976562 L 110.933594 75.378906 L 111.550781 74.175781 L 111.855469 73.574219 L 112.78125 71.769531 L 113.085938 71.167969 L 113.394531 70.570312 L 114.320312 68.765625 L 114.625 68.164062 L 115.550781 66.359375 L 115.855469 65.761719 L 117.089844 63.355469 L 117.394531 62.753906 L 117.703125 62.152344 L 118.011719 61.554688 L 118.320312 60.953125 L 118.625 60.351562 L 119.859375 57.945312 L 120.164062 57.34375 L 120.472656 56.746094 L 121.398438 54.941406 L 121.703125 54.339844 L 122.628906 52.535156 L 122.933594 51.9375 L 124.167969 49.53125 L 124.472656 48.929688 L 125.089844 47.726562 L 125.398438 47.128906 L 125.703125 46.527344 L 126.9375 44.121094 L 127.242188 43.519531 L 127.550781 42.921875 L 128.167969 41.71875 L 128.472656 41.117188 L 129.707031 38.710938 L 130.011719 38.113281 L 130.9375 36.308594 L 131.242188 35.707031 L 132.167969 33.902344 L 132.476562 33.304688 L 132.78125 32.703125 L 133.707031 30.898438 L 134.011719 30.296875 L 134.320312 29.695312 L 134.628906 29.097656 L 135.246094 27.894531 L 135.550781 27.292969 L 136.785156 24.886719 L 137.089844 24.289062 L 138.015625 22.484375 L 138.320312 21.882812 L 138.628906 21.882812 L 139.554688 23.6875 L 139.859375 24.289062 L 140.167969 24.886719 L 140.785156 26.089844 L 141.089844 26.691406 L 142.324219 29.097656 L 142.628906 29.695312 L 143.554688 31.5 L 143.859375 32.101562 L 144.476562 33.304688 L 144.785156 33.902344 L 145.09375 34.503906 L 145.398438 35.105469 L 146.324219 36.910156 L 146.628906 37.511719 L 146.9375 38.113281 L 147.246094 38.710938 L 147.863281 39.914062 L 148.167969 40.515625 L 149.09375 42.320312 L 149.398438 42.921875 L 149.707031 43.519531 L 150.632812 45.324219 L 150.9375 45.925781 L 151.554688 47.128906 L 151.863281 47.726562 L 152.171875 48.328125 L 152.476562 48.929688 L 153.402344 50.734375 L 153.707031 51.335938 L 154.015625 51.9375 L 154.324219 52.535156 L 154.941406 53.738281 L 155.246094 54.339844 L 156.171875 56.144531 L 156.476562 56.746094 L 156.785156 57.34375 L 157.710938 59.148438 L 158.015625 59.75 L 158.941406 61.554688 L 159.246094 62.152344 L 160.480469 64.558594 L 160.785156 65.160156 L 161.09375 65.761719 L 161.402344 66.359375 L 161.710938 66.960938 L 162.015625 67.5625 L 163.25 69.96875 L 163.554688 70.570312 L 163.863281 71.167969 L 164.480469 72.371094 L 164.785156 72.972656 L 166.019531 75.378906 L 166.324219 75.976562 L 167.25 77.78125 L 167.554688 78.382812 L 168.171875 79.585938 L 168.480469 80.183594 L 168.789062 80.785156 L 169.09375 81.386719 L 170.328125 83.792969 L 170.632812 84.394531 L 170.941406 84.992188 L 171.558594 86.195312 L 171.863281 86.796875 L 173.097656 89.203125 L 173.402344 89.800781 L 174.328125 91.605469 L 174.632812 92.207031 L 175.25 93.410156 L 175.558594 94.007812 L 175.867188 94.609375 L 176.171875 95.210938 L 177.097656 97.015625 L 177.402344 97.617188 L 177.710938 98.21875 L 178.019531 98.816406 L 178.636719 100.019531 L 178.941406 100.621094 L 179.867188 102.425781 L 180.171875 103.027344 L 180.480469 103.625 L 181.40625 105.429688 L 181.710938 106.03125 L 182.636719 107.835938 L 182.941406 108.433594 L 184.175781 110.839844 L 184.480469 111.441406 L 184.789062 112.042969 L 185.097656 112.640625 L 185.714844 113.84375 L 186.019531 114.445312 L 186.945312 116.25 L 187.25 116.851562 L 187.558594 117.449219 L 188.484375 119.253906 L 188.789062 119.855469 L 189.714844 121.660156 L 190.019531 122.257812 L 191.253906 124.664062 L 191.558594 125.265625 L 191.867188 125.867188 L 192.175781 126.464844 L 192.484375 127.066406 L 192.789062 127.667969 L 194.023438 130.074219 L 194.328125 130.675781 L 194.636719 131.273438 L 195.253906 132.476562 L 195.558594 133.078125 L 196.792969 135.484375 L 197.097656 136.082031 L 198.023438 137.886719 L 198.328125 138.488281 L 198.945312 139.691406 L 199.253906 140.289062 L 199.5625 140.890625 L 199.867188 141.492188 L 201.101562 143.898438 L 201.40625 144.5 L 201.714844 145.097656 L 202.332031 146.300781 L 202.636719 146.902344 L 203.871094 149.308594 L 204.175781 149.90625 L 205.101562 151.710938 L 205.40625 152.3125 L 206.332031 154.117188 L 206.640625 154.714844 L 206.945312 155.316406 L 207.871094 157.121094 L 208.175781 157.722656 L 208.484375 158.324219 L 208.792969 158.921875 L 209.410156 160.125 L 209.714844 160.726562 L 210.640625 162.53125 L 210.945312 163.132812 L 211.253906 163.730469 L 212.179688 165.535156 L 212.484375 166.136719 L 213.410156 167.941406 L 213.714844 168.539062 L 214.949219 170.945312 L 215.253906 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.492188"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.492188"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.492188"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.492188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.511719"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.511719"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.511719"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.511719"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.019531"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.019531"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.019531"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.019531"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.054688 L 54.019531 134.054688 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.5625 L 54.019531 96.5625 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.074219 L 54.019531 59.074219 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.582031 L 54.019531 21.582031 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 183.28125 L 61.695312 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 183.28125 L 100.085938 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 183.28125 L 138.476562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 183.28125 L 176.867188 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 183.28125 L 215.253906 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="52.359375" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="57.694962" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="60.360413" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="65.695999" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="90.75" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="96.085587" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="98.751038" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="104.086624" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="129.140625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="134.476212" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="137.141663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="142.477249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="167.53125" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="172.866837" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="175.532288" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="180.867874" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="205.917969" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="211.253555" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="213.919006" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="219.254593" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="135.476562" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-1" x="23.335938" y="10.800781"/>
+ <use xlink:href="#glyph5-2" x="30.666016" y="10.800781"/>
+ <use xlink:href="#glyph5-3" x="35.335938" y="10.800781"/>
+ <use xlink:href="#glyph5-4" x="38.669922" y="10.800781"/>
+ <use xlink:href="#glyph5-5" x="45.34375" y="10.800781"/>
+ <use xlink:href="#glyph5-6" x="52.673828" y="10.800781"/>
+ <use xlink:href="#glyph5-7" x="60.003906" y="10.800781"/>
+ <use xlink:href="#glyph5-8" x="63.337891" y="10.800781"/>
+</g>
+<g clip-path="url(#clip20)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 237.332031 216 L 474.664062 216 L 474.664062 0 L 237.332031 0 Z "/>
+</g>
+<g clip-path="url(#clip21)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 237.332031 216 L 474.664062 216 L 474.664062 0 L 237.332031 0 Z "/>
+</g>
+<g clip-path="url(#clip22)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 291.351562 179.027344 L 460.265625 179.027344 L 460.265625 14.398438 L 291.351562 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip23)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 154.882812 L 460.265625 154.882812 "/>
+</g>
+<g clip-path="url(#clip24)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 116.882812 L 460.265625 116.882812 "/>
+</g>
+<g clip-path="url(#clip25)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 78.882812 L 460.265625 78.882812 "/>
+</g>
+<g clip-path="url(#clip26)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 40.882812 L 460.265625 40.882812 "/>
+</g>
+<g clip-path="url(#clip27)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 318.222656 179.027344 L 318.222656 14.398438 "/>
+</g>
+<g clip-path="url(#clip28)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.613281 179.027344 L 356.613281 14.398438 "/>
+</g>
+<g clip-path="url(#clip29)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 395.003906 179.027344 L 395.003906 14.398438 "/>
+</g>
+<g clip-path="url(#clip30)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 433.394531 179.027344 L 433.394531 14.398438 "/>
+</g>
+<g clip-path="url(#clip31)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 173.882812 L 460.265625 173.882812 "/>
+</g>
+<g clip-path="url(#clip32)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 135.882812 L 460.265625 135.882812 "/>
+</g>
+<g clip-path="url(#clip33)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 97.882812 L 460.265625 97.882812 "/>
+</g>
+<g clip-path="url(#clip34)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 59.882812 L 460.265625 59.882812 "/>
+</g>
+<g clip-path="url(#clip35)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 21.882812 L 460.265625 21.882812 "/>
+</g>
+<g clip-path="url(#clip36)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 179.027344 L 299.03125 14.398438 "/>
+</g>
+<g clip-path="url(#clip37)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 179.027344 L 337.417969 14.398438 "/>
+</g>
+<g clip-path="url(#clip38)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 179.027344 L 375.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip39)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 179.027344 L 414.199219 14.398438 "/>
+</g>
+<g clip-path="url(#clip40)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 179.027344 L 452.589844 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 299.03125 171.546875 L 299.335938 171.488281 L 299.644531 171.433594 L 299.953125 171.371094 L 300.261719 171.3125 L 300.566406 171.25 L 301.492188 171.050781 L 301.800781 170.980469 L 302.105469 170.90625 L 302.722656 170.757812 L 303.03125 170.679688 L 303.335938 170.597656 L 303.644531 170.515625 L 304.261719 170.34375 L 304.570312 170.25 L 304.875 170.15625 L 305.183594 170.0625 L 305.492188 169.964844 L 305.800781 169.863281 L 306.105469 169.757812 L 306.722656 169.539062 L 307.339844 169.304688 L 307.644531 169.183594 L 307.953125 169.058594 L 308.261719 168.929688 L 308.570312 168.796875 L 308.878906 168.660156 L 309.183594 168.515625 L 309.492188 168.371094 L 309.800781 168.222656 L 310.109375 168.066406 L 310.414062 167.90625 L 310.722656 167.742188 L 311.03125 167.574219 L 311.339844 167.398438 L 311.648438 167.214844 L 311.953125 167.03125 L 312.261719 166.839844 L 312.570312 166.640625 L 312.878906 166.433594 L 313.183594 166.222656 L 313.492188 166.007812 L 313.800781 165.78125 L 314.109375 165.550781 L 314.417969 165.308594 L 314.722656 165.0625 L 315.03125 164.808594 L 315.339844 164.542969 L 315.648438 164.273438 L 315.953125 163.992188 L 316.261719 163.699219 L 316.570312 163.402344 L 316.878906 163.09375 L 317.1875 162.773438 L 317.492188 162.445312 L 317.800781 162.101562 L 318.109375 161.75 L 318.417969 161.386719 L 318.722656 161.011719 L 319.03125 160.625 L 319.339844 160.226562 L 319.648438 159.8125 L 319.957031 159.386719 L 320.261719 158.945312 L 320.570312 158.492188 L 320.878906 158.019531 L 321.1875 157.535156 L 321.492188 157.035156 L 321.800781 156.515625 L 322.109375 155.984375 L 322.417969 155.429688 L 322.726562 154.859375 L 323.03125 154.273438 L 323.339844 153.664062 L 323.648438 153.039062 L 323.957031 152.390625 L 324.265625 151.722656 L 324.570312 151.035156 L 324.878906 150.324219 L 325.1875 149.59375 L 325.496094 148.835938 L 325.800781 148.054688 L 326.109375 147.253906 L 326.417969 146.425781 L 326.726562 145.570312 L 327.035156 144.691406 L 327.339844 143.785156 L 327.648438 142.851562 L 327.957031 141.890625 L 328.265625 140.902344 L 328.570312 139.882812 L 328.878906 138.839844 L 329.1875 137.761719 L 329.496094 136.65625 L 329.804688 135.519531 L 330.109375 134.355469 L 330.417969 133.15625 L 330.726562 131.929688 L 331.035156 130.667969 L 331.339844 129.378906 L 331.648438 128.054688 L 331.957031 126.699219 L 332.265625 125.316406 L 332.574219 123.898438 L 332.878906 122.449219 L 333.1875 120.972656 L 333.496094 119.460938 L 333.804688 117.921875 L 334.109375 116.351562 L 334.417969 114.753906 L 334.726562 113.128906 L 335.035156 111.476562 L 335.34375 109.800781 L 335.648438 108.097656 L 335.957031 106.367188 L 336.265625 104.617188 L 336.574219 102.847656 L 336.878906 101.058594 L 337.1875 99.25 L 337.496094 97.425781 L 337.804688 95.589844 L 338.113281 93.738281 L 338.417969 91.878906 L 338.726562 90.007812 L 339.34375 86.257812 L 339.648438 84.378906 L 339.957031 82.5 L 340.265625 80.625 L 340.574219 78.753906 L 340.882812 76.894531 L 341.1875 75.046875 L 341.496094 73.207031 L 341.804688 71.386719 L 342.113281 69.585938 L 342.421875 67.800781 L 342.726562 66.039062 L 343.035156 64.304688 L 343.34375 62.59375 L 343.652344 60.914062 L 343.957031 59.265625 L 344.265625 57.648438 L 344.574219 56.0625 L 344.882812 54.515625 L 345.191406 53.003906 L 345.496094 51.53125 L 345.804688 50.097656 L 346.113281 48.703125 L 346.421875 47.351562 L 346.726562 46.039062 L 347.035156 44.769531 L 347.34375 43.542969 L 347.652344 42.359375 L 347.960938 41.21875 L 348.265625 40.125 L 348.574219 39.070312 L 348.882812 38.054688 L 349.191406 37.085938 L 349.496094 36.15625 L 349.804688 35.269531 L 350.113281 34.425781 L 350.421875 33.617188 L 350.730469 32.847656 L 351.035156 32.117188 L 351.34375 31.425781 L 351.652344 30.769531 L 351.960938 30.144531 L 352.265625 29.558594 L 352.574219 29.003906 L 352.882812 28.480469 L 353.191406 27.984375 L 353.5 27.523438 L 353.804688 27.085938 L 354.113281 26.679688 L 354.421875 26.296875 L 354.730469 25.9375 L 355.035156 25.605469 L 355.34375 25.292969 L 355.652344 25.003906 L 355.960938 24.734375 L 356.269531 24.480469 L 356.574219 24.25 L 356.882812 24.035156 L 357.191406 23.835938 L 357.5 23.652344 L 357.808594 23.484375 L 358.113281 23.328125 L 358.421875 23.183594 L 358.730469 23.050781 L 359.039062 22.933594 L 359.34375 22.824219 L 359.652344 22.722656 L 359.960938 22.632812 L 360.269531 22.550781 L 360.578125 22.472656 L 360.882812 22.40625 L 361.191406 22.34375 L 361.5 22.289062 L 361.808594 22.238281 L 362.113281 22.195312 L 362.421875 22.15625 L 362.730469 22.121094 L 363.039062 22.089844 L 363.347656 22.0625 L 363.652344 22.035156 L 364.578125 21.976562 L 364.882812 21.964844 L 365.191406 21.949219 L 365.5 21.941406 L 365.808594 21.929688 L 366.117188 21.921875 L 366.421875 21.914062 L 367.347656 21.902344 L 367.652344 21.898438 L 368.269531 21.890625 L 368.578125 21.890625 L 368.886719 21.886719 L 369.808594 21.886719 L 370.117188 21.882812 L 381.503906 21.882812 L 381.808594 21.886719 L 382.734375 21.886719 L 383.039062 21.890625 L 383.347656 21.890625 L 384.273438 21.902344 L 384.578125 21.90625 L 385.195312 21.914062 L 385.503906 21.921875 L 385.808594 21.929688 L 386.117188 21.941406 L 386.425781 21.949219 L 386.734375 21.964844 L 387.042969 21.976562 L 387.347656 21.996094 L 387.964844 22.035156 L 388.273438 22.0625 L 388.578125 22.089844 L 388.886719 22.121094 L 389.195312 22.15625 L 389.503906 22.195312 L 389.8125 22.238281 L 390.117188 22.289062 L 390.425781 22.34375 L 390.734375 22.40625 L 391.042969 22.472656 L 391.351562 22.550781 L 391.65625 22.632812 L 391.964844 22.722656 L 392.273438 22.824219 L 392.582031 22.933594 L 392.886719 23.050781 L 393.195312 23.183594 L 393.503906 23.328125 L 393.8125 23.484375 L 394.121094 23.652344 L 394.425781 23.835938 L 394.734375 24.035156 L 395.042969 24.25 L 395.351562 24.480469 L 395.65625 24.734375 L 395.964844 25.003906 L 396.273438 25.292969 L 396.582031 25.605469 L 396.890625 25.9375 L 397.195312 26.296875 L 397.503906 26.679688 L 397.8125 27.085938 L 398.121094 27.523438 L 398.425781 27.984375 L 398.734375 28.480469 L 399.042969 29.003906 L 399.351562 29.558594 L 399.660156 30.144531 L 399.964844 30.769531 L 400.273438 31.425781 L 400.582031 32.117188 L 400.890625 32.847656 L 401.195312 33.617188 L 401.503906 34.425781 L 401.8125 35.269531 L 402.121094 36.15625 L 402.429688 37.085938 L 402.734375 38.054688 L 403.042969 39.070312 L 403.351562 40.125 L 403.660156 41.21875 L 403.964844 42.359375 L 404.273438 43.542969 L 404.582031 44.769531 L 404.890625 46.039062 L 405.199219 47.351562 L 405.503906 48.703125 L 405.8125 50.097656 L 406.121094 51.53125 L 406.429688 53.003906 L 406.738281 54.515625 L 407.042969 56.0625 L 407.351562 57.648438 L 407.660156 59.265625 L 407.96875 60.914062 L 408.273438 62.59375 L 408.582031 64.304688 L 408.890625 66.039062 L 409.199219 67.800781 L 409.507812 69.585938 L 409.8125 71.386719 L 410.121094 73.207031 L 410.429688 75.046875 L 410.738281 76.894531 L 411.042969 78.753906 L 411.351562 80.625 L 411.660156 82.5 L 412.277344 86.257812 L 412.582031 88.132812 L 412.890625 90.007812 L 413.199219 91.878906 L 413.507812 93.738281 L 413.8125 95.589844 L 414.121094 97.425781 L 414.429688 99.25 L 414.738281 101.058594 L 415.046875 102.847656 L 415.351562 104.617188 L 415.660156 106.367188 L 415.96875 108.097656 L 416.277344 109.800781 L 416.582031 111.476562 L 416.890625 113.128906 L 417.199219 114.753906 L 417.507812 116.351562 L 417.816406 117.921875 L 418.121094 119.460938 L 418.429688 120.972656 L 418.738281 122.449219 L 419.046875 123.898438 L 419.351562 125.316406 L 419.660156 126.699219 L 419.96875 128.054688 L 420.277344 129.378906 L 420.585938 130.667969 L 420.890625 131.929688 L 421.199219 133.15625 L 421.507812 134.355469 L 421.816406 135.519531 L 422.125 136.65625 L 422.429688 137.761719 L 422.738281 138.839844 L 423.046875 139.882812 L 423.355469 140.902344 L 423.660156 141.890625 L 423.96875 142.851562 L 424.277344 143.785156 L 424.585938 144.691406 L 424.894531 145.570312 L 425.199219 146.425781 L 425.507812 147.253906 L 425.816406 148.054688 L 426.125 148.835938 L 426.429688 149.59375 L 426.738281 150.324219 L 427.046875 151.035156 L 427.355469 151.722656 L 427.664062 152.390625 L 427.96875 153.039062 L 428.277344 153.664062 L 428.585938 154.273438 L 428.894531 154.859375 L 429.199219 155.429688 L 429.507812 155.984375 L 429.816406 156.515625 L 430.125 157.035156 L 430.433594 157.535156 L 430.738281 158.019531 L 431.046875 158.492188 L 431.355469 158.945312 L 431.664062 159.386719 L 431.96875 159.8125 L 432.277344 160.226562 L 432.585938 160.625 L 432.894531 161.011719 L 433.203125 161.386719 L 433.507812 161.75 L 433.816406 162.101562 L 434.125 162.445312 L 434.433594 162.773438 L 434.738281 163.09375 L 435.046875 163.402344 L 435.355469 163.699219 L 435.664062 163.992188 L 435.972656 164.273438 L 436.277344 164.542969 L 436.585938 164.808594 L 436.894531 165.0625 L 437.203125 165.308594 L 437.507812 165.550781 L 437.816406 165.78125 L 438.125 166.007812 L 438.433594 166.222656 L 438.742188 166.433594 L 439.046875 166.640625 L 439.355469 166.839844 L 439.664062 167.03125 L 440.28125 167.398438 L 440.585938 167.574219 L 440.894531 167.742188 L 441.203125 167.90625 L 441.511719 168.066406 L 441.816406 168.222656 L 442.125 168.371094 L 442.742188 168.660156 L 443.050781 168.796875 L 443.355469 168.929688 L 443.664062 169.058594 L 443.972656 169.183594 L 444.28125 169.304688 L 444.585938 169.421875 L 444.894531 169.539062 L 445.511719 169.757812 L 445.820312 169.863281 L 446.125 169.964844 L 446.433594 170.0625 L 447.050781 170.25 L 447.355469 170.34375 L 447.972656 170.515625 L 448.589844 170.679688 L 448.894531 170.757812 L 449.820312 170.980469 L 450.125 171.050781 L 451.050781 171.25 L 451.359375 171.3125 L 451.664062 171.371094 L 451.972656 171.433594 L 452.28125 171.488281 L 452.589844 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="177.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="177.320312"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="177.320312"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="177.320312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="139.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="139.320312"/>
+ <use xlink:href="#glyph0-3" x="273.594788" y="139.320312"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="139.320312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="101.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="101.320312"/>
+ <use xlink:href="#glyph0-4" x="273.594788" y="101.320312"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="101.320312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="63.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="63.320312"/>
+ <use xlink:href="#glyph0-5" x="273.594788" y="63.320312"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="63.320312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="265.59375" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 173.882812 L 291.351562 173.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 135.882812 L 291.351562 135.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 97.882812 L 291.351562 97.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 59.882812 L 291.351562 59.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 21.882812 L 291.351562 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 183.28125 L 299.03125 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 183.28125 L 337.417969 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 183.28125 L 375.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 183.28125 L 414.199219 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 183.28125 L 452.589844 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="289.695312" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="295.030899" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="297.69635" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="303.031937" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="328.082031" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="333.417618" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="336.083069" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="341.418655" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="366.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="371.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="374.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="379.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="404.863281" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="410.198868" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="412.864319" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="418.199905" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="443.253906" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="448.589493" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="451.254944" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="456.59053" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="372.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="258.992188" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="258.992188" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="258.992188" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="258.992188" y="90.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-9" x="248.335938" y="10.800781"/>
+ <use xlink:href="#glyph5-8" x="257.001953" y="10.800781"/>
+ <use xlink:href="#glyph5-7" x="263.675781" y="10.800781"/>
+ <use xlink:href="#glyph5-7" x="267.009766" y="10.800781"/>
+</g>
+<g clip-path="url(#clip41)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 474.667969 216 L 712 216 L 712 0 L 474.667969 0 Z "/>
+</g>
+<g clip-path="url(#clip42)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 474.667969 216 L 712 216 L 712 0 L 474.667969 0 Z "/>
+</g>
+<g clip-path="url(#clip43)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 528.683594 179.027344 L 697.597656 179.027344 L 697.597656 14.398438 L 528.683594 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip44)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 152.835938 L 697.601562 152.835938 "/>
+</g>
+<g clip-path="url(#clip45)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 115.421875 L 697.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip46)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 78.007812 L 697.601562 78.007812 "/>
+</g>
+<g clip-path="url(#clip47)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 40.589844 L 697.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip48)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.558594 179.027344 L 555.558594 14.398438 "/>
+</g>
+<g clip-path="url(#clip49)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 593.949219 179.027344 L 593.949219 14.398438 "/>
+</g>
+<g clip-path="url(#clip50)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 632.335938 179.027344 L 632.335938 14.398438 "/>
+</g>
+<g clip-path="url(#clip51)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 670.726562 179.027344 L 670.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip52)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 171.546875 L 697.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip53)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 134.128906 L 697.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip54)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 96.714844 L 697.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip55)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 59.296875 L 697.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip56)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 21.882812 L 697.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip57)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 179.027344 L 536.363281 14.398438 "/>
+</g>
+<g clip-path="url(#clip58)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 179.027344 L 574.753906 14.398438 "/>
+</g>
+<g clip-path="url(#clip59)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 179.027344 L 613.140625 14.398438 "/>
+</g>
+<g clip-path="url(#clip60)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 179.027344 L 651.53125 14.398438 "/>
+</g>
+<g clip-path="url(#clip61)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 179.027344 L 689.921875 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 536.363281 171.546875 L 536.671875 171.542969 L 536.976562 171.527344 L 537.285156 171.503906 L 537.59375 171.46875 L 537.902344 171.425781 L 538.210938 171.371094 L 538.515625 171.308594 L 538.824219 171.238281 L 539.132812 171.15625 L 539.441406 171.066406 L 539.746094 170.964844 L 540.054688 170.851562 L 540.363281 170.734375 L 540.671875 170.601562 L 540.980469 170.464844 L 541.285156 170.316406 L 541.59375 170.15625 L 541.902344 169.988281 L 542.210938 169.808594 L 542.515625 169.621094 L 542.824219 169.425781 L 543.132812 169.21875 L 543.441406 169.003906 L 543.75 168.777344 L 544.054688 168.539062 L 544.363281 168.296875 L 544.671875 168.039062 L 544.980469 167.777344 L 545.289062 167.503906 L 545.59375 167.21875 L 545.902344 166.925781 L 546.210938 166.621094 L 546.519531 166.308594 L 546.824219 165.988281 L 547.132812 165.65625 L 547.441406 165.3125 L 547.75 164.964844 L 548.058594 164.601562 L 548.363281 164.230469 L 548.671875 163.851562 L 548.980469 163.460938 L 549.289062 163.0625 L 549.59375 162.65625 L 549.902344 162.238281 L 550.210938 161.808594 L 550.519531 161.371094 L 550.828125 160.925781 L 551.132812 160.46875 L 551.441406 160 L 551.75 159.523438 L 552.058594 159.039062 L 552.363281 158.542969 L 552.671875 158.039062 L 552.980469 157.523438 L 553.289062 157 L 553.597656 156.464844 L 553.902344 155.921875 L 554.210938 155.371094 L 554.519531 154.808594 L 554.828125 154.234375 L 555.132812 153.652344 L 555.441406 153.0625 L 555.75 152.460938 L 556.058594 151.851562 L 556.367188 151.230469 L 556.671875 150.601562 L 556.980469 149.960938 L 557.289062 149.3125 L 557.597656 148.652344 L 557.902344 147.984375 L 558.210938 147.304688 L 558.519531 146.617188 L 558.828125 145.921875 L 559.136719 145.214844 L 559.441406 144.5 L 559.75 143.773438 L 560.058594 143.035156 L 560.367188 142.292969 L 560.671875 141.535156 L 560.980469 140.773438 L 561.289062 139.996094 L 561.597656 139.214844 L 561.90625 138.421875 L 562.210938 137.617188 L 562.519531 136.804688 L 562.828125 135.984375 L 563.136719 135.152344 L 563.445312 134.308594 L 563.75 133.457031 L 564.058594 132.597656 L 564.367188 131.726562 L 564.675781 130.847656 L 564.980469 129.957031 L 565.289062 129.058594 L 565.597656 128.148438 L 565.90625 127.230469 L 566.214844 126.304688 L 566.519531 125.367188 L 566.828125 124.417969 L 567.136719 123.460938 L 567.445312 122.496094 L 567.75 121.519531 L 568.058594 120.53125 L 568.367188 119.539062 L 568.675781 118.53125 L 568.984375 117.519531 L 569.289062 116.492188 L 569.597656 115.460938 L 569.90625 114.417969 L 570.214844 113.363281 L 570.519531 112.300781 L 570.828125 111.230469 L 571.136719 110.148438 L 571.445312 109.054688 L 571.753906 107.953125 L 572.058594 106.84375 L 572.367188 105.722656 L 572.675781 104.59375 L 572.984375 103.453125 L 573.289062 102.304688 L 573.597656 101.144531 L 573.90625 99.976562 L 574.214844 98.796875 L 574.523438 97.609375 L 574.828125 96.414062 L 575.136719 95.222656 L 575.445312 94.039062 L 575.753906 92.867188 L 576.058594 91.703125 L 576.367188 90.546875 L 576.675781 89.402344 L 576.984375 88.269531 L 577.292969 87.144531 L 577.597656 86.027344 L 577.90625 84.921875 L 578.214844 83.824219 L 578.523438 82.738281 L 578.832031 81.660156 L 579.136719 80.59375 L 579.445312 79.535156 L 579.753906 78.488281 L 580.0625 77.449219 L 580.367188 76.421875 L 580.675781 75.402344 L 580.984375 74.390625 L 581.292969 73.390625 L 581.601562 72.402344 L 581.90625 71.417969 L 582.214844 70.449219 L 582.523438 69.488281 L 582.832031 68.535156 L 583.136719 67.59375 L 583.445312 66.660156 L 583.753906 65.734375 L 584.0625 64.824219 L 584.371094 63.917969 L 584.675781 63.023438 L 584.984375 62.140625 L 585.292969 61.265625 L 585.601562 60.398438 L 585.90625 59.542969 L 586.214844 58.695312 L 586.523438 57.859375 L 586.832031 57.03125 L 587.140625 56.214844 L 587.445312 55.40625 L 587.753906 54.609375 L 588.0625 53.820312 L 588.371094 53.042969 L 588.675781 52.273438 L 588.984375 51.511719 L 589.292969 50.761719 L 589.601562 50.023438 L 589.910156 49.292969 L 590.214844 48.570312 L 590.523438 47.859375 L 590.832031 47.15625 L 591.140625 46.464844 L 591.445312 45.78125 L 591.753906 45.109375 L 592.0625 44.445312 L 592.371094 43.789062 L 592.679688 43.144531 L 592.984375 42.511719 L 593.292969 41.886719 L 593.601562 41.269531 L 593.910156 40.664062 L 594.21875 40.070312 L 594.523438 39.480469 L 594.832031 38.90625 L 595.140625 38.335938 L 595.449219 37.78125 L 595.753906 37.230469 L 596.0625 36.691406 L 596.371094 36.164062 L 596.679688 35.644531 L 596.988281 35.136719 L 597.292969 34.636719 L 597.601562 34.144531 L 597.910156 33.664062 L 598.21875 33.191406 L 598.523438 32.730469 L 598.832031 32.277344 L 599.140625 31.835938 L 599.449219 31.402344 L 599.757812 30.980469 L 600.0625 30.566406 L 600.371094 30.164062 L 600.679688 29.769531 L 600.988281 29.382812 L 601.292969 29.007812 L 601.601562 28.644531 L 601.910156 28.289062 L 602.21875 27.941406 L 602.527344 27.605469 L 602.832031 27.277344 L 603.140625 26.960938 L 603.449219 26.652344 L 603.757812 26.355469 L 604.0625 26.066406 L 604.371094 25.789062 L 604.679688 25.519531 L 604.988281 25.257812 L 605.296875 25.007812 L 605.601562 24.769531 L 605.910156 24.539062 L 606.21875 24.316406 L 606.527344 24.105469 L 606.832031 23.902344 L 607.140625 23.710938 L 607.449219 23.527344 L 607.757812 23.355469 L 608.066406 23.191406 L 608.371094 23.039062 L 608.679688 22.894531 L 608.988281 22.757812 L 609.296875 22.632812 L 609.601562 22.519531 L 609.910156 22.410156 L 610.21875 22.316406 L 610.527344 22.230469 L 610.835938 22.152344 L 611.140625 22.085938 L 611.449219 22.027344 L 611.757812 21.980469 L 612.066406 21.941406 L 612.375 21.910156 L 612.679688 21.894531 L 612.988281 21.882812 L 613.296875 21.882812 L 613.605469 21.894531 L 613.910156 21.910156 L 614.21875 21.941406 L 614.527344 21.980469 L 614.835938 22.027344 L 615.144531 22.085938 L 615.449219 22.152344 L 615.757812 22.230469 L 616.066406 22.316406 L 616.375 22.410156 L 616.679688 22.519531 L 616.988281 22.632812 L 617.296875 22.757812 L 617.605469 22.894531 L 617.914062 23.039062 L 618.21875 23.191406 L 618.527344 23.355469 L 618.835938 23.527344 L 619.144531 23.710938 L 619.449219 23.902344 L 619.757812 24.105469 L 620.066406 24.316406 L 620.375 24.539062 L 620.683594 24.769531 L 620.988281 25.007812 L 621.296875 25.257812 L 621.605469 25.519531 L 621.914062 25.789062 L 622.21875 26.066406 L 622.527344 26.355469 L 622.835938 26.652344 L 623.144531 26.960938 L 623.453125 27.277344 L 623.757812 27.605469 L 624.066406 27.941406 L 624.375 28.289062 L 624.683594 28.644531 L 624.988281 29.007812 L 625.296875 29.382812 L 625.605469 29.769531 L 625.914062 30.164062 L 626.222656 30.566406 L 626.527344 30.980469 L 626.835938 31.402344 L 627.144531 31.835938 L 627.453125 32.277344 L 627.761719 32.730469 L 628.066406 33.191406 L 628.375 33.664062 L 628.683594 34.144531 L 628.992188 34.636719 L 629.296875 35.136719 L 629.605469 35.644531 L 629.914062 36.164062 L 630.222656 36.691406 L 630.53125 37.230469 L 630.835938 37.78125 L 631.144531 38.335938 L 631.453125 38.90625 L 631.761719 39.480469 L 632.066406 40.070312 L 632.375 40.664062 L 632.683594 41.269531 L 632.992188 41.886719 L 633.300781 42.511719 L 633.605469 43.144531 L 633.914062 43.789062 L 634.222656 44.445312 L 634.53125 45.109375 L 634.835938 45.78125 L 635.144531 46.464844 L 635.453125 47.15625 L 635.761719 47.859375 L 636.070312 48.570312 L 636.375 49.292969 L 636.683594 50.023438 L 636.992188 50.761719 L 637.300781 51.511719 L 637.605469 52.273438 L 637.914062 53.042969 L 638.222656 53.820312 L 638.53125 54.609375 L 638.839844 55.40625 L 639.144531 56.214844 L 639.453125 57.03125 L 639.761719 57.859375 L 640.070312 58.695312 L 640.375 59.542969 L 640.683594 60.398438 L 640.992188 61.265625 L 641.300781 62.140625 L 641.609375 63.023438 L 641.914062 63.917969 L 642.222656 64.824219 L 642.53125 65.734375 L 642.839844 66.660156 L 643.148438 67.59375 L 643.453125 68.535156 L 643.761719 69.488281 L 644.070312 70.449219 L 644.378906 71.417969 L 644.683594 72.402344 L 644.992188 73.390625 L 645.300781 74.390625 L 645.609375 75.402344 L 645.917969 76.421875 L 646.222656 77.449219 L 646.53125 78.488281 L 646.839844 79.535156 L 647.148438 80.59375 L 647.453125 81.660156 L 647.761719 82.738281 L 648.070312 83.824219 L 648.378906 84.921875 L 648.6875 86.027344 L 648.992188 87.144531 L 649.300781 88.269531 L 649.609375 89.402344 L 649.917969 90.546875 L 650.222656 91.703125 L 650.53125 92.867188 L 650.839844 94.039062 L 651.148438 95.222656 L 651.457031 96.414062 L 651.761719 97.609375 L 652.070312 98.796875 L 652.378906 99.976562 L 652.6875 101.144531 L 652.992188 102.304688 L 653.300781 103.453125 L 653.609375 104.59375 L 653.917969 105.722656 L 654.226562 106.84375 L 654.53125 107.953125 L 654.839844 109.054688 L 655.148438 110.148438 L 655.457031 111.230469 L 655.761719 112.300781 L 656.070312 113.363281 L 656.378906 114.417969 L 656.6875 115.460938 L 656.996094 116.492188 L 657.300781 117.519531 L 657.609375 118.53125 L 657.917969 119.539062 L 658.226562 120.53125 L 658.53125 121.519531 L 658.839844 122.496094 L 659.148438 123.460938 L 659.457031 124.417969 L 659.765625 125.367188 L 660.070312 126.304688 L 660.378906 127.230469 L 660.6875 128.148438 L 660.996094 129.058594 L 661.304688 129.957031 L 661.609375 130.847656 L 661.917969 131.726562 L 662.226562 132.597656 L 662.535156 133.457031 L 662.839844 134.308594 L 663.148438 135.152344 L 663.457031 135.984375 L 663.765625 136.804688 L 664.074219 137.617188 L 664.378906 138.421875 L 664.6875 139.214844 L 664.996094 139.996094 L 665.304688 140.773438 L 665.609375 141.535156 L 665.917969 142.292969 L 666.226562 143.035156 L 666.535156 143.773438 L 666.84375 144.5 L 667.148438 145.214844 L 667.457031 145.921875 L 667.765625 146.617188 L 668.074219 147.304688 L 668.378906 147.984375 L 668.6875 148.652344 L 668.996094 149.3125 L 669.304688 149.960938 L 669.613281 150.601562 L 669.917969 151.230469 L 670.226562 151.851562 L 670.535156 152.460938 L 670.84375 153.0625 L 671.148438 153.652344 L 671.457031 154.234375 L 671.765625 154.808594 L 672.074219 155.371094 L 672.382812 155.921875 L 672.6875 156.464844 L 672.996094 157 L 673.304688 157.523438 L 673.613281 158.039062 L 673.917969 158.542969 L 674.226562 159.039062 L 674.535156 159.523438 L 674.84375 160 L 675.152344 160.46875 L 675.457031 160.925781 L 675.765625 161.371094 L 676.074219 161.808594 L 676.382812 162.238281 L 676.691406 162.65625 L 676.996094 163.0625 L 677.304688 163.460938 L 677.613281 163.851562 L 677.921875 164.230469 L 678.226562 164.601562 L 678.535156 164.964844 L 678.84375 165.3125 L 679.152344 165.65625 L 679.460938 165.988281 L 679.765625 166.308594 L 680.074219 166.621094 L 680.382812 166.925781 L 680.691406 167.21875 L 680.996094 167.503906 L 681.304688 167.777344 L 681.613281 168.039062 L 681.921875 168.296875 L 682.230469 168.539062 L 682.535156 168.777344 L 682.84375 169.003906 L 683.152344 169.21875 L 683.460938 169.425781 L 683.765625 169.621094 L 684.074219 169.808594 L 684.382812 169.988281 L 684.691406 170.15625 L 685 170.316406 L 685.304688 170.464844 L 685.613281 170.601562 L 685.921875 170.734375 L 686.230469 170.851562 L 686.535156 170.964844 L 686.84375 171.066406 L 687.152344 171.15625 L 687.460938 171.238281 L 687.769531 171.308594 L 688.074219 171.371094 L 688.382812 171.425781 L 688.691406 171.46875 L 689 171.503906 L 689.304688 171.527344 L 689.613281 171.542969 L 689.921875 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="510.926819" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="510.926819" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="510.926819" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="502.925781" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 171.546875 L 528.683594 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 134.128906 L 528.683594 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 96.714844 L 528.683594 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 59.296875 L 528.683594 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 21.882812 L 528.683594 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 183.28125 L 536.363281 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 183.28125 L 574.753906 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 183.28125 L 613.140625 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 183.28125 L 651.53125 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 183.28125 L 689.921875 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="527.027344" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="532.36293" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="535.028381" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="540.363968" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="565.417969" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="570.753555" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="573.419006" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="578.754593" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="603.804688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="609.140274" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="611.805725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="617.141312" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="642.195312" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="647.530899" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="650.19635" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="655.531937" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="680.585938" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="685.921524" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="688.586975" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="693.922562" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="610.140625" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="496.324219" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="496.324219" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="496.324219" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="496.324219" y="90.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-10" x="498.34375" y="10.800781"/>
+ <use xlink:href="#glyph5-3" x="506.347656" y="10.800781"/>
+ <use xlink:href="#glyph5-11" x="509.681641" y="10.800781"/>
+ <use xlink:href="#glyph5-12" x="517.685547" y="10.800781"/>
+ <use xlink:href="#glyph5-4" x="525.015625" y="10.800781"/>
+ <use xlink:href="#glyph5-13" x="531.689453" y="10.800781"/>
+ <use xlink:href="#glyph5-8" x="539.019531" y="10.800781"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 432 L 237.332031 432 L 237.332031 216 L 0 216 Z "/>
+<g clip-path="url(#clip62)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 432 L 237.332031 432 L 237.332031 216 L 0 216 Z "/>
+</g>
+<g clip-path="url(#clip63)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 395.027344 L 222.933594 395.027344 L 222.933594 230.398438 L 54.019531 230.398438 Z "/>
+</g>
+<g clip-path="url(#clip64)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 368.839844 L 222.933594 368.839844 "/>
+</g>
+<g clip-path="url(#clip65)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 331.421875 L 222.933594 331.421875 "/>
+</g>
+<g clip-path="url(#clip66)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 294.007812 L 222.933594 294.007812 "/>
+</g>
+<g clip-path="url(#clip67)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 256.589844 L 222.933594 256.589844 "/>
+</g>
+<g clip-path="url(#clip68)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 80.890625 395.027344 L 80.890625 230.398438 "/>
+</g>
+<g clip-path="url(#clip69)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 119.28125 395.027344 L 119.28125 230.398438 "/>
+</g>
+<g clip-path="url(#clip70)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.671875 395.027344 L 157.671875 230.398438 "/>
+</g>
+<g clip-path="url(#clip71)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 196.058594 395.027344 L 196.058594 230.398438 "/>
+</g>
+<g clip-path="url(#clip72)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 387.546875 L 222.933594 387.546875 "/>
+</g>
+<g clip-path="url(#clip73)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 350.128906 L 222.933594 350.128906 "/>
+</g>
+<g clip-path="url(#clip74)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 312.714844 L 222.933594 312.714844 "/>
+</g>
+<g clip-path="url(#clip75)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 275.296875 L 222.933594 275.296875 "/>
+</g>
+<g clip-path="url(#clip76)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 237.882812 L 222.933594 237.882812 "/>
+</g>
+<g clip-path="url(#clip77)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 395.027344 L 61.695312 230.398438 "/>
+</g>
+<g clip-path="url(#clip78)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 395.027344 L 100.085938 230.398438 "/>
+</g>
+<g clip-path="url(#clip79)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 395.027344 L 138.476562 230.398438 "/>
+</g>
+<g clip-path="url(#clip80)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 395.027344 L 176.867188 230.398438 "/>
+</g>
+<g clip-path="url(#clip81)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 395.027344 L 215.253906 230.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 61.695312 387.546875 L 62.003906 386.347656 L 62.3125 385.144531 L 62.621094 383.945312 L 62.925781 382.746094 L 63.851562 379.148438 L 64.15625 377.949219 L 64.773438 375.550781 L 65.082031 374.347656 L 65.390625 373.148438 L 65.695312 371.949219 L 66.621094 368.351562 L 66.925781 367.152344 L 67.234375 365.953125 L 67.542969 364.75 L 68.160156 362.351562 L 68.464844 361.152344 L 69.390625 357.554688 L 69.695312 356.355469 L 70.003906 355.152344 L 70.929688 351.554688 L 71.234375 350.355469 L 72.160156 346.757812 L 72.46875 345.554688 L 72.773438 344.355469 L 73.699219 340.757812 L 74.003906 339.558594 L 74.621094 337.160156 L 74.929688 335.957031 L 75.238281 334.757812 L 75.542969 333.558594 L 76.46875 329.960938 L 76.773438 328.761719 L 77.082031 327.5625 L 77.390625 326.359375 L 78.007812 323.960938 L 78.3125 322.761719 L 79.238281 319.164062 L 79.542969 317.964844 L 79.851562 316.761719 L 80.777344 313.164062 L 81.082031 311.964844 L 82.007812 308.367188 L 82.3125 307.164062 L 83.546875 302.367188 L 83.851562 301.167969 L 84.46875 298.769531 L 84.777344 297.566406 L 85.082031 296.367188 L 86.316406 291.570312 L 86.621094 290.371094 L 86.929688 289.171875 L 87.238281 287.96875 L 87.855469 285.570312 L 88.160156 284.371094 L 89.085938 280.773438 L 89.390625 279.574219 L 89.699219 278.375 L 90.007812 277.171875 L 90.625 274.773438 L 90.929688 273.574219 L 91.855469 269.976562 L 92.160156 268.777344 L 92.46875 267.574219 L 93.394531 263.976562 L 93.699219 262.777344 L 94.625 259.179688 L 94.929688 257.976562 L 96.164062 253.179688 L 96.46875 251.980469 L 97.085938 249.582031 L 97.394531 248.378906 L 97.699219 247.179688 L 98.933594 242.382812 L 99.238281 241.183594 L 99.546875 239.984375 L 99.855469 238.78125 L 100.164062 237.882812 L 176.789062 237.882812 L 177.097656 238.78125 L 177.402344 239.984375 L 178.636719 244.78125 L 178.941406 245.980469 L 179.558594 248.378906 L 179.867188 249.582031 L 180.171875 250.78125 L 181.40625 255.578125 L 181.710938 256.777344 L 182.019531 257.976562 L 182.328125 259.179688 L 182.636719 260.378906 L 182.941406 261.578125 L 184.175781 266.375 L 184.480469 267.574219 L 184.789062 268.777344 L 185.714844 272.375 L 186.019531 273.574219 L 186.945312 277.171875 L 187.25 278.375 L 188.484375 283.171875 L 188.789062 284.371094 L 189.714844 287.96875 L 190.019531 289.171875 L 191.253906 293.96875 L 191.558594 295.167969 L 192.175781 297.566406 L 192.484375 298.769531 L 192.789062 299.96875 L 194.023438 304.765625 L 194.328125 305.964844 L 194.636719 307.164062 L 194.945312 308.367188 L 195.253906 309.566406 L 195.558594 310.765625 L 196.792969 315.5625 L 197.097656 316.761719 L 197.40625 317.964844 L 198.023438 320.363281 L 198.328125 321.5625 L 199.5625 326.359375 L 199.867188 327.5625 L 201.101562 332.359375 L 201.40625 333.558594 L 202.023438 335.957031 L 202.332031 337.160156 L 202.636719 338.359375 L 203.871094 343.15625 L 204.175781 344.355469 L 204.484375 345.554688 L 204.792969 346.757812 L 205.101562 347.957031 L 205.40625 349.15625 L 206.640625 353.953125 L 206.945312 355.152344 L 207.253906 356.355469 L 207.871094 358.753906 L 208.175781 359.953125 L 209.410156 364.75 L 209.714844 365.953125 L 210.640625 369.550781 L 210.945312 370.75 L 211.871094 374.347656 L 212.179688 375.550781 L 212.484375 376.75 L 213.410156 380.347656 L 213.714844 381.546875 L 214.640625 385.144531 L 214.949219 386.347656 L 215.253906 387.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="390.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="390.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="390.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="390.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="353.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="353.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="353.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="353.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="316.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="316.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="316.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="316.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="278.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="278.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="278.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="278.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="241.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="241.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="241.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="241.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 387.546875 L 54.019531 387.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 350.128906 L 54.019531 350.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 312.714844 L 54.019531 312.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 275.296875 L 54.019531 275.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 237.882812 L 54.019531 237.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 399.28125 L 61.695312 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 399.28125 L 100.085938 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 399.28125 L 138.476562 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 399.28125 L 176.867188 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 399.28125 L 215.253906 395.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="52.359375" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="57.694962" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="60.360413" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="65.695999" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="90.75" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="96.085587" y="408.992188"/>
+ <use xlink:href="#glyph0-3" x="98.751038" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="104.086624" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="129.140625" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="134.476212" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="137.141663" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="142.477249" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="167.53125" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="172.866837" y="408.992188"/>
+ <use xlink:href="#glyph0-5" x="175.532288" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="180.867874" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="205.917969" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="211.253555" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="213.919006" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="219.254593" y="408.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="135.476562" y="421.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="324.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="317.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="312.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="306.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-1" x="28.335938" y="226.800781"/>
+ <use xlink:href="#glyph5-2" x="35.666016" y="226.800781"/>
+ <use xlink:href="#glyph5-4" x="40.335938" y="226.800781"/>
+ <use xlink:href="#glyph5-13" x="47.009766" y="226.800781"/>
+ <use xlink:href="#glyph5-8" x="54.339844" y="226.800781"/>
+ <use xlink:href="#glyph5-14" x="61.013672" y="226.800781"/>
+ <use xlink:href="#glyph5-15" x="67.013672" y="226.800781"/>
+ <use xlink:href="#glyph5-3" x="74.34375" y="226.800781"/>
+ <use xlink:href="#glyph5-16" x="77.677734" y="226.800781"/>
+</g>
+<g clip-path="url(#clip82)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 237.332031 432 L 474.664062 432 L 474.664062 216 L 237.332031 216 Z "/>
+</g>
+<g clip-path="url(#clip83)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 237.332031 432 L 474.664062 432 L 474.664062 216 L 237.332031 216 Z "/>
+</g>
+<g clip-path="url(#clip84)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 291.351562 395.027344 L 460.265625 395.027344 L 460.265625 230.398438 L 291.351562 230.398438 Z "/>
+</g>
+<g clip-path="url(#clip85)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 368.835938 L 460.265625 368.835938 "/>
+</g>
+<g clip-path="url(#clip86)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 331.421875 L 460.265625 331.421875 "/>
+</g>
+<g clip-path="url(#clip87)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 294.003906 L 460.265625 294.003906 "/>
+</g>
+<g clip-path="url(#clip88)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 256.589844 L 460.265625 256.589844 "/>
+</g>
+<g clip-path="url(#clip89)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 318.222656 395.027344 L 318.222656 230.398438 "/>
+</g>
+<g clip-path="url(#clip90)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.613281 395.027344 L 356.613281 230.398438 "/>
+</g>
+<g clip-path="url(#clip91)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 395.003906 395.027344 L 395.003906 230.398438 "/>
+</g>
+<g clip-path="url(#clip92)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 433.394531 395.027344 L 433.394531 230.398438 "/>
+</g>
+<g clip-path="url(#clip93)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 387.546875 L 460.265625 387.546875 "/>
+</g>
+<g clip-path="url(#clip94)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 350.128906 L 460.265625 350.128906 "/>
+</g>
+<g clip-path="url(#clip95)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 312.714844 L 460.265625 312.714844 "/>
+</g>
+<g clip-path="url(#clip96)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 275.296875 L 460.265625 275.296875 "/>
+</g>
+<g clip-path="url(#clip97)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 237.882812 L 460.265625 237.882812 "/>
+</g>
+<g clip-path="url(#clip98)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 395.027344 L 299.03125 230.398438 "/>
+</g>
+<g clip-path="url(#clip99)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 395.027344 L 337.417969 230.398438 "/>
+</g>
+<g clip-path="url(#clip100)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 395.027344 L 375.808594 230.398438 "/>
+</g>
+<g clip-path="url(#clip101)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 395.027344 L 414.199219 230.398438 "/>
+</g>
+<g clip-path="url(#clip102)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 395.027344 L 452.589844 230.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 299.03125 387.546875 L 299.335938 387.539062 L 299.644531 387.523438 L 299.953125 387.492188 L 300.261719 387.449219 L 300.566406 387.398438 L 300.875 387.332031 L 301.183594 387.253906 L 301.492188 387.167969 L 301.800781 387.066406 L 302.105469 386.953125 L 302.414062 386.828125 L 302.722656 386.691406 L 303.03125 386.546875 L 303.335938 386.386719 L 303.644531 386.214844 L 303.953125 386.03125 L 304.261719 385.839844 L 304.570312 385.632812 L 304.875 385.414062 L 305.183594 385.183594 L 305.492188 384.945312 L 305.800781 384.691406 L 306.105469 384.429688 L 306.414062 384.15625 L 306.722656 383.867188 L 307.03125 383.570312 L 307.339844 383.261719 L 307.644531 382.941406 L 307.953125 382.613281 L 308.261719 382.269531 L 308.570312 381.917969 L 308.878906 381.554688 L 309.183594 381.179688 L 309.492188 380.792969 L 309.800781 380.394531 L 310.109375 379.988281 L 310.414062 379.570312 L 310.722656 379.140625 L 311.03125 378.703125 L 311.339844 378.253906 L 311.648438 377.792969 L 311.953125 377.324219 L 312.261719 376.84375 L 312.570312 376.351562 L 312.878906 375.851562 L 313.183594 375.339844 L 313.492188 374.820312 L 313.800781 374.289062 L 314.109375 373.75 L 314.417969 373.199219 L 314.722656 372.640625 L 315.03125 372.070312 L 315.339844 371.492188 L 315.648438 370.902344 L 315.953125 370.308594 L 316.261719 369.699219 L 316.570312 369.085938 L 316.878906 368.460938 L 317.1875 367.828125 L 317.492188 367.1875 L 317.800781 366.535156 L 318.109375 365.878906 L 318.417969 365.210938 L 318.722656 364.535156 L 319.03125 363.851562 L 319.339844 363.160156 L 319.648438 362.457031 L 319.957031 361.75 L 320.261719 361.035156 L 320.570312 360.3125 L 320.878906 359.582031 L 321.1875 358.84375 L 321.492188 358.097656 L 321.800781 357.34375 L 322.109375 356.585938 L 322.417969 355.816406 L 322.726562 355.042969 L 323.03125 354.265625 L 323.339844 353.476562 L 323.648438 352.683594 L 323.957031 351.882812 L 324.265625 351.078125 L 324.570312 350.265625 L 324.878906 349.449219 L 325.1875 348.625 L 325.496094 347.792969 L 325.800781 346.960938 L 326.417969 345.273438 L 326.726562 344.421875 L 327.035156 343.566406 L 327.339844 342.707031 L 327.648438 341.839844 L 327.957031 340.96875 L 328.265625 340.09375 L 328.570312 339.214844 L 328.878906 338.332031 L 329.1875 337.445312 L 329.496094 336.554688 L 329.804688 335.660156 L 330.109375 334.761719 L 330.417969 333.859375 L 330.726562 332.953125 L 331.035156 332.042969 L 331.339844 331.132812 L 331.648438 330.21875 L 331.957031 329.300781 L 332.574219 327.457031 L 332.878906 326.53125 L 333.1875 325.605469 L 333.804688 323.746094 L 334.109375 322.8125 L 334.417969 321.878906 L 335.34375 319.066406 L 335.648438 318.128906 L 336.574219 315.304688 L 336.878906 314.363281 L 337.1875 313.421875 L 337.496094 312.476562 L 338.113281 310.59375 L 338.417969 309.652344 L 339.035156 307.769531 L 339.34375 306.832031 L 339.648438 305.890625 L 339.957031 304.953125 L 340.265625 304.019531 L 340.574219 303.082031 L 340.882812 302.148438 L 341.1875 301.21875 L 341.496094 300.285156 L 342.421875 297.507812 L 342.726562 296.585938 L 343.035156 295.667969 L 343.652344 293.839844 L 343.957031 292.929688 L 344.574219 291.117188 L 345.191406 289.320312 L 345.496094 288.425781 L 346.113281 286.652344 L 346.421875 285.773438 L 346.726562 284.894531 L 347.035156 284.023438 L 347.34375 283.15625 L 347.652344 282.292969 L 347.960938 281.433594 L 348.265625 280.578125 L 348.574219 279.730469 L 348.882812 278.886719 L 349.191406 278.050781 L 349.496094 277.21875 L 349.804688 276.390625 L 350.113281 275.570312 L 350.421875 274.753906 L 350.730469 273.945312 L 351.035156 273.144531 L 351.34375 272.347656 L 351.652344 271.554688 L 351.960938 270.773438 L 352.265625 269.996094 L 352.574219 269.226562 L 352.882812 268.460938 L 353.191406 267.707031 L 353.5 266.957031 L 353.804688 266.214844 L 354.113281 265.480469 L 354.421875 264.753906 L 354.730469 264.035156 L 355.035156 263.320312 L 355.34375 262.617188 L 355.652344 261.921875 L 355.960938 261.234375 L 356.269531 260.554688 L 356.574219 259.882812 L 356.882812 259.21875 L 357.191406 258.566406 L 357.5 257.917969 L 357.808594 257.28125 L 358.113281 256.652344 L 358.421875 256.035156 L 358.730469 255.421875 L 359.039062 254.820312 L 359.34375 254.230469 L 359.652344 253.644531 L 359.960938 253.070312 L 360.269531 252.507812 L 360.578125 251.953125 L 360.882812 251.40625 L 361.191406 250.871094 L 361.5 250.347656 L 361.808594 249.832031 L 362.113281 249.324219 L 362.421875 248.828125 L 362.730469 248.34375 L 363.039062 247.867188 L 363.347656 247.402344 L 363.652344 246.949219 L 363.960938 246.503906 L 364.269531 246.070312 L 364.578125 245.648438 L 364.882812 245.234375 L 365.191406 244.832031 L 365.5 244.441406 L 365.808594 244.0625 L 366.117188 243.691406 L 366.421875 243.332031 L 366.730469 242.984375 L 367.039062 242.648438 L 367.347656 242.324219 L 367.652344 242.007812 L 367.960938 241.707031 L 368.269531 241.414062 L 368.578125 241.132812 L 368.886719 240.863281 L 369.191406 240.605469 L 369.5 240.359375 L 369.808594 240.125 L 370.117188 239.902344 L 370.421875 239.691406 L 370.730469 239.492188 L 371.039062 239.300781 L 371.347656 239.125 L 371.65625 238.960938 L 371.960938 238.808594 L 372.269531 238.664062 L 372.578125 238.535156 L 372.886719 238.417969 L 373.195312 238.308594 L 373.5 238.214844 L 373.808594 238.132812 L 374.117188 238.0625 L 374.425781 238 L 374.730469 237.953125 L 375.039062 237.917969 L 375.347656 237.894531 L 375.65625 237.882812 L 375.964844 237.882812 L 376.269531 237.894531 L 376.578125 237.917969 L 376.886719 237.953125 L 377.195312 238 L 377.5 238.0625 L 377.808594 238.132812 L 378.117188 238.214844 L 378.425781 238.308594 L 378.734375 238.417969 L 379.039062 238.535156 L 379.347656 238.664062 L 379.65625 238.808594 L 379.964844 238.960938 L 380.269531 239.125 L 380.578125 239.300781 L 380.886719 239.492188 L 381.195312 239.691406 L 381.503906 239.902344 L 381.808594 240.125 L 382.117188 240.359375 L 382.425781 240.605469 L 382.734375 240.863281 L 383.039062 241.132812 L 383.347656 241.414062 L 383.65625 241.707031 L 383.964844 242.007812 L 384.273438 242.324219 L 384.578125 242.648438 L 384.886719 242.984375 L 385.195312 243.332031 L 385.503906 243.691406 L 385.808594 244.0625 L 386.117188 244.441406 L 386.425781 244.832031 L 386.734375 245.234375 L 387.042969 245.648438 L 387.347656 246.070312 L 387.65625 246.503906 L 387.964844 246.949219 L 388.273438 247.402344 L 388.578125 247.867188 L 388.886719 248.34375 L 389.195312 248.828125 L 389.503906 249.324219 L 389.8125 249.832031 L 390.117188 250.347656 L 390.425781 250.871094 L 390.734375 251.40625 L 391.042969 251.953125 L 391.351562 252.507812 L 391.65625 253.070312 L 391.964844 253.644531 L 392.273438 254.230469 L 392.582031 254.820312 L 392.886719 255.421875 L 393.195312 256.035156 L 393.503906 256.652344 L 393.8125 257.28125 L 394.121094 257.917969 L 394.425781 258.566406 L 394.734375 259.21875 L 395.042969 259.882812 L 395.351562 260.554688 L 395.65625 261.234375 L 395.964844 261.921875 L 396.273438 262.617188 L 396.582031 263.320312 L 396.890625 264.035156 L 397.195312 264.753906 L 397.503906 265.480469 L 397.8125 266.214844 L 398.121094 266.957031 L 398.425781 267.707031 L 398.734375 268.460938 L 399.042969 269.226562 L 399.351562 269.996094 L 399.660156 270.773438 L 399.964844 271.554688 L 400.273438 272.347656 L 400.582031 273.144531 L 400.890625 273.945312 L 401.195312 274.753906 L 401.503906 275.570312 L 401.8125 276.390625 L 402.121094 277.21875 L 402.429688 278.050781 L 402.734375 278.886719 L 403.042969 279.730469 L 403.351562 280.578125 L 403.660156 281.433594 L 403.964844 282.292969 L 404.273438 283.15625 L 404.582031 284.023438 L 404.890625 284.894531 L 405.199219 285.773438 L 405.503906 286.652344 L 406.121094 288.425781 L 406.429688 289.320312 L 406.738281 290.21875 L 407.042969 291.117188 L 407.660156 292.929688 L 407.96875 293.839844 L 408.273438 294.753906 L 408.582031 295.667969 L 408.890625 296.585938 L 409.199219 297.507812 L 409.507812 298.433594 L 409.8125 299.359375 L 410.121094 300.285156 L 410.429688 301.21875 L 410.738281 302.148438 L 411.042969 303.082031 L 411.351562 304.019531 L 411.660156 304.953125 L 411.96875 305.890625 L 412.277344 306.832031 L 412.582031 307.769531 L 413.507812 310.59375 L 413.8125 311.535156 L 414.121094 312.476562 L 414.429688 313.421875 L 415.046875 315.304688 L 415.351562 316.246094 L 415.96875 318.128906 L 416.277344 319.066406 L 416.582031 320.003906 L 417.199219 321.878906 L 417.816406 323.746094 L 418.121094 324.675781 L 418.429688 325.605469 L 419.046875 327.457031 L 419.351562 328.378906 L 419.660156 329.300781 L 419.96875 330.21875 L 420.277344 331.132812 L 420.585938 332.042969 L 420.890625 332.953125 L 421.199219 333.859375 L 421.507812 334.761719 L 421.816406 335.660156 L 422.125 336.554688 L 422.429688 337.445312 L 422.738281 338.332031 L 423.046875 339.214844 L 423.355469 340.09375 L 423.660156 340.96875 L 423.96875 341.839844 L 424.277344 342.707031 L 424.585938 343.566406 L 424.894531 344.421875 L 425.199219 345.273438 L 425.816406 346.960938 L 426.125 347.792969 L 426.429688 348.625 L 426.738281 349.449219 L 427.046875 350.265625 L 427.355469 351.078125 L 427.664062 351.882812 L 427.96875 352.683594 L 428.277344 353.476562 L 428.585938 354.265625 L 428.894531 355.042969 L 429.199219 355.816406 L 429.507812 356.585938 L 429.816406 357.34375 L 430.125 358.097656 L 430.433594 358.84375 L 430.738281 359.582031 L 431.046875 360.3125 L 431.355469 361.035156 L 431.664062 361.75 L 431.96875 362.457031 L 432.277344 363.160156 L 432.585938 363.851562 L 432.894531 364.535156 L 433.203125 365.210938 L 433.507812 365.878906 L 433.816406 366.535156 L 434.125 367.1875 L 434.433594 367.828125 L 434.738281 368.460938 L 435.046875 369.085938 L 435.355469 369.699219 L 435.664062 370.308594 L 435.972656 370.902344 L 436.277344 371.492188 L 436.585938 372.070312 L 436.894531 372.640625 L 437.203125 373.199219 L 437.507812 373.75 L 437.816406 374.289062 L 438.125 374.820312 L 438.433594 375.339844 L 438.742188 375.851562 L 439.046875 376.351562 L 439.355469 376.84375 L 439.664062 377.324219 L 439.972656 377.792969 L 440.28125 378.253906 L 440.585938 378.703125 L 440.894531 379.140625 L 441.203125 379.570312 L 441.511719 379.988281 L 441.816406 380.394531 L 442.125 380.792969 L 442.433594 381.179688 L 442.742188 381.554688 L 443.050781 381.917969 L 443.355469 382.269531 L 443.664062 382.613281 L 443.972656 382.941406 L 444.28125 383.261719 L 444.585938 383.570312 L 444.894531 383.867188 L 445.203125 384.15625 L 445.511719 384.429688 L 445.820312 384.691406 L 446.125 384.945312 L 446.433594 385.183594 L 446.742188 385.414062 L 447.050781 385.632812 L 447.355469 385.839844 L 447.664062 386.03125 L 447.972656 386.214844 L 448.28125 386.386719 L 448.589844 386.546875 L 448.894531 386.691406 L 449.203125 386.828125 L 449.511719 386.953125 L 449.820312 387.066406 L 450.125 387.167969 L 450.433594 387.253906 L 450.742188 387.332031 L 451.050781 387.398438 L 451.359375 387.449219 L 451.664062 387.492188 L 451.972656 387.523438 L 452.28125 387.539062 L 452.589844 387.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="390.984375"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="390.984375"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="390.984375"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="390.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="353.566406"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="353.566406"/>
+ <use xlink:href="#glyph0-3" x="273.594788" y="353.566406"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="353.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="316.152344"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="316.152344"/>
+ <use xlink:href="#glyph0-4" x="273.594788" y="316.152344"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="316.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="278.734375"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="278.734375"/>
+ <use xlink:href="#glyph0-5" x="273.594788" y="278.734375"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="278.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="265.59375" y="241.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="241.320312"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="241.320312"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="241.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 387.546875 L 291.351562 387.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 350.128906 L 291.351562 350.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 312.714844 L 291.351562 312.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 275.296875 L 291.351562 275.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 237.882812 L 291.351562 237.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 399.28125 L 299.03125 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 399.28125 L 337.417969 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 399.28125 L 375.808594 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 399.28125 L 414.199219 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 399.28125 L 452.589844 395.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="289.695312" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="295.030899" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="297.69635" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="303.031937" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="328.082031" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="333.417618" y="408.992188"/>
+ <use xlink:href="#glyph0-3" x="336.083069" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="341.418655" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="366.472656" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="371.808243" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="374.473694" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="379.80928" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="404.863281" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="410.198868" y="408.992188"/>
+ <use xlink:href="#glyph0-5" x="412.864319" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="418.199905" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="443.253906" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="448.589493" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="451.254944" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="456.59053" y="408.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="372.808594" y="421.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="258.992188" y="324.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="258.992188" y="317.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="258.992188" y="312.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="258.992188" y="306.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-17" x="257.335938" y="226.800781"/>
+ <use xlink:href="#glyph5-15" x="266.001953" y="226.800781"/>
+ <use xlink:href="#glyph5-18" x="273.332031" y="226.800781"/>
+ <use xlink:href="#glyph5-3" x="280.005859" y="226.800781"/>
+ <use xlink:href="#glyph5-5" x="283.339844" y="226.800781"/>
+ <use xlink:href="#glyph5-8" x="290.669922" y="226.800781"/>
+</g>
+<g clip-path="url(#clip103)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 474.667969 432 L 712 432 L 712 216 L 474.667969 216 Z "/>
+</g>
+<g clip-path="url(#clip104)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 474.667969 432 L 712 432 L 712 216 L 474.667969 216 Z "/>
+</g>
+<g clip-path="url(#clip105)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 528.683594 395.027344 L 697.597656 395.027344 L 697.597656 230.398438 L 528.683594 230.398438 Z "/>
+</g>
+<g clip-path="url(#clip106)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 369.476562 L 697.601562 369.476562 "/>
+</g>
+<g clip-path="url(#clip107)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 331.292969 L 697.601562 331.292969 "/>
+</g>
+<g clip-path="url(#clip108)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 293.113281 L 697.601562 293.113281 "/>
+</g>
+<g clip-path="url(#clip109)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 254.929688 L 697.601562 254.929688 "/>
+</g>
+<g clip-path="url(#clip110)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.558594 395.027344 L 555.558594 230.398438 "/>
+</g>
+<g clip-path="url(#clip111)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 593.949219 395.027344 L 593.949219 230.398438 "/>
+</g>
+<g clip-path="url(#clip112)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 632.335938 395.027344 L 632.335938 230.398438 "/>
+</g>
+<g clip-path="url(#clip113)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 670.726562 395.027344 L 670.726562 230.398438 "/>
+</g>
+<g clip-path="url(#clip114)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 388.566406 L 697.601562 388.566406 "/>
+</g>
+<g clip-path="url(#clip115)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 350.386719 L 697.601562 350.386719 "/>
+</g>
+<g clip-path="url(#clip116)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 312.203125 L 697.601562 312.203125 "/>
+</g>
+<g clip-path="url(#clip117)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 274.019531 L 697.601562 274.019531 "/>
+</g>
+<g clip-path="url(#clip118)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 235.839844 L 697.601562 235.839844 "/>
+</g>
+<g clip-path="url(#clip119)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 395.027344 L 536.363281 230.398438 "/>
+</g>
+<g clip-path="url(#clip120)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 395.027344 L 574.753906 230.398438 "/>
+</g>
+<g clip-path="url(#clip121)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 395.027344 L 613.140625 230.398438 "/>
+</g>
+<g clip-path="url(#clip122)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 395.027344 L 651.53125 230.398438 "/>
+</g>
+<g clip-path="url(#clip123)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 395.027344 L 689.921875 230.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 536.363281 387.546875 L 536.671875 387.503906 L 536.976562 387.460938 L 537.285156 387.417969 L 537.59375 387.371094 L 538.210938 387.269531 L 538.515625 387.21875 L 538.824219 387.164062 L 539.441406 387.046875 L 539.746094 386.984375 L 540.054688 386.921875 L 540.363281 386.855469 L 540.980469 386.714844 L 541.285156 386.636719 L 541.59375 386.5625 L 541.902344 386.480469 L 542.210938 386.394531 L 542.515625 386.308594 L 542.824219 386.21875 L 543.441406 386.023438 L 543.75 385.921875 L 544.054688 385.816406 L 544.363281 385.707031 L 544.980469 385.472656 L 545.289062 385.347656 L 545.59375 385.21875 L 545.902344 385.085938 L 546.210938 384.945312 L 546.519531 384.800781 L 546.824219 384.652344 L 547.132812 384.496094 L 547.441406 384.332031 L 547.75 384.164062 L 548.058594 383.988281 L 548.363281 383.808594 L 548.671875 383.621094 L 548.980469 383.425781 L 549.289062 383.222656 L 549.59375 383.011719 L 549.902344 382.792969 L 550.210938 382.566406 L 550.519531 382.332031 L 550.828125 382.085938 L 551.132812 381.832031 L 551.441406 381.570312 L 551.75 381.296875 L 552.058594 381.015625 L 552.363281 380.722656 L 552.671875 380.417969 L 552.980469 380.101562 L 553.289062 379.777344 L 553.597656 379.4375 L 553.902344 379.089844 L 554.210938 378.726562 L 554.519531 378.351562 L 554.828125 377.960938 L 555.132812 377.558594 L 555.441406 377.144531 L 555.75 376.710938 L 556.058594 376.265625 L 556.367188 375.804688 L 556.671875 375.328125 L 556.980469 374.835938 L 557.289062 374.328125 L 557.597656 373.800781 L 557.902344 373.257812 L 558.210938 372.695312 L 558.519531 372.117188 L 558.828125 371.519531 L 559.136719 370.902344 L 559.441406 370.265625 L 559.75 369.609375 L 560.058594 368.933594 L 560.367188 368.238281 L 560.671875 367.523438 L 560.980469 366.785156 L 561.289062 366.027344 L 561.597656 365.246094 L 561.90625 364.441406 L 562.210938 363.617188 L 562.519531 362.769531 L 562.828125 361.898438 L 563.136719 361.003906 L 563.445312 360.085938 L 563.75 359.144531 L 564.058594 358.183594 L 564.367188 357.195312 L 564.675781 356.183594 L 564.980469 355.148438 L 565.289062 354.089844 L 565.597656 353.007812 L 565.90625 351.90625 L 566.214844 350.777344 L 566.519531 349.625 L 566.828125 348.449219 L 567.136719 347.253906 L 567.445312 346.035156 L 567.75 344.792969 L 568.058594 343.53125 L 568.367188 342.25 L 568.675781 340.945312 L 568.984375 339.621094 L 569.289062 338.28125 L 569.597656 336.917969 L 569.90625 335.539062 L 570.214844 334.144531 L 570.519531 332.734375 L 570.828125 331.304688 L 571.136719 329.863281 L 571.445312 328.410156 L 571.753906 326.941406 L 572.058594 325.464844 L 572.367188 323.972656 L 572.675781 322.476562 L 572.984375 320.96875 L 573.289062 319.457031 L 573.597656 317.9375 L 573.90625 316.414062 L 574.523438 313.359375 L 574.828125 311.828125 L 575.136719 310.296875 L 575.445312 308.769531 L 575.753906 307.246094 L 576.058594 305.722656 L 576.367188 304.207031 L 576.675781 302.695312 L 576.984375 301.195312 L 577.292969 299.703125 L 577.597656 298.21875 L 577.90625 296.746094 L 578.214844 295.285156 L 578.523438 293.835938 L 578.832031 292.402344 L 579.136719 290.980469 L 579.445312 289.578125 L 579.753906 288.191406 L 580.0625 286.820312 L 580.367188 285.46875 L 580.675781 284.136719 L 580.984375 282.824219 L 581.292969 281.53125 L 581.601562 280.261719 L 581.90625 279.007812 L 582.214844 277.78125 L 582.523438 276.574219 L 582.832031 275.386719 L 583.136719 274.226562 L 583.445312 273.085938 L 583.753906 271.972656 L 584.0625 270.878906 L 584.371094 269.808594 L 584.675781 268.765625 L 584.984375 267.742188 L 585.292969 266.742188 L 585.601562 265.769531 L 585.90625 264.820312 L 586.214844 263.890625 L 586.523438 262.988281 L 586.832031 262.105469 L 587.140625 261.246094 L 587.445312 260.414062 L 587.753906 259.601562 L 588.0625 258.808594 L 588.371094 258.039062 L 588.675781 257.292969 L 588.984375 256.566406 L 589.292969 255.863281 L 589.601562 255.179688 L 589.910156 254.515625 L 590.214844 253.871094 L 590.523438 253.25 L 590.832031 252.644531 L 591.140625 252.058594 L 591.445312 251.488281 L 591.753906 250.941406 L 592.0625 250.40625 L 592.371094 249.894531 L 592.679688 249.394531 L 592.984375 248.914062 L 593.292969 248.445312 L 593.601562 247.996094 L 593.910156 247.5625 L 594.21875 247.140625 L 594.523438 246.734375 L 594.832031 246.34375 L 595.140625 245.964844 L 595.449219 245.601562 L 595.753906 245.25 L 596.0625 244.910156 L 596.371094 244.582031 L 596.679688 244.265625 L 596.988281 243.960938 L 597.292969 243.667969 L 597.601562 243.386719 L 597.910156 243.113281 L 598.21875 242.851562 L 598.523438 242.597656 L 598.832031 242.355469 L 599.140625 242.125 L 599.449219 241.898438 L 599.757812 241.683594 L 600.0625 241.476562 L 600.371094 241.277344 L 600.679688 241.085938 L 600.988281 240.902344 L 601.292969 240.726562 L 601.601562 240.558594 L 601.910156 240.394531 L 602.21875 240.238281 L 602.527344 240.089844 L 602.832031 239.949219 L 603.140625 239.8125 L 603.449219 239.679688 L 603.757812 239.558594 L 604.0625 239.4375 L 604.371094 239.324219 L 604.679688 239.214844 L 604.988281 239.113281 L 605.296875 239.015625 L 605.601562 238.921875 L 605.910156 238.832031 L 606.527344 238.667969 L 606.832031 238.59375 L 607.140625 238.523438 L 607.449219 238.457031 L 607.757812 238.394531 L 608.066406 238.335938 L 608.371094 238.28125 L 608.679688 238.230469 L 608.988281 238.183594 L 609.296875 238.140625 L 609.601562 238.097656 L 609.910156 238.0625 L 610.527344 238 L 610.835938 237.972656 L 611.140625 237.949219 L 611.449219 237.929688 L 611.757812 237.914062 L 612.066406 237.902344 L 612.375 237.894531 L 612.679688 237.886719 L 612.988281 237.882812 L 613.296875 237.882812 L 613.605469 237.886719 L 613.910156 237.894531 L 614.21875 237.902344 L 614.527344 237.914062 L 614.835938 237.929688 L 615.144531 237.949219 L 615.449219 237.972656 L 615.757812 238 L 616.375 238.0625 L 616.679688 238.097656 L 617.296875 238.183594 L 617.605469 238.230469 L 617.914062 238.28125 L 618.21875 238.335938 L 618.527344 238.394531 L 618.835938 238.457031 L 619.144531 238.523438 L 619.449219 238.59375 L 619.757812 238.667969 L 620.375 238.832031 L 620.683594 238.921875 L 620.988281 239.015625 L 621.296875 239.113281 L 621.605469 239.214844 L 621.914062 239.324219 L 622.21875 239.4375 L 622.835938 239.679688 L 623.144531 239.8125 L 623.453125 239.949219 L 623.757812 240.089844 L 624.066406 240.238281 L 624.375 240.394531 L 624.683594 240.558594 L 624.988281 240.726562 L 625.296875 240.902344 L 625.605469 241.085938 L 625.914062 241.277344 L 626.222656 241.476562 L 626.527344 241.683594 L 626.835938 241.898438 L 627.144531 242.125 L 627.453125 242.355469 L 627.761719 242.597656 L 628.066406 242.851562 L 628.375 243.113281 L 628.683594 243.386719 L 628.992188 243.667969 L 629.296875 243.960938 L 629.605469 244.265625 L 629.914062 244.582031 L 630.222656 244.910156 L 630.53125 245.25 L 630.835938 245.601562 L 631.144531 245.964844 L 631.453125 246.34375 L 631.761719 246.734375 L 632.066406 247.140625 L 632.375 247.5625 L 632.683594 247.996094 L 632.992188 248.445312 L 633.300781 248.914062 L 633.605469 249.394531 L 633.914062 249.894531 L 634.222656 250.40625 L 634.53125 250.941406 L 634.835938 251.488281 L 635.144531 252.058594 L 635.453125 252.644531 L 635.761719 253.25 L 636.070312 253.871094 L 636.375 254.515625 L 636.683594 255.179688 L 636.992188 255.863281 L 637.300781 256.566406 L 637.605469 257.292969 L 637.914062 258.039062 L 638.222656 258.808594 L 638.53125 259.601562 L 638.839844 260.414062 L 639.144531 261.246094 L 639.453125 262.105469 L 639.761719 262.988281 L 640.070312 263.890625 L 640.375 264.820312 L 640.683594 265.769531 L 640.992188 266.742188 L 641.300781 267.742188 L 641.609375 268.765625 L 641.914062 269.808594 L 642.222656 270.878906 L 642.53125 271.972656 L 642.839844 273.085938 L 643.148438 274.226562 L 643.453125 275.386719 L 643.761719 276.574219 L 644.070312 277.78125 L 644.378906 279.007812 L 644.683594 280.261719 L 644.992188 281.53125 L 645.300781 282.824219 L 645.609375 284.136719 L 645.917969 285.46875 L 646.222656 286.820312 L 646.53125 288.191406 L 646.839844 289.578125 L 647.148438 290.980469 L 647.453125 292.402344 L 647.761719 293.835938 L 648.070312 295.285156 L 648.378906 296.746094 L 648.6875 298.21875 L 648.992188 299.703125 L 649.300781 301.195312 L 649.609375 302.695312 L 649.917969 304.207031 L 650.222656 305.722656 L 650.839844 308.769531 L 651.148438 310.296875 L 651.457031 311.828125 L 651.761719 313.359375 L 652.378906 316.414062 L 652.6875 317.9375 L 652.992188 319.457031 L 653.300781 320.96875 L 653.609375 322.476562 L 653.917969 323.972656 L 654.226562 325.464844 L 654.53125 326.941406 L 654.839844 328.410156 L 655.148438 329.863281 L 655.457031 331.304688 L 655.761719 332.734375 L 656.070312 334.144531 L 656.378906 335.539062 L 656.6875 336.917969 L 656.996094 338.28125 L 657.300781 339.621094 L 657.609375 340.945312 L 657.917969 342.25 L 658.226562 343.53125 L 658.53125 344.792969 L 658.839844 346.035156 L 659.148438 347.253906 L 659.457031 348.449219 L 659.765625 349.625 L 660.070312 350.777344 L 660.378906 351.90625 L 660.6875 353.007812 L 660.996094 354.089844 L 661.304688 355.148438 L 661.609375 356.183594 L 661.917969 357.195312 L 662.226562 358.183594 L 662.535156 359.144531 L 662.839844 360.085938 L 663.148438 361.003906 L 663.457031 361.898438 L 663.765625 362.769531 L 664.074219 363.617188 L 664.378906 364.441406 L 664.6875 365.246094 L 664.996094 366.027344 L 665.304688 366.785156 L 665.609375 367.523438 L 665.917969 368.238281 L 666.226562 368.933594 L 666.535156 369.609375 L 666.84375 370.265625 L 667.148438 370.902344 L 667.457031 371.519531 L 667.765625 372.117188 L 668.074219 372.695312 L 668.378906 373.257812 L 668.6875 373.800781 L 668.996094 374.328125 L 669.304688 374.835938 L 669.613281 375.328125 L 669.917969 375.804688 L 670.226562 376.265625 L 670.535156 376.710938 L 670.84375 377.144531 L 671.148438 377.558594 L 671.457031 377.960938 L 671.765625 378.351562 L 672.074219 378.726562 L 672.382812 379.089844 L 672.6875 379.4375 L 672.996094 379.777344 L 673.304688 380.101562 L 673.613281 380.417969 L 673.917969 380.722656 L 674.226562 381.015625 L 674.535156 381.296875 L 674.84375 381.570312 L 675.152344 381.832031 L 675.457031 382.085938 L 675.765625 382.332031 L 676.074219 382.566406 L 676.382812 382.792969 L 676.691406 383.011719 L 676.996094 383.222656 L 677.304688 383.425781 L 677.613281 383.621094 L 677.921875 383.808594 L 678.226562 383.988281 L 678.535156 384.164062 L 678.84375 384.332031 L 679.152344 384.496094 L 679.460938 384.652344 L 679.765625 384.800781 L 680.074219 384.945312 L 680.382812 385.085938 L 680.691406 385.21875 L 680.996094 385.347656 L 681.304688 385.472656 L 681.921875 385.707031 L 682.230469 385.816406 L 682.535156 385.921875 L 682.84375 386.023438 L 683.460938 386.21875 L 683.765625 386.308594 L 684.382812 386.480469 L 684.691406 386.5625 L 685 386.636719 L 685.304688 386.714844 L 685.921875 386.855469 L 686.230469 386.921875 L 686.535156 386.984375 L 686.84375 387.046875 L 687.460938 387.164062 L 687.769531 387.21875 L 688.074219 387.269531 L 688.691406 387.371094 L 689 387.417969 L 689.304688 387.460938 L 689.921875 387.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="392.003906"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="392.003906"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="392.003906"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="392.003906"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="353.824219"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="353.824219"/>
+ <use xlink:href="#glyph0-3" x="510.926819" y="353.824219"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="353.824219"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="315.640625"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="315.640625"/>
+ <use xlink:href="#glyph0-4" x="510.926819" y="315.640625"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="315.640625"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="277.457031"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="277.457031"/>
+ <use xlink:href="#glyph0-5" x="510.926819" y="277.457031"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="277.457031"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="502.925781" y="239.277344"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="239.277344"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="239.277344"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="239.277344"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 388.566406 L 528.683594 388.566406 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 350.386719 L 528.683594 350.386719 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 312.203125 L 528.683594 312.203125 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 274.019531 L 528.683594 274.019531 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 235.839844 L 528.683594 235.839844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 399.28125 L 536.363281 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 399.28125 L 574.753906 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 399.28125 L 613.140625 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 399.28125 L 651.53125 395.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 399.28125 L 689.921875 395.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="527.027344" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="532.36293" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="535.028381" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="540.363968" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="565.417969" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="570.753555" y="408.992188"/>
+ <use xlink:href="#glyph0-3" x="573.419006" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="578.754593" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="603.804688" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="609.140274" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="611.805725" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="617.141312" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="642.195312" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="647.530899" y="408.992188"/>
+ <use xlink:href="#glyph0-5" x="650.19635" y="408.992188"/>
+ <use xlink:href="#glyph0-4" x="655.531937" y="408.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="680.585938" y="408.992188"/>
+ <use xlink:href="#glyph0-2" x="685.921524" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="688.586975" y="408.992188"/>
+ <use xlink:href="#glyph0-1" x="693.922562" y="408.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="610.140625" y="421.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="496.324219" y="324.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="496.324219" y="317.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="496.324219" y="312.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="496.324219" y="306.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-11" x="527.675781" y="226.800781"/>
+ <use xlink:href="#glyph5-3" x="535.679688" y="226.800781"/>
+ <use xlink:href="#glyph5-6" x="539.013672" y="226.800781"/>
+ <use xlink:href="#glyph5-19" x="546.34375" y="226.800781"/>
+ <use xlink:href="#glyph5-15" x="557.013672" y="226.800781"/>
+ <use xlink:href="#glyph5-3" x="564.34375" y="226.800781"/>
+ <use xlink:href="#glyph5-16" x="567.677734" y="226.800781"/>
+ <use xlink:href="#glyph5-20" x="575.007812" y="226.800781"/>
+ <use xlink:href="#glyph5-3" x="583.673828" y="226.800781"/>
+ <use xlink:href="#glyph5-21" x="587.007812" y="226.800781"/>
+ <use xlink:href="#glyph5-21" x="591.003906" y="226.800781"/>
+ <use xlink:href="#glyph5-8" x="595" y="226.800781"/>
+ <use xlink:href="#glyph5-2" x="601.673828" y="226.800781"/>
+ <use xlink:href="#glyph5-8" x="606.34375" y="226.800781"/>
+ <use xlink:href="#glyph5-5" x="613.017578" y="226.800781"/>
+ <use xlink:href="#glyph5-22" x="620.347656" y="226.800781"/>
+ <use xlink:href="#glyph5-8" x="627.021484" y="226.800781"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 648 L 237.332031 648 L 237.332031 432 L 0 432 Z "/>
+<g clip-path="url(#clip124)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 648 L 237.332031 648 L 237.332031 432 L 0 432 Z "/>
+</g>
+<g clip-path="url(#clip125)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 611.027344 L 222.933594 611.027344 L 222.933594 446.398438 L 54.019531 446.398438 Z "/>
+</g>
+<g clip-path="url(#clip126)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 584.839844 L 222.933594 584.839844 "/>
+</g>
+<g clip-path="url(#clip127)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 547.421875 L 222.933594 547.421875 "/>
+</g>
+<g clip-path="url(#clip128)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 510.007812 L 222.933594 510.007812 "/>
+</g>
+<g clip-path="url(#clip129)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 472.589844 L 222.933594 472.589844 "/>
+</g>
+<g clip-path="url(#clip130)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 80.890625 611.027344 L 80.890625 446.398438 "/>
+</g>
+<g clip-path="url(#clip131)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 119.28125 611.027344 L 119.28125 446.398438 "/>
+</g>
+<g clip-path="url(#clip132)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.671875 611.027344 L 157.671875 446.398438 "/>
+</g>
+<g clip-path="url(#clip133)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 196.058594 611.027344 L 196.058594 446.398438 "/>
+</g>
+<g clip-path="url(#clip134)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 603.546875 L 222.933594 603.546875 "/>
+</g>
+<g clip-path="url(#clip135)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 566.128906 L 222.933594 566.128906 "/>
+</g>
+<g clip-path="url(#clip136)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 528.714844 L 222.933594 528.714844 "/>
+</g>
+<g clip-path="url(#clip137)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 491.296875 L 222.933594 491.296875 "/>
+</g>
+<g clip-path="url(#clip138)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 453.882812 L 222.933594 453.882812 "/>
+</g>
+<g clip-path="url(#clip139)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 611.027344 L 61.695312 446.398438 "/>
+</g>
+<g clip-path="url(#clip140)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 611.027344 L 100.085938 446.398438 "/>
+</g>
+<g clip-path="url(#clip141)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 611.027344 L 138.476562 446.398438 "/>
+</g>
+<g clip-path="url(#clip142)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 611.027344 L 176.867188 446.398438 "/>
+</g>
+<g clip-path="url(#clip143)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 611.027344 L 215.253906 446.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 61.695312 603.546875 L 99.855469 603.546875 L 100.164062 453.882812 L 176.789062 453.882812 L 177.097656 603.546875 L 215.253906 603.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="606.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="606.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="606.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="606.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="569.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="569.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="569.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="569.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="532.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="532.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="532.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="532.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="494.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="494.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="494.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="494.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="457.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="457.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="457.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="457.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 603.546875 L 54.019531 603.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 566.128906 L 54.019531 566.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 528.714844 L 54.019531 528.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 491.296875 L 54.019531 491.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 453.882812 L 54.019531 453.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 615.28125 L 61.695312 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 615.28125 L 100.085938 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 615.28125 L 138.476562 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 615.28125 L 176.867188 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 615.28125 L 215.253906 611.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="52.359375" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="57.694962" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="60.360413" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="65.695999" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="90.75" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="96.085587" y="624.992188"/>
+ <use xlink:href="#glyph0-3" x="98.751038" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="104.086624" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="129.140625" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="134.476212" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="137.141663" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="142.477249" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="167.53125" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="172.866837" y="624.992188"/>
+ <use xlink:href="#glyph0-5" x="175.532288" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="180.867874" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="205.917969" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="211.253555" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="213.919006" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="219.254593" y="624.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="135.476562" y="637.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="540.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="533.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="528.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="522.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-23" x="28.675781" y="442.800781"/>
+ <use xlink:href="#glyph5-8" x="37.341797" y="442.800781"/>
+ <use xlink:href="#glyph5-22" x="44.015625" y="442.800781"/>
+ <use xlink:href="#glyph5-24" x="50.689453" y="442.800781"/>
+ <use xlink:href="#glyph5-4" x="54.685547" y="442.800781"/>
+ <use xlink:href="#glyph5-5" x="61.359375" y="442.800781"/>
+ <use xlink:href="#glyph5-6" x="68.689453" y="442.800781"/>
+ <use xlink:href="#glyph5-7" x="76.019531" y="442.800781"/>
+ <use xlink:href="#glyph5-8" x="79.353516" y="442.800781"/>
+</g>
+<g clip-path="url(#clip144)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 237.332031 648 L 474.664062 648 L 474.664062 432 L 237.332031 432 Z "/>
+</g>
+<g clip-path="url(#clip145)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 237.332031 648 L 474.664062 648 L 474.664062 432 L 237.332031 432 Z "/>
+</g>
+<g clip-path="url(#clip146)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 291.351562 611.027344 L 460.265625 611.027344 L 460.265625 446.398438 L 291.351562 446.398438 Z "/>
+</g>
+<g clip-path="url(#clip147)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 590.855469 L 460.265625 590.855469 "/>
+</g>
+<g clip-path="url(#clip148)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 551.71875 L 460.265625 551.71875 "/>
+</g>
+<g clip-path="url(#clip149)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 512.585938 L 460.265625 512.585938 "/>
+</g>
+<g clip-path="url(#clip150)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 473.449219 L 460.265625 473.449219 "/>
+</g>
+<g clip-path="url(#clip151)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 318.222656 611.027344 L 318.222656 446.398438 "/>
+</g>
+<g clip-path="url(#clip152)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.613281 611.027344 L 356.613281 446.398438 "/>
+</g>
+<g clip-path="url(#clip153)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 395.003906 611.027344 L 395.003906 446.398438 "/>
+</g>
+<g clip-path="url(#clip154)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 433.394531 611.027344 L 433.394531 446.398438 "/>
+</g>
+<g clip-path="url(#clip155)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 610.425781 L 460.265625 610.425781 "/>
+</g>
+<g clip-path="url(#clip156)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 571.289062 L 460.265625 571.289062 "/>
+</g>
+<g clip-path="url(#clip157)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 532.152344 L 460.265625 532.152344 "/>
+</g>
+<g clip-path="url(#clip158)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 493.015625 L 460.265625 493.015625 "/>
+</g>
+<g clip-path="url(#clip159)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 453.882812 L 460.265625 453.882812 "/>
+</g>
+<g clip-path="url(#clip160)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 611.027344 L 299.03125 446.398438 "/>
+</g>
+<g clip-path="url(#clip161)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 611.027344 L 337.417969 446.398438 "/>
+</g>
+<g clip-path="url(#clip162)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 611.027344 L 375.808594 446.398438 "/>
+</g>
+<g clip-path="url(#clip163)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 611.027344 L 414.199219 446.398438 "/>
+</g>
+<g clip-path="url(#clip164)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 611.027344 L 452.589844 446.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 299.03125 603.546875 L 299.335938 603.371094 L 299.644531 603.195312 L 300.261719 602.828125 L 300.566406 602.636719 L 300.875 602.445312 L 301.492188 602.046875 L 301.800781 601.839844 L 302.105469 601.632812 L 302.414062 601.417969 L 303.03125 600.980469 L 303.335938 600.753906 L 303.953125 600.285156 L 304.261719 600.046875 L 304.570312 599.800781 L 304.875 599.550781 L 305.183594 599.296875 L 305.492188 599.039062 L 305.800781 598.777344 L 306.105469 598.507812 L 306.414062 598.234375 L 306.722656 597.957031 L 307.03125 597.671875 L 307.339844 597.382812 L 307.644531 597.089844 L 307.953125 596.789062 L 308.261719 596.484375 L 308.570312 596.175781 L 308.878906 595.859375 L 309.183594 595.539062 L 309.492188 595.214844 L 309.800781 594.882812 L 310.109375 594.542969 L 310.414062 594.199219 L 310.722656 593.851562 L 311.03125 593.496094 L 311.339844 593.136719 L 311.648438 592.769531 L 311.953125 592.398438 L 312.261719 592.019531 L 312.570312 591.632812 L 312.878906 591.242188 L 313.183594 590.847656 L 313.800781 590.035156 L 314.109375 589.617188 L 314.417969 589.195312 L 314.722656 588.765625 L 315.03125 588.332031 L 315.339844 587.890625 L 315.648438 587.441406 L 315.953125 586.988281 L 316.261719 586.527344 L 316.570312 586.058594 L 316.878906 585.585938 L 317.1875 585.105469 L 317.492188 584.617188 L 317.800781 584.125 L 318.109375 583.621094 L 318.417969 583.113281 L 318.722656 582.597656 L 319.03125 582.078125 L 319.339844 581.550781 L 319.648438 581.015625 L 319.957031 580.472656 L 320.261719 579.921875 L 320.570312 579.367188 L 320.878906 578.804688 L 321.1875 578.234375 L 321.492188 577.65625 L 321.800781 577.070312 L 322.109375 576.480469 L 322.417969 575.882812 L 322.726562 575.277344 L 323.03125 574.664062 L 323.339844 574.046875 L 323.648438 573.417969 L 323.957031 572.785156 L 324.265625 572.144531 L 324.570312 571.5 L 324.878906 570.84375 L 325.1875 570.183594 L 325.496094 569.515625 L 325.800781 568.839844 L 326.109375 568.15625 L 326.417969 567.46875 L 326.726562 566.773438 L 327.035156 566.070312 L 327.339844 565.363281 L 327.648438 564.644531 L 327.957031 563.921875 L 328.265625 563.195312 L 328.570312 562.457031 L 328.878906 561.714844 L 329.1875 560.964844 L 329.496094 560.210938 L 329.804688 559.449219 L 330.109375 558.679688 L 330.417969 557.90625 L 330.726562 557.125 L 331.035156 556.339844 L 331.339844 555.546875 L 331.648438 554.746094 L 331.957031 553.941406 L 332.265625 553.128906 L 332.574219 552.3125 L 332.878906 551.488281 L 333.1875 550.660156 L 333.496094 549.828125 L 333.804688 548.988281 L 334.109375 548.144531 L 334.417969 547.292969 L 334.726562 546.4375 L 335.035156 545.578125 L 335.34375 544.714844 L 335.648438 543.84375 L 335.957031 542.96875 L 336.265625 542.089844 L 336.574219 541.207031 L 336.878906 540.316406 L 337.1875 539.425781 L 337.804688 537.628906 L 338.113281 536.722656 L 338.417969 535.816406 L 339.035156 533.988281 L 339.34375 533.070312 L 339.648438 532.148438 L 339.957031 531.222656 L 340.574219 529.363281 L 340.882812 528.429688 L 341.1875 527.496094 L 341.496094 526.558594 L 342.421875 523.734375 L 342.726562 522.789062 L 343.035156 521.839844 L 343.34375 520.894531 L 343.652344 519.945312 L 343.957031 518.996094 L 344.265625 518.042969 L 344.574219 517.09375 L 344.882812 516.140625 L 345.191406 515.191406 L 345.496094 514.238281 L 345.804688 513.289062 L 346.113281 512.335938 L 346.421875 511.386719 L 346.726562 510.4375 L 347.035156 509.492188 L 347.34375 508.542969 L 347.960938 506.652344 L 348.265625 505.710938 L 349.191406 502.898438 L 349.496094 501.96875 L 350.113281 500.109375 L 350.421875 499.1875 L 350.730469 498.269531 L 351.035156 497.351562 L 351.34375 496.441406 L 351.960938 494.628906 L 352.265625 493.730469 L 352.574219 492.835938 L 352.882812 491.949219 L 353.191406 491.066406 L 353.5 490.1875 L 353.804688 489.316406 L 354.113281 488.449219 L 354.421875 487.589844 L 354.730469 486.734375 L 355.035156 485.886719 L 355.34375 485.046875 L 355.652344 484.210938 L 355.960938 483.386719 L 356.269531 482.566406 L 356.574219 481.757812 L 356.882812 480.953125 L 357.191406 480.15625 L 357.5 479.371094 L 357.808594 478.589844 L 358.113281 477.820312 L 358.421875 477.0625 L 358.730469 476.308594 L 359.039062 475.566406 L 359.34375 474.832031 L 359.652344 474.109375 L 359.960938 473.394531 L 360.269531 472.691406 L 360.578125 472 L 360.882812 471.316406 L 361.191406 470.644531 L 361.5 469.984375 L 361.808594 469.332031 L 362.113281 468.695312 L 362.421875 468.066406 L 362.730469 467.449219 L 363.039062 466.847656 L 363.347656 466.253906 L 363.652344 465.675781 L 363.960938 465.105469 L 364.269531 464.550781 L 364.578125 464.007812 L 364.882812 463.476562 L 365.191406 462.960938 L 365.5 462.457031 L 365.808594 461.964844 L 366.117188 461.488281 L 366.421875 461.023438 L 366.730469 460.574219 L 367.039062 460.136719 L 367.347656 459.710938 L 367.652344 459.304688 L 367.960938 458.910156 L 368.269531 458.527344 L 368.578125 458.160156 L 368.886719 457.808594 L 369.191406 457.472656 L 369.5 457.148438 L 369.808594 456.839844 L 370.117188 456.546875 L 370.421875 456.269531 L 370.730469 456.007812 L 371.039062 455.757812 L 371.347656 455.523438 L 371.65625 455.308594 L 371.960938 455.105469 L 372.269531 454.917969 L 372.578125 454.746094 L 372.886719 454.589844 L 373.195312 454.449219 L 373.5 454.324219 L 373.808594 454.210938 L 374.117188 454.117188 L 374.425781 454.039062 L 374.730469 453.976562 L 375.039062 453.929688 L 375.347656 453.898438 L 375.65625 453.882812 L 375.964844 453.882812 L 376.269531 453.898438 L 376.578125 453.929688 L 376.886719 453.976562 L 377.195312 454.039062 L 377.5 454.117188 L 377.808594 454.210938 L 378.117188 454.324219 L 378.425781 454.449219 L 378.734375 454.589844 L 379.039062 454.746094 L 379.347656 454.917969 L 379.65625 455.105469 L 379.964844 455.308594 L 380.269531 455.523438 L 380.578125 455.757812 L 380.886719 456.007812 L 381.195312 456.269531 L 381.503906 456.546875 L 381.808594 456.839844 L 382.117188 457.148438 L 382.425781 457.472656 L 382.734375 457.808594 L 383.039062 458.160156 L 383.347656 458.527344 L 383.65625 458.910156 L 383.964844 459.304688 L 384.273438 459.710938 L 384.578125 460.136719 L 384.886719 460.574219 L 385.195312 461.023438 L 385.503906 461.488281 L 385.808594 461.964844 L 386.117188 462.457031 L 386.425781 462.960938 L 386.734375 463.476562 L 387.042969 464.007812 L 387.347656 464.550781 L 387.65625 465.105469 L 387.964844 465.675781 L 388.273438 466.253906 L 388.578125 466.847656 L 388.886719 467.449219 L 389.195312 468.066406 L 389.503906 468.695312 L 389.8125 469.332031 L 390.117188 469.984375 L 390.425781 470.644531 L 390.734375 471.316406 L 391.042969 472 L 391.351562 472.691406 L 391.65625 473.394531 L 391.964844 474.109375 L 392.273438 474.832031 L 392.582031 475.566406 L 392.886719 476.308594 L 393.195312 477.0625 L 393.503906 477.820312 L 393.8125 478.589844 L 394.121094 479.371094 L 394.425781 480.15625 L 394.734375 480.953125 L 395.042969 481.757812 L 395.351562 482.566406 L 395.65625 483.386719 L 395.964844 484.210938 L 396.273438 485.046875 L 396.582031 485.886719 L 396.890625 486.734375 L 397.195312 487.589844 L 397.503906 488.449219 L 397.8125 489.316406 L 398.121094 490.1875 L 398.425781 491.066406 L 398.734375 491.949219 L 399.042969 492.835938 L 399.351562 493.730469 L 399.660156 494.628906 L 399.964844 495.535156 L 400.273438 496.441406 L 400.582031 497.351562 L 400.890625 498.269531 L 401.195312 499.1875 L 401.503906 500.109375 L 402.429688 502.898438 L 402.734375 503.835938 L 403.351562 505.710938 L 403.660156 506.652344 L 403.964844 507.597656 L 404.273438 508.542969 L 404.582031 509.492188 L 404.890625 510.4375 L 405.199219 511.386719 L 405.503906 512.335938 L 405.8125 513.289062 L 406.121094 514.238281 L 406.429688 515.191406 L 406.738281 516.140625 L 407.042969 517.09375 L 407.351562 518.042969 L 407.660156 518.996094 L 407.96875 519.945312 L 408.273438 520.894531 L 408.582031 521.839844 L 408.890625 522.789062 L 409.199219 523.734375 L 409.507812 524.675781 L 409.8125 525.617188 L 410.121094 526.558594 L 410.429688 527.496094 L 410.738281 528.429688 L 411.042969 529.363281 L 411.660156 531.222656 L 411.96875 532.148438 L 412.277344 533.070312 L 412.582031 533.988281 L 413.199219 535.816406 L 413.507812 536.722656 L 413.8125 537.628906 L 414.429688 539.425781 L 415.046875 541.207031 L 415.351562 542.089844 L 415.660156 542.96875 L 415.96875 543.84375 L 416.277344 544.714844 L 416.582031 545.578125 L 416.890625 546.4375 L 417.199219 547.292969 L 417.507812 548.144531 L 417.816406 548.988281 L 418.121094 549.828125 L 418.429688 550.660156 L 418.738281 551.488281 L 419.046875 552.3125 L 419.351562 553.128906 L 419.660156 553.941406 L 419.96875 554.746094 L 420.277344 555.546875 L 420.585938 556.339844 L 420.890625 557.125 L 421.199219 557.90625 L 421.507812 558.679688 L 421.816406 559.449219 L 422.125 560.210938 L 422.429688 560.964844 L 422.738281 561.714844 L 423.046875 562.457031 L 423.355469 563.195312 L 423.660156 563.921875 L 423.96875 564.644531 L 424.277344 565.363281 L 424.585938 566.070312 L 424.894531 566.773438 L 425.199219 567.46875 L 425.507812 568.15625 L 425.816406 568.839844 L 426.125 569.515625 L 426.429688 570.183594 L 426.738281 570.84375 L 427.046875 571.5 L 427.355469 572.144531 L 427.664062 572.785156 L 427.96875 573.417969 L 428.277344 574.046875 L 428.585938 574.664062 L 428.894531 575.277344 L 429.199219 575.882812 L 429.507812 576.480469 L 429.816406 577.070312 L 430.125 577.65625 L 430.433594 578.234375 L 430.738281 578.804688 L 431.046875 579.367188 L 431.355469 579.921875 L 431.664062 580.472656 L 431.96875 581.015625 L 432.277344 581.550781 L 432.585938 582.078125 L 432.894531 582.597656 L 433.203125 583.113281 L 433.507812 583.621094 L 433.816406 584.125 L 434.125 584.617188 L 434.433594 585.105469 L 434.738281 585.585938 L 435.046875 586.058594 L 435.355469 586.527344 L 435.664062 586.988281 L 435.972656 587.441406 L 436.277344 587.890625 L 436.585938 588.332031 L 436.894531 588.765625 L 437.203125 589.195312 L 437.507812 589.617188 L 437.816406 590.035156 L 438.433594 590.847656 L 438.742188 591.242188 L 439.046875 591.632812 L 439.355469 592.019531 L 439.664062 592.398438 L 439.972656 592.769531 L 440.28125 593.136719 L 440.585938 593.496094 L 440.894531 593.851562 L 441.203125 594.199219 L 441.511719 594.542969 L 441.816406 594.882812 L 442.125 595.214844 L 442.433594 595.539062 L 442.742188 595.859375 L 443.050781 596.175781 L 443.355469 596.484375 L 443.664062 596.789062 L 443.972656 597.089844 L 444.28125 597.382812 L 444.585938 597.671875 L 444.894531 597.957031 L 445.203125 598.234375 L 445.511719 598.507812 L 445.820312 598.777344 L 446.125 599.039062 L 446.433594 599.296875 L 446.742188 599.550781 L 447.050781 599.800781 L 447.355469 600.046875 L 447.664062 600.285156 L 448.28125 600.753906 L 448.589844 600.980469 L 448.894531 601.199219 L 449.203125 601.417969 L 449.511719 601.632812 L 449.820312 601.839844 L 450.125 602.046875 L 450.742188 602.445312 L 451.359375 602.828125 L 451.664062 603.011719 L 451.972656 603.195312 L 452.589844 603.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="613.863281"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="613.863281"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="613.863281"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="613.863281"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="574.726562"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="574.726562"/>
+ <use xlink:href="#glyph0-3" x="273.594788" y="574.726562"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="574.726562"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="535.589844"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="535.589844"/>
+ <use xlink:href="#glyph0-4" x="273.594788" y="535.589844"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="535.589844"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="496.453125"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="496.453125"/>
+ <use xlink:href="#glyph0-5" x="273.594788" y="496.453125"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="496.453125"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="265.59375" y="457.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="457.320312"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="457.320312"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="457.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 610.425781 L 291.351562 610.425781 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 571.289062 L 291.351562 571.289062 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 532.152344 L 291.351562 532.152344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 493.015625 L 291.351562 493.015625 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 453.882812 L 291.351562 453.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 615.28125 L 299.03125 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 615.28125 L 337.417969 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 615.28125 L 375.808594 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 615.28125 L 414.199219 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 615.28125 L 452.589844 611.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="289.695312" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="295.030899" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="297.69635" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="303.031937" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="328.082031" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="333.417618" y="624.992188"/>
+ <use xlink:href="#glyph0-3" x="336.083069" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="341.418655" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="366.472656" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="371.808243" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="374.473694" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="379.80928" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="404.863281" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="410.198868" y="624.992188"/>
+ <use xlink:href="#glyph0-5" x="412.864319" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="418.199905" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="443.253906" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="448.589493" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="451.254944" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="456.59053" y="624.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="372.808594" y="637.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="258.992188" y="540.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="258.992188" y="533.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="258.992188" y="528.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="258.992188" y="522.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-25" x="264.34375" y="442.800781"/>
+ <use xlink:href="#glyph5-4" x="273.677734" y="442.800781"/>
+ <use xlink:href="#glyph5-26" x="280.351562" y="442.800781"/>
+ <use xlink:href="#glyph5-18" x="287.681641" y="442.800781"/>
+ <use xlink:href="#glyph5-18" x="294.355469" y="442.800781"/>
+ <use xlink:href="#glyph5-3" x="301.029297" y="442.800781"/>
+ <use xlink:href="#glyph5-4" x="304.363281" y="442.800781"/>
+ <use xlink:href="#glyph5-5" x="311.037109" y="442.800781"/>
+</g>
+<g clip-path="url(#clip165)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 474.667969 648 L 712 648 L 712 432 L 474.667969 432 Z "/>
+</g>
+<g clip-path="url(#clip166)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 474.667969 648 L 712 648 L 712 432 L 474.667969 432 Z "/>
+</g>
+<g clip-path="url(#clip167)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 528.683594 611.027344 L 697.597656 611.027344 L 697.597656 446.398438 L 528.683594 446.398438 Z "/>
+</g>
+<g clip-path="url(#clip168)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 598.894531 L 697.601562 598.894531 "/>
+</g>
+<g clip-path="url(#clip169)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 560.433594 L 697.601562 560.433594 "/>
+</g>
+<g clip-path="url(#clip170)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 521.96875 L 697.601562 521.96875 "/>
+</g>
+<g clip-path="url(#clip171)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 483.503906 L 697.601562 483.503906 "/>
+</g>
+<g clip-path="url(#clip172)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.558594 611.027344 L 555.558594 446.398438 "/>
+</g>
+<g clip-path="url(#clip173)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 593.949219 611.027344 L 593.949219 446.398438 "/>
+</g>
+<g clip-path="url(#clip174)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 632.335938 611.027344 L 632.335938 446.398438 "/>
+</g>
+<g clip-path="url(#clip175)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 670.726562 611.027344 L 670.726562 446.398438 "/>
+</g>
+<g clip-path="url(#clip176)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 579.664062 L 697.601562 579.664062 "/>
+</g>
+<g clip-path="url(#clip177)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 541.199219 L 697.601562 541.199219 "/>
+</g>
+<g clip-path="url(#clip178)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 502.738281 L 697.601562 502.738281 "/>
+</g>
+<g clip-path="url(#clip179)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 464.273438 L 697.601562 464.273438 "/>
+</g>
+<g clip-path="url(#clip180)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 611.027344 L 536.363281 446.398438 "/>
+</g>
+<g clip-path="url(#clip181)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 611.027344 L 574.753906 446.398438 "/>
+</g>
+<g clip-path="url(#clip182)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 611.027344 L 613.140625 446.398438 "/>
+</g>
+<g clip-path="url(#clip183)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 611.027344 L 651.53125 446.398438 "/>
+</g>
+<g clip-path="url(#clip184)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 611.027344 L 689.921875 446.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 536.363281 603.546875 L 536.671875 603.273438 L 536.976562 602.996094 L 537.285156 602.714844 L 537.59375 602.429688 L 538.210938 601.84375 L 538.515625 601.539062 L 538.824219 601.234375 L 539.132812 600.925781 L 539.441406 600.609375 L 539.746094 600.285156 L 540.054688 599.960938 L 540.363281 599.628906 L 540.671875 599.289062 L 540.980469 598.945312 L 541.285156 598.597656 L 541.59375 598.246094 L 542.210938 597.519531 L 542.515625 597.148438 L 542.824219 596.769531 L 543.132812 596.386719 L 543.441406 596 L 543.75 595.605469 L 544.054688 595.203125 L 544.363281 594.796875 L 544.671875 594.382812 L 544.980469 593.960938 L 545.289062 593.535156 L 545.59375 593.105469 L 545.902344 592.664062 L 546.210938 592.21875 L 546.519531 591.769531 L 546.824219 591.308594 L 547.132812 590.84375 L 547.441406 590.371094 L 547.75 589.894531 L 548.058594 589.40625 L 548.363281 588.914062 L 548.671875 588.417969 L 548.980469 587.910156 L 549.289062 587.398438 L 549.59375 586.878906 L 549.902344 586.351562 L 550.210938 585.816406 L 550.519531 585.273438 L 550.828125 584.726562 L 551.132812 584.171875 L 551.441406 583.609375 L 551.75 583.039062 L 552.058594 582.460938 L 552.363281 581.875 L 552.671875 581.285156 L 552.980469 580.6875 L 553.289062 580.078125 L 553.597656 579.464844 L 553.902344 578.84375 L 554.210938 578.214844 L 554.519531 577.582031 L 554.828125 576.9375 L 555.132812 576.285156 L 555.441406 575.628906 L 555.75 574.964844 L 556.058594 574.292969 L 556.367188 573.613281 L 556.671875 572.925781 L 556.980469 572.230469 L 557.289062 571.527344 L 557.597656 570.820312 L 557.902344 570.105469 L 558.210938 569.382812 L 558.519531 568.652344 L 558.828125 567.914062 L 559.136719 567.171875 L 559.441406 566.417969 L 559.75 565.660156 L 560.058594 564.898438 L 560.367188 564.125 L 560.671875 563.347656 L 560.980469 562.5625 L 561.289062 561.773438 L 561.597656 560.976562 L 561.90625 560.171875 L 562.210938 559.359375 L 562.519531 558.542969 L 562.828125 557.722656 L 563.136719 556.894531 L 563.445312 556.058594 L 563.75 555.21875 L 564.058594 554.375 L 564.367188 553.523438 L 564.675781 552.667969 L 564.980469 551.804688 L 565.289062 550.9375 L 565.597656 550.066406 L 566.214844 548.308594 L 566.519531 547.421875 L 566.828125 546.53125 L 567.136719 545.636719 L 567.445312 544.738281 L 567.75 543.832031 L 568.058594 542.925781 L 568.367188 542.015625 L 568.984375 540.1875 L 569.289062 539.265625 L 569.597656 538.34375 L 569.90625 537.414062 L 570.214844 536.488281 L 570.519531 535.554688 L 571.136719 533.6875 L 571.753906 531.8125 L 572.058594 530.871094 L 572.675781 528.988281 L 572.984375 528.042969 L 573.289062 527.101562 L 574.523438 523.320312 L 574.828125 522.375 L 575.136719 521.433594 L 575.445312 520.488281 L 575.753906 519.546875 L 576.058594 518.605469 L 576.984375 515.792969 L 577.292969 514.859375 L 577.597656 513.925781 L 577.90625 512.996094 L 578.523438 511.144531 L 578.832031 510.226562 L 579.136719 509.308594 L 579.445312 508.390625 L 579.753906 507.480469 L 580.0625 506.574219 L 580.367188 505.671875 L 580.675781 504.769531 L 580.984375 503.875 L 581.292969 502.984375 L 581.601562 502.101562 L 581.90625 501.21875 L 582.214844 500.34375 L 582.523438 499.472656 L 582.832031 498.605469 L 583.136719 497.746094 L 583.753906 496.042969 L 584.0625 495.203125 L 584.371094 494.367188 L 584.675781 493.535156 L 584.984375 492.710938 L 585.292969 491.894531 L 585.601562 491.085938 L 585.90625 490.28125 L 586.214844 489.484375 L 586.523438 488.695312 L 586.832031 487.914062 L 587.140625 487.140625 L 587.445312 486.371094 L 587.753906 485.613281 L 588.0625 484.859375 L 588.371094 484.117188 L 588.675781 483.378906 L 588.984375 482.652344 L 589.292969 481.929688 L 589.601562 481.21875 L 589.910156 480.515625 L 590.214844 479.820312 L 590.523438 479.132812 L 590.832031 478.453125 L 591.140625 477.78125 L 591.445312 477.121094 L 591.753906 476.46875 L 592.0625 475.824219 L 592.371094 475.191406 L 592.679688 474.5625 L 592.984375 473.945312 L 593.292969 473.335938 L 593.601562 472.738281 L 593.910156 472.148438 L 594.21875 471.566406 L 594.523438 470.996094 L 594.832031 470.433594 L 595.140625 469.878906 L 595.449219 469.335938 L 595.753906 468.800781 L 596.0625 468.273438 L 596.371094 467.757812 L 596.679688 467.25 L 596.988281 466.753906 L 597.292969 466.265625 L 597.601562 465.785156 L 597.910156 465.316406 L 598.21875 464.855469 L 598.523438 464.40625 L 598.832031 463.964844 L 599.140625 463.535156 L 599.449219 463.113281 L 599.757812 462.699219 L 600.0625 462.296875 L 600.371094 461.902344 L 600.679688 461.519531 L 600.988281 461.144531 L 601.292969 460.78125 L 601.601562 460.425781 L 601.910156 460.078125 L 602.21875 459.742188 L 602.527344 459.414062 L 602.832031 459.097656 L 603.140625 458.789062 L 603.449219 458.492188 L 603.757812 458.203125 L 604.0625 457.921875 L 604.371094 457.652344 L 604.679688 457.390625 L 604.988281 457.140625 L 605.296875 456.898438 L 605.601562 456.664062 L 605.910156 456.441406 L 606.21875 456.230469 L 606.527344 456.023438 L 606.832031 455.828125 L 607.140625 455.644531 L 607.449219 455.46875 L 607.757812 455.300781 L 608.066406 455.144531 L 608.371094 454.996094 L 608.679688 454.855469 L 608.988281 454.726562 L 609.296875 454.605469 L 609.601562 454.492188 L 609.910156 454.390625 L 610.21875 454.300781 L 610.527344 454.214844 L 610.835938 454.140625 L 611.140625 454.078125 L 611.449219 454.023438 L 611.757812 453.976562 L 612.066406 453.9375 L 612.375 453.910156 L 612.679688 453.890625 L 612.988281 453.882812 L 613.296875 453.882812 L 613.605469 453.890625 L 613.910156 453.910156 L 614.21875 453.9375 L 614.527344 453.976562 L 614.835938 454.023438 L 615.144531 454.078125 L 615.449219 454.140625 L 615.757812 454.214844 L 616.066406 454.300781 L 616.375 454.390625 L 616.679688 454.492188 L 616.988281 454.605469 L 617.296875 454.726562 L 617.605469 454.855469 L 617.914062 454.996094 L 618.21875 455.144531 L 618.527344 455.300781 L 618.835938 455.46875 L 619.144531 455.644531 L 619.449219 455.828125 L 619.757812 456.023438 L 620.066406 456.230469 L 620.375 456.441406 L 620.683594 456.664062 L 620.988281 456.898438 L 621.296875 457.140625 L 621.605469 457.390625 L 621.914062 457.652344 L 622.21875 457.921875 L 622.527344 458.203125 L 622.835938 458.492188 L 623.144531 458.789062 L 623.453125 459.097656 L 623.757812 459.414062 L 624.066406 459.742188 L 624.375 460.078125 L 624.683594 460.425781 L 624.988281 460.78125 L 625.296875 461.144531 L 625.605469 461.519531 L 625.914062 461.902344 L 626.222656 462.296875 L 626.527344 462.699219 L 626.835938 463.113281 L 627.144531 463.535156 L 627.453125 463.964844 L 627.761719 464.40625 L 628.066406 464.855469 L 628.375 465.316406 L 628.683594 465.785156 L 628.992188 466.265625 L 629.296875 466.753906 L 629.605469 467.25 L 629.914062 467.757812 L 630.222656 468.273438 L 630.53125 468.800781 L 630.835938 469.335938 L 631.144531 469.878906 L 631.453125 470.433594 L 631.761719 470.996094 L 632.066406 471.566406 L 632.375 472.148438 L 632.683594 472.738281 L 632.992188 473.335938 L 633.300781 473.945312 L 633.605469 474.5625 L 633.914062 475.191406 L 634.222656 475.824219 L 634.53125 476.46875 L 634.835938 477.121094 L 635.144531 477.78125 L 635.453125 478.453125 L 635.761719 479.132812 L 636.070312 479.820312 L 636.375 480.515625 L 636.683594 481.21875 L 636.992188 481.929688 L 637.300781 482.652344 L 637.605469 483.378906 L 637.914062 484.117188 L 638.222656 484.859375 L 638.53125 485.613281 L 638.839844 486.371094 L 639.144531 487.140625 L 639.453125 487.914062 L 639.761719 488.695312 L 640.070312 489.484375 L 640.375 490.28125 L 640.683594 491.085938 L 640.992188 491.894531 L 641.300781 492.710938 L 641.609375 493.535156 L 641.914062 494.367188 L 642.222656 495.203125 L 642.53125 496.042969 L 643.148438 497.746094 L 643.453125 498.605469 L 643.761719 499.472656 L 644.070312 500.34375 L 644.378906 501.21875 L 644.683594 502.101562 L 644.992188 502.984375 L 645.300781 503.875 L 645.609375 504.769531 L 645.917969 505.671875 L 646.222656 506.574219 L 646.53125 507.480469 L 646.839844 508.390625 L 647.148438 509.308594 L 647.453125 510.226562 L 647.761719 511.144531 L 648.378906 512.996094 L 648.6875 513.925781 L 648.992188 514.859375 L 649.300781 515.792969 L 649.917969 517.667969 L 650.222656 518.605469 L 650.839844 520.488281 L 651.148438 521.433594 L 651.457031 522.375 L 651.761719 523.320312 L 652.6875 526.15625 L 652.992188 527.101562 L 653.300781 528.042969 L 653.609375 528.988281 L 654.226562 530.871094 L 654.53125 531.8125 L 655.148438 533.6875 L 655.457031 534.621094 L 655.761719 535.554688 L 656.070312 536.488281 L 656.378906 537.414062 L 656.6875 538.34375 L 656.996094 539.265625 L 657.300781 540.1875 L 657.917969 542.015625 L 658.226562 542.925781 L 658.53125 543.832031 L 658.839844 544.738281 L 659.148438 545.636719 L 659.457031 546.53125 L 659.765625 547.421875 L 660.070312 548.308594 L 660.6875 550.066406 L 660.996094 550.9375 L 661.304688 551.804688 L 661.609375 552.667969 L 661.917969 553.523438 L 662.226562 554.375 L 662.535156 555.21875 L 662.839844 556.058594 L 663.148438 556.894531 L 663.457031 557.722656 L 663.765625 558.542969 L 664.074219 559.359375 L 664.378906 560.171875 L 664.6875 560.976562 L 664.996094 561.773438 L 665.304688 562.5625 L 665.609375 563.347656 L 665.917969 564.125 L 666.226562 564.898438 L 666.535156 565.660156 L 666.84375 566.417969 L 667.148438 567.171875 L 667.457031 567.914062 L 667.765625 568.652344 L 668.074219 569.382812 L 668.378906 570.105469 L 668.6875 570.820312 L 668.996094 571.527344 L 669.304688 572.230469 L 669.613281 572.925781 L 669.917969 573.613281 L 670.226562 574.292969 L 670.535156 574.964844 L 670.84375 575.628906 L 671.148438 576.285156 L 671.457031 576.9375 L 671.765625 577.582031 L 672.074219 578.214844 L 672.382812 578.84375 L 672.6875 579.464844 L 672.996094 580.078125 L 673.304688 580.6875 L 673.613281 581.285156 L 673.917969 581.875 L 674.226562 582.460938 L 674.535156 583.039062 L 674.84375 583.609375 L 675.152344 584.171875 L 675.457031 584.726562 L 675.765625 585.273438 L 676.074219 585.816406 L 676.382812 586.351562 L 676.691406 586.878906 L 676.996094 587.398438 L 677.304688 587.910156 L 677.613281 588.417969 L 677.921875 588.914062 L 678.226562 589.40625 L 678.535156 589.894531 L 678.84375 590.371094 L 679.152344 590.84375 L 679.460938 591.308594 L 679.765625 591.769531 L 680.074219 592.21875 L 680.382812 592.664062 L 680.691406 593.105469 L 680.996094 593.535156 L 681.304688 593.960938 L 681.613281 594.382812 L 681.921875 594.796875 L 682.230469 595.203125 L 682.535156 595.605469 L 682.84375 596 L 683.152344 596.386719 L 683.460938 596.769531 L 683.765625 597.148438 L 684.074219 597.519531 L 684.691406 598.246094 L 685 598.597656 L 685.304688 598.945312 L 685.613281 599.289062 L 685.921875 599.628906 L 686.230469 599.960938 L 686.535156 600.285156 L 686.84375 600.609375 L 687.152344 600.925781 L 687.460938 601.234375 L 687.769531 601.539062 L 688.074219 601.84375 L 688.691406 602.429688 L 689 602.714844 L 689.304688 602.996094 L 689.613281 603.273438 L 689.921875 603.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="508.261719" y="583.101562"/>
+ <use xlink:href="#glyph0-2" x="513.597305" y="583.101562"/>
+ <use xlink:href="#glyph0-3" x="516.262756" y="583.101562"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="508.261719" y="544.636719"/>
+ <use xlink:href="#glyph0-2" x="513.597305" y="544.636719"/>
+ <use xlink:href="#glyph0-7" x="516.262756" y="544.636719"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="508.261719" y="506.175781"/>
+ <use xlink:href="#glyph0-2" x="513.597305" y="506.175781"/>
+ <use xlink:href="#glyph0-8" x="516.262756" y="506.175781"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="508.261719" y="467.710938"/>
+ <use xlink:href="#glyph0-2" x="513.597305" y="467.710938"/>
+ <use xlink:href="#glyph0-9" x="516.262756" y="467.710938"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 579.664062 L 528.683594 579.664062 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 541.199219 L 528.683594 541.199219 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 502.738281 L 528.683594 502.738281 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 464.273438 L 528.683594 464.273438 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 615.28125 L 536.363281 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 615.28125 L 574.753906 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 615.28125 L 613.140625 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 615.28125 L 651.53125 611.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 615.28125 L 689.921875 611.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="527.027344" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="532.36293" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="535.028381" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="540.363968" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="565.417969" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="570.753555" y="624.992188"/>
+ <use xlink:href="#glyph0-3" x="573.419006" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="578.754593" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="603.804688" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="609.140274" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="611.805725" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="617.141312" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="642.195312" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="647.530899" y="624.992188"/>
+ <use xlink:href="#glyph0-5" x="650.19635" y="624.992188"/>
+ <use xlink:href="#glyph0-4" x="655.531937" y="624.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="680.585938" y="624.992188"/>
+ <use xlink:href="#glyph0-2" x="685.921524" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="688.586975" y="624.992188"/>
+ <use xlink:href="#glyph0-1" x="693.922562" y="624.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="610.140625" y="637.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="496.324219" y="540.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="496.324219" y="533.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="496.324219" y="528.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="496.324219" y="522.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-11" x="521" y="442.800781"/>
+ <use xlink:href="#glyph5-3" x="529.003906" y="442.800781"/>
+ <use xlink:href="#glyph5-6" x="532.337891" y="442.800781"/>
+ <use xlink:href="#glyph5-19" x="539.667969" y="442.800781"/>
+ <use xlink:href="#glyph5-15" x="550.337891" y="442.800781"/>
+ <use xlink:href="#glyph5-3" x="557.667969" y="442.800781"/>
+ <use xlink:href="#glyph5-16" x="561.001953" y="442.800781"/>
+ <use xlink:href="#glyph5-10" x="568.332031" y="442.800781"/>
+ <use xlink:href="#glyph5-2" x="576.335938" y="442.800781"/>
+ <use xlink:href="#glyph5-15" x="581.005859" y="442.800781"/>
+ <use xlink:href="#glyph5-16" x="588.335938" y="442.800781"/>
+ <use xlink:href="#glyph5-26" x="595.666016" y="442.800781"/>
+ <use xlink:href="#glyph5-22" x="602.996094" y="442.800781"/>
+ <use xlink:href="#glyph5-24" x="609.669922" y="442.800781"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 864 L 237.332031 864 L 237.332031 648 L 0 648 Z "/>
+<g clip-path="url(#clip185)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 864 L 237.332031 864 L 237.332031 648 L 0 648 Z "/>
+</g>
+<g clip-path="url(#clip186)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 827.027344 L 222.933594 827.027344 L 222.933594 662.398438 L 54.019531 662.398438 Z "/>
+</g>
+<g clip-path="url(#clip187)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 800.515625 L 222.933594 800.515625 "/>
+</g>
+<g clip-path="url(#clip188)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 762.449219 L 222.933594 762.449219 "/>
+</g>
+<g clip-path="url(#clip189)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 724.386719 L 222.933594 724.386719 "/>
+</g>
+<g clip-path="url(#clip190)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 686.320312 L 222.933594 686.320312 "/>
+</g>
+<g clip-path="url(#clip191)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 80.890625 827.027344 L 80.890625 662.398438 "/>
+</g>
+<g clip-path="url(#clip192)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 119.28125 827.027344 L 119.28125 662.398438 "/>
+</g>
+<g clip-path="url(#clip193)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.671875 827.027344 L 157.671875 662.398438 "/>
+</g>
+<g clip-path="url(#clip194)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 196.058594 827.027344 L 196.058594 662.398438 "/>
+</g>
+<g clip-path="url(#clip195)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 819.546875 L 222.933594 819.546875 "/>
+</g>
+<g clip-path="url(#clip196)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 781.480469 L 222.933594 781.480469 "/>
+</g>
+<g clip-path="url(#clip197)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 743.417969 L 222.933594 743.417969 "/>
+</g>
+<g clip-path="url(#clip198)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 705.355469 L 222.933594 705.355469 "/>
+</g>
+<g clip-path="url(#clip199)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 667.289062 L 222.933594 667.289062 "/>
+</g>
+<g clip-path="url(#clip200)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 827.027344 L 61.695312 662.398438 "/>
+</g>
+<g clip-path="url(#clip201)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 827.027344 L 100.085938 662.398438 "/>
+</g>
+<g clip-path="url(#clip202)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 827.027344 L 138.476562 662.398438 "/>
+</g>
+<g clip-path="url(#clip203)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 827.027344 L 176.867188 662.398438 "/>
+</g>
+<g clip-path="url(#clip204)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 827.027344 L 215.253906 662.398438 "/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 65.417969 819.546875 C 65.417969 824.507812 57.976562 824.507812 57.976562 819.546875 C 57.976562 814.585938 65.417969 814.585938 65.417969 819.546875 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 68.1875 808.5625 C 68.1875 813.523438 60.746094 813.523438 60.746094 808.5625 C 60.746094 803.601562 68.1875 803.601562 68.1875 808.5625 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 71.261719 796.355469 C 71.261719 801.316406 63.824219 801.316406 63.824219 796.355469 C 63.824219 791.394531 71.261719 791.394531 71.261719 796.355469 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 74.339844 784.152344 C 74.339844 789.113281 66.898438 789.113281 66.898438 784.152344 C 66.898438 779.191406 74.339844 779.191406 74.339844 784.152344 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 77.417969 771.945312 C 77.417969 776.90625 69.976562 776.90625 69.976562 771.945312 C 69.976562 766.984375 77.417969 766.984375 77.417969 771.945312 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 80.496094 759.742188 C 80.496094 764.703125 73.054688 764.703125 73.054688 759.742188 C 73.054688 754.78125 80.496094 754.78125 80.496094 759.742188 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 83.574219 747.535156 C 83.574219 752.496094 76.132812 752.496094 76.132812 747.535156 C 76.132812 742.578125 83.574219 742.578125 83.574219 747.535156 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 86.648438 735.332031 C 86.648438 740.292969 79.210938 740.292969 79.210938 735.332031 C 79.210938 730.371094 86.648438 730.371094 86.648438 735.332031 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 89.726562 723.128906 C 89.726562 728.085938 82.285156 728.085938 82.285156 723.128906 C 82.285156 718.167969 89.726562 718.167969 89.726562 723.128906 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 92.804688 710.921875 C 92.804688 715.882812 85.363281 715.882812 85.363281 710.921875 C 85.363281 705.960938 92.804688 705.960938 92.804688 710.921875 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 95.882812 698.71875 C 95.882812 703.679688 88.441406 703.679688 88.441406 698.71875 C 88.441406 693.757812 95.882812 693.757812 95.882812 698.71875 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 98.960938 686.511719 C 98.960938 691.472656 91.519531 691.472656 91.519531 686.511719 C 91.519531 681.550781 98.960938 681.550781 98.960938 686.511719 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 102.035156 674.308594 C 102.035156 679.269531 94.597656 679.269531 94.597656 674.308594 C 94.597656 669.347656 102.035156 669.347656 102.035156 674.308594 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 105.113281 669.882812 C 105.113281 674.84375 97.671875 674.84375 97.671875 669.882812 C 97.671875 664.921875 105.113281 664.921875 105.113281 669.882812 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 108.191406 675.984375 C 108.191406 680.945312 100.75 680.945312 100.75 675.984375 C 100.75 671.023438 108.191406 671.023438 108.191406 675.984375 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 111.269531 682.089844 C 111.269531 687.046875 103.828125 687.046875 103.828125 682.089844 C 103.828125 677.128906 111.269531 677.128906 111.269531 682.089844 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 114.347656 688.191406 C 114.347656 693.152344 106.90625 693.152344 106.90625 688.191406 C 106.90625 683.230469 114.347656 683.230469 114.347656 688.191406 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 117.421875 694.292969 C 117.421875 699.253906 109.984375 699.253906 109.984375 694.292969 C 109.984375 689.332031 117.421875 689.332031 117.421875 694.292969 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 120.5 700.394531 C 120.5 705.355469 113.058594 705.355469 113.058594 700.394531 C 113.058594 695.433594 120.5 695.433594 120.5 700.394531 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 123.578125 706.496094 C 123.578125 711.457031 116.136719 711.457031 116.136719 706.496094 C 116.136719 701.539062 123.578125 701.539062 123.578125 706.496094 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 126.65625 712.601562 C 126.65625 717.5625 119.214844 717.5625 119.214844 712.601562 C 119.214844 707.640625 126.65625 707.640625 126.65625 712.601562 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 129.734375 718.703125 C 129.734375 723.664062 122.292969 723.664062 122.292969 718.703125 C 122.292969 713.742188 129.734375 713.742188 129.734375 718.703125 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 132.808594 724.804688 C 132.808594 729.765625 125.371094 729.765625 125.371094 724.804688 C 125.371094 719.84375 132.808594 719.84375 132.808594 724.804688 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 135.886719 730.90625 C 135.886719 735.867188 128.445312 735.867188 128.445312 730.90625 C 128.445312 725.945312 135.886719 725.945312 135.886719 730.90625 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 138.964844 737.011719 C 138.964844 741.972656 131.523438 741.972656 131.523438 737.011719 C 131.523438 732.050781 138.964844 732.050781 138.964844 737.011719 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 142.042969 743.113281 C 142.042969 748.074219 134.601562 748.074219 134.601562 743.113281 C 134.601562 738.152344 142.042969 738.152344 142.042969 743.113281 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 145.121094 737.621094 C 145.121094 742.582031 137.679688 742.582031 137.679688 737.621094 C 137.679688 732.660156 145.121094 732.660156 145.121094 737.621094 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 148.195312 731.519531 C 148.195312 736.480469 140.757812 736.480469 140.757812 731.519531 C 140.757812 726.558594 148.195312 726.558594 148.195312 731.519531 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 151.273438 725.414062 C 151.273438 730.375 143.832031 730.375 143.832031 725.414062 C 143.832031 720.453125 151.273438 720.453125 151.273438 725.414062 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 154.351562 719.3125 C 154.351562 724.273438 146.910156 724.273438 146.910156 719.3125 C 146.910156 714.351562 154.351562 714.351562 154.351562 719.3125 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 157.429688 713.210938 C 157.429688 718.171875 149.988281 718.171875 149.988281 713.210938 C 149.988281 708.25 157.429688 708.25 157.429688 713.210938 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 160.507812 707.109375 C 160.507812 712.070312 153.066406 712.070312 153.066406 707.109375 C 153.066406 702.148438 160.507812 702.148438 160.507812 707.109375 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 163.582031 701.003906 C 163.582031 705.964844 156.144531 705.964844 156.144531 701.003906 C 156.144531 696.046875 163.582031 696.046875 163.582031 701.003906 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 166.660156 694.902344 C 166.660156 699.863281 159.21875 699.863281 159.21875 694.902344 C 159.21875 689.941406 166.660156 689.941406 166.660156 694.902344 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 169.738281 688.800781 C 169.738281 693.761719 162.296875 693.761719 162.296875 688.800781 C 162.296875 683.839844 169.738281 683.839844 169.738281 688.800781 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 172.816406 682.699219 C 172.816406 687.660156 165.375 687.660156 165.375 682.699219 C 165.375 677.738281 172.816406 677.738281 172.816406 682.699219 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 175.894531 676.597656 C 175.894531 681.554688 168.453125 681.554688 168.453125 676.597656 C 168.453125 671.636719 175.894531 671.636719 175.894531 676.597656 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 178.96875 670.492188 C 178.96875 675.453125 171.53125 675.453125 171.53125 670.492188 C 171.53125 665.53125 178.96875 665.53125 178.96875 670.492188 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 182.046875 673.085938 C 182.046875 678.046875 174.605469 678.046875 174.605469 673.085938 C 174.605469 668.125 182.046875 668.125 182.046875 673.085938 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 185.125 685.292969 C 185.125 690.253906 177.683594 690.253906 177.683594 685.292969 C 177.683594 680.332031 185.125 680.332031 185.125 685.292969 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 188.203125 697.496094 C 188.203125 702.457031 180.761719 702.457031 180.761719 697.496094 C 180.761719 692.535156 188.203125 692.535156 188.203125 697.496094 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 191.28125 709.703125 C 191.28125 714.664062 183.839844 714.664062 183.839844 709.703125 C 183.839844 704.742188 191.28125 704.742188 191.28125 709.703125 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 194.355469 721.90625 C 194.355469 726.867188 186.917969 726.867188 186.917969 721.90625 C 186.917969 716.945312 194.355469 716.945312 194.355469 721.90625 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 197.433594 734.113281 C 197.433594 739.070312 189.992188 739.070312 189.992188 734.113281 C 189.992188 729.152344 197.433594 729.152344 197.433594 734.113281 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 200.511719 746.316406 C 200.511719 751.277344 193.070312 751.277344 193.070312 746.316406 C 193.070312 741.355469 200.511719 741.355469 200.511719 746.316406 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 203.589844 758.519531 C 203.589844 763.480469 196.148438 763.480469 196.148438 758.519531 C 196.148438 753.5625 203.589844 753.5625 203.589844 758.519531 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 206.667969 770.726562 C 206.667969 775.6875 199.226562 775.6875 199.226562 770.726562 C 199.226562 765.765625 206.667969 765.765625 206.667969 770.726562 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 209.742188 782.929688 C 209.742188 787.890625 202.304688 787.890625 202.304688 782.929688 C 202.304688 777.96875 209.742188 777.96875 209.742188 782.929688 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 212.820312 795.136719 C 212.820312 800.097656 205.378906 800.097656 205.378906 795.136719 C 205.378906 790.175781 212.820312 790.175781 212.820312 795.136719 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 215.898438 807.339844 C 215.898438 812.300781 208.457031 812.300781 208.457031 807.339844 C 208.457031 802.378906 215.898438 802.378906 215.898438 807.339844 "/>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 218.976562 819.546875 C 218.976562 824.507812 211.535156 824.507812 211.535156 819.546875 C 211.535156 814.585938 218.976562 814.585938 218.976562 819.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="822.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="822.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="822.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="822.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="784.917969"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="784.917969"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="784.917969"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="784.917969"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="746.855469"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="746.855469"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="746.855469"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="746.855469"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="708.792969"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="708.792969"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="708.792969"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="708.792969"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="670.726562"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="670.726562"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="670.726562"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="670.726562"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 819.546875 L 54.019531 819.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 781.480469 L 54.019531 781.480469 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 743.417969 L 54.019531 743.417969 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 705.355469 L 54.019531 705.355469 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 667.289062 L 54.019531 667.289062 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 831.28125 L 61.695312 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 831.28125 L 100.085938 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 831.28125 L 138.476562 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 831.28125 L 176.867188 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 831.28125 L 215.253906 827.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="52.359375" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="57.694962" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="60.360413" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="65.695999" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="90.75" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="96.085587" y="840.992188"/>
+ <use xlink:href="#glyph0-3" x="98.751038" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="104.086624" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="129.140625" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="134.476212" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="137.141663" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="142.477249" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="167.53125" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="172.866837" y="840.992188"/>
+ <use xlink:href="#glyph0-5" x="175.532288" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="180.867874" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="205.917969" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="211.253555" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="213.919006" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="219.254593" y="840.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="135.476562" y="853.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="756.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="749.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="744.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="738.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-20" x="23.679688" y="658.800781"/>
+ <use xlink:href="#glyph5-3" x="32.345703" y="658.800781"/>
+ <use xlink:href="#glyph5-18" x="35.679688" y="658.800781"/>
+ <use xlink:href="#glyph5-22" x="42.353516" y="658.800781"/>
+ <use xlink:href="#glyph5-2" x="49.027344" y="658.800781"/>
+ <use xlink:href="#glyph5-8" x="53.697266" y="658.800781"/>
+ <use xlink:href="#glyph5-24" x="60.371094" y="658.800781"/>
+ <use xlink:href="#glyph5-8" x="64.367188" y="658.800781"/>
+</g>
+<g clip-path="url(#clip205)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 237.332031 864 L 474.664062 864 L 474.664062 648 L 237.332031 648 Z "/>
+</g>
+<g clip-path="url(#clip206)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 237.332031 864 L 474.664062 864 L 474.664062 648 L 237.332031 648 Z "/>
+</g>
+<g clip-path="url(#clip207)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 291.351562 827.027344 L 460.265625 827.027344 L 460.265625 662.398438 L 291.351562 662.398438 Z "/>
+</g>
+<g clip-path="url(#clip208)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 802.214844 L 460.265625 802.214844 "/>
+</g>
+<g clip-path="url(#clip209)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 763.226562 L 460.265625 763.226562 "/>
+</g>
+<g clip-path="url(#clip210)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 724.234375 L 460.265625 724.234375 "/>
+</g>
+<g clip-path="url(#clip211)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 685.242188 L 460.265625 685.242188 "/>
+</g>
+<g clip-path="url(#clip212)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 318.222656 827.027344 L 318.222656 662.398438 "/>
+</g>
+<g clip-path="url(#clip213)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.613281 827.027344 L 356.613281 662.398438 "/>
+</g>
+<g clip-path="url(#clip214)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 395.003906 827.027344 L 395.003906 662.398438 "/>
+</g>
+<g clip-path="url(#clip215)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 433.394531 827.027344 L 433.394531 662.398438 "/>
+</g>
+<g clip-path="url(#clip216)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 821.710938 L 460.265625 821.710938 "/>
+</g>
+<g clip-path="url(#clip217)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 782.71875 L 460.265625 782.71875 "/>
+</g>
+<g clip-path="url(#clip218)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 743.730469 L 460.265625 743.730469 "/>
+</g>
+<g clip-path="url(#clip219)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 704.738281 L 460.265625 704.738281 "/>
+</g>
+<g clip-path="url(#clip220)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 665.746094 L 460.265625 665.746094 "/>
+</g>
+<g clip-path="url(#clip221)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 827.027344 L 299.03125 662.398438 "/>
+</g>
+<g clip-path="url(#clip222)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 827.027344 L 337.417969 662.398438 "/>
+</g>
+<g clip-path="url(#clip223)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 827.027344 L 375.808594 662.398438 "/>
+</g>
+<g clip-path="url(#clip224)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 827.027344 L 414.199219 662.398438 "/>
+</g>
+<g clip-path="url(#clip225)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 827.027344 L 452.589844 662.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 299.03125 819.546875 L 299.335938 819.480469 L 299.644531 819.414062 L 299.953125 819.34375 L 300.261719 819.269531 L 300.566406 819.199219 L 300.875 819.121094 L 301.183594 819.046875 L 301.800781 818.882812 L 302.105469 818.800781 L 302.722656 818.628906 L 303.03125 818.539062 L 303.335938 818.445312 L 303.644531 818.351562 L 303.953125 818.253906 L 304.570312 818.050781 L 304.875 817.945312 L 305.183594 817.839844 L 305.492188 817.730469 L 305.800781 817.617188 L 306.105469 817.5 L 306.414062 817.382812 L 306.722656 817.261719 L 307.339844 817.011719 L 307.644531 816.878906 L 307.953125 816.746094 L 308.570312 816.472656 L 308.878906 816.328125 L 309.183594 816.183594 L 309.800781 815.878906 L 310.109375 815.722656 L 310.414062 815.5625 L 310.722656 815.398438 L 311.03125 815.230469 L 311.648438 814.886719 L 311.953125 814.707031 L 312.261719 814.523438 L 312.570312 814.335938 L 312.878906 814.144531 L 313.183594 813.949219 L 313.492188 813.75 L 313.800781 813.546875 L 314.417969 813.125 L 314.722656 812.90625 L 315.03125 812.683594 L 315.339844 812.457031 L 315.648438 812.226562 L 315.953125 811.992188 L 316.261719 811.75 L 316.570312 811.503906 L 316.878906 811.253906 L 317.1875 810.996094 L 317.492188 810.734375 L 317.800781 810.46875 L 318.109375 810.199219 L 318.417969 809.921875 L 318.722656 809.636719 L 319.03125 809.351562 L 319.648438 808.757812 L 319.957031 808.453125 L 320.261719 808.140625 L 320.570312 807.824219 L 320.878906 807.5 L 321.1875 807.171875 L 321.492188 806.835938 L 321.800781 806.496094 L 322.109375 806.148438 L 322.417969 805.792969 L 322.726562 805.433594 L 323.03125 805.066406 L 323.339844 804.695312 L 323.648438 804.316406 L 323.957031 803.929688 L 324.265625 803.535156 L 324.570312 803.132812 L 324.878906 802.726562 L 325.1875 802.3125 L 325.496094 801.890625 L 325.800781 801.464844 L 326.109375 801.027344 L 326.417969 800.585938 L 326.726562 800.136719 L 327.035156 799.679688 L 327.339844 799.214844 L 327.648438 798.742188 L 327.957031 798.261719 L 328.265625 797.773438 L 328.570312 797.28125 L 328.878906 796.777344 L 329.1875 796.265625 L 329.496094 795.746094 L 329.804688 795.222656 L 330.109375 794.6875 L 330.417969 794.144531 L 330.726562 793.59375 L 331.035156 793.035156 L 331.339844 792.46875 L 331.648438 791.894531 L 331.957031 791.3125 L 332.265625 790.71875 L 332.574219 790.121094 L 333.1875 788.894531 L 333.496094 788.269531 L 333.804688 787.636719 L 334.109375 786.996094 L 334.417969 786.34375 L 334.726562 785.683594 L 335.035156 785.019531 L 335.34375 784.339844 L 335.648438 783.65625 L 335.957031 782.960938 L 336.265625 782.261719 L 336.574219 781.550781 L 336.878906 780.828125 L 337.1875 780.101562 L 337.496094 779.363281 L 337.804688 778.617188 L 338.113281 777.863281 L 338.417969 777.101562 L 338.726562 776.328125 L 339.035156 775.546875 L 339.34375 774.757812 L 339.648438 773.960938 L 339.957031 773.152344 L 340.265625 772.335938 L 340.574219 771.511719 L 340.882812 770.679688 L 341.1875 769.839844 L 341.496094 768.988281 L 341.804688 768.128906 L 342.113281 767.261719 L 342.421875 766.386719 L 342.726562 765.503906 L 343.035156 764.609375 L 343.34375 763.710938 L 343.652344 762.800781 L 343.957031 761.882812 L 344.265625 760.957031 L 344.574219 760.023438 L 344.882812 759.082031 L 345.191406 758.132812 L 345.496094 757.175781 L 345.804688 756.210938 L 346.113281 755.238281 L 346.421875 754.253906 L 346.726562 753.265625 L 347.035156 752.269531 L 347.34375 751.265625 L 347.652344 750.257812 L 347.960938 749.238281 L 348.265625 748.214844 L 348.574219 747.179688 L 348.882812 746.140625 L 349.191406 745.097656 L 349.496094 744.042969 L 349.804688 742.984375 L 350.113281 741.917969 L 350.421875 740.847656 L 350.730469 739.769531 L 351.035156 738.683594 L 351.34375 737.59375 L 351.652344 736.5 L 351.960938 735.398438 L 352.265625 734.292969 L 352.574219 733.179688 L 352.882812 732.0625 L 353.191406 730.941406 L 353.5 729.8125 L 353.804688 728.679688 L 354.113281 727.546875 L 354.421875 726.40625 L 354.730469 725.261719 L 355.035156 724.113281 L 355.34375 722.960938 L 355.652344 721.804688 L 355.960938 720.644531 L 356.269531 719.480469 L 356.574219 718.316406 L 356.882812 717.148438 L 357.5 714.804688 L 357.808594 713.628906 L 358.113281 712.453125 L 358.730469 710.09375 L 359.039062 708.910156 L 359.34375 707.726562 L 360.578125 702.992188 L 360.882812 701.816406 L 361.191406 700.65625 L 361.5 699.507812 L 361.808594 698.375 L 362.113281 697.253906 L 362.421875 696.152344 L 362.730469 695.0625 L 363.039062 693.988281 L 363.347656 692.933594 L 363.652344 691.894531 L 363.960938 690.875 L 364.269531 689.871094 L 364.578125 688.886719 L 364.882812 687.925781 L 365.191406 686.980469 L 365.5 686.058594 L 365.808594 685.15625 L 366.117188 684.277344 L 366.421875 683.417969 L 366.730469 682.582031 L 367.039062 681.769531 L 367.347656 680.980469 L 367.652344 680.214844 L 367.960938 679.476562 L 368.269531 678.757812 L 368.578125 678.070312 L 368.886719 677.402344 L 369.191406 676.765625 L 369.5 676.152344 L 369.808594 675.566406 L 370.117188 675.007812 L 370.421875 674.476562 L 370.730469 673.972656 L 371.039062 673.496094 L 371.347656 673.050781 L 371.65625 672.632812 L 371.960938 672.242188 L 372.269531 671.882812 L 372.578125 671.550781 L 372.886719 671.25 L 373.195312 670.976562 L 373.5 670.734375 L 373.808594 670.523438 L 374.117188 670.339844 L 374.425781 670.1875 L 374.730469 670.066406 L 375.039062 669.972656 L 375.347656 669.914062 L 375.65625 669.882812 L 375.964844 669.882812 L 376.269531 669.914062 L 376.578125 669.972656 L 376.886719 670.066406 L 377.195312 670.1875 L 377.5 670.339844 L 377.808594 670.523438 L 378.117188 670.734375 L 378.425781 670.976562 L 378.734375 671.25 L 379.039062 671.550781 L 379.347656 671.882812 L 379.65625 672.242188 L 379.964844 672.632812 L 380.269531 673.050781 L 380.578125 673.496094 L 380.886719 673.972656 L 381.195312 674.476562 L 381.503906 675.007812 L 381.808594 675.566406 L 382.117188 676.152344 L 382.425781 676.765625 L 382.734375 677.402344 L 383.039062 678.070312 L 383.347656 678.757812 L 383.65625 679.476562 L 383.964844 680.214844 L 384.273438 680.980469 L 384.578125 681.769531 L 384.886719 682.582031 L 385.195312 683.417969 L 385.503906 684.277344 L 385.808594 685.15625 L 386.117188 686.058594 L 386.425781 686.980469 L 386.734375 687.925781 L 387.042969 688.886719 L 387.347656 689.871094 L 387.65625 690.875 L 387.964844 691.894531 L 388.273438 692.933594 L 388.578125 693.988281 L 388.886719 695.0625 L 389.195312 696.152344 L 389.503906 697.253906 L 389.8125 698.375 L 390.117188 699.507812 L 390.425781 700.65625 L 390.734375 701.816406 L 391.042969 702.992188 L 391.351562 704.175781 L 391.65625 705.359375 L 392.582031 708.910156 L 392.886719 710.09375 L 393.503906 712.453125 L 394.121094 714.804688 L 394.425781 715.976562 L 394.734375 717.148438 L 395.042969 718.316406 L 395.351562 719.480469 L 395.65625 720.644531 L 395.964844 721.804688 L 396.273438 722.960938 L 396.582031 724.113281 L 396.890625 725.261719 L 397.195312 726.40625 L 397.503906 727.546875 L 398.121094 729.8125 L 398.425781 730.941406 L 398.734375 732.0625 L 399.042969 733.179688 L 399.351562 734.292969 L 399.660156 735.398438 L 399.964844 736.5 L 400.273438 737.59375 L 400.582031 738.683594 L 400.890625 739.769531 L 401.195312 740.847656 L 401.503906 741.917969 L 401.8125 742.984375 L 402.121094 744.042969 L 402.429688 745.097656 L 402.734375 746.140625 L 403.042969 747.179688 L 403.351562 748.214844 L 403.660156 749.238281 L 403.964844 750.257812 L 404.273438 751.265625 L 404.582031 752.269531 L 404.890625 753.265625 L 405.199219 754.253906 L 405.503906 755.238281 L 405.8125 756.210938 L 406.121094 757.175781 L 406.429688 758.132812 L 406.738281 759.082031 L 407.042969 760.023438 L 407.351562 760.957031 L 407.660156 761.882812 L 407.96875 762.800781 L 408.273438 763.710938 L 408.582031 764.609375 L 408.890625 765.503906 L 409.199219 766.386719 L 409.507812 767.261719 L 409.8125 768.128906 L 410.121094 768.988281 L 410.429688 769.839844 L 410.738281 770.679688 L 411.042969 771.511719 L 411.351562 772.335938 L 411.660156 773.152344 L 411.96875 773.960938 L 412.277344 774.757812 L 412.582031 775.546875 L 412.890625 776.328125 L 413.199219 777.101562 L 413.507812 777.863281 L 413.8125 778.617188 L 414.121094 779.363281 L 414.429688 780.101562 L 414.738281 780.828125 L 415.046875 781.550781 L 415.351562 782.261719 L 415.660156 782.960938 L 415.96875 783.65625 L 416.277344 784.339844 L 416.582031 785.019531 L 416.890625 785.683594 L 417.199219 786.34375 L 417.507812 786.996094 L 417.816406 787.636719 L 418.121094 788.269531 L 418.429688 788.894531 L 418.738281 789.511719 L 419.046875 790.121094 L 419.351562 790.71875 L 419.660156 791.3125 L 419.96875 791.894531 L 420.277344 792.46875 L 420.585938 793.035156 L 420.890625 793.59375 L 421.199219 794.144531 L 421.507812 794.6875 L 421.816406 795.222656 L 422.125 795.746094 L 422.429688 796.265625 L 422.738281 796.777344 L 423.046875 797.28125 L 423.355469 797.773438 L 423.660156 798.261719 L 423.96875 798.742188 L 424.277344 799.214844 L 424.585938 799.679688 L 424.894531 800.136719 L 425.199219 800.585938 L 425.507812 801.027344 L 425.816406 801.464844 L 426.125 801.890625 L 426.429688 802.3125 L 426.738281 802.726562 L 427.046875 803.132812 L 427.355469 803.535156 L 427.664062 803.929688 L 427.96875 804.316406 L 428.277344 804.695312 L 428.585938 805.066406 L 428.894531 805.433594 L 429.199219 805.792969 L 429.507812 806.148438 L 429.816406 806.496094 L 430.125 806.835938 L 430.433594 807.171875 L 430.738281 807.5 L 431.046875 807.824219 L 431.355469 808.140625 L 431.664062 808.453125 L 431.96875 808.757812 L 432.585938 809.351562 L 433.203125 809.921875 L 433.507812 810.199219 L 433.816406 810.46875 L 434.125 810.734375 L 434.433594 810.996094 L 434.738281 811.253906 L 435.046875 811.503906 L 435.355469 811.75 L 435.664062 811.992188 L 435.972656 812.226562 L 436.277344 812.457031 L 436.585938 812.683594 L 436.894531 812.90625 L 437.203125 813.125 L 437.507812 813.335938 L 437.816406 813.546875 L 438.125 813.75 L 438.433594 813.949219 L 438.742188 814.144531 L 439.046875 814.335938 L 439.355469 814.523438 L 439.664062 814.707031 L 439.972656 814.886719 L 440.28125 815.058594 L 440.585938 815.230469 L 440.894531 815.398438 L 441.203125 815.5625 L 441.511719 815.722656 L 441.816406 815.878906 L 442.433594 816.183594 L 443.050781 816.472656 L 443.355469 816.609375 L 443.664062 816.746094 L 444.28125 817.011719 L 444.585938 817.136719 L 444.894531 817.261719 L 445.203125 817.382812 L 445.820312 817.617188 L 446.125 817.730469 L 446.433594 817.839844 L 447.050781 818.050781 L 447.355469 818.152344 L 447.664062 818.253906 L 447.972656 818.351562 L 448.589844 818.539062 L 448.894531 818.628906 L 449.511719 818.800781 L 449.820312 818.882812 L 450.125 818.964844 L 450.433594 819.046875 L 450.742188 819.121094 L 451.050781 819.199219 L 451.359375 819.269531 L 451.664062 819.34375 L 451.972656 819.414062 L 452.589844 819.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="270.929688" y="825.148438"/>
+ <use xlink:href="#glyph0-2" x="276.265274" y="825.148438"/>
+ <use xlink:href="#glyph0-1" x="278.930725" y="825.148438"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="270.929688" y="786.15625"/>
+ <use xlink:href="#glyph0-2" x="276.265274" y="786.15625"/>
+ <use xlink:href="#glyph0-3" x="278.930725" y="786.15625"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="270.929688" y="747.167969"/>
+ <use xlink:href="#glyph0-2" x="276.265274" y="747.167969"/>
+ <use xlink:href="#glyph0-7" x="278.930725" y="747.167969"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="270.929688" y="708.175781"/>
+ <use xlink:href="#glyph0-2" x="276.265274" y="708.175781"/>
+ <use xlink:href="#glyph0-8" x="278.930725" y="708.175781"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="270.929688" y="669.183594"/>
+ <use xlink:href="#glyph0-2" x="276.265274" y="669.183594"/>
+ <use xlink:href="#glyph0-9" x="278.930725" y="669.183594"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 821.710938 L 291.351562 821.710938 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 782.71875 L 291.351562 782.71875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 743.730469 L 291.351562 743.730469 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 704.738281 L 291.351562 704.738281 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 665.746094 L 291.351562 665.746094 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 831.28125 L 299.03125 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 831.28125 L 337.417969 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 831.28125 L 375.808594 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 831.28125 L 414.199219 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 831.28125 L 452.589844 827.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="289.695312" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="295.030899" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="297.69635" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="303.031937" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="328.082031" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="333.417618" y="840.992188"/>
+ <use xlink:href="#glyph0-3" x="336.083069" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="341.418655" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="366.472656" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="371.808243" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="374.473694" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="379.80928" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="404.863281" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="410.198868" y="840.992188"/>
+ <use xlink:href="#glyph0-5" x="412.864319" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="418.199905" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="443.253906" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="448.589493" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="451.254944" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="456.59053" y="840.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="372.808594" y="853.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="258.992188" y="756.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="258.992188" y="749.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="258.992188" y="744.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="258.992188" y="738.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-25" x="287.011719" y="658.800781"/>
+ <use xlink:href="#glyph5-4" x="296.345703" y="658.800781"/>
+ <use xlink:href="#glyph5-26" x="303.019531" y="658.800781"/>
+ <use xlink:href="#glyph5-18" x="310.349609" y="658.800781"/>
+ <use xlink:href="#glyph5-18" x="317.023438" y="658.800781"/>
+ <use xlink:href="#glyph5-3" x="323.697266" y="658.800781"/>
+ <use xlink:href="#glyph5-4" x="327.03125" y="658.800781"/>
+ <use xlink:href="#glyph5-5" x="333.705078" y="658.800781"/>
+ <use xlink:href="#glyph5-10" x="341.035156" y="658.800781"/>
+ <use xlink:href="#glyph5-2" x="349.039062" y="658.800781"/>
+ <use xlink:href="#glyph5-15" x="353.708984" y="658.800781"/>
+ <use xlink:href="#glyph5-16" x="361.039062" y="658.800781"/>
+ <use xlink:href="#glyph5-26" x="368.369141" y="658.800781"/>
+ <use xlink:href="#glyph5-22" x="375.699219" y="658.800781"/>
+ <use xlink:href="#glyph5-24" x="382.373047" y="658.800781"/>
+</g>
+<g clip-path="url(#clip226)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 474.667969 864 L 712 864 L 712 648 L 474.667969 648 Z "/>
+</g>
+<g clip-path="url(#clip227)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 474.667969 864 L 712 864 L 712 648 L 474.667969 648 Z "/>
+</g>
+<g clip-path="url(#clip228)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 528.683594 827.027344 L 697.597656 827.027344 L 697.597656 662.398438 L 528.683594 662.398438 Z "/>
+</g>
+<g clip-path="url(#clip229)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 801.546875 L 697.601562 801.546875 "/>
+</g>
+<g clip-path="url(#clip230)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 763.496094 L 697.601562 763.496094 "/>
+</g>
+<g clip-path="url(#clip231)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 725.441406 L 697.601562 725.441406 "/>
+</g>
+<g clip-path="url(#clip232)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 687.390625 L 697.601562 687.390625 "/>
+</g>
+<g clip-path="url(#clip233)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.558594 827.027344 L 555.558594 662.398438 "/>
+</g>
+<g clip-path="url(#clip234)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 593.949219 827.027344 L 593.949219 662.398438 "/>
+</g>
+<g clip-path="url(#clip235)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 632.335938 827.027344 L 632.335938 662.398438 "/>
+</g>
+<g clip-path="url(#clip236)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 670.726562 827.027344 L 670.726562 662.398438 "/>
+</g>
+<g clip-path="url(#clip237)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 820.570312 L 697.601562 820.570312 "/>
+</g>
+<g clip-path="url(#clip238)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 782.519531 L 697.601562 782.519531 "/>
+</g>
+<g clip-path="url(#clip239)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 744.46875 L 697.601562 744.46875 "/>
+</g>
+<g clip-path="url(#clip240)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 706.417969 L 697.601562 706.417969 "/>
+</g>
+<g clip-path="url(#clip241)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 668.367188 L 697.601562 668.367188 "/>
+</g>
+<g clip-path="url(#clip242)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 827.027344 L 536.363281 662.398438 "/>
+</g>
+<g clip-path="url(#clip243)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 827.027344 L 574.753906 662.398438 "/>
+</g>
+<g clip-path="url(#clip244)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 827.027344 L 613.140625 662.398438 "/>
+</g>
+<g clip-path="url(#clip245)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 827.027344 L 651.53125 662.398438 "/>
+</g>
+<g clip-path="url(#clip246)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 827.027344 L 689.921875 662.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 536.363281 819.546875 L 536.671875 819.523438 L 536.976562 819.503906 L 537.285156 819.480469 L 537.59375 819.460938 L 538.210938 819.414062 L 538.515625 819.390625 L 539.132812 819.34375 L 539.441406 819.316406 L 539.746094 819.292969 L 540.054688 819.265625 L 540.363281 819.242188 L 540.980469 819.1875 L 541.285156 819.15625 L 541.902344 819.101562 L 542.210938 819.070312 L 542.515625 819.039062 L 543.75 818.914062 L 544.054688 818.878906 L 545.289062 818.738281 L 545.59375 818.699219 L 545.902344 818.664062 L 546.519531 818.585938 L 546.824219 818.542969 L 547.132812 818.503906 L 548.058594 818.375 L 548.363281 818.332031 L 549.289062 818.191406 L 549.59375 818.144531 L 550.828125 817.941406 L 551.132812 817.886719 L 552.058594 817.722656 L 552.363281 817.664062 L 552.980469 817.546875 L 553.597656 817.421875 L 553.902344 817.359375 L 554.828125 817.160156 L 555.132812 817.089844 L 555.441406 817.019531 L 555.75 816.945312 L 556.058594 816.875 L 556.367188 816.796875 L 556.671875 816.722656 L 557.289062 816.566406 L 557.597656 816.484375 L 557.902344 816.402344 L 558.519531 816.230469 L 558.828125 816.140625 L 559.136719 816.054688 L 559.441406 815.960938 L 560.058594 815.773438 L 560.367188 815.675781 L 560.671875 815.578125 L 560.980469 815.476562 L 561.90625 815.160156 L 562.210938 815.050781 L 562.828125 814.824219 L 563.445312 814.589844 L 563.75 814.46875 L 564.367188 814.21875 L 564.675781 814.089844 L 564.980469 813.957031 L 565.289062 813.824219 L 565.90625 813.550781 L 566.214844 813.40625 L 566.519531 813.261719 L 567.136719 812.964844 L 567.445312 812.808594 L 567.75 812.652344 L 568.058594 812.492188 L 568.367188 812.328125 L 568.984375 811.992188 L 569.289062 811.816406 L 569.597656 811.640625 L 569.90625 811.460938 L 570.214844 811.273438 L 570.519531 811.085938 L 570.828125 810.894531 L 571.136719 810.699219 L 571.445312 810.5 L 571.753906 810.296875 L 572.058594 810.085938 L 572.367188 809.875 L 572.675781 809.660156 L 572.984375 809.4375 L 573.289062 809.210938 L 573.597656 808.980469 L 573.90625 808.746094 L 574.214844 808.507812 L 574.523438 808.265625 L 574.828125 808.015625 L 575.136719 807.761719 L 575.753906 807.238281 L 576.058594 806.96875 L 576.367188 806.691406 L 576.675781 806.410156 L 576.984375 806.125 L 577.292969 805.832031 L 577.597656 805.53125 L 577.90625 805.230469 L 578.214844 804.917969 L 578.523438 804.601562 L 578.832031 804.277344 L 579.136719 803.949219 L 579.445312 803.613281 L 579.753906 803.269531 L 580.0625 802.917969 L 580.367188 802.5625 L 580.675781 802.195312 L 580.984375 801.824219 L 581.292969 801.445312 L 581.601562 801.058594 L 581.90625 800.664062 L 582.214844 800.257812 L 582.523438 799.847656 L 582.832031 799.429688 L 583.136719 799 L 583.445312 798.5625 L 583.753906 798.117188 L 584.0625 797.664062 L 584.371094 797.199219 L 584.675781 796.726562 L 584.984375 796.246094 L 585.292969 795.753906 L 585.601562 795.25 L 585.90625 794.738281 L 586.214844 794.214844 L 586.523438 793.679688 L 586.832031 793.136719 L 587.140625 792.582031 L 587.445312 792.015625 L 587.753906 791.4375 L 588.0625 790.847656 L 588.371094 790.246094 L 588.675781 789.632812 L 588.984375 789.003906 L 589.292969 788.367188 L 589.601562 787.714844 L 589.910156 787.050781 L 590.214844 786.371094 L 590.523438 785.679688 L 590.832031 784.972656 L 591.140625 784.25 L 591.445312 783.515625 L 591.753906 782.765625 L 592.0625 782 L 592.371094 781.21875 L 592.679688 780.421875 L 592.984375 779.609375 L 593.292969 778.78125 L 593.601562 777.9375 L 593.910156 777.074219 L 594.21875 776.191406 L 594.523438 775.292969 L 594.832031 774.378906 L 595.140625 773.441406 L 595.449219 772.488281 L 595.753906 771.515625 L 596.0625 770.523438 L 596.371094 769.507812 L 596.679688 768.476562 L 596.988281 767.421875 L 597.292969 766.34375 L 597.601562 765.246094 L 597.910156 764.128906 L 598.21875 762.984375 L 598.523438 761.820312 L 598.832031 760.628906 L 599.140625 759.417969 L 599.449219 758.179688 L 599.757812 756.914062 L 600.0625 755.628906 L 600.371094 754.3125 L 600.679688 752.972656 L 600.988281 751.601562 L 601.292969 750.207031 L 601.601562 748.78125 L 601.910156 747.328125 L 602.21875 745.847656 L 602.527344 744.335938 L 602.832031 742.789062 L 603.140625 741.214844 L 603.449219 739.609375 L 603.757812 737.972656 L 604.0625 736.300781 L 604.371094 734.59375 L 604.679688 732.851562 L 604.988281 731.078125 L 605.296875 729.265625 L 605.601562 727.417969 L 605.910156 725.53125 L 606.21875 723.609375 L 606.527344 721.644531 L 606.832031 719.644531 L 607.140625 717.601562 L 607.449219 715.515625 L 607.757812 713.390625 L 608.066406 711.21875 L 608.371094 709.007812 L 608.679688 706.746094 L 608.988281 704.445312 L 609.296875 702.09375 L 609.601562 699.695312 L 609.910156 697.246094 L 610.21875 694.75 L 610.527344 692.203125 L 610.835938 689.605469 L 611.140625 686.953125 L 611.449219 684.25 L 611.757812 681.492188 L 612.066406 678.675781 L 612.375 675.804688 L 612.679688 672.871094 L 612.988281 669.882812 L 613.296875 669.882812 L 613.605469 672.871094 L 613.910156 675.804688 L 614.21875 678.675781 L 614.527344 681.492188 L 614.835938 684.25 L 615.144531 686.953125 L 615.449219 689.605469 L 615.757812 692.203125 L 616.066406 694.75 L 616.375 697.246094 L 616.679688 699.695312 L 616.988281 702.09375 L 617.296875 704.445312 L 617.605469 706.746094 L 617.914062 709.007812 L 618.21875 711.21875 L 618.527344 713.390625 L 618.835938 715.515625 L 619.144531 717.601562 L 619.449219 719.644531 L 619.757812 721.644531 L 620.066406 723.609375 L 620.375 725.53125 L 620.683594 727.417969 L 620.988281 729.265625 L 621.296875 731.078125 L 621.605469 732.851562 L 621.914062 734.59375 L 622.21875 736.300781 L 622.527344 737.972656 L 622.835938 739.609375 L 623.144531 741.214844 L 623.453125 742.789062 L 623.757812 744.335938 L 624.066406 745.847656 L 624.375 747.328125 L 624.683594 748.78125 L 624.988281 750.207031 L 625.296875 751.601562 L 625.605469 752.972656 L 625.914062 754.3125 L 626.222656 755.628906 L 626.527344 756.914062 L 626.835938 758.179688 L 627.144531 759.417969 L 627.453125 760.628906 L 627.761719 761.820312 L 628.066406 762.984375 L 628.375 764.128906 L 628.683594 765.246094 L 628.992188 766.34375 L 629.296875 767.421875 L 629.605469 768.476562 L 629.914062 769.507812 L 630.222656 770.523438 L 630.53125 771.515625 L 630.835938 772.488281 L 631.144531 773.441406 L 631.453125 774.378906 L 631.761719 775.292969 L 632.066406 776.191406 L 632.375 777.074219 L 632.683594 777.9375 L 632.992188 778.78125 L 633.300781 779.609375 L 633.605469 780.421875 L 633.914062 781.21875 L 634.222656 782 L 634.53125 782.765625 L 634.835938 783.515625 L 635.144531 784.25 L 635.453125 784.972656 L 635.761719 785.679688 L 636.070312 786.371094 L 636.375 787.050781 L 636.683594 787.714844 L 636.992188 788.367188 L 637.300781 789.003906 L 637.605469 789.632812 L 637.914062 790.246094 L 638.222656 790.847656 L 638.53125 791.4375 L 638.839844 792.015625 L 639.144531 792.582031 L 639.453125 793.136719 L 639.761719 793.679688 L 640.070312 794.214844 L 640.375 794.738281 L 640.683594 795.25 L 640.992188 795.753906 L 641.300781 796.246094 L 641.609375 796.726562 L 641.914062 797.199219 L 642.222656 797.664062 L 642.53125 798.117188 L 642.839844 798.5625 L 643.148438 799 L 643.453125 799.429688 L 643.761719 799.847656 L 644.070312 800.257812 L 644.378906 800.664062 L 644.683594 801.058594 L 644.992188 801.445312 L 645.300781 801.824219 L 645.609375 802.195312 L 645.917969 802.5625 L 646.222656 802.917969 L 646.53125 803.269531 L 646.839844 803.613281 L 647.148438 803.949219 L 647.453125 804.277344 L 647.761719 804.601562 L 648.070312 804.917969 L 648.378906 805.230469 L 648.6875 805.53125 L 648.992188 805.832031 L 649.300781 806.125 L 649.609375 806.410156 L 649.917969 806.691406 L 650.222656 806.96875 L 650.53125 807.238281 L 651.148438 807.761719 L 651.457031 808.015625 L 651.761719 808.265625 L 652.070312 808.507812 L 652.378906 808.746094 L 652.6875 808.980469 L 652.992188 809.210938 L 653.300781 809.4375 L 653.609375 809.660156 L 653.917969 809.875 L 654.226562 810.085938 L 654.53125 810.296875 L 654.839844 810.5 L 655.148438 810.699219 L 655.457031 810.894531 L 655.761719 811.085938 L 656.378906 811.460938 L 656.6875 811.640625 L 656.996094 811.816406 L 657.300781 811.992188 L 657.917969 812.328125 L 658.226562 812.492188 L 658.53125 812.652344 L 659.148438 812.964844 L 659.765625 813.261719 L 660.070312 813.40625 L 660.378906 813.550781 L 660.996094 813.824219 L 661.304688 813.957031 L 661.609375 814.089844 L 661.917969 814.21875 L 662.535156 814.46875 L 662.839844 814.589844 L 663.457031 814.824219 L 664.074219 815.050781 L 664.378906 815.160156 L 665.304688 815.476562 L 665.609375 815.578125 L 666.226562 815.773438 L 666.84375 815.960938 L 667.148438 816.054688 L 667.457031 816.140625 L 667.765625 816.230469 L 668.074219 816.316406 L 668.378906 816.402344 L 668.996094 816.566406 L 669.613281 816.722656 L 669.917969 816.796875 L 670.226562 816.875 L 670.535156 816.945312 L 670.84375 817.019531 L 671.148438 817.089844 L 671.457031 817.160156 L 672.382812 817.359375 L 672.6875 817.421875 L 673.304688 817.546875 L 673.613281 817.605469 L 673.917969 817.664062 L 674.226562 817.722656 L 675.152344 817.886719 L 675.457031 817.941406 L 676.691406 818.144531 L 676.996094 818.191406 L 677.921875 818.332031 L 678.226562 818.375 L 679.152344 818.503906 L 679.460938 818.542969 L 679.765625 818.585938 L 680.382812 818.664062 L 680.691406 818.699219 L 680.996094 818.738281 L 682.230469 818.878906 L 682.535156 818.914062 L 683.460938 819.007812 L 683.765625 819.039062 L 684.382812 819.101562 L 685 819.15625 L 685.304688 819.1875 L 685.921875 819.242188 L 686.230469 819.265625 L 686.535156 819.292969 L 686.84375 819.316406 L 687.152344 819.34375 L 687.769531 819.390625 L 688.074219 819.414062 L 688.691406 819.460938 L 689 819.480469 L 689.304688 819.503906 L 689.613281 819.523438 L 689.921875 819.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="824.007812"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="824.007812"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="824.007812"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="824.007812"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="785.957031"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="785.957031"/>
+ <use xlink:href="#glyph0-3" x="510.926819" y="785.957031"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="785.957031"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="747.90625"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="747.90625"/>
+ <use xlink:href="#glyph0-4" x="510.926819" y="747.90625"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="747.90625"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="709.855469"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="709.855469"/>
+ <use xlink:href="#glyph0-5" x="510.926819" y="709.855469"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="709.855469"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="502.925781" y="671.804688"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="671.804688"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="671.804688"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="671.804688"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 820.570312 L 528.683594 820.570312 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 782.519531 L 528.683594 782.519531 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 744.46875 L 528.683594 744.46875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 706.417969 L 528.683594 706.417969 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 668.367188 L 528.683594 668.367188 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 831.28125 L 536.363281 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 831.28125 L 574.753906 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 831.28125 L 613.140625 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 831.28125 L 651.53125 827.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 831.28125 L 689.921875 827.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="527.027344" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="532.36293" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="535.028381" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="540.363968" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="565.417969" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="570.753555" y="840.992188"/>
+ <use xlink:href="#glyph0-3" x="573.419006" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="578.754593" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="603.804688" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="609.140274" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="611.805725" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="617.141312" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="642.195312" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="647.530899" y="840.992188"/>
+ <use xlink:href="#glyph0-5" x="650.19635" y="840.992188"/>
+ <use xlink:href="#glyph0-4" x="655.531937" y="840.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="680.585938" y="840.992188"/>
+ <use xlink:href="#glyph0-2" x="685.921524" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="688.586975" y="840.992188"/>
+ <use xlink:href="#glyph0-1" x="693.922562" y="840.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="610.140625" y="853.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="496.324219" y="756.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="496.324219" y="749.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="496.324219" y="744.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="496.324219" y="738.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-11" x="490.675781" y="658.800781"/>
+ <use xlink:href="#glyph5-13" x="498.679688" y="658.800781"/>
+ <use xlink:href="#glyph5-3" x="506.009766" y="658.800781"/>
+ <use xlink:href="#glyph5-27" x="509.34375" y="658.800781"/>
+ <use xlink:href="#glyph5-8" x="516.017578" y="658.800781"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 1080 L 237.332031 1080 L 237.332031 864 L 0 864 Z "/>
+<g clip-path="url(#clip247)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 1080 L 237.332031 1080 L 237.332031 864 L 0 864 Z "/>
+</g>
+<g clip-path="url(#clip248)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 1043.027344 L 222.933594 1043.027344 L 222.933594 878.398438 L 54.019531 878.398438 Z "/>
+</g>
+<g clip-path="url(#clip249)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1016.839844 L 222.933594 1016.839844 "/>
+</g>
+<g clip-path="url(#clip250)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 979.421875 L 222.933594 979.421875 "/>
+</g>
+<g clip-path="url(#clip251)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 942.007812 L 222.933594 942.007812 "/>
+</g>
+<g clip-path="url(#clip252)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 904.589844 L 222.933594 904.589844 "/>
+</g>
+<g clip-path="url(#clip253)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 80.890625 1043.027344 L 80.890625 878.398438 "/>
+</g>
+<g clip-path="url(#clip254)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 119.28125 1043.027344 L 119.28125 878.398438 "/>
+</g>
+<g clip-path="url(#clip255)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.671875 1043.027344 L 157.671875 878.398438 "/>
+</g>
+<g clip-path="url(#clip256)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 196.058594 1043.027344 L 196.058594 878.398438 "/>
+</g>
+<g clip-path="url(#clip257)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1035.546875 L 222.933594 1035.546875 "/>
+</g>
+<g clip-path="url(#clip258)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 998.128906 L 222.933594 998.128906 "/>
+</g>
+<g clip-path="url(#clip259)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 960.714844 L 222.933594 960.714844 "/>
+</g>
+<g clip-path="url(#clip260)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 923.296875 L 222.933594 923.296875 "/>
+</g>
+<g clip-path="url(#clip261)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 885.882812 L 222.933594 885.882812 "/>
+</g>
+<g clip-path="url(#clip262)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 1043.027344 L 61.695312 878.398438 "/>
+</g>
+<g clip-path="url(#clip263)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 1043.027344 L 100.085938 878.398438 "/>
+</g>
+<g clip-path="url(#clip264)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 1043.027344 L 138.476562 878.398438 "/>
+</g>
+<g clip-path="url(#clip265)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 1043.027344 L 176.867188 878.398438 "/>
+</g>
+<g clip-path="url(#clip266)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 1043.027344 L 215.253906 878.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 61.695312 1035.546875 L 176.789062 1035.546875 L 177.097656 885.882812 L 215.253906 885.882812 "/>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 61.695312 885.882812 L 99.855469 885.882812 L 100.164062 1035.546875 L 215.253906 1035.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="1038.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="1038.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="1038.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="1038.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="1001.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="1001.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="1001.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="1001.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="964.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="964.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="964.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="964.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="926.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="926.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="926.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="926.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="889.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="889.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="889.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="889.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1035.546875 L 54.019531 1035.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 998.128906 L 54.019531 998.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 960.714844 L 54.019531 960.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 923.296875 L 54.019531 923.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 885.882812 L 54.019531 885.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 1047.28125 L 61.695312 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 1047.28125 L 100.085938 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 1047.28125 L 138.476562 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 1047.28125 L 176.867188 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 1047.28125 L 215.253906 1043.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="52.359375" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="57.694962" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="60.360413" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="65.695999" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="90.75" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="96.085587" y="1056.992188"/>
+ <use xlink:href="#glyph0-3" x="98.751038" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="104.086624" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="129.140625" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="134.476212" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="137.141663" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="142.477249" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="167.53125" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="172.866837" y="1056.992188"/>
+ <use xlink:href="#glyph0-5" x="175.532288" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="180.867874" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="205.917969" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="211.253555" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="213.919006" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="219.254593" y="1056.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="135.476562" y="1069.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="972.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="965.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="960.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="954.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-9" x="18.671875" y="874.800781"/>
+ <use xlink:href="#glyph5-3" x="27.337891" y="874.800781"/>
+ <use xlink:href="#glyph5-5" x="30.671875" y="874.800781"/>
+ <use xlink:href="#glyph5-4" x="38.001953" y="874.800781"/>
+ <use xlink:href="#glyph5-2" x="44.675781" y="874.800781"/>
+ <use xlink:href="#glyph5-28" x="49.345703" y="874.800781"/>
+</g>
+<g clip-path="url(#clip267)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 237.332031 1080 L 474.664062 1080 L 474.664062 864 L 237.332031 864 Z "/>
+</g>
+<g clip-path="url(#clip268)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 237.332031 1080 L 474.664062 1080 L 474.664062 864 L 237.332031 864 Z "/>
+</g>
+<g clip-path="url(#clip269)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 291.351562 1043.027344 L 460.265625 1043.027344 L 460.265625 878.398438 L 291.351562 878.398438 Z "/>
+</g>
+<g clip-path="url(#clip270)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1016.839844 L 460.265625 1016.839844 "/>
+</g>
+<g clip-path="url(#clip271)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 979.421875 L 460.265625 979.421875 "/>
+</g>
+<g clip-path="url(#clip272)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 942.007812 L 460.265625 942.007812 "/>
+</g>
+<g clip-path="url(#clip273)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 904.589844 L 460.265625 904.589844 "/>
+</g>
+<g clip-path="url(#clip274)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 318.222656 1043.027344 L 318.222656 878.398438 "/>
+</g>
+<g clip-path="url(#clip275)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.613281 1043.027344 L 356.613281 878.398438 "/>
+</g>
+<g clip-path="url(#clip276)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 395.003906 1043.027344 L 395.003906 878.398438 "/>
+</g>
+<g clip-path="url(#clip277)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 433.394531 1043.027344 L 433.394531 878.398438 "/>
+</g>
+<g clip-path="url(#clip278)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1035.546875 L 460.265625 1035.546875 "/>
+</g>
+<g clip-path="url(#clip279)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 998.128906 L 460.265625 998.128906 "/>
+</g>
+<g clip-path="url(#clip280)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 960.714844 L 460.265625 960.714844 "/>
+</g>
+<g clip-path="url(#clip281)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 923.296875 L 460.265625 923.296875 "/>
+</g>
+<g clip-path="url(#clip282)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 885.882812 L 460.265625 885.882812 "/>
+</g>
+<g clip-path="url(#clip283)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 1043.027344 L 299.03125 878.398438 "/>
+</g>
+<g clip-path="url(#clip284)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 1043.027344 L 337.417969 878.398438 "/>
+</g>
+<g clip-path="url(#clip285)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 1043.027344 L 375.808594 878.398438 "/>
+</g>
+<g clip-path="url(#clip286)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 1043.027344 L 414.199219 878.398438 "/>
+</g>
+<g clip-path="url(#clip287)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 1043.027344 L 452.589844 878.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 299.03125 1035.546875 L 329.496094 1035.546875 L 329.804688 1035.445312 L 330.109375 1034.945312 L 331.035156 1033.445312 L 331.339844 1032.945312 L 332.574219 1030.945312 L 332.878906 1030.445312 L 333.1875 1029.949219 L 333.804688 1028.949219 L 334.109375 1028.449219 L 335.34375 1026.449219 L 335.648438 1025.949219 L 336.574219 1024.449219 L 336.878906 1023.949219 L 338.113281 1021.949219 L 338.417969 1021.449219 L 339.34375 1019.949219 L 339.648438 1019.449219 L 340.882812 1017.449219 L 341.1875 1016.949219 L 342.421875 1014.949219 L 342.726562 1014.449219 L 343.035156 1013.953125 L 343.652344 1012.953125 L 343.957031 1012.453125 L 345.191406 1010.453125 L 345.496094 1009.953125 L 346.421875 1008.453125 L 346.726562 1007.953125 L 347.960938 1005.953125 L 348.265625 1005.453125 L 349.191406 1003.953125 L 349.496094 1003.453125 L 350.730469 1001.453125 L 351.035156 1000.953125 L 351.960938 999.453125 L 352.265625 998.953125 L 352.574219 998.457031 L 353.5 996.957031 L 353.804688 996.457031 L 354.730469 994.957031 L 355.035156 994.457031 L 356.269531 992.457031 L 356.574219 991.957031 L 357.808594 989.957031 L 358.113281 989.457031 L 359.039062 987.957031 L 359.34375 987.457031 L 360.578125 985.457031 L 360.882812 984.957031 L 361.808594 983.457031 L 362.113281 982.957031 L 362.421875 982.460938 L 363.347656 980.960938 L 363.652344 980.460938 L 364.578125 978.960938 L 364.882812 978.460938 L 366.117188 976.460938 L 366.421875 975.960938 L 367.347656 974.460938 L 367.652344 973.960938 L 368.886719 971.960938 L 369.191406 971.460938 L 370.117188 969.960938 L 370.421875 969.460938 L 371.65625 967.460938 L 371.960938 966.964844 L 373.195312 964.964844 L 373.5 964.464844 L 374.425781 962.964844 L 374.730469 962.464844 L 375.964844 960.464844 L 376.269531 959.964844 L 377.195312 958.464844 L 377.5 957.964844 L 378.734375 955.964844 L 379.039062 955.464844 L 379.964844 953.964844 L 380.269531 953.464844 L 381.195312 951.964844 L 381.503906 951.46875 L 381.808594 950.96875 L 382.734375 949.46875 L 383.039062 948.96875 L 384.273438 946.96875 L 384.578125 946.46875 L 385.503906 944.96875 L 385.808594 944.46875 L 387.042969 942.46875 L 387.347656 941.96875 L 388.273438 940.46875 L 388.578125 939.96875 L 389.8125 937.96875 L 390.117188 937.46875 L 391.042969 935.96875 L 391.351562 935.472656 L 391.65625 934.972656 L 392.582031 933.472656 L 392.886719 932.972656 L 394.121094 930.972656 L 394.425781 930.472656 L 395.351562 928.972656 L 395.65625 928.472656 L 396.890625 926.472656 L 397.195312 925.972656 L 398.121094 924.472656 L 398.425781 923.972656 L 399.660156 921.972656 L 399.964844 921.472656 L 400.582031 920.472656 L 400.890625 919.976562 L 401.195312 919.476562 L 402.429688 917.476562 L 402.734375 916.976562 L 403.660156 915.476562 L 403.964844 914.976562 L 405.199219 912.976562 L 405.503906 912.476562 L 406.738281 910.476562 L 407.042969 909.976562 L 407.96875 908.476562 L 408.273438 907.976562 L 409.507812 905.976562 L 409.8125 905.476562 L 410.429688 904.476562 L 410.738281 903.980469 L 411.042969 903.480469 L 412.277344 901.480469 L 412.582031 900.980469 L 413.507812 899.480469 L 413.8125 898.980469 L 415.046875 896.980469 L 415.351562 896.480469 L 416.277344 894.980469 L 416.582031 894.480469 L 417.816406 892.480469 L 418.121094 891.980469 L 419.046875 890.480469 L 419.351562 889.980469 L 419.96875 888.980469 L 420.277344 888.484375 L 420.585938 887.984375 L 420.890625 887.484375 L 421.816406 885.984375 L 422.125 885.882812 L 452.589844 885.882812 "/>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 299.03125 885.882812 L 329.496094 885.882812 L 329.804688 885.984375 L 330.109375 886.484375 L 331.035156 887.984375 L 331.339844 888.484375 L 331.648438 888.980469 L 332.574219 890.480469 L 332.878906 890.980469 L 333.804688 892.480469 L 334.109375 892.980469 L 335.34375 894.980469 L 335.648438 895.480469 L 336.574219 896.980469 L 336.878906 897.480469 L 338.113281 899.480469 L 338.417969 899.980469 L 339.34375 901.480469 L 339.648438 901.980469 L 340.882812 903.980469 L 341.1875 904.476562 L 342.421875 906.476562 L 342.726562 906.976562 L 343.652344 908.476562 L 343.957031 908.976562 L 345.191406 910.976562 L 345.496094 911.476562 L 346.421875 912.976562 L 346.726562 913.476562 L 347.960938 915.476562 L 348.265625 915.976562 L 349.191406 917.476562 L 349.496094 917.976562 L 350.730469 919.976562 L 351.035156 920.472656 L 351.960938 921.972656 L 352.265625 922.472656 L 353.5 924.472656 L 353.804688 924.972656 L 354.730469 926.472656 L 355.035156 926.972656 L 356.269531 928.972656 L 356.574219 929.472656 L 357.808594 931.472656 L 358.113281 931.972656 L 359.039062 933.472656 L 359.34375 933.972656 L 360.269531 935.472656 L 360.578125 935.96875 L 360.882812 936.46875 L 361.808594 937.96875 L 362.113281 938.46875 L 363.347656 940.46875 L 363.652344 940.96875 L 364.578125 942.46875 L 364.882812 942.96875 L 366.117188 944.96875 L 366.421875 945.46875 L 367.347656 946.96875 L 367.652344 947.46875 L 368.886719 949.46875 L 369.191406 949.96875 L 370.117188 951.46875 L 370.421875 951.964844 L 371.65625 953.964844 L 371.960938 954.464844 L 373.195312 956.464844 L 373.5 956.964844 L 374.425781 958.464844 L 374.730469 958.964844 L 375.964844 960.964844 L 376.269531 961.464844 L 377.195312 962.964844 L 377.5 963.464844 L 378.734375 965.464844 L 379.039062 965.964844 L 379.65625 966.964844 L 379.964844 967.460938 L 380.269531 967.960938 L 381.503906 969.960938 L 381.808594 970.460938 L 382.734375 971.960938 L 383.039062 972.460938 L 384.273438 974.460938 L 384.578125 974.960938 L 385.503906 976.460938 L 385.808594 976.960938 L 387.042969 978.960938 L 387.347656 979.460938 L 388.273438 980.960938 L 388.578125 981.460938 L 389.195312 982.460938 L 389.503906 982.957031 L 389.8125 983.457031 L 390.117188 983.957031 L 391.351562 985.957031 L 391.65625 986.457031 L 392.582031 987.957031 L 392.886719 988.457031 L 394.121094 990.457031 L 394.425781 990.957031 L 395.351562 992.457031 L 395.65625 992.957031 L 396.890625 994.957031 L 397.195312 995.457031 L 398.121094 996.957031 L 398.425781 997.457031 L 399.042969 998.457031 L 399.351562 998.953125 L 399.660156 999.453125 L 399.964844 999.953125 L 400.890625 1001.453125 L 401.195312 1001.953125 L 402.429688 1003.953125 L 402.734375 1004.453125 L 403.660156 1005.953125 L 403.964844 1006.453125 L 405.199219 1008.453125 L 405.503906 1008.953125 L 406.738281 1010.953125 L 407.042969 1011.453125 L 407.96875 1012.953125 L 408.273438 1013.453125 L 408.582031 1013.953125 L 408.890625 1014.449219 L 409.507812 1015.449219 L 409.8125 1015.949219 L 410.738281 1017.449219 L 411.042969 1017.949219 L 412.277344 1019.949219 L 412.582031 1020.449219 L 413.507812 1021.949219 L 413.8125 1022.449219 L 415.046875 1024.449219 L 415.351562 1024.949219 L 416.277344 1026.449219 L 416.582031 1026.949219 L 417.816406 1028.949219 L 418.121094 1029.449219 L 418.429688 1029.949219 L 418.738281 1030.445312 L 419.046875 1030.945312 L 419.351562 1031.445312 L 420.585938 1033.445312 L 420.890625 1033.945312 L 421.816406 1035.445312 L 422.125 1035.546875 L 452.589844 1035.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1038.984375"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1038.984375"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="1038.984375"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="1038.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1001.566406"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1001.566406"/>
+ <use xlink:href="#glyph0-3" x="273.594788" y="1001.566406"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="1001.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="964.152344"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="964.152344"/>
+ <use xlink:href="#glyph0-4" x="273.594788" y="964.152344"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="964.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="926.734375"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="926.734375"/>
+ <use xlink:href="#glyph0-5" x="273.594788" y="926.734375"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="926.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="265.59375" y="889.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="889.320312"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="889.320312"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="889.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1035.546875 L 291.351562 1035.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 998.128906 L 291.351562 998.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 960.714844 L 291.351562 960.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 923.296875 L 291.351562 923.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 885.882812 L 291.351562 885.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 1047.28125 L 299.03125 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 1047.28125 L 337.417969 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 1047.28125 L 375.808594 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 1047.28125 L 414.199219 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 1047.28125 L 452.589844 1043.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="289.695312" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="295.030899" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="297.69635" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="303.031937" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="328.082031" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="333.417618" y="1056.992188"/>
+ <use xlink:href="#glyph0-3" x="336.083069" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="341.418655" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="366.472656" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="371.808243" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="374.473694" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="379.80928" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="404.863281" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="410.198868" y="1056.992188"/>
+ <use xlink:href="#glyph0-5" x="412.864319" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="418.199905" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="443.253906" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="448.589493" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="451.254944" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="456.59053" y="1056.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="372.808594" y="1069.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="258.992188" y="972.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="258.992188" y="965.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="258.992188" y="960.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="258.992188" y="954.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-23" x="254.003906" y="874.800781"/>
+ <use xlink:href="#glyph5-4" x="262.669922" y="874.800781"/>
+ <use xlink:href="#glyph5-19" x="269.34375" y="874.800781"/>
+ <use xlink:href="#glyph5-13" x="280.013672" y="874.800781"/>
+</g>
+<g clip-path="url(#clip288)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 474.667969 1080 L 712 1080 L 712 864 L 474.667969 864 Z "/>
+</g>
+<g clip-path="url(#clip289)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 474.667969 1080 L 712 1080 L 712 864 L 474.667969 864 Z "/>
+</g>
+<g clip-path="url(#clip290)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 528.683594 1043.027344 L 697.597656 1043.027344 L 697.597656 878.398438 L 528.683594 878.398438 Z "/>
+</g>
+<g clip-path="url(#clip291)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1016.839844 L 697.601562 1016.839844 "/>
+</g>
+<g clip-path="url(#clip292)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 979.421875 L 697.601562 979.421875 "/>
+</g>
+<g clip-path="url(#clip293)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 942.007812 L 697.601562 942.007812 "/>
+</g>
+<g clip-path="url(#clip294)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 904.589844 L 697.601562 904.589844 "/>
+</g>
+<g clip-path="url(#clip295)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.558594 1043.027344 L 555.558594 878.398438 "/>
+</g>
+<g clip-path="url(#clip296)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 593.949219 1043.027344 L 593.949219 878.398438 "/>
+</g>
+<g clip-path="url(#clip297)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 632.335938 1043.027344 L 632.335938 878.398438 "/>
+</g>
+<g clip-path="url(#clip298)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 670.726562 1043.027344 L 670.726562 878.398438 "/>
+</g>
+<g clip-path="url(#clip299)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1035.546875 L 697.601562 1035.546875 "/>
+</g>
+<g clip-path="url(#clip300)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 998.128906 L 697.601562 998.128906 "/>
+</g>
+<g clip-path="url(#clip301)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 960.714844 L 697.601562 960.714844 "/>
+</g>
+<g clip-path="url(#clip302)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 923.296875 L 697.601562 923.296875 "/>
+</g>
+<g clip-path="url(#clip303)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 885.882812 L 697.601562 885.882812 "/>
+</g>
+<g clip-path="url(#clip304)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 1043.027344 L 536.363281 878.398438 "/>
+</g>
+<g clip-path="url(#clip305)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 1043.027344 L 574.753906 878.398438 "/>
+</g>
+<g clip-path="url(#clip306)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 1043.027344 L 613.140625 878.398438 "/>
+</g>
+<g clip-path="url(#clip307)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 1043.027344 L 651.53125 878.398438 "/>
+</g>
+<g clip-path="url(#clip308)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 1043.027344 L 689.921875 878.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 536.363281 1035.546875 L 536.671875 1035.542969 L 536.976562 1035.542969 L 537.59375 1035.527344 L 538.210938 1035.503906 L 538.515625 1035.488281 L 539.132812 1035.449219 L 539.441406 1035.425781 L 539.746094 1035.402344 L 540.054688 1035.371094 L 540.363281 1035.34375 L 540.671875 1035.308594 L 540.980469 1035.277344 L 541.285156 1035.238281 L 541.59375 1035.199219 L 542.210938 1035.113281 L 542.515625 1035.066406 L 543.132812 1034.964844 L 543.441406 1034.910156 L 543.75 1034.851562 L 544.054688 1034.792969 L 544.363281 1034.734375 L 545.289062 1034.535156 L 545.59375 1034.464844 L 546.210938 1034.316406 L 546.519531 1034.238281 L 546.824219 1034.15625 L 547.132812 1034.074219 L 547.441406 1033.988281 L 548.058594 1033.808594 L 548.363281 1033.71875 L 549.289062 1033.425781 L 549.59375 1033.324219 L 550.210938 1033.113281 L 550.519531 1033.003906 L 550.828125 1032.890625 L 551.132812 1032.777344 L 551.441406 1032.660156 L 552.058594 1032.417969 L 552.363281 1032.296875 L 553.289062 1031.910156 L 553.597656 1031.777344 L 553.902344 1031.640625 L 554.210938 1031.503906 L 554.519531 1031.363281 L 554.828125 1031.21875 L 555.132812 1031.074219 L 555.441406 1030.925781 L 556.367188 1030.46875 L 556.671875 1030.308594 L 557.289062 1029.988281 L 557.597656 1029.824219 L 557.902344 1029.65625 L 558.828125 1029.140625 L 559.136719 1028.964844 L 559.441406 1028.785156 L 560.058594 1028.417969 L 560.367188 1028.230469 L 560.671875 1028.042969 L 561.289062 1027.660156 L 561.597656 1027.464844 L 561.90625 1027.265625 L 562.210938 1027.0625 L 562.828125 1026.65625 L 563.136719 1026.445312 L 563.445312 1026.238281 L 563.75 1026.023438 L 564.058594 1025.808594 L 564.675781 1025.371094 L 564.980469 1025.148438 L 565.289062 1024.925781 L 565.597656 1024.695312 L 565.90625 1024.46875 L 566.214844 1024.234375 L 566.519531 1024 L 566.828125 1023.765625 L 567.445312 1023.28125 L 567.75 1023.039062 L 568.058594 1022.792969 L 568.675781 1022.292969 L 568.984375 1022.039062 L 569.289062 1021.78125 L 569.597656 1021.523438 L 570.214844 1021 L 570.519531 1020.734375 L 571.136719 1020.195312 L 571.753906 1019.648438 L 572.058594 1019.371094 L 572.675781 1018.808594 L 572.984375 1018.523438 L 573.289062 1018.234375 L 573.597656 1017.945312 L 574.214844 1017.359375 L 574.523438 1017.0625 L 574.828125 1016.761719 L 575.136719 1016.460938 L 575.753906 1015.851562 L 576.058594 1015.542969 L 576.675781 1014.917969 L 576.984375 1014.601562 L 577.292969 1014.28125 L 577.597656 1013.960938 L 578.214844 1013.3125 L 578.523438 1012.984375 L 578.832031 1012.652344 L 579.136719 1012.320312 L 579.753906 1011.648438 L 580.0625 1011.304688 L 580.367188 1010.964844 L 580.675781 1010.617188 L 580.984375 1010.273438 L 581.601562 1009.570312 L 581.90625 1009.214844 L 582.214844 1008.859375 L 582.523438 1008.5 L 582.832031 1008.136719 L 583.136719 1007.773438 L 583.445312 1007.40625 L 584.371094 1006.292969 L 584.675781 1005.914062 L 585.292969 1005.15625 L 585.601562 1004.773438 L 585.90625 1004.386719 L 586.832031 1003.214844 L 587.140625 1002.820312 L 587.445312 1002.421875 L 588.0625 1001.617188 L 588.371094 1001.210938 L 588.675781 1000.804688 L 589.292969 999.984375 L 589.601562 999.566406 L 589.910156 999.152344 L 590.214844 998.730469 L 590.832031 997.886719 L 591.140625 997.457031 L 591.445312 997.027344 L 591.753906 996.597656 L 592.0625 996.164062 L 592.679688 995.289062 L 592.984375 994.847656 L 593.601562 993.957031 L 594.21875 993.058594 L 594.523438 992.605469 L 595.140625 991.691406 L 595.449219 991.230469 L 595.753906 990.769531 L 596.0625 990.304688 L 596.679688 989.367188 L 596.988281 988.894531 L 597.292969 988.417969 L 597.601562 987.941406 L 598.21875 986.980469 L 598.523438 986.496094 L 599.140625 985.519531 L 599.757812 984.535156 L 600.0625 984.035156 L 600.371094 983.539062 L 600.988281 982.53125 L 601.292969 982.027344 L 601.601562 981.519531 L 602.21875 980.496094 L 602.527344 979.980469 L 602.832031 979.460938 L 603.140625 978.941406 L 603.449219 978.417969 L 603.757812 977.890625 L 604.0625 977.363281 L 604.679688 976.300781 L 605.296875 975.230469 L 605.601562 974.6875 L 605.910156 974.148438 L 606.527344 973.054688 L 606.832031 972.507812 L 607.757812 970.84375 L 608.066406 970.285156 L 608.371094 969.722656 L 608.679688 969.160156 L 608.988281 968.59375 L 609.296875 968.023438 L 609.601562 967.453125 L 610.21875 966.304688 L 610.527344 965.726562 L 610.835938 965.144531 L 611.140625 964.5625 L 611.757812 963.390625 L 612.066406 962.800781 L 612.375 962.207031 L 612.679688 961.613281 L 612.988281 961.015625 L 613.296875 960.414062 L 613.605469 959.816406 L 613.910156 959.222656 L 614.21875 958.628906 L 614.527344 958.039062 L 615.144531 956.867188 L 615.449219 956.285156 L 615.757812 955.703125 L 616.375 954.546875 L 616.679688 953.976562 L 616.988281 953.402344 L 617.605469 952.269531 L 617.914062 951.707031 L 618.21875 951.144531 L 618.835938 950.027344 L 619.144531 949.472656 L 619.449219 948.921875 L 620.375 947.28125 L 620.683594 946.738281 L 620.988281 946.199219 L 621.914062 944.59375 L 622.21875 944.066406 L 622.835938 943.011719 L 623.144531 942.488281 L 623.453125 941.96875 L 623.757812 941.449219 L 624.066406 940.933594 L 624.683594 939.910156 L 624.988281 939.402344 L 625.296875 938.894531 L 625.605469 938.390625 L 626.222656 937.390625 L 626.527344 936.894531 L 627.144531 935.910156 L 627.761719 934.933594 L 628.066406 934.449219 L 628.683594 933.488281 L 628.992188 933.011719 L 629.296875 932.535156 L 629.605469 932.0625 L 630.222656 931.125 L 630.53125 930.660156 L 630.835938 930.199219 L 631.453125 929.277344 L 631.761719 928.824219 L 632.066406 928.371094 L 632.375 927.917969 L 632.683594 927.472656 L 632.992188 927.023438 L 633.300781 926.582031 L 633.605469 926.140625 L 634.222656 925.265625 L 634.53125 924.832031 L 634.835938 924.398438 L 635.144531 923.96875 L 635.453125 923.542969 L 636.070312 922.699219 L 636.375 922.277344 L 636.683594 921.859375 L 636.992188 921.445312 L 637.300781 921.035156 L 637.605469 920.625 L 637.914062 920.214844 L 638.839844 919.007812 L 639.144531 918.609375 L 639.761719 917.820312 L 640.070312 917.429688 L 640.375 917.042969 L 640.683594 916.65625 L 641.300781 915.890625 L 641.609375 915.515625 L 641.914062 915.136719 L 642.222656 914.765625 L 642.53125 914.390625 L 643.148438 913.65625 L 643.453125 913.292969 L 643.761719 912.929688 L 644.070312 912.570312 L 644.378906 912.214844 L 644.683594 911.859375 L 645.300781 911.15625 L 645.609375 910.808594 L 645.917969 910.464844 L 646.222656 910.121094 L 646.53125 909.78125 L 647.148438 909.109375 L 647.453125 908.777344 L 647.761719 908.445312 L 648.070312 908.117188 L 648.6875 907.46875 L 648.992188 907.148438 L 649.300781 906.828125 L 649.609375 906.511719 L 649.917969 906.199219 L 650.222656 905.886719 L 650.53125 905.578125 L 651.148438 904.96875 L 651.457031 904.667969 L 651.761719 904.367188 L 652.378906 903.773438 L 652.6875 903.484375 L 652.992188 903.195312 L 653.300781 902.90625 L 653.609375 902.621094 L 654.226562 902.058594 L 654.53125 901.78125 L 654.839844 901.503906 L 655.148438 901.234375 L 655.457031 900.960938 L 655.761719 900.695312 L 656.378906 900.164062 L 656.6875 899.90625 L 656.996094 899.644531 L 657.300781 899.390625 L 657.609375 899.136719 L 658.226562 898.636719 L 658.53125 898.390625 L 658.839844 898.144531 L 659.148438 897.902344 L 659.457031 897.664062 L 659.765625 897.429688 L 660.070312 897.195312 L 660.378906 896.960938 L 660.6875 896.730469 L 660.996094 896.503906 L 661.304688 896.28125 L 661.609375 896.058594 L 661.917969 895.835938 L 662.535156 895.40625 L 662.839844 895.191406 L 663.148438 894.980469 L 663.765625 894.566406 L 664.074219 894.363281 L 664.378906 894.164062 L 664.6875 893.964844 L 664.996094 893.769531 L 665.304688 893.578125 L 665.609375 893.386719 L 665.917969 893.195312 L 666.84375 892.644531 L 667.148438 892.464844 L 667.765625 892.113281 L 668.074219 891.941406 L 668.378906 891.773438 L 668.6875 891.605469 L 668.996094 891.441406 L 669.613281 891.121094 L 669.917969 890.960938 L 670.226562 890.808594 L 670.535156 890.652344 L 670.84375 890.503906 L 671.148438 890.355469 L 671.765625 890.066406 L 672.074219 889.925781 L 672.382812 889.789062 L 672.6875 889.652344 L 673.304688 889.386719 L 673.613281 889.261719 L 673.917969 889.132812 L 674.226562 889.011719 L 674.535156 888.886719 L 675.152344 888.652344 L 675.457031 888.539062 L 675.765625 888.425781 L 676.074219 888.316406 L 676.691406 888.105469 L 676.996094 888.003906 L 677.304688 887.902344 L 677.613281 887.804688 L 677.921875 887.710938 L 678.226562 887.617188 L 678.535156 887.527344 L 679.152344 887.355469 L 679.460938 887.273438 L 679.765625 887.191406 L 680.074219 887.113281 L 680.691406 886.964844 L 680.996094 886.894531 L 681.304688 886.824219 L 681.613281 886.757812 L 682.230469 886.632812 L 682.535156 886.574219 L 683.152344 886.464844 L 683.460938 886.414062 L 683.765625 886.363281 L 684.074219 886.316406 L 684.691406 886.230469 L 685 886.191406 L 685.304688 886.152344 L 685.613281 886.117188 L 686.230469 886.054688 L 686.535156 886.027344 L 687.152344 885.980469 L 687.769531 885.941406 L 688.074219 885.925781 L 688.691406 885.902344 L 689 885.894531 L 689.304688 885.886719 L 689.613281 885.882812 L 689.921875 885.882812 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1038.984375"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1038.984375"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="1038.984375"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="1038.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1001.566406"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1001.566406"/>
+ <use xlink:href="#glyph0-3" x="510.926819" y="1001.566406"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="1001.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="964.152344"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="964.152344"/>
+ <use xlink:href="#glyph0-4" x="510.926819" y="964.152344"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="964.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="926.734375"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="926.734375"/>
+ <use xlink:href="#glyph0-5" x="510.926819" y="926.734375"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="926.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="502.925781" y="889.320312"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="889.320312"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="889.320312"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="889.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1035.546875 L 528.683594 1035.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 998.128906 L 528.683594 998.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 960.714844 L 528.683594 960.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 923.296875 L 528.683594 923.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 885.882812 L 528.683594 885.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 1047.28125 L 536.363281 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 1047.28125 L 574.753906 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 1047.28125 L 613.140625 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 1047.28125 L 651.53125 1043.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 1047.28125 L 689.921875 1043.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="527.027344" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="532.36293" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="535.028381" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="540.363968" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="565.417969" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="570.753555" y="1056.992188"/>
+ <use xlink:href="#glyph0-3" x="573.419006" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="578.754593" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="603.804688" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="609.140274" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="611.805725" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="617.141312" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="642.195312" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="647.530899" y="1056.992188"/>
+ <use xlink:href="#glyph0-5" x="650.19635" y="1056.992188"/>
+ <use xlink:href="#glyph0-4" x="655.531937" y="1056.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="680.585938" y="1056.992188"/>
+ <use xlink:href="#glyph0-2" x="685.921524" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="688.586975" y="1056.992188"/>
+ <use xlink:href="#glyph0-1" x="693.922562" y="1056.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="610.140625" y="1069.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="496.324219" y="972.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="496.324219" y="965.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="496.324219" y="960.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="496.324219" y="954.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-11" x="496.675781" y="874.800781"/>
+ <use xlink:href="#glyph5-11" x="504.679688" y="874.800781"/>
+ <use xlink:href="#glyph5-12" x="512.683594" y="874.800781"/>
+ <use xlink:href="#glyph5-4" x="520.013672" y="874.800781"/>
+ <use xlink:href="#glyph5-13" x="526.6875" y="874.800781"/>
+ <use xlink:href="#glyph5-8" x="534.017578" y="874.800781"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 1296 L 237.332031 1296 L 237.332031 1080 L 0 1080 Z "/>
+<g clip-path="url(#clip309)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 1296 L 237.332031 1296 L 237.332031 1080 L 0 1080 Z "/>
+</g>
+<g clip-path="url(#clip310)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 1259.027344 L 222.933594 1259.027344 L 222.933594 1094.398438 L 54.019531 1094.398438 Z "/>
+</g>
+<g clip-path="url(#clip311)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1245.933594 L 222.933594 1245.933594 "/>
+</g>
+<g clip-path="url(#clip312)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1204.777344 L 222.933594 1204.777344 "/>
+</g>
+<g clip-path="url(#clip313)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1163.617188 L 222.933594 1163.617188 "/>
+</g>
+<g clip-path="url(#clip314)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1122.460938 L 222.933594 1122.460938 "/>
+</g>
+<g clip-path="url(#clip315)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 80.890625 1259.027344 L 80.890625 1094.398438 "/>
+</g>
+<g clip-path="url(#clip316)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 119.28125 1259.027344 L 119.28125 1094.398438 "/>
+</g>
+<g clip-path="url(#clip317)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.671875 1259.027344 L 157.671875 1094.398438 "/>
+</g>
+<g clip-path="url(#clip318)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 196.058594 1259.027344 L 196.058594 1094.398438 "/>
+</g>
+<g clip-path="url(#clip319)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1225.355469 L 222.933594 1225.355469 "/>
+</g>
+<g clip-path="url(#clip320)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1184.199219 L 222.933594 1184.199219 "/>
+</g>
+<g clip-path="url(#clip321)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1143.039062 L 222.933594 1143.039062 "/>
+</g>
+<g clip-path="url(#clip322)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1101.882812 L 222.933594 1101.882812 "/>
+</g>
+<g clip-path="url(#clip323)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 1259.027344 L 61.695312 1094.398438 "/>
+</g>
+<g clip-path="url(#clip324)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 1259.027344 L 100.085938 1094.398438 "/>
+</g>
+<g clip-path="url(#clip325)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 1259.027344 L 138.476562 1094.398438 "/>
+</g>
+<g clip-path="url(#clip326)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 1259.027344 L 176.867188 1094.398438 "/>
+</g>
+<g clip-path="url(#clip327)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 1259.027344 L 215.253906 1094.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 61.695312 1101.882812 L 92.160156 1101.882812 L 92.46875 1102.15625 L 92.777344 1103.519531 L 93.085938 1104.863281 L 93.394531 1106.191406 L 93.699219 1107.5 L 94.007812 1108.792969 L 94.316406 1110.066406 L 94.625 1111.328125 L 94.929688 1112.570312 L 95.238281 1113.796875 L 95.546875 1115.011719 L 95.855469 1116.207031 L 96.164062 1117.390625 L 96.46875 1118.558594 L 96.777344 1119.710938 L 97.085938 1120.851562 L 97.394531 1121.976562 L 97.699219 1123.089844 L 98.007812 1124.191406 L 98.316406 1125.277344 L 98.625 1126.351562 L 98.933594 1127.410156 L 99.238281 1128.460938 L 99.546875 1129.496094 L 99.855469 1130.519531 L 100.164062 1131.535156 L 100.46875 1132.535156 L 100.777344 1133.523438 L 101.085938 1134.503906 L 101.394531 1135.472656 L 101.703125 1136.429688 L 102.007812 1137.375 L 102.316406 1138.3125 L 102.625 1139.238281 L 102.933594 1140.152344 L 103.242188 1141.058594 L 103.546875 1141.957031 L 103.855469 1142.84375 L 104.164062 1143.71875 L 104.472656 1144.585938 L 104.777344 1145.445312 L 105.085938 1146.296875 L 105.394531 1147.136719 L 105.703125 1147.96875 L 106.011719 1148.792969 L 106.316406 1149.609375 L 106.625 1150.414062 L 106.933594 1151.214844 L 107.242188 1152.003906 L 107.546875 1152.785156 L 107.855469 1153.5625 L 108.164062 1154.328125 L 108.472656 1155.089844 L 108.78125 1155.839844 L 109.085938 1156.585938 L 109.394531 1157.320312 L 109.703125 1158.050781 L 110.011719 1158.773438 L 110.316406 1159.492188 L 110.625 1160.199219 L 110.933594 1160.902344 L 111.242188 1161.597656 L 111.550781 1162.289062 L 111.855469 1162.972656 L 112.164062 1163.648438 L 112.472656 1164.316406 L 112.78125 1164.980469 L 113.085938 1165.640625 L 113.394531 1166.292969 L 113.703125 1166.9375 L 114.011719 1167.578125 L 114.320312 1168.210938 L 114.625 1168.839844 L 114.933594 1169.464844 L 115.242188 1170.082031 L 115.550781 1170.691406 L 115.855469 1171.296875 L 116.164062 1171.898438 L 116.472656 1172.496094 L 116.78125 1173.085938 L 117.089844 1173.671875 L 117.394531 1174.25 L 117.703125 1174.828125 L 118.011719 1175.398438 L 118.320312 1175.960938 L 118.625 1176.523438 L 118.933594 1177.078125 L 119.242188 1177.628906 L 119.550781 1178.175781 L 119.859375 1178.71875 L 120.164062 1179.257812 L 120.78125 1180.320312 L 121.089844 1180.84375 L 121.398438 1181.363281 L 121.703125 1181.878906 L 122.011719 1182.390625 L 122.320312 1182.898438 L 122.628906 1183.402344 L 122.933594 1183.898438 L 123.242188 1184.394531 L 123.550781 1184.886719 L 123.859375 1185.375 L 124.167969 1185.859375 L 124.472656 1186.335938 L 124.78125 1186.8125 L 125.089844 1187.285156 L 125.398438 1187.753906 L 125.703125 1188.21875 L 126.011719 1188.679688 L 126.628906 1189.59375 L 126.9375 1190.042969 L 127.242188 1190.492188 L 127.859375 1191.375 L 128.167969 1191.8125 L 128.472656 1192.246094 L 128.78125 1192.679688 L 129.398438 1193.53125 L 129.707031 1193.953125 L 130.011719 1194.371094 L 130.320312 1194.785156 L 130.9375 1195.605469 L 131.242188 1196.011719 L 131.859375 1196.816406 L 132.167969 1197.214844 L 132.476562 1197.609375 L 132.78125 1198 L 133.089844 1198.390625 L 133.398438 1198.773438 L 133.707031 1199.160156 L 134.011719 1199.539062 L 134.320312 1199.917969 L 134.9375 1200.667969 L 135.246094 1201.035156 L 135.550781 1201.40625 L 136.167969 1202.132812 L 136.785156 1202.851562 L 137.089844 1203.207031 L 137.707031 1203.910156 L 138.015625 1204.257812 L 138.320312 1204.605469 L 138.628906 1204.949219 L 139.246094 1205.628906 L 139.554688 1205.964844 L 139.859375 1206.300781 L 140.167969 1206.632812 L 140.785156 1207.289062 L 141.089844 1207.617188 L 141.398438 1207.941406 L 142.015625 1208.582031 L 142.324219 1208.898438 L 142.628906 1209.214844 L 143.554688 1210.152344 L 144.167969 1210.765625 L 144.476562 1211.066406 L 144.785156 1211.371094 L 145.09375 1211.671875 L 145.398438 1211.96875 L 145.707031 1212.265625 L 146.324219 1212.851562 L 146.628906 1213.144531 L 146.9375 1213.433594 L 147.863281 1214.289062 L 148.167969 1214.570312 L 148.476562 1214.851562 L 149.09375 1215.40625 L 149.398438 1215.683594 L 150.015625 1216.230469 L 150.632812 1216.769531 L 150.9375 1217.035156 L 151.554688 1217.566406 L 152.171875 1218.089844 L 152.476562 1218.351562 L 152.785156 1218.609375 L 153.09375 1218.863281 L 153.402344 1219.121094 L 153.707031 1219.375 L 154.015625 1219.625 L 154.324219 1219.878906 L 154.632812 1220.125 L 154.941406 1220.375 L 155.246094 1220.621094 L 155.554688 1220.867188 L 156.171875 1221.351562 L 156.476562 1221.59375 L 156.785156 1221.835938 L 157.09375 1222.074219 L 157.402344 1222.308594 L 157.710938 1222.546875 L 158.015625 1222.78125 L 158.324219 1223.015625 L 158.941406 1223.476562 L 159.246094 1223.707031 L 160.480469 1224.613281 L 160.785156 1224.835938 L 161.09375 1225.058594 L 161.710938 1225.496094 L 162.015625 1225.714844 L 162.324219 1225.933594 L 163.25 1226.578125 L 163.554688 1226.792969 L 164.480469 1227.425781 L 164.785156 1227.632812 L 165.402344 1228.046875 L 165.710938 1228.25 L 166.019531 1228.457031 L 166.324219 1228.660156 L 166.632812 1228.859375 L 166.941406 1229.0625 L 167.25 1229.261719 L 167.554688 1229.460938 L 167.863281 1229.660156 L 168.789062 1230.246094 L 169.09375 1230.441406 L 169.402344 1230.632812 L 169.710938 1230.828125 L 170.019531 1231.019531 L 170.328125 1231.207031 L 170.632812 1231.398438 L 171.558594 1231.960938 L 171.863281 1232.144531 L 172.171875 1232.332031 L 172.480469 1232.515625 L 172.789062 1232.695312 L 173.097656 1232.878906 L 173.402344 1233.058594 L 173.710938 1233.242188 L 174.019531 1233.417969 L 174.328125 1233.597656 L 174.632812 1233.777344 L 175.558594 1234.304688 L 175.867188 1234.476562 L 176.171875 1234.652344 L 177.097656 1235.167969 L 177.402344 1235.335938 L 177.710938 1235.507812 L 178.636719 1236.011719 L 178.941406 1236.175781 L 179.25 1236.34375 L 179.867188 1236.671875 L 180.171875 1236.835938 L 180.480469 1236.996094 L 180.789062 1237.160156 L 181.40625 1237.480469 L 181.710938 1237.640625 L 182.019531 1237.796875 L 182.328125 1237.957031 L 182.636719 1238.113281 L 182.941406 1238.269531 L 183.558594 1238.582031 L 183.867188 1238.734375 L 184.175781 1238.890625 L 184.480469 1239.042969 L 185.40625 1239.5 L 185.714844 1239.648438 L 186.019531 1239.800781 L 186.945312 1240.246094 L 187.25 1240.390625 L 187.558594 1240.539062 L 187.867188 1240.683594 L 188.175781 1240.832031 L 188.484375 1240.976562 L 188.789062 1241.117188 L 189.40625 1241.40625 L 189.714844 1241.546875 L 190.019531 1241.6875 L 190.328125 1241.832031 L 190.636719 1241.96875 L 191.253906 1242.25 L 191.558594 1242.386719 L 191.867188 1242.527344 L 192.484375 1242.800781 L 192.789062 1242.9375 L 193.097656 1243.074219 L 193.40625 1243.207031 L 193.714844 1243.34375 L 194.023438 1243.476562 L 194.328125 1243.609375 L 195.253906 1244.007812 L 195.558594 1244.136719 L 195.867188 1244.269531 L 196.792969 1244.65625 L 197.097656 1244.785156 L 197.714844 1245.042969 L 198.023438 1245.167969 L 198.328125 1245.296875 L 199.5625 1245.796875 L 199.867188 1245.921875 L 200.175781 1246.042969 L 200.484375 1246.167969 L 200.792969 1246.289062 L 201.101562 1246.414062 L 201.40625 1246.535156 L 202.023438 1246.777344 L 202.332031 1246.894531 L 202.636719 1247.015625 L 202.945312 1247.132812 L 203.253906 1247.253906 L 203.871094 1247.488281 L 204.175781 1247.605469 L 205.101562 1247.957031 L 205.40625 1248.070312 L 205.714844 1248.1875 L 206.640625 1248.527344 L 206.945312 1248.640625 L 207.871094 1248.980469 L 208.175781 1249.089844 L 208.484375 1249.203125 L 209.101562 1249.421875 L 209.410156 1249.535156 L 209.714844 1249.644531 L 210.023438 1249.753906 L 210.332031 1249.859375 L 210.640625 1249.96875 L 210.945312 1250.078125 L 211.253906 1250.183594 L 211.5625 1250.292969 L 212.179688 1250.503906 L 212.484375 1250.609375 L 213.410156 1250.925781 L 213.714844 1251.03125 L 214.023438 1251.132812 L 214.332031 1251.238281 L 214.640625 1251.339844 L 214.949219 1251.445312 L 215.253906 1251.546875 "/>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 61.695312 1251.546875 L 62.003906 1251.445312 L 62.3125 1251.339844 L 62.621094 1251.238281 L 62.925781 1251.132812 L 63.234375 1251.03125 L 63.851562 1250.820312 L 64.15625 1250.714844 L 65.390625 1250.292969 L 65.695312 1250.183594 L 66.003906 1250.078125 L 66.621094 1249.859375 L 66.925781 1249.753906 L 67.542969 1249.535156 L 67.851562 1249.421875 L 68.160156 1249.3125 L 68.464844 1249.203125 L 68.773438 1249.089844 L 69.082031 1248.980469 L 69.390625 1248.867188 L 69.695312 1248.753906 L 70.929688 1248.300781 L 71.234375 1248.1875 L 71.542969 1248.070312 L 71.851562 1247.957031 L 72.46875 1247.722656 L 72.773438 1247.605469 L 73.699219 1247.253906 L 74.003906 1247.132812 L 74.3125 1247.015625 L 74.621094 1246.894531 L 74.929688 1246.777344 L 75.238281 1246.65625 L 75.542969 1246.535156 L 75.851562 1246.414062 L 76.160156 1246.289062 L 76.46875 1246.167969 L 76.773438 1246.042969 L 77.082031 1245.921875 L 78.007812 1245.546875 L 78.3125 1245.421875 L 78.621094 1245.296875 L 78.929688 1245.167969 L 79.238281 1245.042969 L 79.542969 1244.914062 L 80.777344 1244.398438 L 81.082031 1244.269531 L 81.390625 1244.136719 L 81.699219 1244.007812 L 82.007812 1243.875 L 82.3125 1243.742188 L 83.238281 1243.34375 L 83.546875 1243.207031 L 83.851562 1243.074219 L 84.777344 1242.664062 L 85.082031 1242.527344 L 85.390625 1242.386719 L 85.699219 1242.25 L 86.316406 1241.96875 L 86.621094 1241.832031 L 86.929688 1241.6875 L 87.546875 1241.40625 L 87.855469 1241.261719 L 88.160156 1241.117188 L 88.46875 1240.976562 L 88.777344 1240.832031 L 89.085938 1240.683594 L 89.390625 1240.539062 L 89.699219 1240.390625 L 90.007812 1240.246094 L 90.625 1239.949219 L 90.929688 1239.800781 L 91.238281 1239.648438 L 91.546875 1239.5 L 91.855469 1239.347656 L 92.160156 1239.195312 L 92.777344 1238.890625 L 93.085938 1238.734375 L 93.394531 1238.582031 L 93.699219 1238.425781 L 94.625 1237.957031 L 94.929688 1237.796875 L 95.238281 1237.640625 L 96.164062 1237.160156 L 96.46875 1236.996094 L 96.777344 1236.835938 L 97.394531 1236.507812 L 97.699219 1236.34375 L 98.007812 1236.175781 L 98.316406 1236.011719 L 98.933594 1235.675781 L 99.238281 1235.507812 L 99.546875 1235.335938 L 99.855469 1235.167969 L 100.164062 1234.996094 L 100.46875 1234.824219 L 100.777344 1234.652344 L 101.085938 1234.476562 L 101.394531 1234.304688 L 101.703125 1234.128906 L 102.007812 1233.953125 L 102.316406 1233.777344 L 102.933594 1233.417969 L 103.242188 1233.242188 L 103.546875 1233.058594 L 103.855469 1232.878906 L 104.164062 1232.695312 L 104.472656 1232.515625 L 104.777344 1232.332031 L 105.085938 1232.144531 L 105.394531 1231.960938 L 106.011719 1231.585938 L 106.316406 1231.398438 L 106.625 1231.207031 L 106.933594 1231.019531 L 107.242188 1230.828125 L 107.546875 1230.632812 L 107.855469 1230.441406 L 108.78125 1229.855469 L 109.085938 1229.660156 L 110.011719 1229.0625 L 110.316406 1228.859375 L 110.625 1228.660156 L 110.933594 1228.457031 L 111.242188 1228.25 L 111.550781 1228.046875 L 111.855469 1227.839844 L 112.472656 1227.425781 L 112.78125 1227.214844 L 113.085938 1227.003906 L 113.394531 1226.792969 L 114.320312 1226.148438 L 114.625 1225.933594 L 115.550781 1225.277344 L 115.855469 1225.058594 L 116.472656 1224.613281 L 117.089844 1224.160156 L 117.394531 1223.933594 L 117.703125 1223.707031 L 118.320312 1223.246094 L 118.625 1223.015625 L 119.242188 1222.546875 L 119.550781 1222.308594 L 119.859375 1222.074219 L 120.164062 1221.835938 L 121.398438 1220.867188 L 121.703125 1220.621094 L 122.011719 1220.375 L 122.320312 1220.125 L 122.628906 1219.878906 L 122.933594 1219.625 L 123.242188 1219.375 L 123.550781 1219.121094 L 123.859375 1218.863281 L 124.167969 1218.609375 L 124.472656 1218.351562 L 125.398438 1217.566406 L 125.703125 1217.300781 L 126.320312 1216.769531 L 126.9375 1216.230469 L 127.242188 1215.957031 L 127.550781 1215.683594 L 128.167969 1215.128906 L 128.472656 1214.851562 L 129.089844 1214.289062 L 129.707031 1213.71875 L 130.011719 1213.433594 L 130.320312 1213.144531 L 130.9375 1212.558594 L 131.242188 1212.265625 L 131.859375 1211.671875 L 132.167969 1211.371094 L 132.476562 1211.066406 L 132.78125 1210.765625 L 133.089844 1210.457031 L 133.398438 1210.152344 L 133.707031 1209.839844 L 134.011719 1209.527344 L 134.320312 1209.214844 L 134.9375 1208.582031 L 135.246094 1208.261719 L 135.550781 1207.941406 L 135.859375 1207.617188 L 136.785156 1206.632812 L 137.089844 1206.300781 L 137.707031 1205.628906 L 138.015625 1205.289062 L 138.320312 1204.949219 L 138.628906 1204.605469 L 139.246094 1203.910156 L 139.554688 1203.558594 L 139.859375 1203.207031 L 140.167969 1202.851562 L 140.785156 1202.132812 L 141.089844 1201.769531 L 141.398438 1201.40625 L 141.707031 1201.035156 L 142.015625 1200.667969 L 142.324219 1200.292969 L 142.628906 1199.917969 L 143.246094 1199.160156 L 143.554688 1198.773438 L 143.859375 1198.390625 L 144.476562 1197.609375 L 144.785156 1197.214844 L 145.09375 1196.816406 L 145.398438 1196.414062 L 145.707031 1196.011719 L 146.015625 1195.605469 L 146.324219 1195.195312 L 146.628906 1194.785156 L 146.9375 1194.371094 L 147.246094 1193.953125 L 147.554688 1193.53125 L 147.863281 1193.105469 L 148.167969 1192.679688 L 148.785156 1191.8125 L 149.09375 1191.375 L 149.398438 1190.933594 L 149.707031 1190.492188 L 150.324219 1189.59375 L 150.632812 1189.136719 L 150.9375 1188.679688 L 151.246094 1188.21875 L 151.554688 1187.753906 L 151.863281 1187.285156 L 152.171875 1186.8125 L 152.476562 1186.335938 L 152.785156 1185.859375 L 153.09375 1185.375 L 153.402344 1184.886719 L 153.707031 1184.394531 L 154.324219 1183.402344 L 154.632812 1182.898438 L 154.941406 1182.390625 L 155.246094 1181.878906 L 155.554688 1181.363281 L 155.863281 1180.84375 L 156.171875 1180.320312 L 156.476562 1179.789062 L 156.785156 1179.257812 L 157.09375 1178.71875 L 157.402344 1178.175781 L 157.710938 1177.628906 L 158.015625 1177.078125 L 158.324219 1176.523438 L 158.941406 1175.398438 L 159.246094 1174.828125 L 159.863281 1173.671875 L 160.171875 1173.085938 L 160.480469 1172.496094 L 160.785156 1171.898438 L 161.09375 1171.296875 L 161.402344 1170.691406 L 161.710938 1170.082031 L 162.015625 1169.464844 L 162.324219 1168.839844 L 162.632812 1168.210938 L 162.941406 1167.578125 L 163.25 1166.9375 L 163.554688 1166.292969 L 163.863281 1165.640625 L 164.171875 1164.980469 L 164.480469 1164.316406 L 164.785156 1163.648438 L 165.09375 1162.972656 L 165.402344 1162.289062 L 165.710938 1161.597656 L 166.019531 1160.902344 L 166.324219 1160.199219 L 166.632812 1159.492188 L 166.941406 1158.773438 L 167.25 1158.050781 L 167.554688 1157.320312 L 167.863281 1156.585938 L 168.171875 1155.839844 L 168.480469 1155.089844 L 168.789062 1154.328125 L 169.09375 1153.5625 L 169.402344 1152.785156 L 169.710938 1152.003906 L 170.019531 1151.214844 L 170.328125 1150.414062 L 170.632812 1149.609375 L 170.941406 1148.792969 L 171.25 1147.96875 L 171.558594 1147.136719 L 171.863281 1146.296875 L 172.171875 1145.445312 L 172.480469 1144.585938 L 172.789062 1143.71875 L 173.097656 1142.84375 L 173.402344 1141.957031 L 173.710938 1141.058594 L 174.019531 1140.152344 L 174.328125 1139.238281 L 174.632812 1138.3125 L 174.941406 1137.375 L 175.25 1136.429688 L 175.558594 1135.472656 L 175.867188 1134.503906 L 176.171875 1133.523438 L 176.480469 1132.535156 L 176.789062 1131.535156 L 177.097656 1130.519531 L 177.402344 1129.496094 L 177.710938 1128.460938 L 178.019531 1127.410156 L 178.328125 1126.351562 L 178.636719 1125.277344 L 178.941406 1124.191406 L 179.25 1123.089844 L 179.558594 1121.976562 L 179.867188 1120.851562 L 180.171875 1119.710938 L 180.480469 1118.558594 L 180.789062 1117.390625 L 181.097656 1116.207031 L 181.40625 1115.011719 L 181.710938 1113.796875 L 182.019531 1112.570312 L 182.328125 1111.328125 L 182.636719 1110.066406 L 182.941406 1108.792969 L 183.25 1107.5 L 183.558594 1106.191406 L 183.867188 1104.863281 L 184.175781 1103.519531 L 184.480469 1102.15625 L 184.789062 1101.882812 L 215.253906 1101.882812 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="33.59375" y="1228.792969"/>
+ <use xlink:href="#glyph0-2" x="38.929337" y="1228.792969"/>
+ <use xlink:href="#glyph0-7" x="41.594788" y="1228.792969"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="33.59375" y="1187.636719"/>
+ <use xlink:href="#glyph0-2" x="38.929337" y="1187.636719"/>
+ <use xlink:href="#glyph0-8" x="41.594788" y="1187.636719"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="33.59375" y="1146.476562"/>
+ <use xlink:href="#glyph0-2" x="38.929337" y="1146.476562"/>
+ <use xlink:href="#glyph0-9" x="41.594788" y="1146.476562"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="33.59375" y="1105.320312"/>
+ <use xlink:href="#glyph0-2" x="38.929337" y="1105.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594788" y="1105.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1225.355469 L 54.019531 1225.355469 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1184.199219 L 54.019531 1184.199219 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1143.039062 L 54.019531 1143.039062 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1101.882812 L 54.019531 1101.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 1263.28125 L 61.695312 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 1263.28125 L 100.085938 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 1263.28125 L 138.476562 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 1263.28125 L 176.867188 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 1263.28125 L 215.253906 1259.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="52.359375" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="57.694962" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="60.360413" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="65.695999" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="90.75" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="96.085587" y="1272.992188"/>
+ <use xlink:href="#glyph0-3" x="98.751038" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="104.086624" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="129.140625" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="134.476212" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="137.141663" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="142.477249" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="167.53125" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="172.866837" y="1272.992188"/>
+ <use xlink:href="#glyph0-5" x="175.532288" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="180.867874" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="205.917969" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="211.253555" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="213.919006" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="219.254593" y="1272.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="135.476562" y="1285.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="1188.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="1181.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="1176.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="1170.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-17" x="25.011719" y="1090.800781"/>
+ <use xlink:href="#glyph5-15" x="33.677734" y="1090.800781"/>
+ <use xlink:href="#glyph5-5" x="41.007812" y="1090.800781"/>
+ <use xlink:href="#glyph5-22" x="48.337891" y="1090.800781"/>
+ <use xlink:href="#glyph5-4" x="55.011719" y="1090.800781"/>
+ <use xlink:href="#glyph5-29" x="61.685547" y="1090.800781"/>
+ <use xlink:href="#glyph5-8" x="68.359375" y="1090.800781"/>
+</g>
+<g clip-path="url(#clip328)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 237.332031 1296 L 474.664062 1296 L 474.664062 1080 L 237.332031 1080 Z "/>
+</g>
+<g clip-path="url(#clip329)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 237.332031 1296 L 474.664062 1296 L 474.664062 1080 L 237.332031 1080 Z "/>
+</g>
+<g clip-path="url(#clip330)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 291.351562 1259.027344 L 460.265625 1259.027344 L 460.265625 1094.398438 L 291.351562 1094.398438 Z "/>
+</g>
+<g clip-path="url(#clip331)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1232.84375 L 460.265625 1232.84375 "/>
+</g>
+<g clip-path="url(#clip332)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1195.425781 L 460.265625 1195.425781 "/>
+</g>
+<g clip-path="url(#clip333)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1158.003906 L 460.265625 1158.003906 "/>
+</g>
+<g clip-path="url(#clip334)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1120.585938 L 460.265625 1120.585938 "/>
+</g>
+<g clip-path="url(#clip335)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 318.222656 1259.027344 L 318.222656 1094.398438 "/>
+</g>
+<g clip-path="url(#clip336)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.613281 1259.027344 L 356.613281 1094.398438 "/>
+</g>
+<g clip-path="url(#clip337)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 395.003906 1259.027344 L 395.003906 1094.398438 "/>
+</g>
+<g clip-path="url(#clip338)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 433.394531 1259.027344 L 433.394531 1094.398438 "/>
+</g>
+<g clip-path="url(#clip339)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1251.550781 L 460.265625 1251.550781 "/>
+</g>
+<g clip-path="url(#clip340)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1214.132812 L 460.265625 1214.132812 "/>
+</g>
+<g clip-path="url(#clip341)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1176.714844 L 460.265625 1176.714844 "/>
+</g>
+<g clip-path="url(#clip342)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1139.296875 L 460.265625 1139.296875 "/>
+</g>
+<g clip-path="url(#clip343)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1101.875 L 460.265625 1101.875 "/>
+</g>
+<g clip-path="url(#clip344)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 1259.027344 L 299.03125 1094.398438 "/>
+</g>
+<g clip-path="url(#clip345)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 1259.027344 L 337.417969 1094.398438 "/>
+</g>
+<g clip-path="url(#clip346)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 1259.027344 L 375.808594 1094.398438 "/>
+</g>
+<g clip-path="url(#clip347)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 1259.027344 L 414.199219 1094.398438 "/>
+</g>
+<g clip-path="url(#clip348)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 1259.027344 L 452.589844 1094.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 299.03125 1101.882812 L 300.566406 1101.882812 L 300.875 1101.886719 L 303.335938 1101.886719 L 303.644531 1101.890625 L 305.492188 1101.890625 L 305.800781 1101.894531 L 307.339844 1101.894531 L 307.644531 1101.898438 L 308.570312 1101.898438 L 308.878906 1101.902344 L 309.800781 1101.902344 L 310.109375 1101.90625 L 310.722656 1101.90625 L 311.03125 1101.910156 L 311.648438 1101.910156 L 311.953125 1101.914062 L 312.570312 1101.914062 L 312.878906 1101.917969 L 313.183594 1101.917969 L 313.492188 1101.921875 L 313.800781 1101.921875 L 314.109375 1101.925781 L 314.417969 1101.925781 L 314.722656 1101.929688 L 315.03125 1101.929688 L 315.339844 1101.933594 L 315.648438 1101.933594 L 315.953125 1101.9375 L 316.261719 1101.941406 L 316.570312 1101.941406 L 317.1875 1101.949219 L 317.492188 1101.953125 L 317.800781 1101.953125 L 318.417969 1101.960938 L 318.722656 1101.964844 L 319.957031 1101.980469 L 320.261719 1101.984375 L 321.1875 1101.996094 L 321.492188 1102.003906 L 322.109375 1102.011719 L 322.417969 1102.019531 L 322.726562 1102.023438 L 323.03125 1102.03125 L 323.339844 1102.039062 L 323.648438 1102.042969 L 324.265625 1102.058594 L 324.570312 1102.066406 L 325.496094 1102.089844 L 325.800781 1102.097656 L 326.109375 1102.105469 L 326.417969 1102.117188 L 326.726562 1102.125 L 327.035156 1102.136719 L 327.339844 1102.148438 L 327.648438 1102.160156 L 327.957031 1102.167969 L 328.265625 1102.183594 L 328.570312 1102.195312 L 328.878906 1102.207031 L 329.1875 1102.222656 L 329.496094 1102.234375 L 329.804688 1102.25 L 330.109375 1102.265625 L 331.035156 1102.3125 L 331.339844 1102.332031 L 332.574219 1102.410156 L 332.878906 1102.433594 L 333.804688 1102.503906 L 334.109375 1102.527344 L 334.726562 1102.582031 L 335.035156 1102.613281 L 335.34375 1102.640625 L 335.648438 1102.671875 L 335.957031 1102.707031 L 336.265625 1102.738281 L 336.574219 1102.773438 L 336.878906 1102.8125 L 337.1875 1102.847656 L 337.496094 1102.886719 L 338.113281 1102.972656 L 338.417969 1103.015625 L 339.035156 1103.109375 L 339.34375 1103.160156 L 339.648438 1103.210938 L 339.957031 1103.265625 L 340.882812 1103.441406 L 341.1875 1103.507812 L 341.496094 1103.570312 L 342.113281 1103.710938 L 342.421875 1103.785156 L 342.726562 1103.863281 L 343.035156 1103.941406 L 343.652344 1104.113281 L 343.957031 1104.203125 L 344.265625 1104.296875 L 344.574219 1104.394531 L 344.882812 1104.496094 L 345.191406 1104.601562 L 345.496094 1104.710938 L 345.804688 1104.824219 L 346.113281 1104.941406 L 346.421875 1105.0625 L 346.726562 1105.191406 L 347.035156 1105.324219 L 347.34375 1105.460938 L 347.652344 1105.605469 L 347.960938 1105.753906 L 348.265625 1105.90625 L 348.574219 1106.066406 L 348.882812 1106.234375 L 349.191406 1106.40625 L 349.496094 1106.585938 L 349.804688 1106.773438 L 350.113281 1106.964844 L 350.421875 1107.167969 L 350.730469 1107.375 L 351.035156 1107.589844 L 351.34375 1107.816406 L 351.652344 1108.046875 L 351.960938 1108.289062 L 352.265625 1108.539062 L 352.574219 1108.800781 L 352.882812 1109.070312 L 353.191406 1109.351562 L 353.5 1109.640625 L 353.804688 1109.941406 L 354.113281 1110.25 L 354.421875 1110.574219 L 354.730469 1110.90625 L 355.035156 1111.253906 L 355.34375 1111.613281 L 355.652344 1111.984375 L 355.960938 1112.367188 L 356.269531 1112.765625 L 356.574219 1113.179688 L 356.882812 1113.605469 L 357.191406 1114.042969 L 357.5 1114.5 L 357.808594 1114.972656 L 358.113281 1115.457031 L 358.421875 1115.960938 L 358.730469 1116.480469 L 359.039062 1117.019531 L 359.34375 1117.574219 L 359.652344 1118.144531 L 359.960938 1118.734375 L 360.269531 1119.34375 L 360.578125 1119.972656 L 360.882812 1120.617188 L 361.191406 1121.285156 L 361.5 1121.972656 L 361.808594 1122.679688 L 362.113281 1123.410156 L 362.421875 1124.160156 L 362.730469 1124.929688 L 363.039062 1125.722656 L 363.347656 1126.535156 L 363.652344 1127.375 L 363.960938 1128.230469 L 364.269531 1129.113281 L 364.578125 1130.019531 L 364.882812 1130.945312 L 365.191406 1131.894531 L 365.5 1132.871094 L 365.808594 1133.867188 L 366.117188 1134.886719 L 366.421875 1135.929688 L 366.730469 1136.996094 L 367.039062 1138.082031 L 367.347656 1139.195312 L 367.652344 1140.328125 L 367.960938 1141.484375 L 368.269531 1142.664062 L 368.578125 1143.863281 L 368.886719 1145.085938 L 369.191406 1146.328125 L 369.5 1147.589844 L 369.808594 1148.871094 L 370.117188 1150.175781 L 370.421875 1151.496094 L 370.730469 1152.832031 L 371.039062 1154.1875 L 371.347656 1155.558594 L 371.65625 1156.949219 L 371.960938 1158.351562 L 372.269531 1159.765625 L 372.578125 1161.195312 L 372.886719 1162.636719 L 373.195312 1164.089844 L 373.5 1165.550781 L 373.808594 1167.019531 L 374.117188 1168.5 L 374.425781 1169.984375 L 374.730469 1171.472656 L 375.347656 1174.464844 L 375.964844 1177.464844 L 376.269531 1178.964844 L 376.886719 1181.957031 L 377.195312 1183.445312 L 377.5 1184.929688 L 377.808594 1186.40625 L 378.117188 1187.878906 L 378.425781 1189.339844 L 378.734375 1190.792969 L 379.039062 1192.234375 L 379.347656 1193.664062 L 379.65625 1195.078125 L 379.964844 1196.480469 L 380.269531 1197.867188 L 380.578125 1199.242188 L 380.886719 1200.597656 L 381.195312 1201.933594 L 381.503906 1203.253906 L 381.808594 1204.558594 L 382.117188 1205.839844 L 382.425781 1207.101562 L 382.734375 1208.34375 L 383.039062 1209.566406 L 383.347656 1210.765625 L 383.65625 1211.945312 L 383.964844 1213.101562 L 384.273438 1214.234375 L 384.578125 1215.347656 L 384.886719 1216.433594 L 385.195312 1217.5 L 385.503906 1218.542969 L 385.808594 1219.5625 L 386.117188 1220.558594 L 386.425781 1221.53125 L 386.734375 1222.484375 L 387.042969 1223.410156 L 387.347656 1224.316406 L 387.65625 1225.195312 L 387.964844 1226.054688 L 388.273438 1226.890625 L 388.578125 1227.707031 L 388.886719 1228.5 L 389.195312 1229.269531 L 389.503906 1230.019531 L 389.8125 1230.75 L 390.117188 1231.457031 L 390.425781 1232.144531 L 390.734375 1232.808594 L 391.042969 1233.457031 L 391.351562 1234.085938 L 391.65625 1234.695312 L 391.964844 1235.285156 L 392.273438 1235.855469 L 392.582031 1236.410156 L 392.886719 1236.949219 L 393.195312 1237.46875 L 393.503906 1237.972656 L 393.8125 1238.457031 L 394.121094 1238.929688 L 394.425781 1239.382812 L 394.734375 1239.824219 L 395.042969 1240.25 L 395.351562 1240.664062 L 395.65625 1241.058594 L 395.964844 1241.445312 L 396.273438 1241.816406 L 396.582031 1242.175781 L 396.890625 1242.519531 L 397.195312 1242.855469 L 397.503906 1243.175781 L 397.8125 1243.488281 L 398.121094 1243.789062 L 398.425781 1244.078125 L 398.734375 1244.359375 L 399.042969 1244.628906 L 399.351562 1244.886719 L 399.660156 1245.140625 L 399.964844 1245.378906 L 400.273438 1245.613281 L 400.582031 1245.835938 L 400.890625 1246.054688 L 401.195312 1246.261719 L 401.503906 1246.464844 L 401.8125 1246.65625 L 402.121094 1246.84375 L 402.429688 1247.023438 L 402.734375 1247.195312 L 403.042969 1247.363281 L 403.351562 1247.523438 L 403.660156 1247.675781 L 403.964844 1247.824219 L 404.273438 1247.96875 L 404.582031 1248.105469 L 404.890625 1248.238281 L 405.199219 1248.363281 L 405.503906 1248.488281 L 405.8125 1248.605469 L 406.121094 1248.71875 L 406.429688 1248.828125 L 406.738281 1248.933594 L 407.042969 1249.035156 L 407.351562 1249.132812 L 407.660156 1249.226562 L 407.96875 1249.316406 L 408.273438 1249.402344 L 408.890625 1249.566406 L 409.199219 1249.644531 L 409.507812 1249.71875 L 409.8125 1249.789062 L 410.429688 1249.921875 L 410.738281 1249.984375 L 411.042969 1250.046875 L 411.351562 1250.105469 L 412.277344 1250.269531 L 412.582031 1250.316406 L 412.890625 1250.367188 L 413.199219 1250.414062 L 413.507812 1250.457031 L 413.8125 1250.5 L 414.121094 1250.539062 L 414.429688 1250.582031 L 414.738281 1250.617188 L 415.046875 1250.65625 L 415.351562 1250.691406 L 415.660156 1250.722656 L 415.96875 1250.757812 L 416.277344 1250.789062 L 416.582031 1250.816406 L 416.890625 1250.847656 L 417.199219 1250.875 L 417.507812 1250.898438 L 417.816406 1250.925781 L 418.121094 1250.949219 L 419.046875 1251.019531 L 419.351562 1251.039062 L 420.277344 1251.097656 L 420.585938 1251.113281 L 420.890625 1251.132812 L 422.125 1251.195312 L 422.429688 1251.207031 L 422.738281 1251.222656 L 423.355469 1251.246094 L 423.660156 1251.257812 L 424.585938 1251.292969 L 424.894531 1251.300781 L 425.199219 1251.3125 L 425.507812 1251.320312 L 425.816406 1251.332031 L 426.125 1251.339844 L 426.429688 1251.347656 L 427.664062 1251.378906 L 427.96875 1251.386719 L 428.277344 1251.390625 L 428.585938 1251.398438 L 428.894531 1251.402344 L 429.199219 1251.410156 L 429.507812 1251.414062 L 429.816406 1251.421875 L 430.433594 1251.429688 L 430.738281 1251.4375 L 431.664062 1251.449219 L 431.96875 1251.453125 L 433.203125 1251.46875 L 433.507812 1251.472656 L 433.816406 1251.472656 L 434.433594 1251.480469 L 434.738281 1251.484375 L 435.046875 1251.484375 L 435.664062 1251.492188 L 435.972656 1251.492188 L 436.277344 1251.496094 L 436.585938 1251.5 L 436.894531 1251.5 L 437.203125 1251.503906 L 437.507812 1251.503906 L 437.816406 1251.507812 L 438.433594 1251.507812 L 438.742188 1251.511719 L 439.046875 1251.511719 L 439.355469 1251.515625 L 439.972656 1251.515625 L 440.28125 1251.519531 L 440.585938 1251.519531 L 440.894531 1251.523438 L 441.816406 1251.523438 L 442.125 1251.527344 L 443.050781 1251.527344 L 443.355469 1251.53125 L 444.28125 1251.53125 L 444.585938 1251.535156 L 446.125 1251.535156 L 446.433594 1251.539062 L 448.28125 1251.539062 L 448.589844 1251.542969 L 451.359375 1251.542969 L 451.664062 1251.546875 L 452.589844 1251.546875 "/>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 299.03125 1251.546875 L 299.953125 1251.546875 L 300.261719 1251.542969 L 303.03125 1251.542969 L 303.335938 1251.539062 L 305.183594 1251.539062 L 305.492188 1251.535156 L 307.03125 1251.535156 L 307.339844 1251.53125 L 308.261719 1251.53125 L 308.570312 1251.527344 L 309.492188 1251.527344 L 309.800781 1251.523438 L 310.722656 1251.523438 L 311.03125 1251.519531 L 311.339844 1251.519531 L 311.648438 1251.515625 L 312.261719 1251.515625 L 312.570312 1251.511719 L 312.878906 1251.511719 L 313.183594 1251.507812 L 313.800781 1251.507812 L 314.109375 1251.503906 L 314.417969 1251.503906 L 314.722656 1251.5 L 315.03125 1251.5 L 315.648438 1251.492188 L 315.953125 1251.492188 L 316.570312 1251.484375 L 316.878906 1251.484375 L 317.1875 1251.480469 L 317.492188 1251.476562 L 317.800781 1251.472656 L 318.109375 1251.472656 L 318.417969 1251.46875 L 318.722656 1251.464844 L 319.957031 1251.449219 L 320.261719 1251.445312 L 320.878906 1251.4375 L 321.1875 1251.429688 L 321.492188 1251.425781 L 321.800781 1251.421875 L 322.109375 1251.414062 L 322.417969 1251.410156 L 322.726562 1251.402344 L 323.03125 1251.398438 L 323.339844 1251.390625 L 323.648438 1251.386719 L 324.265625 1251.371094 L 324.570312 1251.363281 L 325.496094 1251.339844 L 325.800781 1251.332031 L 326.109375 1251.320312 L 326.417969 1251.3125 L 326.726562 1251.300781 L 327.035156 1251.292969 L 327.339844 1251.28125 L 328.265625 1251.246094 L 328.570312 1251.234375 L 328.878906 1251.222656 L 329.1875 1251.207031 L 329.496094 1251.195312 L 329.804688 1251.179688 L 330.109375 1251.164062 L 330.726562 1251.132812 L 331.035156 1251.113281 L 331.339844 1251.097656 L 332.574219 1251.019531 L 332.878906 1250.996094 L 333.804688 1250.925781 L 334.109375 1250.898438 L 334.417969 1250.875 L 334.726562 1250.847656 L 335.035156 1250.816406 L 335.34375 1250.789062 L 335.648438 1250.757812 L 335.957031 1250.722656 L 336.265625 1250.691406 L 336.574219 1250.65625 L 336.878906 1250.617188 L 337.1875 1250.582031 L 337.496094 1250.539062 L 337.804688 1250.5 L 338.113281 1250.457031 L 338.417969 1250.414062 L 338.726562 1250.367188 L 339.035156 1250.316406 L 339.34375 1250.269531 L 339.648438 1250.214844 L 340.265625 1250.105469 L 340.574219 1250.046875 L 340.882812 1249.984375 L 341.1875 1249.921875 L 341.804688 1249.789062 L 342.113281 1249.71875 L 342.421875 1249.644531 L 342.726562 1249.566406 L 343.34375 1249.402344 L 343.652344 1249.316406 L 343.957031 1249.226562 L 344.265625 1249.132812 L 344.574219 1249.035156 L 344.882812 1248.933594 L 345.191406 1248.828125 L 345.496094 1248.71875 L 345.804688 1248.605469 L 346.113281 1248.488281 L 346.421875 1248.363281 L 346.726562 1248.238281 L 347.035156 1248.105469 L 347.34375 1247.96875 L 347.652344 1247.824219 L 347.960938 1247.675781 L 348.265625 1247.523438 L 348.574219 1247.363281 L 348.882812 1247.195312 L 349.191406 1247.023438 L 349.496094 1246.84375 L 349.804688 1246.65625 L 350.113281 1246.464844 L 350.421875 1246.261719 L 350.730469 1246.054688 L 351.035156 1245.835938 L 351.34375 1245.613281 L 351.652344 1245.378906 L 351.960938 1245.140625 L 352.265625 1244.886719 L 352.574219 1244.628906 L 352.882812 1244.359375 L 353.191406 1244.078125 L 353.5 1243.789062 L 353.804688 1243.488281 L 354.113281 1243.175781 L 354.421875 1242.855469 L 354.730469 1242.519531 L 355.035156 1242.175781 L 355.34375 1241.816406 L 355.652344 1241.445312 L 355.960938 1241.058594 L 356.269531 1240.664062 L 356.574219 1240.25 L 356.882812 1239.824219 L 357.191406 1239.382812 L 357.5 1238.929688 L 357.808594 1238.457031 L 358.113281 1237.972656 L 358.421875 1237.46875 L 358.730469 1236.949219 L 359.039062 1236.410156 L 359.34375 1235.855469 L 359.652344 1235.285156 L 359.960938 1234.695312 L 360.269531 1234.085938 L 360.578125 1233.457031 L 360.882812 1232.808594 L 361.191406 1232.144531 L 361.5 1231.457031 L 361.808594 1230.75 L 362.113281 1230.019531 L 362.421875 1229.269531 L 362.730469 1228.5 L 363.039062 1227.707031 L 363.347656 1226.890625 L 363.652344 1226.054688 L 363.960938 1225.195312 L 364.269531 1224.316406 L 364.578125 1223.410156 L 364.882812 1222.484375 L 365.191406 1221.53125 L 365.5 1220.558594 L 365.808594 1219.5625 L 366.117188 1218.542969 L 366.421875 1217.5 L 366.730469 1216.433594 L 367.039062 1215.347656 L 367.347656 1214.234375 L 367.652344 1213.101562 L 367.960938 1211.945312 L 368.269531 1210.765625 L 368.578125 1209.566406 L 368.886719 1208.34375 L 369.191406 1207.101562 L 369.5 1205.839844 L 369.808594 1204.558594 L 370.117188 1203.253906 L 370.421875 1201.933594 L 370.730469 1200.597656 L 371.039062 1199.242188 L 371.347656 1197.867188 L 371.65625 1196.480469 L 371.960938 1195.078125 L 372.269531 1193.664062 L 372.578125 1192.234375 L 372.886719 1190.792969 L 373.195312 1189.339844 L 373.5 1187.878906 L 373.808594 1186.40625 L 374.117188 1184.929688 L 374.425781 1183.445312 L 374.730469 1181.957031 L 375.347656 1178.964844 L 375.964844 1175.964844 L 376.269531 1174.464844 L 376.886719 1171.472656 L 377.195312 1169.984375 L 377.5 1168.5 L 377.808594 1167.019531 L 378.117188 1165.550781 L 378.425781 1164.089844 L 378.734375 1162.636719 L 379.039062 1161.195312 L 379.347656 1159.765625 L 379.65625 1158.351562 L 379.964844 1156.949219 L 380.269531 1155.558594 L 380.578125 1154.1875 L 380.886719 1152.832031 L 381.195312 1151.496094 L 381.503906 1150.175781 L 381.808594 1148.871094 L 382.117188 1147.589844 L 382.425781 1146.328125 L 382.734375 1145.085938 L 383.039062 1143.863281 L 383.347656 1142.664062 L 383.65625 1141.484375 L 383.964844 1140.328125 L 384.273438 1139.195312 L 384.578125 1138.082031 L 384.886719 1136.996094 L 385.195312 1135.929688 L 385.503906 1134.886719 L 385.808594 1133.867188 L 386.117188 1132.871094 L 386.425781 1131.894531 L 386.734375 1130.945312 L 387.042969 1130.019531 L 387.347656 1129.113281 L 387.65625 1128.230469 L 387.964844 1127.375 L 388.273438 1126.535156 L 388.578125 1125.722656 L 388.886719 1124.929688 L 389.195312 1124.160156 L 389.503906 1123.410156 L 389.8125 1122.679688 L 390.117188 1121.972656 L 390.425781 1121.285156 L 390.734375 1120.617188 L 391.042969 1119.972656 L 391.351562 1119.34375 L 391.65625 1118.734375 L 391.964844 1118.144531 L 392.273438 1117.574219 L 392.582031 1117.019531 L 392.886719 1116.480469 L 393.195312 1115.960938 L 393.503906 1115.457031 L 393.8125 1114.972656 L 394.121094 1114.5 L 394.425781 1114.042969 L 394.734375 1113.605469 L 395.042969 1113.179688 L 395.351562 1112.765625 L 395.65625 1112.367188 L 395.964844 1111.984375 L 396.273438 1111.613281 L 396.582031 1111.253906 L 396.890625 1110.90625 L 397.195312 1110.574219 L 397.503906 1110.25 L 397.8125 1109.941406 L 398.121094 1109.640625 L 398.425781 1109.351562 L 398.734375 1109.070312 L 399.042969 1108.800781 L 399.351562 1108.539062 L 399.660156 1108.289062 L 399.964844 1108.046875 L 400.273438 1107.816406 L 400.582031 1107.589844 L 400.890625 1107.375 L 401.195312 1107.167969 L 401.503906 1106.964844 L 401.8125 1106.773438 L 402.121094 1106.585938 L 402.429688 1106.40625 L 402.734375 1106.234375 L 403.042969 1106.066406 L 403.351562 1105.90625 L 403.660156 1105.753906 L 403.964844 1105.605469 L 404.273438 1105.460938 L 404.582031 1105.324219 L 404.890625 1105.191406 L 405.199219 1105.0625 L 405.503906 1104.941406 L 405.8125 1104.824219 L 406.121094 1104.710938 L 406.429688 1104.601562 L 406.738281 1104.496094 L 407.042969 1104.394531 L 407.351562 1104.296875 L 407.660156 1104.203125 L 407.96875 1104.113281 L 408.273438 1104.027344 L 408.582031 1103.941406 L 409.199219 1103.785156 L 409.507812 1103.710938 L 409.8125 1103.640625 L 410.121094 1103.570312 L 410.429688 1103.507812 L 410.738281 1103.441406 L 411.042969 1103.382812 L 411.660156 1103.265625 L 411.96875 1103.210938 L 412.277344 1103.160156 L 412.582031 1103.109375 L 413.199219 1103.015625 L 413.507812 1102.972656 L 413.8125 1102.929688 L 414.121094 1102.886719 L 414.429688 1102.847656 L 414.738281 1102.8125 L 415.046875 1102.773438 L 415.351562 1102.738281 L 415.660156 1102.707031 L 415.96875 1102.671875 L 416.277344 1102.640625 L 416.582031 1102.613281 L 416.890625 1102.582031 L 417.507812 1102.527344 L 417.816406 1102.503906 L 418.121094 1102.480469 L 419.046875 1102.410156 L 419.351562 1102.390625 L 420.585938 1102.3125 L 420.890625 1102.296875 L 422.125 1102.234375 L 422.429688 1102.222656 L 422.738281 1102.207031 L 423.355469 1102.183594 L 423.660156 1102.167969 L 423.96875 1102.160156 L 424.894531 1102.125 L 425.199219 1102.117188 L 425.507812 1102.105469 L 426.125 1102.089844 L 426.429688 1102.082031 L 427.664062 1102.050781 L 427.96875 1102.042969 L 428.277344 1102.039062 L 428.894531 1102.023438 L 429.199219 1102.019531 L 429.507812 1102.011719 L 430.125 1102.003906 L 430.433594 1101.996094 L 430.738281 1101.992188 L 431.664062 1101.980469 L 431.96875 1101.976562 L 433.203125 1101.960938 L 433.507812 1101.957031 L 433.816406 1101.953125 L 434.125 1101.953125 L 434.433594 1101.949219 L 434.738281 1101.945312 L 435.046875 1101.941406 L 435.355469 1101.941406 L 435.972656 1101.933594 L 436.277344 1101.933594 L 436.585938 1101.929688 L 436.894531 1101.929688 L 437.203125 1101.925781 L 437.507812 1101.925781 L 437.816406 1101.921875 L 438.125 1101.921875 L 438.433594 1101.917969 L 438.742188 1101.917969 L 439.046875 1101.914062 L 439.664062 1101.914062 L 439.972656 1101.910156 L 440.585938 1101.910156 L 440.894531 1101.90625 L 441.511719 1101.90625 L 441.816406 1101.902344 L 442.742188 1101.902344 L 443.050781 1101.898438 L 443.972656 1101.898438 L 444.28125 1101.894531 L 445.820312 1101.894531 L 446.125 1101.890625 L 447.972656 1101.890625 L 448.28125 1101.886719 L 450.742188 1101.886719 L 451.050781 1101.882812 L 452.589844 1101.882812 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1254.988281"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1254.988281"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="1254.988281"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="1254.988281"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1217.570312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1217.570312"/>
+ <use xlink:href="#glyph0-3" x="273.594788" y="1217.570312"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="1217.570312"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1180.152344"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1180.152344"/>
+ <use xlink:href="#glyph0-4" x="273.594788" y="1180.152344"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="1180.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1142.734375"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1142.734375"/>
+ <use xlink:href="#glyph0-5" x="273.594788" y="1142.734375"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="1142.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="265.59375" y="1105.3125"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1105.3125"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="1105.3125"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="1105.3125"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1251.550781 L 291.351562 1251.550781 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1214.132812 L 291.351562 1214.132812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1176.714844 L 291.351562 1176.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1139.296875 L 291.351562 1139.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1101.875 L 291.351562 1101.875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 1263.28125 L 299.03125 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 1263.28125 L 337.417969 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 1263.28125 L 375.808594 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 1263.28125 L 414.199219 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 1263.28125 L 452.589844 1259.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="289.695312" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="295.030899" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="297.69635" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="303.031937" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="328.082031" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="333.417618" y="1272.992188"/>
+ <use xlink:href="#glyph0-3" x="336.083069" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="341.418655" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="366.472656" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="371.808243" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="374.473694" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="379.80928" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="404.863281" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="410.198868" y="1272.992188"/>
+ <use xlink:href="#glyph0-5" x="412.864319" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="418.199905" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="443.253906" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="448.589493" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="451.254944" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="456.59053" y="1272.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="372.808594" y="1285.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="258.992188" y="1188.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="258.992188" y="1181.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="258.992188" y="1176.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="258.992188" y="1170.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-11" x="260.996094" y="1090.800781"/>
+ <use xlink:href="#glyph5-3" x="269" y="1090.800781"/>
+ <use xlink:href="#glyph5-6" x="272.333984" y="1090.800781"/>
+ <use xlink:href="#glyph5-19" x="279.664062" y="1090.800781"/>
+ <use xlink:href="#glyph5-15" x="290.333984" y="1090.800781"/>
+ <use xlink:href="#glyph5-3" x="297.664062" y="1090.800781"/>
+ <use xlink:href="#glyph5-16" x="300.998047" y="1090.800781"/>
+</g>
+<g clip-path="url(#clip349)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 474.667969 1296 L 712 1296 L 712 1080 L 474.667969 1080 Z "/>
+</g>
+<g clip-path="url(#clip350)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 474.667969 1296 L 712 1296 L 712 1080 L 474.667969 1080 Z "/>
+</g>
+<g clip-path="url(#clip351)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 528.683594 1259.027344 L 697.597656 1259.027344 L 697.597656 1094.398438 L 528.683594 1094.398438 Z "/>
+</g>
+<g clip-path="url(#clip352)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1232.839844 L 697.601562 1232.839844 "/>
+</g>
+<g clip-path="url(#clip353)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1195.421875 L 697.601562 1195.421875 "/>
+</g>
+<g clip-path="url(#clip354)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1158.007812 L 697.601562 1158.007812 "/>
+</g>
+<g clip-path="url(#clip355)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1120.589844 L 697.601562 1120.589844 "/>
+</g>
+<g clip-path="url(#clip356)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.558594 1259.027344 L 555.558594 1094.398438 "/>
+</g>
+<g clip-path="url(#clip357)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 593.949219 1259.027344 L 593.949219 1094.398438 "/>
+</g>
+<g clip-path="url(#clip358)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 632.335938 1259.027344 L 632.335938 1094.398438 "/>
+</g>
+<g clip-path="url(#clip359)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 670.726562 1259.027344 L 670.726562 1094.398438 "/>
+</g>
+<g clip-path="url(#clip360)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1251.546875 L 697.601562 1251.546875 "/>
+</g>
+<g clip-path="url(#clip361)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1214.128906 L 697.601562 1214.128906 "/>
+</g>
+<g clip-path="url(#clip362)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1176.714844 L 697.601562 1176.714844 "/>
+</g>
+<g clip-path="url(#clip363)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1139.296875 L 697.601562 1139.296875 "/>
+</g>
+<g clip-path="url(#clip364)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1101.882812 L 697.601562 1101.882812 "/>
+</g>
+<g clip-path="url(#clip365)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 1259.027344 L 536.363281 1094.398438 "/>
+</g>
+<g clip-path="url(#clip366)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 1259.027344 L 574.753906 1094.398438 "/>
+</g>
+<g clip-path="url(#clip367)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 1259.027344 L 613.140625 1094.398438 "/>
+</g>
+<g clip-path="url(#clip368)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 1259.027344 L 651.53125 1094.398438 "/>
+</g>
+<g clip-path="url(#clip369)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 1259.027344 L 689.921875 1094.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 536.363281 1101.882812 L 536.671875 1101.882812 L 536.976562 1101.886719 L 537.59375 1101.902344 L 538.210938 1101.925781 L 538.515625 1101.941406 L 539.132812 1101.980469 L 539.441406 1102.003906 L 539.746094 1102.027344 L 540.054688 1102.054688 L 540.671875 1102.117188 L 540.980469 1102.152344 L 541.285156 1102.191406 L 541.59375 1102.230469 L 542.210938 1102.316406 L 542.515625 1102.363281 L 543.132812 1102.464844 L 543.75 1102.574219 L 544.054688 1102.632812 L 544.671875 1102.757812 L 544.980469 1102.824219 L 545.289062 1102.894531 L 545.59375 1102.964844 L 546.210938 1103.113281 L 546.519531 1103.191406 L 546.824219 1103.273438 L 547.132812 1103.355469 L 547.75 1103.527344 L 548.058594 1103.617188 L 548.363281 1103.710938 L 548.671875 1103.804688 L 548.980469 1103.902344 L 549.289062 1104.003906 L 549.59375 1104.105469 L 550.210938 1104.316406 L 550.519531 1104.425781 L 550.828125 1104.539062 L 551.132812 1104.652344 L 551.75 1104.886719 L 552.058594 1105.011719 L 552.363281 1105.132812 L 552.671875 1105.261719 L 552.980469 1105.386719 L 553.597656 1105.652344 L 553.902344 1105.789062 L 554.210938 1105.925781 L 554.519531 1106.066406 L 554.828125 1106.210938 L 555.132812 1106.355469 L 555.75 1106.652344 L 556.058594 1106.808594 L 556.367188 1106.960938 L 556.671875 1107.121094 L 557.289062 1107.441406 L 557.597656 1107.605469 L 557.902344 1107.773438 L 558.210938 1107.941406 L 558.519531 1108.113281 L 559.136719 1108.464844 L 559.441406 1108.644531 L 560.367188 1109.195312 L 560.671875 1109.386719 L 561.289062 1109.769531 L 561.597656 1109.964844 L 561.90625 1110.164062 L 562.210938 1110.363281 L 562.519531 1110.566406 L 563.136719 1110.980469 L 563.445312 1111.191406 L 563.75 1111.40625 L 564.367188 1111.835938 L 564.675781 1112.058594 L 564.980469 1112.28125 L 565.289062 1112.503906 L 565.597656 1112.730469 L 565.90625 1112.960938 L 566.214844 1113.195312 L 566.519531 1113.429688 L 566.828125 1113.664062 L 567.136719 1113.902344 L 567.445312 1114.144531 L 567.75 1114.390625 L 568.058594 1114.636719 L 568.675781 1115.136719 L 568.984375 1115.390625 L 569.289062 1115.644531 L 569.597656 1115.90625 L 569.90625 1116.164062 L 570.214844 1116.429688 L 570.519531 1116.695312 L 570.828125 1116.960938 L 571.136719 1117.234375 L 571.445312 1117.503906 L 571.753906 1117.78125 L 572.058594 1118.058594 L 572.675781 1118.621094 L 572.984375 1118.90625 L 573.289062 1119.195312 L 573.90625 1119.773438 L 574.523438 1120.367188 L 574.828125 1120.667969 L 575.136719 1120.96875 L 575.753906 1121.578125 L 576.058594 1121.886719 L 576.675781 1122.511719 L 576.984375 1122.828125 L 577.292969 1123.148438 L 577.597656 1123.46875 L 578.214844 1124.117188 L 578.523438 1124.445312 L 578.832031 1124.777344 L 579.136719 1125.109375 L 579.753906 1125.78125 L 580.0625 1126.121094 L 580.367188 1126.464844 L 580.675781 1126.808594 L 580.984375 1127.15625 L 581.601562 1127.859375 L 581.90625 1128.214844 L 582.214844 1128.570312 L 582.523438 1128.929688 L 582.832031 1129.292969 L 583.136719 1129.65625 L 583.753906 1130.390625 L 584.0625 1130.765625 L 584.371094 1131.136719 L 584.675781 1131.515625 L 584.984375 1131.890625 L 585.601562 1132.65625 L 585.90625 1133.042969 L 586.214844 1133.429688 L 586.523438 1133.820312 L 587.140625 1134.609375 L 587.445312 1135.007812 L 588.371094 1136.214844 L 588.675781 1136.625 L 589.292969 1137.445312 L 589.601562 1137.859375 L 589.910156 1138.277344 L 590.214844 1138.699219 L 590.832031 1139.542969 L 591.140625 1139.96875 L 591.445312 1140.398438 L 592.0625 1141.265625 L 592.679688 1142.140625 L 592.984375 1142.582031 L 593.292969 1143.023438 L 593.601562 1143.472656 L 593.910156 1143.917969 L 594.21875 1144.371094 L 594.523438 1144.824219 L 594.832031 1145.277344 L 595.449219 1146.199219 L 595.753906 1146.660156 L 596.0625 1147.125 L 596.679688 1148.0625 L 596.988281 1148.535156 L 597.292969 1149.011719 L 597.601562 1149.488281 L 598.21875 1150.449219 L 598.523438 1150.933594 L 599.140625 1151.910156 L 599.757812 1152.894531 L 600.0625 1153.390625 L 600.679688 1154.390625 L 600.988281 1154.894531 L 601.292969 1155.402344 L 601.601562 1155.910156 L 602.21875 1156.933594 L 602.527344 1157.449219 L 602.832031 1157.96875 L 603.140625 1158.488281 L 603.449219 1159.011719 L 603.757812 1159.539062 L 604.0625 1160.066406 L 604.371094 1160.59375 L 605.296875 1162.199219 L 605.601562 1162.738281 L 605.910156 1163.28125 L 606.527344 1164.375 L 606.832031 1164.921875 L 607.140625 1165.472656 L 607.449219 1166.027344 L 608.066406 1167.144531 L 608.371094 1167.707031 L 608.679688 1168.269531 L 609.296875 1169.402344 L 609.601562 1169.976562 L 609.910156 1170.546875 L 610.527344 1171.703125 L 610.835938 1172.285156 L 611.140625 1172.867188 L 611.757812 1174.039062 L 612.066406 1174.628906 L 612.375 1175.222656 L 612.679688 1175.816406 L 612.988281 1176.414062 L 613.296875 1177.015625 L 613.605469 1177.613281 L 613.910156 1178.207031 L 614.21875 1178.800781 L 614.527344 1179.390625 L 615.144531 1180.5625 L 615.449219 1181.144531 L 615.757812 1181.726562 L 616.066406 1182.304688 L 616.375 1182.878906 L 616.679688 1183.453125 L 617.296875 1184.59375 L 617.605469 1185.160156 L 617.914062 1185.722656 L 618.21875 1186.285156 L 618.527344 1186.84375 L 619.144531 1187.953125 L 619.449219 1188.507812 L 620.375 1190.148438 L 620.683594 1190.6875 L 620.988281 1191.230469 L 621.605469 1192.300781 L 621.914062 1192.832031 L 622.21875 1193.363281 L 622.835938 1194.417969 L 623.144531 1194.941406 L 623.453125 1195.460938 L 623.757812 1195.980469 L 624.066406 1196.496094 L 624.683594 1197.519531 L 624.988281 1198.027344 L 625.914062 1199.539062 L 626.222656 1200.035156 L 626.527344 1200.535156 L 627.144531 1201.519531 L 627.761719 1202.496094 L 628.066406 1202.980469 L 628.683594 1203.941406 L 628.992188 1204.417969 L 629.296875 1204.894531 L 629.605469 1205.367188 L 630.222656 1206.304688 L 630.53125 1206.769531 L 630.835938 1207.230469 L 631.144531 1207.691406 L 631.761719 1208.605469 L 632.066406 1209.058594 L 632.683594 1209.957031 L 633.300781 1210.847656 L 633.605469 1211.289062 L 634.222656 1212.164062 L 634.53125 1212.597656 L 634.835938 1213.027344 L 635.453125 1213.886719 L 636.070312 1214.730469 L 636.375 1215.152344 L 636.683594 1215.566406 L 636.992188 1215.984375 L 637.300781 1216.394531 L 637.605469 1216.804688 L 638.222656 1217.617188 L 638.839844 1218.421875 L 639.144531 1218.820312 L 639.453125 1219.214844 L 640.070312 1219.996094 L 640.375 1220.386719 L 640.683594 1220.773438 L 640.992188 1221.15625 L 641.609375 1221.914062 L 641.914062 1222.292969 L 642.839844 1223.40625 L 643.148438 1223.773438 L 643.453125 1224.136719 L 643.761719 1224.5 L 644.070312 1224.859375 L 644.378906 1225.214844 L 644.683594 1225.570312 L 645.300781 1226.273438 L 645.609375 1226.617188 L 645.917969 1226.964844 L 646.222656 1227.304688 L 646.53125 1227.648438 L 647.148438 1228.320312 L 647.453125 1228.652344 L 647.761719 1228.984375 L 648.070312 1229.3125 L 648.6875 1229.960938 L 648.992188 1230.28125 L 649.300781 1230.601562 L 649.609375 1230.917969 L 649.917969 1231.230469 L 650.222656 1231.542969 L 650.53125 1231.851562 L 651.148438 1232.460938 L 651.457031 1232.761719 L 651.761719 1233.0625 L 652.070312 1233.359375 L 652.6875 1233.945312 L 652.992188 1234.234375 L 653.300781 1234.523438 L 653.609375 1234.808594 L 654.226562 1235.371094 L 654.53125 1235.648438 L 655.148438 1236.195312 L 655.457031 1236.464844 L 655.761719 1236.734375 L 656.070312 1237 L 656.6875 1237.523438 L 656.996094 1237.78125 L 657.300781 1238.039062 L 657.609375 1238.292969 L 658.226562 1238.792969 L 658.53125 1239.039062 L 659.457031 1239.765625 L 659.765625 1240 L 660.070312 1240.234375 L 660.378906 1240.46875 L 660.6875 1240.695312 L 660.996094 1240.925781 L 661.304688 1241.148438 L 661.609375 1241.371094 L 662.226562 1241.808594 L 662.535156 1242.023438 L 662.839844 1242.238281 L 663.148438 1242.445312 L 663.457031 1242.65625 L 664.074219 1243.0625 L 664.378906 1243.265625 L 664.6875 1243.464844 L 664.996094 1243.660156 L 665.304688 1243.851562 L 665.609375 1244.042969 L 666.226562 1244.417969 L 666.84375 1244.785156 L 667.148438 1244.964844 L 667.457031 1245.140625 L 668.074219 1245.484375 L 668.378906 1245.65625 L 668.6875 1245.824219 L 668.996094 1245.988281 L 669.613281 1246.308594 L 669.917969 1246.46875 L 670.84375 1246.925781 L 671.148438 1247.074219 L 671.765625 1247.363281 L 672.074219 1247.503906 L 672.382812 1247.640625 L 672.6875 1247.777344 L 672.996094 1247.910156 L 673.613281 1248.167969 L 673.917969 1248.296875 L 674.84375 1248.660156 L 675.152344 1248.777344 L 675.457031 1248.890625 L 675.765625 1249.003906 L 676.074219 1249.113281 L 676.691406 1249.324219 L 676.996094 1249.425781 L 677.921875 1249.71875 L 678.226562 1249.808594 L 678.84375 1249.988281 L 679.152344 1250.074219 L 679.460938 1250.15625 L 679.765625 1250.238281 L 680.074219 1250.316406 L 680.691406 1250.464844 L 680.996094 1250.535156 L 681.921875 1250.734375 L 682.230469 1250.792969 L 682.535156 1250.851562 L 682.84375 1250.910156 L 683.152344 1250.964844 L 683.460938 1251.015625 L 683.765625 1251.066406 L 684.074219 1251.113281 L 684.691406 1251.199219 L 685 1251.238281 L 685.304688 1251.277344 L 685.613281 1251.308594 L 685.921875 1251.34375 L 686.230469 1251.371094 L 686.535156 1251.402344 L 687.152344 1251.449219 L 687.769531 1251.488281 L 688.074219 1251.503906 L 688.691406 1251.527344 L 689 1251.535156 L 689.304688 1251.542969 L 689.613281 1251.542969 L 689.921875 1251.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1254.984375"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1254.984375"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="1254.984375"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="1254.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1217.566406"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1217.566406"/>
+ <use xlink:href="#glyph0-3" x="510.926819" y="1217.566406"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="1217.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1180.152344"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1180.152344"/>
+ <use xlink:href="#glyph0-4" x="510.926819" y="1180.152344"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="1180.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1142.734375"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1142.734375"/>
+ <use xlink:href="#glyph0-5" x="510.926819" y="1142.734375"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="1142.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="502.925781" y="1105.320312"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1105.320312"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="1105.320312"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="1105.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1251.546875 L 528.683594 1251.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1214.128906 L 528.683594 1214.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1176.714844 L 528.683594 1176.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1139.296875 L 528.683594 1139.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1101.882812 L 528.683594 1101.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 1263.28125 L 536.363281 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 1263.28125 L 574.753906 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 1263.28125 L 613.140625 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 1263.28125 L 651.53125 1259.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 1263.28125 L 689.921875 1259.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="527.027344" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="532.36293" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="535.028381" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="540.363968" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="565.417969" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="570.753555" y="1272.992188"/>
+ <use xlink:href="#glyph0-3" x="573.419006" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="578.754593" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="603.804688" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="609.140274" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="611.805725" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="617.141312" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="642.195312" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="647.530899" y="1272.992188"/>
+ <use xlink:href="#glyph0-5" x="650.19635" y="1272.992188"/>
+ <use xlink:href="#glyph0-4" x="655.531937" y="1272.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="680.585938" y="1272.992188"/>
+ <use xlink:href="#glyph0-2" x="685.921524" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="688.586975" y="1272.992188"/>
+ <use xlink:href="#glyph0-1" x="693.922562" y="1272.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="610.140625" y="1285.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="496.324219" y="1188.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="496.324219" y="1181.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="496.324219" y="1176.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="496.324219" y="1170.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-30" x="496.339844" y="1090.800781"/>
+ <use xlink:href="#glyph5-11" x="503.669922" y="1090.800781"/>
+ <use xlink:href="#glyph5-12" x="511.673828" y="1090.800781"/>
+ <use xlink:href="#glyph5-4" x="519.003906" y="1090.800781"/>
+ <use xlink:href="#glyph5-13" x="525.677734" y="1090.800781"/>
+ <use xlink:href="#glyph5-8" x="533.007812" y="1090.800781"/>
+</g>
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0 1512 L 237.332031 1512 L 237.332031 1296 L 0 1296 Z "/>
+<g clip-path="url(#clip370)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 1512 L 237.332031 1512 L 237.332031 1296 L 0 1296 Z "/>
+</g>
+<g clip-path="url(#clip371)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 1475.027344 L 222.933594 1475.027344 L 222.933594 1310.398438 L 54.019531 1310.398438 Z "/>
+</g>
+<g clip-path="url(#clip372)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1448.839844 L 222.933594 1448.839844 "/>
+</g>
+<g clip-path="url(#clip373)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1411.421875 L 222.933594 1411.421875 "/>
+</g>
+<g clip-path="url(#clip374)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1374.007812 L 222.933594 1374.007812 "/>
+</g>
+<g clip-path="url(#clip375)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1336.589844 L 222.933594 1336.589844 "/>
+</g>
+<g clip-path="url(#clip376)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 80.890625 1475.027344 L 80.890625 1310.398438 "/>
+</g>
+<g clip-path="url(#clip377)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 119.28125 1475.027344 L 119.28125 1310.398438 "/>
+</g>
+<g clip-path="url(#clip378)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 157.671875 1475.027344 L 157.671875 1310.398438 "/>
+</g>
+<g clip-path="url(#clip379)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 196.058594 1475.027344 L 196.058594 1310.398438 "/>
+</g>
+<g clip-path="url(#clip380)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1467.546875 L 222.933594 1467.546875 "/>
+</g>
+<g clip-path="url(#clip381)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1430.128906 L 222.933594 1430.128906 "/>
+</g>
+<g clip-path="url(#clip382)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1392.714844 L 222.933594 1392.714844 "/>
+</g>
+<g clip-path="url(#clip383)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1355.296875 L 222.933594 1355.296875 "/>
+</g>
+<g clip-path="url(#clip384)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 1317.882812 L 222.933594 1317.882812 "/>
+</g>
+<g clip-path="url(#clip385)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 1475.027344 L 61.695312 1310.398438 "/>
+</g>
+<g clip-path="url(#clip386)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 1475.027344 L 100.085938 1310.398438 "/>
+</g>
+<g clip-path="url(#clip387)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 1475.027344 L 138.476562 1310.398438 "/>
+</g>
+<g clip-path="url(#clip388)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 1475.027344 L 176.867188 1310.398438 "/>
+</g>
+<g clip-path="url(#clip389)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 1475.027344 L 215.253906 1310.398438 "/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph6-1" x="74.902344" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph7-1" x="88.023438" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph6-2" x="101.144531" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph7-2" x="121.875" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph6-1" x="156.402344" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph8-1" x="164.277344" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph6-2" x="176.078125" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph8-2" x="190.25" y="1402.058594"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="1470.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="1470.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="1470.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="1470.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="1433.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="1433.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="1433.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="1433.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="1396.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="1396.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="1396.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="1396.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="1358.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="1358.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="1358.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="1358.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="1321.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="1321.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="1321.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="1321.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1467.546875 L 54.019531 1467.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1430.128906 L 54.019531 1430.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1392.714844 L 54.019531 1392.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1355.296875 L 54.019531 1355.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 1317.882812 L 54.019531 1317.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 61.695312 1479.28125 L 61.695312 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 100.085938 1479.28125 L 100.085938 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 138.476562 1479.28125 L 138.476562 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 176.867188 1479.28125 L 176.867188 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 215.253906 1479.28125 L 215.253906 1475.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="52.359375" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="57.694962" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="60.360413" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="65.695999" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="90.75" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="96.085587" y="1488.992188"/>
+ <use xlink:href="#glyph0-3" x="98.751038" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="104.086624" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="129.140625" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="134.476212" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="137.141663" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="142.477249" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="167.53125" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="172.866837" y="1488.992188"/>
+ <use xlink:href="#glyph0-5" x="175.532288" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="180.867874" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="205.917969" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="211.253555" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="213.919006" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="219.254593" y="1488.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="135.476562" y="1501.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-2" x="21.683594" y="1402.375"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.683594" y="1399.042969"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.683594" y="1394.046875"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.683594" y="1388.046875"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-31" x="25.328125" y="1306.800781"/>
+ <use xlink:href="#glyph5-26" x="32.658203" y="1306.800781"/>
+ <use xlink:href="#glyph5-5" x="39.988281" y="1306.800781"/>
+ <use xlink:href="#glyph5-22" x="47.318359" y="1306.800781"/>
+ <use xlink:href="#glyph5-24" x="53.992188" y="1306.800781"/>
+ <use xlink:href="#glyph5-3" x="57.988281" y="1306.800781"/>
+ <use xlink:href="#glyph5-15" x="61.322266" y="1306.800781"/>
+ <use xlink:href="#glyph5-5" x="68.652344" y="1306.800781"/>
+</g>
+<g clip-path="url(#clip390)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 237.332031 1512 L 474.664062 1512 L 474.664062 1296 L 237.332031 1296 Z "/>
+</g>
+<g clip-path="url(#clip391)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 237.332031 1512 L 474.664062 1512 L 474.664062 1296 L 237.332031 1296 Z "/>
+</g>
+<g clip-path="url(#clip392)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 291.351562 1475.027344 L 460.265625 1475.027344 L 460.265625 1310.398438 L 291.351562 1310.398438 Z "/>
+</g>
+<g clip-path="url(#clip393)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1448.839844 L 460.265625 1448.839844 "/>
+</g>
+<g clip-path="url(#clip394)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1411.421875 L 460.265625 1411.421875 "/>
+</g>
+<g clip-path="url(#clip395)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1374.007812 L 460.265625 1374.007812 "/>
+</g>
+<g clip-path="url(#clip396)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1336.589844 L 460.265625 1336.589844 "/>
+</g>
+<g clip-path="url(#clip397)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 318.222656 1475.027344 L 318.222656 1310.398438 "/>
+</g>
+<g clip-path="url(#clip398)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 356.613281 1475.027344 L 356.613281 1310.398438 "/>
+</g>
+<g clip-path="url(#clip399)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 395.003906 1475.027344 L 395.003906 1310.398438 "/>
+</g>
+<g clip-path="url(#clip400)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 433.394531 1475.027344 L 433.394531 1310.398438 "/>
+</g>
+<g clip-path="url(#clip401)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1467.546875 L 460.265625 1467.546875 "/>
+</g>
+<g clip-path="url(#clip402)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1430.128906 L 460.265625 1430.128906 "/>
+</g>
+<g clip-path="url(#clip403)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1392.714844 L 460.265625 1392.714844 "/>
+</g>
+<g clip-path="url(#clip404)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1355.296875 L 460.265625 1355.296875 "/>
+</g>
+<g clip-path="url(#clip405)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 291.351562 1317.882812 L 460.265625 1317.882812 "/>
+</g>
+<g clip-path="url(#clip406)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 1475.027344 L 299.03125 1310.398438 "/>
+</g>
+<g clip-path="url(#clip407)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 1475.027344 L 337.417969 1310.398438 "/>
+</g>
+<g clip-path="url(#clip408)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 1475.027344 L 375.808594 1310.398438 "/>
+</g>
+<g clip-path="url(#clip409)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 1475.027344 L 414.199219 1310.398438 "/>
+</g>
+<g clip-path="url(#clip410)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 1475.027344 L 452.589844 1310.398438 "/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph9-1" x="312.132812" y="1456.953125"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph10-1" x="317.699219" y="1451.386719"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph9-2" x="326.042969" y="1443.042969"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph10-2" x="336.066406" y="1433.019531"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph11-1" x="349.046875" y="1420.039062"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph10-3" x="364.917969" y="1404.632812"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph12-1" x="389.914062" y="1414.882812"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph9-3" x="385.332031" y="1383.753906"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph12-1" x="399.023437" y="1377.402344"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph9-4" x="398.46875" y="1370.617188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph12-1" x="412.160156" y="1364.265625"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph11-2" x="415.316406" y="1353.769531"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph9-5" x="430.027344" y="1339.058594"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1470.984375"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1470.984375"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="1470.984375"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="1470.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1433.566406"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1433.566406"/>
+ <use xlink:href="#glyph0-3" x="273.594788" y="1433.566406"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="1433.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1396.152344"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1396.152344"/>
+ <use xlink:href="#glyph0-4" x="273.594788" y="1396.152344"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="1396.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="265.59375" y="1358.734375"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1358.734375"/>
+ <use xlink:href="#glyph0-5" x="273.594788" y="1358.734375"/>
+ <use xlink:href="#glyph0-4" x="278.930374" y="1358.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="265.59375" y="1321.320312"/>
+ <use xlink:href="#glyph0-2" x="270.929337" y="1321.320312"/>
+ <use xlink:href="#glyph0-1" x="273.594788" y="1321.320312"/>
+ <use xlink:href="#glyph0-1" x="278.930374" y="1321.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1467.546875 L 291.351562 1467.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1430.128906 L 291.351562 1430.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1392.714844 L 291.351562 1392.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1355.296875 L 291.351562 1355.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 287.097656 1317.882812 L 291.351562 1317.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 299.03125 1479.28125 L 299.03125 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 337.417969 1479.28125 L 337.417969 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 375.808594 1479.28125 L 375.808594 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 414.199219 1479.28125 L 414.199219 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 452.589844 1479.28125 L 452.589844 1475.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="289.695312" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="295.030899" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="297.69635" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="303.031937" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="328.082031" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="333.417618" y="1488.992188"/>
+ <use xlink:href="#glyph0-3" x="336.083069" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="341.418655" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="366.472656" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="371.808243" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="374.473694" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="379.80928" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="404.863281" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="410.198868" y="1488.992188"/>
+ <use xlink:href="#glyph0-5" x="412.864319" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="418.199905" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="443.253906" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="448.589493" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="451.254944" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="456.59053" y="1488.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="372.808594" y="1501.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-2" x="259.015625" y="1402.375"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="259.015625" y="1399.042969"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="259.015625" y="1394.046875"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="259.015625" y="1388.046875"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-32" x="255.339844" y="1306.800781"/>
+ <use xlink:href="#glyph5-3" x="262.669922" y="1306.800781"/>
+ <use xlink:href="#glyph5-5" x="266.003906" y="1306.800781"/>
+ <use xlink:href="#glyph5-8" x="273.333984" y="1306.800781"/>
+ <use xlink:href="#glyph5-4" x="280.007812" y="1306.800781"/>
+ <use xlink:href="#glyph5-2" x="286.681641" y="1306.800781"/>
+</g>
+<g clip-path="url(#clip411)" clip-rule="nonzero">
+<path style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 474.667969 1512 L 712 1512 L 712 1296 L 474.667969 1296 Z "/>
+</g>
+<g clip-path="url(#clip412)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 528.683594 1475.027344 L 697.597656 1475.027344 L 697.597656 1310.398438 L 528.683594 1310.398438 Z "/>
+</g>
+<g clip-path="url(#clip413)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1448.839844 L 697.601562 1448.839844 "/>
+</g>
+<g clip-path="url(#clip414)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1411.421875 L 697.601562 1411.421875 "/>
+</g>
+<g clip-path="url(#clip415)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1374.007812 L 697.601562 1374.007812 "/>
+</g>
+<g clip-path="url(#clip416)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1336.589844 L 697.601562 1336.589844 "/>
+</g>
+<g clip-path="url(#clip417)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 555.558594 1475.027344 L 555.558594 1310.398438 "/>
+</g>
+<g clip-path="url(#clip418)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 593.949219 1475.027344 L 593.949219 1310.398438 "/>
+</g>
+<g clip-path="url(#clip419)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 632.335938 1475.027344 L 632.335938 1310.398438 "/>
+</g>
+<g clip-path="url(#clip420)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 670.726562 1475.027344 L 670.726562 1310.398438 "/>
+</g>
+<g clip-path="url(#clip421)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1467.546875 L 697.601562 1467.546875 "/>
+</g>
+<g clip-path="url(#clip422)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1430.128906 L 697.601562 1430.128906 "/>
+</g>
+<g clip-path="url(#clip423)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1392.714844 L 697.601562 1392.714844 "/>
+</g>
+<g clip-path="url(#clip424)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1355.296875 L 697.601562 1355.296875 "/>
+</g>
+<g clip-path="url(#clip425)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 528.683594 1317.882812 L 697.601562 1317.882812 "/>
+</g>
+<g clip-path="url(#clip426)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 1475.027344 L 536.363281 1310.398438 "/>
+</g>
+<g clip-path="url(#clip427)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 1475.027344 L 574.753906 1310.398438 "/>
+</g>
+<g clip-path="url(#clip428)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 1475.027344 L 613.140625 1310.398438 "/>
+</g>
+<g clip-path="url(#clip429)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 1475.027344 L 651.53125 1310.398438 "/>
+</g>
+<g clip-path="url(#clip430)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 1475.027344 L 689.921875 1310.398438 "/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph6-1" x="568.894531" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph8-1" x="576.769531" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph6-2" x="588.570312" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph8-2" x="602.742188" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph7-3" x="621.101562" y="1402.058594"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph6-3" x="643.21875" y="1402.058594"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1470.984375"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1470.984375"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="1470.984375"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="1470.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1433.566406"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1433.566406"/>
+ <use xlink:href="#glyph0-3" x="510.926819" y="1433.566406"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="1433.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1396.152344"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1396.152344"/>
+ <use xlink:href="#glyph0-4" x="510.926819" y="1396.152344"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="1396.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="502.925781" y="1358.734375"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1358.734375"/>
+ <use xlink:href="#glyph0-5" x="510.926819" y="1358.734375"/>
+ <use xlink:href="#glyph0-4" x="516.262405" y="1358.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="502.925781" y="1321.320312"/>
+ <use xlink:href="#glyph0-2" x="508.261368" y="1321.320312"/>
+ <use xlink:href="#glyph0-1" x="510.926819" y="1321.320312"/>
+ <use xlink:href="#glyph0-1" x="516.262405" y="1321.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1467.546875 L 528.683594 1467.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1430.128906 L 528.683594 1430.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1392.714844 L 528.683594 1392.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1355.296875 L 528.683594 1355.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 524.433594 1317.882812 L 528.683594 1317.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 536.363281 1479.28125 L 536.363281 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 574.753906 1479.28125 L 574.753906 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 613.140625 1479.28125 L 613.140625 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 651.53125 1479.28125 L 651.53125 1475.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 689.921875 1479.28125 L 689.921875 1475.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="527.027344" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="532.36293" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="535.028381" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="540.363968" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="565.417969" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="570.753555" y="1488.992188"/>
+ <use xlink:href="#glyph0-3" x="573.419006" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="578.754593" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="603.804688" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="609.140274" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="611.805725" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="617.141312" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="642.195312" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="647.530899" y="1488.992188"/>
+ <use xlink:href="#glyph0-5" x="650.19635" y="1488.992188"/>
+ <use xlink:href="#glyph0-4" x="655.531937" y="1488.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="680.585938" y="1488.992188"/>
+ <use xlink:href="#glyph0-2" x="685.921524" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="688.586975" y="1488.992188"/>
+ <use xlink:href="#glyph0-1" x="693.922562" y="1488.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="610.140625" y="1501.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-2" x="496.347656" y="1402.375"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="496.347656" y="1399.042969"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="496.347656" y="1394.046875"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="496.347656" y="1388.046875"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph5-17" x="500.667969" y="1306.800781"/>
+ <use xlink:href="#glyph5-15" x="509.333984" y="1306.800781"/>
+ <use xlink:href="#glyph5-5" x="516.664062" y="1306.800781"/>
+ <use xlink:href="#glyph5-18" x="523.994141" y="1306.800781"/>
+ <use xlink:href="#glyph5-24" x="530.667969" y="1306.800781"/>
+ <use xlink:href="#glyph5-4" x="534.664062" y="1306.800781"/>
+ <use xlink:href="#glyph5-5" x="541.337891" y="1306.800781"/>
+ <use xlink:href="#glyph5-24" x="548.667969" y="1306.800781"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/trapezoid.svg b/documentation/ui/figure/trapezoid.svg
new file mode 100644
index 0000000..4cd17a2
--- /dev/null
+++ b/documentation/ui/figure/trapezoid.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface186">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.839844 L 201.601562 152.839844 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.421875 L 201.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.007812 L 201.601562 78.007812 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.589844 L 201.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.128906 L 201.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 60.996094 170.347656 L 61.265625 169.144531 L 61.53125 167.945312 L 62.878906 161.949219 L 63.144531 160.75 L 63.414062 159.550781 L 63.683594 158.347656 L 64.492188 154.75 L 64.757812 153.550781 L 65.566406 149.953125 L 65.835938 148.75 L 66.105469 147.550781 L 66.371094 146.351562 L 67.71875 140.355469 L 67.984375 139.152344 L 69.332031 133.15625 L 69.597656 131.957031 L 69.867188 130.757812 L 70.136719 129.554688 L 70.945312 125.957031 L 71.210938 124.757812 L 72.019531 121.160156 L 72.289062 119.957031 L 72.558594 118.757812 L 72.824219 117.558594 L 73.902344 112.761719 L 74.167969 111.5625 L 74.4375 110.359375 L 75.515625 105.5625 L 75.78125 104.363281 L 76.320312 101.964844 L 76.589844 100.761719 L 77.128906 98.363281 L 77.394531 97.164062 L 78.472656 92.367188 L 78.742188 91.164062 L 79.007812 89.964844 L 80.355469 83.96875 L 80.621094 82.769531 L 80.890625 81.566406 L 81.96875 76.769531 L 82.234375 75.570312 L 82.773438 73.171875 L 83.042969 71.96875 L 83.582031 69.570312 L 83.847656 68.371094 L 85.195312 62.375 L 85.460938 61.171875 L 86.808594 55.175781 L 87.074219 53.976562 L 87.34375 52.777344 L 87.613281 51.574219 L 88.152344 49.175781 L 88.417969 47.976562 L 89.496094 43.179688 L 89.765625 41.976562 L 90.03125 40.777344 L 91.378906 34.78125 L 91.644531 33.582031 L 91.914062 32.378906 L 92.992188 27.582031 L 93.257812 26.382812 L 93.796875 23.984375 L 94.066406 22.78125 L 94.335938 21.882812 L 161.28125 21.882812 L 161.550781 22.78125 L 161.820312 23.984375 L 162.628906 27.582031 L 162.894531 28.78125 L 163.703125 32.378906 L 163.972656 33.582031 L 164.242188 34.78125 L 164.507812 35.980469 L 165.855469 41.976562 L 166.121094 43.179688 L 167.46875 49.175781 L 167.734375 50.375 L 168.003906 51.574219 L 168.273438 52.777344 L 169.082031 56.375 L 169.347656 57.574219 L 170.15625 61.171875 L 170.425781 62.375 L 170.695312 63.574219 L 170.960938 64.773438 L 172.308594 70.769531 L 172.574219 71.96875 L 172.84375 73.171875 L 173.921875 77.96875 L 174.1875 79.167969 L 174.726562 81.566406 L 174.996094 82.769531 L 175.535156 85.167969 L 175.800781 86.367188 L 176.878906 91.164062 L 177.144531 92.367188 L 178.492188 98.363281 L 178.757812 99.5625 L 179.027344 100.761719 L 179.296875 101.964844 L 180.105469 105.5625 L 180.371094 106.761719 L 181.179688 110.359375 L 181.449219 111.5625 L 181.71875 112.761719 L 181.984375 113.960938 L 183.332031 119.957031 L 183.597656 121.160156 L 184.945312 127.15625 L 185.210938 128.355469 L 185.480469 129.554688 L 185.75 130.757812 L 186.558594 134.355469 L 186.824219 135.554688 L 187.632812 139.152344 L 187.902344 140.355469 L 188.171875 141.554688 L 188.4375 142.753906 L 189.785156 148.75 L 190.050781 149.953125 L 191.128906 154.75 L 191.394531 155.949219 L 191.933594 158.347656 L 192.203125 159.550781 L 192.742188 161.949219 L 193.007812 163.148438 L 194.355469 169.144531 L 194.621094 170.347656 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.128906 L 54.019531 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/triangle.svg b/documentation/ui/figure/triangle.svg
new file mode 100644
index 0000000..fd3e09d
--- /dev/null
+++ b/documentation/ui/figure/triangle.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface181">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.800781 L 201.601562 152.800781 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.308594 L 201.601562 115.308594 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 77.820312 L 201.601562 77.820312 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.328125 L 201.601562 40.328125 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.054688 L 201.601562 134.054688 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.5625 L 201.601562 96.5625 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.074219 L 201.601562 59.074219 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.582031 L 201.601562 21.582031 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 171.546875 L 61.265625 170.34375 L 61.53125 169.742188 L 62.070312 168.539062 L 62.339844 167.941406 L 62.878906 166.738281 L 63.144531 166.136719 L 64.222656 163.730469 L 64.492188 163.132812 L 64.757812 162.53125 L 66.105469 159.523438 L 66.371094 158.921875 L 66.640625 158.324219 L 67.71875 155.917969 L 67.984375 155.316406 L 68.253906 154.714844 L 68.523438 154.117188 L 69.332031 152.3125 L 69.597656 151.710938 L 70.40625 149.90625 L 70.675781 149.308594 L 70.945312 148.707031 L 71.210938 148.105469 L 72.558594 145.097656 L 72.824219 144.5 L 73.902344 142.09375 L 74.167969 141.492188 L 74.707031 140.289062 L 74.976562 139.691406 L 75.515625 138.488281 L 75.78125 137.886719 L 76.589844 136.082031 L 76.859375 135.484375 L 77.128906 134.882812 L 77.394531 134.28125 L 78.742188 131.273438 L 79.007812 130.675781 L 80.355469 127.667969 L 80.621094 127.066406 L 80.890625 126.464844 L 81.160156 125.867188 L 81.96875 124.0625 L 82.234375 123.460938 L 82.773438 122.257812 L 83.042969 121.660156 L 83.582031 120.457031 L 83.847656 119.855469 L 84.925781 117.449219 L 85.195312 116.851562 L 85.460938 116.25 L 86.808594 113.242188 L 87.074219 112.640625 L 87.34375 112.042969 L 88.152344 110.238281 L 88.417969 109.636719 L 88.957031 108.433594 L 89.226562 107.835938 L 89.765625 106.632812 L 90.03125 106.03125 L 91.109375 103.625 L 91.378906 103.027344 L 91.644531 102.425781 L 92.992188 99.417969 L 93.257812 98.816406 L 93.527344 98.21875 L 94.605469 95.8125 L 94.871094 95.210938 L 95.410156 94.007812 L 95.679688 93.410156 L 96.21875 92.207031 L 96.484375 91.605469 L 97.292969 89.800781 L 97.5625 89.203125 L 97.832031 88.601562 L 98.097656 88 L 99.445312 84.992188 L 99.710938 84.394531 L 101.058594 81.386719 L 101.324219 80.785156 L 101.59375 80.183594 L 101.863281 79.585938 L 102.402344 78.382812 L 102.667969 77.78125 L 103.476562 75.976562 L 103.746094 75.378906 L 104.015625 74.777344 L 104.28125 74.175781 L 105.628906 71.167969 L 105.894531 70.570312 L 107.242188 67.5625 L 107.507812 66.960938 L 107.777344 66.359375 L 108.046875 65.761719 L 108.855469 63.957031 L 109.121094 63.355469 L 109.660156 62.152344 L 109.929688 61.554688 L 110.46875 60.351562 L 110.734375 59.75 L 111.8125 57.34375 L 112.082031 56.746094 L 112.347656 56.144531 L 113.695312 53.136719 L 113.960938 52.535156 L 114.230469 51.9375 L 115.308594 49.53125 L 115.574219 48.929688 L 116.113281 47.726562 L 116.382812 47.128906 L 116.921875 45.925781 L 117.1875 45.324219 L 117.996094 43.519531 L 118.265625 42.921875 L 118.53125 42.320312 L 119.878906 39.3125 L 120.144531 38.710938 L 120.414062 38.113281 L 121.492188 35.707031 L 121.757812 35.105469 L 122.296875 33.902344 L 122.566406 33.304688 L 123.105469 32.101562 L 123.371094 31.5 L 124.179688 29.695312 L 124.449219 29.097656 L 124.71875 28.496094 L 124.984375 27.894531 L 126.332031 24.886719 L 126.597656 24.289062 L 127.675781 21.882812 L 127.945312 21.882812 L 128.210938 22.484375 L 129.019531 24.289062 L 129.289062 24.886719 L 129.558594 25.488281 L 129.824219 26.089844 L 131.171875 29.097656 L 131.4375 29.695312 L 132.515625 32.101562 L 132.78125 32.703125 L 133.050781 33.304688 L 133.320312 33.902344 L 134.128906 35.707031 L 134.394531 36.308594 L 135.203125 38.113281 L 135.472656 38.710938 L 135.742188 39.3125 L 136.007812 39.914062 L 137.355469 42.921875 L 137.621094 43.519531 L 138.96875 46.527344 L 139.234375 47.128906 L 139.503906 47.726562 L 140.582031 50.132812 L 140.847656 50.734375 L 141.386719 51.9375 L 141.65625 52.535156 L 142.195312 53.738281 L 142.460938 54.339844 L 143.539062 56.746094 L 143.808594 57.34375 L 144.074219 57.945312 L 145.421875 60.953125 L 145.6875 61.554688 L 145.957031 62.152344 L 146.765625 63.957031 L 147.03125 64.558594 L 147.570312 65.761719 L 147.839844 66.359375 L 148.378906 67.5625 L 148.644531 68.164062 L 149.722656 70.570312 L 149.992188 71.167969 L 150.257812 71.769531 L 151.605469 74.777344 L 151.871094 75.378906 L 152.140625 75.976562 L 153.21875 78.382812 L 153.484375 78.984375 L 153.753906 79.585938 L 154.023438 80.183594 L 154.832031 81.988281 L 155.097656 82.589844 L 155.90625 84.394531 L 156.175781 84.992188 L 156.445312 85.59375 L 156.710938 86.195312 L 158.058594 89.203125 L 158.324219 89.800781 L 159.671875 92.808594 L 159.9375 93.410156 L 160.207031 94.007812 L 161.015625 95.8125 L 161.28125 96.414062 L 162.089844 98.21875 L 162.359375 98.816406 L 162.628906 99.417969 L 162.894531 100.019531 L 164.242188 103.027344 L 164.507812 103.625 L 165.855469 106.632812 L 166.121094 107.234375 L 166.390625 107.835938 L 166.660156 108.433594 L 167.46875 110.238281 L 167.734375 110.839844 L 168.273438 112.042969 L 168.542969 112.640625 L 169.082031 113.84375 L 169.347656 114.445312 L 170.425781 116.851562 L 170.695312 117.449219 L 170.960938 118.050781 L 172.308594 121.058594 L 172.574219 121.660156 L 172.84375 122.257812 L 173.921875 124.664062 L 174.1875 125.265625 L 174.457031 125.867188 L 174.726562 126.464844 L 175.535156 128.269531 L 175.800781 128.871094 L 176.609375 130.675781 L 176.878906 131.273438 L 177.144531 131.875 L 178.492188 134.882812 L 178.757812 135.484375 L 179.027344 136.082031 L 180.105469 138.488281 L 180.371094 139.089844 L 180.640625 139.691406 L 180.910156 140.289062 L 181.71875 142.09375 L 181.984375 142.695312 L 182.792969 144.5 L 183.0625 145.097656 L 183.332031 145.699219 L 183.597656 146.300781 L 184.945312 149.308594 L 185.210938 149.90625 L 186.558594 152.914062 L 186.824219 153.515625 L 187.09375 154.117188 L 187.363281 154.714844 L 188.171875 156.519531 L 188.4375 157.121094 L 188.976562 158.324219 L 189.246094 158.921875 L 189.785156 160.125 L 190.050781 160.726562 L 191.128906 163.132812 L 191.394531 163.730469 L 192.742188 166.738281 L 193.007812 167.339844 L 193.277344 167.941406 L 193.546875 168.539062 L 194.355469 170.34375 L 194.621094 170.945312 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.492188"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.492188"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.492188"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.492188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.511719"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.511719"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.511719"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.511719"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.019531"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.019531"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.019531"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.019531"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.054688 L 54.019531 134.054688 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.5625 L 54.019531 96.5625 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.074219 L 54.019531 59.074219 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.582031 L 54.019531 21.582031 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/figure/zShape.svg b/documentation/ui/figure/zShape.svg
new file mode 100644
index 0000000..40b41b3
--- /dev/null
+++ b/documentation/ui/figure/zShape.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216pt" height="216pt" viewBox="0 0 216 216" version="1.1">
+<defs>
+<g>
+<symbol overflow="visible" id="glyph0-0">
+<path style="stroke:none;" d="M 0.3125 0 L 0.3125 -6.875 L 5.765625 -6.875 L 5.765625 0 Z M 4.90625 -0.859375 L 4.90625 -6.015625 L 1.171875 -6.015625 L 1.171875 -0.859375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-1">
+<path style="stroke:none;" d="M 2.59375 -6.703125 C 3.457031 -6.703125 4.085938 -6.347656 4.484375 -5.640625 C 4.773438 -5.085938 4.921875 -4.328125 4.921875 -3.359375 C 4.921875 -2.453125 4.785156 -1.695312 4.515625 -1.09375 C 4.128906 -0.238281 3.488281 0.1875 2.59375 0.1875 C 1.78125 0.1875 1.179688 -0.160156 0.796875 -0.859375 C 0.460938 -1.453125 0.296875 -2.238281 0.296875 -3.21875 C 0.296875 -3.976562 0.394531 -4.632812 0.59375 -5.1875 C 0.957031 -6.195312 1.625 -6.703125 2.59375 -6.703125 Z M 2.578125 -0.578125 C 3.015625 -0.578125 3.363281 -0.769531 3.625 -1.15625 C 3.882812 -1.550781 4.015625 -2.273438 4.015625 -3.328125 C 4.015625 -4.085938 3.921875 -4.710938 3.734375 -5.203125 C 3.546875 -5.703125 3.179688 -5.953125 2.640625 -5.953125 C 2.148438 -5.953125 1.789062 -5.71875 1.5625 -5.25 C 1.332031 -4.78125 1.21875 -4.09375 1.21875 -3.1875 C 1.21875 -2.5 1.289062 -1.945312 1.4375 -1.53125 C 1.65625 -0.894531 2.035156 -0.578125 2.578125 -0.578125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-2">
+<path style="stroke:none;" d="M 0.8125 -1.015625 L 1.796875 -1.015625 L 1.796875 0 L 0.8125 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-3">
+<path style="stroke:none;" d="M 0.296875 0 C 0.328125 -0.570312 0.445312 -1.070312 0.65625 -1.5 C 0.863281 -1.9375 1.269531 -2.328125 1.875 -2.671875 L 2.765625 -3.1875 C 3.171875 -3.425781 3.457031 -3.628906 3.625 -3.796875 C 3.875 -4.054688 4 -4.351562 4 -4.6875 C 4 -5.070312 3.878906 -5.378906 3.640625 -5.609375 C 3.410156 -5.835938 3.101562 -5.953125 2.71875 -5.953125 C 2.132812 -5.953125 1.734375 -5.734375 1.515625 -5.296875 C 1.398438 -5.066406 1.335938 -4.742188 1.328125 -4.328125 L 0.46875 -4.328125 C 0.476562 -4.910156 0.582031 -5.382812 0.78125 -5.75 C 1.144531 -6.40625 1.789062 -6.734375 2.71875 -6.734375 C 3.488281 -6.734375 4.050781 -6.523438 4.40625 -6.109375 C 4.757812 -5.691406 4.9375 -5.226562 4.9375 -4.71875 C 4.9375 -4.1875 4.75 -3.726562 4.375 -3.34375 C 4.15625 -3.125 3.757812 -2.851562 3.1875 -2.53125 L 2.546875 -2.1875 C 2.242188 -2.019531 2.003906 -1.859375 1.828125 -1.703125 C 1.515625 -1.429688 1.316406 -1.128906 1.234375 -0.796875 L 4.90625 -0.796875 L 4.90625 0 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-4">
+<path style="stroke:none;" d="M 1.1875 -1.703125 C 1.238281 -1.222656 1.460938 -0.894531 1.859375 -0.71875 C 2.054688 -0.625 2.285156 -0.578125 2.546875 -0.578125 C 3.046875 -0.578125 3.414062 -0.734375 3.65625 -1.046875 C 3.894531 -1.367188 4.015625 -1.722656 4.015625 -2.109375 C 4.015625 -2.578125 3.867188 -2.9375 3.578125 -3.1875 C 3.296875 -3.445312 2.957031 -3.578125 2.5625 -3.578125 C 2.269531 -3.578125 2.019531 -3.519531 1.8125 -3.40625 C 1.601562 -3.289062 1.425781 -3.132812 1.28125 -2.9375 L 0.546875 -2.984375 L 1.0625 -6.59375 L 4.546875 -6.59375 L 4.546875 -5.78125 L 1.703125 -5.78125 L 1.40625 -3.921875 C 1.5625 -4.035156 1.710938 -4.125 1.859375 -4.1875 C 2.109375 -4.289062 2.394531 -4.34375 2.71875 -4.34375 C 3.332031 -4.34375 3.851562 -4.140625 4.28125 -3.734375 C 4.707031 -3.335938 4.921875 -2.835938 4.921875 -2.234375 C 4.921875 -1.597656 4.722656 -1.035156 4.328125 -0.546875 C 3.941406 -0.0664062 3.320312 0.171875 2.46875 0.171875 C 1.914062 0.171875 1.429688 0.0195312 1.015625 -0.28125 C 0.597656 -0.59375 0.363281 -1.066406 0.3125 -1.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-5">
+<path style="stroke:none;" d="M 5.015625 -6.59375 L 5.015625 -5.859375 C 4.796875 -5.648438 4.507812 -5.285156 4.15625 -4.765625 C 3.800781 -4.242188 3.484375 -3.6875 3.203125 -3.09375 C 2.929688 -2.507812 2.726562 -1.976562 2.59375 -1.5 C 2.5 -1.1875 2.378906 -0.6875 2.234375 0 L 1.3125 0 C 1.519531 -1.28125 1.988281 -2.554688 2.71875 -3.828125 C 3.144531 -4.566406 3.59375 -5.207031 4.0625 -5.75 L 0.34375 -5.75 L 0.34375 -6.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph0-6">
+<path style="stroke:none;" d="M 0.921875 -4.75 L 0.921875 -5.390625 C 1.523438 -5.453125 1.945312 -5.550781 2.1875 -5.6875 C 2.425781 -5.832031 2.609375 -6.164062 2.734375 -6.6875 L 3.390625 -6.6875 L 3.390625 0 L 2.5 0 L 2.5 -4.75 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-0">
+<path style="stroke:none;" d="M 0.390625 0 L 0.390625 -8.609375 L 7.21875 -8.609375 L 7.21875 0 Z M 6.140625 -1.078125 L 6.140625 -7.53125 L 1.46875 -7.53125 L 1.46875 -1.078125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph1-1">
+<path style="stroke:none;" d="M 0.171875 -6.28125 L 1.546875 -6.28125 L 2.984375 -4.0625 L 4.4375 -6.28125 L 5.71875 -6.25 L 3.609375 -3.21875 L 5.8125 0 L 4.46875 0 L 2.90625 -2.359375 L 1.40625 0 L 0.0625 0 L 2.28125 -3.21875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-0">
+<path style="stroke:none;" d="M 2.125 -0.59375 L -8.46875 -0.59375 L -8.46875 -6.59375 L 2.125 -6.59375 Z M 1.453125 -1.265625 L 1.453125 -5.9375 L -7.78125 -5.9375 L -7.78125 -1.265625 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph2-1">
+<path style="stroke:none;" d="M -1.828125 -2 C -1.265625 -2 -0.882812 -2.050781 -0.6875 -2.15625 C -0.5 -2.269531 -0.40625 -2.472656 -0.40625 -2.765625 C -0.40625 -3.222656 -0.726562 -3.601562 -1.375 -3.90625 C -2.019531 -4.207031 -2.835938 -4.359375 -3.828125 -4.359375 L -5.390625 -4.359375 L -5.390625 -5.46875 L -1.453125 -5.46875 C -1.097656 -5.46875 -0.832031 -5.503906 -0.65625 -5.578125 C -0.488281 -5.648438 -0.40625 -5.765625 -0.40625 -5.921875 C -0.40625 -6.085938 -0.488281 -6.210938 -0.65625 -6.296875 C -0.820312 -6.390625 -1.066406 -6.4375 -1.390625 -6.4375 L -1.5625 -6.4375 L -1.5625 -6.6875 C -1.53125 -6.6875 -1.492188 -6.6875 -1.453125 -6.6875 C -1.421875 -6.695312 -1.367188 -6.703125 -1.296875 -6.703125 C -0.847656 -6.703125 -0.5 -6.601562 -0.25 -6.40625 C -0.0078125 -6.21875 0.109375 -5.953125 0.109375 -5.609375 C 0.109375 -5.210938 -0.0625 -4.910156 -0.40625 -4.703125 C -0.75 -4.503906 -1.265625 -4.398438 -1.953125 -4.390625 C -1.242188 -4.210938 -0.722656 -3.96875 -0.390625 -3.65625 C -0.0546875 -3.351562 0.109375 -2.96875 0.109375 -2.5 C 0.109375 -2.144531 0.00390625 -1.851562 -0.203125 -1.625 C -0.410156 -1.394531 -0.71875 -1.234375 -1.125 -1.140625 C -1.050781 -1.128906 -0.941406 -1.125 -0.796875 -1.125 C -0.285156 -1.125 0.273438 -1.253906 0.890625 -1.515625 C 1.515625 -1.773438 1.882812 -1.90625 2 -1.90625 C 2.15625 -1.90625 2.28125 -1.859375 2.375 -1.765625 C 2.46875 -1.671875 2.515625 -1.546875 2.515625 -1.390625 C 2.515625 -1.210938 2.445312 -1.082031 2.3125 -1 C 2.175781 -0.914062 1.960938 -0.875 1.671875 -0.875 C 1.597656 -0.875 1.363281 -0.878906 0.96875 -0.890625 C 0.582031 -0.910156 0.226562 -0.921875 -0.09375 -0.921875 C -0.382812 -0.921875 -0.789062 -0.914062 -1.3125 -0.90625 C -1.832031 -0.894531 -2.210938 -0.890625 -2.453125 -0.890625 L -5.390625 -0.890625 L -5.390625 -2 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-0">
+<path style="stroke:none;" d="M 2.65625 -0.75 L -10.578125 -0.75 L -10.578125 -8.25 L 2.65625 -8.25 Z M 1.8125 -1.59375 L 1.8125 -7.40625 L -9.734375 -7.40625 L -9.734375 -1.59375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-1">
+<path style="stroke:none;" d="M -10.546875 -4.296875 C -9.796875 -3.460938 -8.925781 -2.867188 -7.9375 -2.515625 C -6.945312 -2.171875 -5.617188 -2 -3.953125 -2 C -2.273438 -2 -0.945312 -2.171875 0.03125 -2.515625 C 1.019531 -2.867188 1.890625 -3.460938 2.640625 -4.296875 L 2.953125 -3.984375 C 2.191406 -2.953125 1.203125 -2.144531 -0.015625 -1.5625 C -1.234375 -0.976562 -2.546875 -0.6875 -3.953125 -0.6875 C -5.359375 -0.6875 -6.671875 -0.976562 -7.890625 -1.5625 C -9.117188 -2.15625 -10.109375 -2.960938 -10.859375 -3.984375 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph3-2">
+<path style="stroke:none;" d="M -10.546875 -0.703125 L -10.859375 -0.984375 C -10.109375 -2.023438 -9.117188 -2.835938 -7.890625 -3.421875 C -6.660156 -4.015625 -5.347656 -4.3125 -3.953125 -4.3125 C -2.546875 -4.3125 -1.234375 -4.015625 -0.015625 -3.421875 C 1.203125 -2.835938 2.191406 -2.023438 2.953125 -0.984375 L 2.640625 -0.703125 C 1.898438 -1.535156 1.035156 -2.125 0.046875 -2.46875 C -0.929688 -2.820312 -2.265625 -3 -3.953125 -3 C -5.628906 -3 -6.957031 -2.820312 -7.9375 -2.46875 C -8.925781 -2.125 -9.796875 -1.535156 -10.546875 -0.703125 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-0">
+<path style="stroke:none;" d="M 0 -0.390625 L -8.609375 -0.390625 L -8.609375 -7.21875 L 0 -7.21875 Z M -1.078125 -6.140625 L -7.53125 -6.140625 L -7.53125 -1.46875 L -1.078125 -1.46875 Z "/>
+</symbol>
+<symbol overflow="visible" id="glyph4-1">
+<path style="stroke:none;" d="M -6.28125 -0.171875 L -6.28125 -1.546875 L -4.0625 -2.984375 L -6.28125 -4.4375 L -6.25 -5.71875 L -3.21875 -3.609375 L 0 -5.8125 L 0 -4.46875 L -2.359375 -2.90625 L 0 -1.40625 L 0 -0.0625 L -3.21875 -2.28125 Z "/>
+</symbol>
+</g>
+<clipPath id="clip1">
+ <path d="M 54.019531 14.398438 L 202 14.398438 L 202 180 L 54.019531 180 Z "/>
+</clipPath>
+<clipPath id="clip2">
+ <path d="M 54.019531 152 L 202 152 L 202 154 L 54.019531 154 Z "/>
+</clipPath>
+<clipPath id="clip3">
+ <path d="M 54.019531 115 L 202 115 L 202 116 L 54.019531 116 Z "/>
+</clipPath>
+<clipPath id="clip4">
+ <path d="M 54.019531 77 L 202 77 L 202 79 L 54.019531 79 Z "/>
+</clipPath>
+<clipPath id="clip5">
+ <path d="M 54.019531 40 L 202 40 L 202 41 L 54.019531 41 Z "/>
+</clipPath>
+<clipPath id="clip6">
+ <path d="M 77 14.398438 L 78 14.398438 L 78 180 L 77 180 Z "/>
+</clipPath>
+<clipPath id="clip7">
+ <path d="M 110 14.398438 L 112 14.398438 L 112 180 L 110 180 Z "/>
+</clipPath>
+<clipPath id="clip8">
+ <path d="M 144 14.398438 L 145 14.398438 L 145 180 L 144 180 Z "/>
+</clipPath>
+<clipPath id="clip9">
+ <path d="M 177 14.398438 L 179 14.398438 L 179 180 L 177 180 Z "/>
+</clipPath>
+<clipPath id="clip10">
+ <path d="M 54.019531 171 L 202.601562 171 L 202.601562 173 L 54.019531 173 Z "/>
+</clipPath>
+<clipPath id="clip11">
+ <path d="M 54.019531 133 L 202.601562 133 L 202.601562 135 L 54.019531 135 Z "/>
+</clipPath>
+<clipPath id="clip12">
+ <path d="M 54.019531 96 L 202.601562 96 L 202.601562 98 L 54.019531 98 Z "/>
+</clipPath>
+<clipPath id="clip13">
+ <path d="M 54.019531 58 L 202.601562 58 L 202.601562 60 L 54.019531 60 Z "/>
+</clipPath>
+<clipPath id="clip14">
+ <path d="M 54.019531 21 L 202.601562 21 L 202.601562 23 L 54.019531 23 Z "/>
+</clipPath>
+<clipPath id="clip15">
+ <path d="M 60 14.398438 L 62 14.398438 L 62 180 L 60 180 Z "/>
+</clipPath>
+<clipPath id="clip16">
+ <path d="M 93 14.398438 L 95 14.398438 L 95 180 L 93 180 Z "/>
+</clipPath>
+<clipPath id="clip17">
+ <path d="M 127 14.398438 L 129 14.398438 L 129 180 L 127 180 Z "/>
+</clipPath>
+<clipPath id="clip18">
+ <path d="M 160 14.398438 L 162 14.398438 L 162 180 L 160 180 Z "/>
+</clipPath>
+<clipPath id="clip19">
+ <path d="M 194 14.398438 L 196 14.398438 L 196 180 L 194 180 Z "/>
+</clipPath>
+</defs>
+<g id="surface266">
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<rect x="0" y="0" width="216" height="216" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 216 L 216 216 L 216 0 L 0 0 Z "/>
+<g clip-path="url(#clip1)" clip-rule="nonzero">
+<path style=" stroke:none;fill-rule:nonzero;fill:rgb(89.803922%,89.803922%,89.803922%);fill-opacity:1;" d="M 54.019531 179.027344 L 201.601562 179.027344 L 201.601562 14.398438 L 54.019531 14.398438 Z "/>
+</g>
+<g clip-path="url(#clip2)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 152.839844 L 201.601562 152.839844 "/>
+</g>
+<g clip-path="url(#clip3)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 115.421875 L 201.601562 115.421875 "/>
+</g>
+<g clip-path="url(#clip4)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 78.007812 L 201.601562 78.007812 "/>
+</g>
+<g clip-path="url(#clip5)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 40.589844 L 201.601562 40.589844 "/>
+</g>
+<g clip-path="url(#clip6)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 77.496094 179.027344 L 77.496094 14.398438 "/>
+</g>
+<g clip-path="url(#clip7)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.039062 179.027344 L 111.039062 14.398438 "/>
+</g>
+<g clip-path="url(#clip8)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 144.578125 179.027344 L 144.578125 14.398438 "/>
+</g>
+<g clip-path="url(#clip9)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:0.531496;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(94.901961%,94.901961%,94.901961%);stroke-opacity:1;stroke-miterlimit:10;" d="M 178.121094 179.027344 L 178.121094 14.398438 "/>
+</g>
+<g clip-path="url(#clip10)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 171.546875 L 201.601562 171.546875 "/>
+</g>
+<g clip-path="url(#clip11)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 134.128906 L 201.601562 134.128906 "/>
+</g>
+<g clip-path="url(#clip12)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 96.714844 L 201.601562 96.714844 "/>
+</g>
+<g clip-path="url(#clip13)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 59.296875 L 201.601562 59.296875 "/>
+</g>
+<g clip-path="url(#clip14)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 54.019531 21.882812 L 201.601562 21.882812 "/>
+</g>
+<g clip-path="url(#clip15)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 179.027344 L 60.726562 14.398438 "/>
+</g>
+<g clip-path="url(#clip16)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 179.027344 L 94.269531 14.398438 "/>
+</g>
+<g clip-path="url(#clip17)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 179.027344 L 127.808594 14.398438 "/>
+</g>
+<g clip-path="url(#clip18)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 179.027344 L 161.351562 14.398438 "/>
+</g>
+<g clip-path="url(#clip19)" clip-rule="nonzero">
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(100%,100%,100%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 179.027344 L 194.890625 14.398438 "/>
+</g>
+<path style="fill:none;stroke-width:7.440945;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:1;" d="M 60.726562 21.882812 L 60.996094 21.882812 L 61.265625 21.886719 L 61.53125 21.894531 L 61.800781 21.902344 L 62.339844 21.925781 L 62.609375 21.941406 L 62.878906 21.960938 L 63.144531 21.980469 L 63.683594 22.027344 L 63.953125 22.054688 L 64.492188 22.117188 L 64.757812 22.152344 L 65.296875 22.230469 L 65.835938 22.316406 L 66.105469 22.363281 L 66.371094 22.414062 L 66.640625 22.464844 L 67.179688 22.574219 L 67.449219 22.632812 L 67.71875 22.695312 L 67.984375 22.757812 L 68.253906 22.824219 L 68.792969 22.964844 L 69.332031 23.113281 L 69.597656 23.191406 L 70.136719 23.355469 L 70.675781 23.527344 L 70.945312 23.617188 L 71.210938 23.710938 L 71.480469 23.804688 L 71.75 23.902344 L 72.289062 24.105469 L 72.558594 24.210938 L 72.824219 24.316406 L 73.09375 24.425781 L 73.632812 24.652344 L 73.902344 24.769531 L 74.167969 24.886719 L 74.4375 25.011719 L 74.707031 25.132812 L 74.976562 25.261719 L 75.246094 25.386719 L 75.515625 25.519531 L 75.78125 25.652344 L 76.320312 25.925781 L 76.589844 26.066406 L 77.128906 26.355469 L 77.394531 26.503906 L 77.664062 26.652344 L 77.933594 26.808594 L 78.203125 26.960938 L 78.742188 27.28125 L 79.007812 27.441406 L 79.277344 27.605469 L 79.816406 27.941406 L 80.085938 28.113281 L 80.355469 28.289062 L 80.621094 28.464844 L 80.890625 28.644531 L 81.699219 29.195312 L 81.96875 29.386719 L 82.234375 29.578125 L 82.503906 29.769531 L 82.773438 29.964844 L 83.3125 30.363281 L 83.582031 30.566406 L 83.847656 30.773438 L 84.117188 30.980469 L 84.386719 31.191406 L 85.195312 31.835938 L 85.460938 32.058594 L 86 32.503906 L 86.269531 32.730469 L 86.539062 32.960938 L 86.808594 33.195312 L 87.074219 33.429688 L 87.34375 33.664062 L 87.613281 33.902344 L 87.882812 34.144531 L 88.152344 34.390625 L 88.417969 34.636719 L 88.957031 35.136719 L 89.496094 35.644531 L 89.765625 35.90625 L 90.03125 36.164062 L 90.839844 36.960938 L 91.109375 37.234375 L 91.378906 37.503906 L 91.644531 37.78125 L 91.914062 38.058594 L 92.453125 38.621094 L 92.722656 38.90625 L 92.992188 39.195312 L 93.257812 39.484375 L 93.527344 39.773438 L 94.066406 40.367188 L 94.605469 40.96875 L 94.871094 41.273438 L 95.140625 41.578125 L 95.410156 41.886719 L 95.949219 42.511719 L 96.21875 42.828125 L 96.484375 43.148438 L 96.753906 43.46875 L 97.292969 44.117188 L 97.5625 44.445312 L 97.832031 44.777344 L 98.097656 45.109375 L 98.636719 45.78125 L 98.90625 46.121094 L 99.445312 46.808594 L 99.710938 47.15625 L 100.25 47.859375 L 100.789062 48.570312 L 101.058594 48.929688 L 101.324219 49.292969 L 101.59375 49.65625 L 102.132812 50.390625 L 102.402344 50.765625 L 102.667969 51.136719 L 102.9375 51.515625 L 103.207031 51.890625 L 103.746094 52.65625 L 104.015625 53.042969 L 104.28125 53.429688 L 104.550781 53.820312 L 105.089844 54.609375 L 105.359375 55.007812 L 105.628906 55.410156 L 105.894531 55.8125 L 106.164062 56.214844 L 106.972656 57.445312 L 107.242188 57.859375 L 107.507812 58.277344 L 108.316406 59.542969 L 108.585938 59.96875 L 108.855469 60.398438 L 109.121094 60.832031 L 109.390625 61.265625 L 109.929688 62.140625 L 110.46875 63.023438 L 110.734375 63.472656 L 111.003906 63.917969 L 111.8125 65.277344 L 112.082031 65.738281 L 112.347656 66.199219 L 112.617188 66.660156 L 112.886719 67.125 L 113.425781 68.0625 L 113.695312 68.535156 L 113.960938 69.011719 L 114.230469 69.488281 L 114.769531 70.449219 L 115.039062 70.933594 L 115.308594 71.421875 L 115.574219 71.910156 L 116.113281 72.894531 L 116.382812 73.390625 L 116.921875 74.390625 L 117.1875 74.894531 L 117.726562 75.910156 L 118.265625 76.933594 L 118.53125 77.449219 L 119.070312 78.488281 L 119.339844 79.011719 L 119.878906 80.066406 L 120.144531 80.59375 L 120.953125 82.199219 L 121.222656 82.738281 L 121.492188 83.28125 L 121.757812 83.828125 L 122.296875 84.921875 L 122.566406 85.472656 L 122.835938 86.027344 L 123.105469 86.585938 L 123.371094 87.144531 L 123.910156 88.269531 L 124.449219 89.402344 L 124.71875 89.976562 L 124.984375 90.546875 L 125.523438 91.703125 L 126.0625 92.867188 L 126.332031 93.453125 L 126.597656 94.039062 L 126.867188 94.628906 L 127.40625 95.816406 L 127.675781 96.414062 L 127.945312 97.015625 L 128.210938 97.613281 L 128.75 98.800781 L 129.019531 99.390625 L 129.558594 100.5625 L 129.824219 101.144531 L 130.09375 101.726562 L 130.363281 102.304688 L 130.902344 103.453125 L 131.171875 104.023438 L 131.4375 104.59375 L 131.707031 105.160156 L 132.246094 106.285156 L 132.515625 106.84375 L 132.78125 107.398438 L 133.320312 108.507812 L 134.128906 110.148438 L 134.394531 110.6875 L 134.664062 111.230469 L 135.203125 112.300781 L 135.742188 113.363281 L 136.007812 113.890625 L 136.277344 114.417969 L 136.546875 114.941406 L 137.085938 115.980469 L 137.355469 116.496094 L 137.621094 117.007812 L 137.890625 117.519531 L 138.160156 118.027344 L 138.96875 119.539062 L 139.234375 120.035156 L 139.503906 120.535156 L 140.042969 121.519531 L 140.582031 122.496094 L 140.847656 122.980469 L 141.386719 123.941406 L 141.925781 124.894531 L 142.195312 125.367188 L 142.460938 125.835938 L 142.730469 126.304688 L 143 126.769531 L 143.539062 127.691406 L 143.808594 128.148438 L 144.074219 128.605469 L 144.34375 129.058594 L 144.882812 129.957031 L 145.421875 130.847656 L 145.6875 131.289062 L 146.226562 132.164062 L 146.496094 132.597656 L 146.765625 133.027344 L 147.03125 133.457031 L 147.300781 133.886719 L 148.109375 135.152344 L 148.378906 135.566406 L 148.644531 135.984375 L 149.183594 136.804688 L 149.722656 137.617188 L 149.992188 138.019531 L 150.257812 138.421875 L 150.527344 138.820312 L 150.796875 139.214844 L 151.605469 140.386719 L 151.871094 140.773438 L 152.140625 141.15625 L 152.949219 142.292969 L 153.21875 142.664062 L 153.484375 143.035156 L 153.753906 143.40625 L 154.023438 143.773438 L 154.5625 144.5 L 154.832031 144.859375 L 155.097656 145.214844 L 155.367188 145.570312 L 155.90625 146.273438 L 156.175781 146.617188 L 156.445312 146.964844 L 156.710938 147.304688 L 156.980469 147.648438 L 157.519531 148.320312 L 158.058594 148.984375 L 158.324219 149.3125 L 158.863281 149.960938 L 159.402344 150.601562 L 159.671875 150.917969 L 159.9375 151.230469 L 160.207031 151.542969 L 160.476562 151.851562 L 161.015625 152.460938 L 161.28125 152.761719 L 161.550781 153.0625 L 161.820312 153.359375 L 162.359375 153.945312 L 162.628906 154.234375 L 162.894531 154.523438 L 163.164062 154.808594 L 163.703125 155.371094 L 163.972656 155.648438 L 164.242188 155.921875 L 164.507812 156.195312 L 165.046875 156.734375 L 165.316406 157 L 165.855469 157.523438 L 166.121094 157.78125 L 166.390625 158.039062 L 166.660156 158.292969 L 167.199219 158.792969 L 167.46875 159.039062 L 167.734375 159.28125 L 168.273438 159.765625 L 169.082031 160.46875 L 169.347656 160.695312 L 169.617188 160.925781 L 170.15625 161.371094 L 170.695312 161.808594 L 170.960938 162.023438 L 171.230469 162.238281 L 171.5 162.445312 L 171.769531 162.65625 L 172.308594 163.0625 L 172.574219 163.265625 L 172.84375 163.464844 L 173.113281 163.660156 L 173.652344 164.042969 L 173.921875 164.230469 L 174.1875 164.417969 L 174.726562 164.785156 L 174.996094 164.964844 L 175.265625 165.140625 L 175.535156 165.3125 L 175.800781 165.484375 L 176.070312 165.65625 L 176.339844 165.824219 L 176.609375 165.988281 L 176.878906 166.148438 L 177.144531 166.308594 L 177.414062 166.46875 L 178.222656 166.925781 L 178.492188 167.074219 L 178.757812 167.21875 L 179.027344 167.363281 L 179.296875 167.503906 L 179.835938 167.777344 L 180.105469 167.910156 L 180.371094 168.039062 L 180.910156 168.296875 L 181.71875 168.660156 L 181.984375 168.777344 L 182.523438 169.003906 L 182.792969 169.113281 L 183.332031 169.324219 L 183.597656 169.425781 L 184.40625 169.71875 L 184.945312 169.898438 L 185.210938 169.988281 L 185.480469 170.074219 L 186.019531 170.238281 L 186.289062 170.316406 L 186.558594 170.390625 L 186.824219 170.464844 L 187.09375 170.535156 L 187.902344 170.734375 L 188.171875 170.792969 L 188.4375 170.851562 L 188.707031 170.910156 L 188.976562 170.964844 L 189.515625 171.066406 L 189.785156 171.113281 L 190.050781 171.15625 L 190.320312 171.199219 L 190.859375 171.277344 L 191.128906 171.308594 L 191.394531 171.34375 L 191.664062 171.371094 L 191.933594 171.402344 L 192.472656 171.449219 L 192.742188 171.46875 L 193.007812 171.488281 L 193.277344 171.503906 L 193.816406 171.527344 L 194.355469 171.542969 L 194.621094 171.542969 L 194.890625 171.546875 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="174.984375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="174.984375"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="174.984375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="137.566406"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="137.566406"/>
+ <use xlink:href="#glyph0-3" x="36.25885" y="137.566406"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="137.566406"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="100.152344"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="100.152344"/>
+ <use xlink:href="#glyph0-4" x="36.25885" y="100.152344"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="100.152344"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="28.257812" y="62.734375"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="62.734375"/>
+ <use xlink:href="#glyph0-5" x="36.25885" y="62.734375"/>
+ <use xlink:href="#glyph0-4" x="41.594437" y="62.734375"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="28.257812" y="25.320312"/>
+ <use xlink:href="#glyph0-2" x="33.593399" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="36.25885" y="25.320312"/>
+ <use xlink:href="#glyph0-1" x="41.594437" y="25.320312"/>
+</g>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 171.546875 L 54.019531 171.546875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 134.128906 L 54.019531 134.128906 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 96.714844 L 54.019531 96.714844 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 59.296875 L 54.019531 59.296875 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 49.765625 21.882812 L 54.019531 21.882812 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 60.726562 183.28125 L 60.726562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 94.269531 183.28125 L 94.269531 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 127.808594 183.28125 L 127.808594 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 161.351562 183.28125 L 161.351562 179.027344 "/>
+<path style="fill:none;stroke-width:1.062992;stroke-linecap:butt;stroke-linejoin:round;stroke:rgb(49.803922%,49.803922%,49.803922%);stroke-opacity:1;stroke-miterlimit:10;" d="M 194.890625 183.28125 L 194.890625 179.027344 "/>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="51.390625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="56.726212" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="59.391663" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="64.727249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="84.933594" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="90.26918" y="192.992188"/>
+ <use xlink:href="#glyph0-3" x="92.934631" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="98.270218" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="118.472656" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="123.808243" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="126.473694" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="131.80928" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-1" x="152.015625" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="157.351212" y="192.992188"/>
+ <use xlink:href="#glyph0-5" x="160.016663" y="192.992188"/>
+ <use xlink:href="#glyph0-4" x="165.352249" y="192.992188"/>
+</g>
+<g style="fill:rgb(49.803922%,49.803922%,49.803922%);fill-opacity:1;">
+ <use xlink:href="#glyph0-6" x="185.554688" y="192.992188"/>
+ <use xlink:href="#glyph0-2" x="190.890274" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="193.555725" y="192.992188"/>
+ <use xlink:href="#glyph0-1" x="198.891312" y="192.992188"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph1-1" x="124.808594" y="205.199219"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph2-1" x="21.660156" y="108.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-1" x="21.660156" y="101.210938"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph4-1" x="21.660156" y="96.214844"/>
+</g>
+<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
+ <use xlink:href="#glyph3-2" x="21.660156" y="90.214844"/>
+</g>
+</g>
+</svg>
diff --git a/documentation/ui/footer.html b/documentation/ui/footer.html
new file mode 100644
index 0000000..2a56075
--- /dev/null
+++ b/documentation/ui/footer.html
@@ -0,0 +1,22 @@
+<!-- HTML footer for doxygen 1.8.11-->
+<!-- start footer part -->
+<!--BEGIN GENERATE_TREEVIEW-->
+<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+ <ul>
+ $navpath
+ <li>Copyright © 2010-2017 FuzzyLite Limited. All rights reserved.</li>
+ <li class="footer">$generatedby
+ <a href="http://www.doxygen.org/index.html">
+ <img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
+ </ul>
+</div>
+<!--END GENERATE_TREEVIEW-->
+<!--BEGIN !GENERATE_TREEVIEW-->
+<hr class="footer"/><address class="footer"><small>
+$generatedby &#160;<a href="http://www.doxygen.org/index.html">
+<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
+</a> $doxygenversion
+</small></address>
+<!--END !GENERATE_TREEVIEW-->
+</body>
+</html>
diff --git a/documentation/ui/header.html b/documentation/ui/header.html
new file mode 100644
index 0000000..a8b2bb9
--- /dev/null
+++ b/documentation/ui/header.html
@@ -0,0 +1,77 @@
+<!-- HTML header for doxygen 1.8.11-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
+<meta http-equiv="X-UA-Compatible" content="IE=9"/>
+<meta name="generator" content="Doxygen $doxygenversion"/>
+<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
+<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
+
+<link rel="apple-touch-icon" sizes="57x57" href="$relpath^apple-touch-icon-57x57.png">
+<link rel="apple-touch-icon" sizes="60x60" href="$relpath^apple-touch-icon-60x60.png">
+<link rel="apple-touch-icon" sizes="72x72" href="$relpath^apple-touch-icon-72x72.png">
+<link rel="apple-touch-icon" sizes="76x76" href="$relpath^apple-touch-icon-76x76.png">
+<link rel="apple-touch-icon" sizes="114x114" href="$relpath^apple-touch-icon-114x114.png">
+<link rel="apple-touch-icon" sizes="120x120" href="$relpath^apple-touch-icon-120x120.png">
+<link rel="apple-touch-icon" sizes="144x144" href="$relpath^apple-touch-icon-144x144.png">
+<link rel="apple-touch-icon" sizes="152x152" href="$relpath^apple-touch-icon-152x152.png">
+<link rel="apple-touch-icon" sizes="180x180" href="$relpath^apple-touch-icon-180x180.png">
+<link rel="icon" type="image/png" href="$relpath^favicon-32x32.png" sizes="32x32">
+<link rel="icon" type="image/png" href="$relpath^android-chrome-192x192.png" sizes="192x192">
+<link rel="icon" type="image/png" href="$relpath^favicon-96x96.png" sizes="96x96">
+<link rel="icon" type="image/png" href="$relpath^favicon-16x16.png" sizes="16x16">
+<link rel="manifest" href="$relpath^manifest.json">
+<link rel="mask-icon" href="$relpath^safari-pinned-tab.svg" color="#00d200">
+<meta name="msapplication-TileColor" content="#da532c">
+<meta name="msapplication-TileImage" content="$relpath^mstile-144x144.png">
+<meta name="theme-color" content="#ffffff">
+<link rel="shortcut icon" href="$relpath^favicon.ico" type="image/x-icon" />
+
+
+<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
+<script type="text/javascript" src="$relpath^jquery.js"></script>
+<script type="text/javascript" src="$relpath^dynsections.js"></script>
+$treeview
+$search
+$mathjax
+<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
+$extrastylesheet
+</head>
+<body>
+<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
+
+<!--BEGIN TITLEAREA-->
+<div id="titlearea">
+<table cellspacing="0" cellpadding="0">
+ <tbody>
+ <tr style="height: 56px;">
+ <!--BEGIN PROJECT_LOGO-->
+ <td id="projectlogo"><a href="http://www.fuzzylite.com/" title="http://www.fuzzylite.com" target="_blank"><img src="$relpath^$projectlogo"/></a></td>
+ <!--END PROJECT_LOGO-->
+ <!--BEGIN PROJECT_NAME-->
+ <td id="projectalign" style="padding-left: 0.5em;">
+ <div id="projectname">$projectname
+ <!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
+ </div>
+ <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
+ </td>
+ <!--END PROJECT_NAME-->
+ <!--BEGIN !PROJECT_NAME-->
+ <!--BEGIN PROJECT_BRIEF-->
+ <td style="padding-left: 0.5em;">
+ <div id="projectbrief">$projectbrief</div>
+ </td>
+ <!--END PROJECT_BRIEF-->
+ <!--END !PROJECT_NAME-->
+ <!--BEGIN DISABLE_INDEX-->
+ <!--BEGIN SEARCHENGINE-->
+ <td>$searchbox</td>
+ <!--END SEARCHENGINE-->
+ <!--END DISABLE_INDEX-->
+ </tr>
+ </tbody>
+</table>
+</div>
+<!--END TITLEAREA-->
+<!-- end header part -->
diff --git a/documentation/ui/image/android-chrome-144x144.png b/documentation/ui/image/android-chrome-144x144.png
new file mode 100644
index 0000000..13a60a8
--- /dev/null
+++ b/documentation/ui/image/android-chrome-144x144.png
Binary files differ
diff --git a/documentation/ui/image/android-chrome-192x192.png b/documentation/ui/image/android-chrome-192x192.png
new file mode 100644
index 0000000..8507762
--- /dev/null
+++ b/documentation/ui/image/android-chrome-192x192.png
Binary files differ
diff --git a/documentation/ui/image/android-chrome-36x36.png b/documentation/ui/image/android-chrome-36x36.png
new file mode 100644
index 0000000..ad8e7d1
--- /dev/null
+++ b/documentation/ui/image/android-chrome-36x36.png
Binary files differ
diff --git a/documentation/ui/image/android-chrome-48x48.png b/documentation/ui/image/android-chrome-48x48.png
new file mode 100644
index 0000000..94b2dfe
--- /dev/null
+++ b/documentation/ui/image/android-chrome-48x48.png
Binary files differ
diff --git a/documentation/ui/image/android-chrome-72x72.png b/documentation/ui/image/android-chrome-72x72.png
new file mode 100644
index 0000000..8f90b01
--- /dev/null
+++ b/documentation/ui/image/android-chrome-72x72.png
Binary files differ
diff --git a/documentation/ui/image/android-chrome-96x96.png b/documentation/ui/image/android-chrome-96x96.png
new file mode 100644
index 0000000..7b29762
--- /dev/null
+++ b/documentation/ui/image/android-chrome-96x96.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-114x114.png b/documentation/ui/image/apple-touch-icon-114x114.png
new file mode 100644
index 0000000..0b70f67
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-114x114.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-120x120.png b/documentation/ui/image/apple-touch-icon-120x120.png
new file mode 100644
index 0000000..b43d10e
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-120x120.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-144x144.png b/documentation/ui/image/apple-touch-icon-144x144.png
new file mode 100644
index 0000000..07a81e6
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-144x144.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-152x152.png b/documentation/ui/image/apple-touch-icon-152x152.png
new file mode 100644
index 0000000..7900187
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-152x152.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-180x180.png b/documentation/ui/image/apple-touch-icon-180x180.png
new file mode 100644
index 0000000..3d9e74f
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-180x180.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-57x57.png b/documentation/ui/image/apple-touch-icon-57x57.png
new file mode 100644
index 0000000..cf40432
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-57x57.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-60x60.png b/documentation/ui/image/apple-touch-icon-60x60.png
new file mode 100644
index 0000000..2f208d1
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-60x60.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-72x72.png b/documentation/ui/image/apple-touch-icon-72x72.png
new file mode 100644
index 0000000..2e8f273
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-72x72.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-76x76.png b/documentation/ui/image/apple-touch-icon-76x76.png
new file mode 100644
index 0000000..a10c74f
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-76x76.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon-precomposed.png b/documentation/ui/image/apple-touch-icon-precomposed.png
new file mode 100644
index 0000000..9cdd1f0
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon-precomposed.png
Binary files differ
diff --git a/documentation/ui/image/apple-touch-icon.png b/documentation/ui/image/apple-touch-icon.png
new file mode 100644
index 0000000..3d9e74f
--- /dev/null
+++ b/documentation/ui/image/apple-touch-icon.png
Binary files differ
diff --git a/documentation/ui/image/browserconfig.xml b/documentation/ui/image/browserconfig.xml
new file mode 100644
index 0000000..65380f3
--- /dev/null
+++ b/documentation/ui/image/browserconfig.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<browserconfig>
+ <msapplication>
+ <tile>
+ <square70x70logo src="/mstile-70x70.png"/>
+ <square150x150logo src="/mstile-150x150.png"/>
+ <square310x310logo src="/mstile-310x310.png"/>
+ <wide310x150logo src="/mstile-310x150.png"/>
+ <TileColor>#da532c</TileColor>
+ </tile>
+ </msapplication>
+</browserconfig>
diff --git a/documentation/ui/image/favicon-16x16.png b/documentation/ui/image/favicon-16x16.png
new file mode 100644
index 0000000..3e95d61
--- /dev/null
+++ b/documentation/ui/image/favicon-16x16.png
Binary files differ
diff --git a/documentation/ui/image/favicon-32x32.png b/documentation/ui/image/favicon-32x32.png
new file mode 100644
index 0000000..d7db569
--- /dev/null
+++ b/documentation/ui/image/favicon-32x32.png
Binary files differ
diff --git a/documentation/ui/image/favicon-96x96.png b/documentation/ui/image/favicon-96x96.png
new file mode 100644
index 0000000..7b29762
--- /dev/null
+++ b/documentation/ui/image/favicon-96x96.png
Binary files differ
diff --git a/documentation/ui/image/favicon.ico b/documentation/ui/image/favicon.ico
new file mode 100644
index 0000000..c2e7915
--- /dev/null
+++ b/documentation/ui/image/favicon.ico
Binary files differ
diff --git a/documentation/ui/image/manifest.json b/documentation/ui/image/manifest.json
new file mode 100644
index 0000000..b595012
--- /dev/null
+++ b/documentation/ui/image/manifest.json
@@ -0,0 +1,41 @@
+{
+ "name": "fuzzylite",
+ "icons": [
+ {
+ "src": "\/android-chrome-36x36.png",
+ "sizes": "36x36",
+ "type": "image\/png",
+ "density": "0.75"
+ },
+ {
+ "src": "\/android-chrome-48x48.png",
+ "sizes": "48x48",
+ "type": "image\/png",
+ "density": "1.0"
+ },
+ {
+ "src": "\/android-chrome-72x72.png",
+ "sizes": "72x72",
+ "type": "image\/png",
+ "density": "1.5"
+ },
+ {
+ "src": "\/android-chrome-96x96.png",
+ "sizes": "96x96",
+ "type": "image\/png",
+ "density": "2.0"
+ },
+ {
+ "src": "\/android-chrome-144x144.png",
+ "sizes": "144x144",
+ "type": "image\/png",
+ "density": "3.0"
+ },
+ {
+ "src": "\/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image\/png",
+ "density": "4.0"
+ }
+ ]
+}
diff --git a/documentation/ui/image/mstile-144x144.png b/documentation/ui/image/mstile-144x144.png
new file mode 100644
index 0000000..fcba19e
--- /dev/null
+++ b/documentation/ui/image/mstile-144x144.png
Binary files differ
diff --git a/documentation/ui/image/mstile-150x150.png b/documentation/ui/image/mstile-150x150.png
new file mode 100644
index 0000000..6748bc1
--- /dev/null
+++ b/documentation/ui/image/mstile-150x150.png
Binary files differ
diff --git a/documentation/ui/image/mstile-310x150.png b/documentation/ui/image/mstile-310x150.png
new file mode 100644
index 0000000..29c3eaa
--- /dev/null
+++ b/documentation/ui/image/mstile-310x150.png
Binary files differ
diff --git a/documentation/ui/image/mstile-310x310.png b/documentation/ui/image/mstile-310x310.png
new file mode 100644
index 0000000..16aa141
--- /dev/null
+++ b/documentation/ui/image/mstile-310x310.png
Binary files differ
diff --git a/documentation/ui/image/mstile-70x70.png b/documentation/ui/image/mstile-70x70.png
new file mode 100644
index 0000000..6531179
--- /dev/null
+++ b/documentation/ui/image/mstile-70x70.png
Binary files differ
diff --git a/documentation/ui/image/safari-pinned-tab.svg b/documentation/ui/image/safari-pinned-tab.svg
new file mode 100644
index 0000000..6f4db51
--- /dev/null
+++ b/documentation/ui/image/safari-pinned-tab.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="72.000000pt" height="73.000000pt" viewBox="0 0 72.000000 73.000000"
+ preserveAspectRatio="xMidYMid meet">
+<metadata>
+Created by potrace 1.11, written by Peter Selinger 2001-2013
+</metadata>
+<g transform="translate(0.000000,73.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M69 713 c-16 -6 -38 -27 -49 -45 -19 -31 -20 -50 -20 -301 0 -382
+-25 -357 357 -357 248 0 270 2 300 20 17 10 37 28 43 40 8 14 11 111 11 296 0
+382 27 354 -347 357 -188 1 -275 -2 -295 -10z m561 -28 c56 -29 60 -50 60
+-313 0 -145 -4 -251 -11 -270 -22 -63 -38 -67 -299 -70 -260 -4 -298 2 -334
+51 -20 27 -21 40 -21 281 0 279 3 298 60 322 47 20 506 19 545 -1z"/>
+<path d="M477 633 c-3 -4 -13 -37 -22 -73 -9 -36 -21 -83 -27 -105 l-11 -40
+-17 65 c-34 128 -41 150 -48 150 -5 0 -19 -44 -31 -97 -13 -54 -27 -104 -31
+-112 -4 -8 -18 32 -35 98 -15 62 -31 109 -35 104 -7 -8 -130 -493 -130 -513 0
+-6 93 -10 265 -10 246 0 265 1 265 18 0 20 -126 511 -133 518 -3 3 -7 2 -10
+-3z m-223 -151 l27 -107 -34 -130 -34 -130 -57 -3 c-52 -3 -57 -1 -52 15 3 10
+26 101 51 203 59 237 65 260 69 260 2 0 16 -48 30 -108z m146 -114 c0 -50 -9
+-58 -61 -58 -27 0 -49 2 -49 5 0 3 14 63 32 133 l32 127 23 -90 c12 -49 23
+-102 23 -117z m129 25 c5 -21 23 -91 39 -155 l30 -118 -179 0 c-98 0 -179 3
+-179 8 0 4 8 39 18 77 l18 70 62 3 c70 3 73 6 92 95 l13 57 38 0 c36 0 39 -2
+48 -37z"/>
+</g>
+</svg>
diff --git a/documentation/ui/stylesheet.css b/documentation/ui/stylesheet.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/documentation/ui/stylesheet.css
diff --git a/examples/application/CMakeLists.txt b/examples/application/CMakeLists.txt
new file mode 100644
index 0000000..3ec0869
--- /dev/null
+++ b/examples/application/CMakeLists.txt
@@ -0,0 +1,140 @@
+cmake_minimum_required(VERSION 2.8.8)
+
+project(FuzzyLiteDemo CXX)
+
+#Some default policies and variables
+if (APPLE)
+ cmake_policy(SET CMP0042 NEW)
+endif()
+if (MSVC)
+ cmake_policy(SET CMP0054 NEW)
+endif()
+
+if(NOT CMAKE_VERBOSE_MAKEFILE)
+ set(CMAKE_VERBOSE_MAKEFILE false)
+endif()
+
+if( NOT CMAKE_BUILD_TYPE )
+ set( CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo
+MinSizeRel." FORCE )
+endif()
+
+option(FL_BACKTRACE "Provide backtrace information in case of errors" ON)
+option(FL_STATIC "Statically link to fuzzylite libraries" ON)
+
+set(BacktraceLibrary)
+
+if (MSVC AND FL_BACKTRACE)
+ set(BacktraceLibrary dbghelp)
+endif()
+
+if (CMAKE_BUILD_TYPE MATCHES Debug)
+ set(FL_DEBUG ON)
+else()
+ set(FL_DEBUG OFF)
+endif()
+
+
+set(FL_SYSTEM_LIBRARY FALSE) #Finds the library installed in the system
+set(FL_LIBRARY_DIR)
+
+if (NOT FL_SYSTEM_LIBRARY)
+ #it is possible to find the FuzzyLiteLibrary locally as follows,
+ #assuming the submodule of fuzzylite is added to the ${PROJECT_SOURCE_DIR}:
+ set(FL_HOME ${PROJECT_SOURCE_DIR}/../../fuzzylite/)
+ set(FL_INCLUDE_DIR ${FL_HOME})
+ if (FL_DEBUG)
+ set(FL_LIBRARY_DIR ${FL_HOME}/debug/bin)
+ else()
+ set(FL_LIBRARY_DIR ${FL_HOME}/release/bin)
+ endif()
+ message("Finding FuzzyLiteLibrary locally at ${FL_LIBRARY_DIR}")
+
+ include_directories(${FL_INCLUDE_DIR})
+endif()
+
+set(FL_POSTFIX)
+if (FL_STATIC)
+ set(FL_POSTFIX "-static")
+endif()
+if (FL_DEBUG)
+ set(FL_POSTFIX "${FL_POSTFIX}-debug")
+endif()
+
+set(FL_LIBRARY_NAME fuzzylite${FL_POSTFIX})
+find_library (FuzzyLiteLibrary ${FL_LIBRARY_NAME} HINTS ${FL_LIBRARY_DIR})
+
+if (MSVC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19)
+#C++11 not available before Visual Studio 2015
+ if (NOT FL_CPP98)
+ set(FL_CPP98 ON)
+ endif()
+endif()
+
+
+#if building using C++98
+if(FL_CPP98)
+ add_definitions(-DFL_CPP98)
+ if(NOT MSVC)
+ #Set C++98 by default in Clang and others
+ add_definitions(-std=c++98)
+ endif()
+else()
+ if(NOT MSVC)
+ #Set C++11 by default in Clang and others
+ add_definitions(-std=c++11)
+ endif()
+endif(FL_CPP98)
+
+#we add the definition of the building path to remove it when using macro FL_LOG
+add_definitions(-DFL_BUILD_PATH="${CMAKE_SOURCE_DIR}") #used to determine
+#we add the sources
+set(sources src/main.cpp)
+
+
+
+if(MSVC)
+#Set compilation flags in Windows
+ set(CMAKE_CXX_FLAGS "/W4 /EHsc")
+ #Wx: Treat warnings as errors. W4: All warnings
+ #http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
+ #EHsc: call destructors on __try __catch, and to ignore C4530: C++ exception handler used. Note, unwind semantics are not enabled
+endif()
+
+
+#we create the binary
+add_executable(binary ${sources})
+if (NOT FL_STATIC)
+ target_compile_definitions(binary PRIVATE FL_IMPORT_LIBRARY)
+endif()
+#linking the fuzzylite library
+target_link_libraries (binary ${FuzzyLiteLibrary} ${BacktraceLibrary})
+#setting the name of the product
+set_target_properties(binary PROPERTIES OUTPUT_NAME FuzzyLiteDemo)
+#specially for windows
+set_target_properties(binary PROPERTIES OUTPUT_NAME FuzzyLiteDemo IMPORT_PREFIX tmp-) #To prevent LNK1149 in Windows
+#in case of building on debug mode
+set_target_properties(binary PROPERTIES DEBUG_POSTFIX d)
+
+
+
+message("=====================================")
+message("FuzzyLite Demo v6.0\n")
+message("FL_HOME=${FL_HOME}")
+message("FL_LIBRARY_NAME=${FL_LIBRARY_NAME}")
+message("FuzzyLiteLibrary=${FuzzyLiteLibrary}")
+message("")
+message("FL_BACKTRACE=${FL_BACKTRACE}")
+message("FL_STATIC=${FL_STATIC}")
+message("FL_DEBUG=${FL_DEBUG}")
+message("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
+message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}")
+message("CMAKE_CXX_COMPILER_VERSION=${CMAKE_CXX_COMPILER_VERSION}")
+message("CMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}")
+message("COMPILE_DEFINITIONS:")
+get_directory_property(fl-definitions DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS )
+foreach(d ${fl-definitions})
+ message( STATUS "Defined: " ${d} )
+endforeach()
+message("=====================================\n")
+
diff --git a/examples/application/clean.sh b/examples/application/clean.sh
new file mode 100755
index 0000000..4f4bc9c
--- /dev/null
+++ b/examples/application/clean.sh
@@ -0,0 +1 @@
+rm -rf CMakeCache.txt CMakeFiles Makefile cmake_install.cmake FuzzyLiteDemo \ No newline at end of file
diff --git a/examples/application/compile.bat b/examples/application/compile.bat
new file mode 100644
index 0000000..8baf5a3
--- /dev/null
+++ b/examples/application/compile.bat
@@ -0,0 +1,24 @@
+FL_HOME="../../fuzzylite/"
+
+rem Static Linking
+rem --------------
+rem For C++11
+cl.exe src/main.cpp %FL_HOME%/release/bin/fuzzylite-static.lib /I%FL_HOME% /EHsc /MD
+
+rem For C++98
+cl.exe src/main.cpp %FL_HOME%/release/bin/fuzzylite-static.lib /I%FL_HOME% /DFL_CPP98=ON /EHsc /MD
+
+
+rem Dynamic Linking
+rem ---------------
+rem For C++11
+rem For C++11
+cl.exe src/main.cpp %FL_HOME%/release/bin/fuzzylite-static.lib /I%FL_HOME% /DFL_IMPORT_LIBRARY /EHsc /MD
+
+rem For C++98
+cl.exe src/main.cpp %FL_HOME%/release/bin/fuzzylite-static.lib /I%FL_HOME% /DFL_CPP98=ON /DFL_IMPORT_LIBRARY /EHsc /MD
+
+rem Note: when using dynamic linking, the path to fuzzylite libraries must be specified. For example, run from console the following:
+
+set PATH="%FL_HOME%\release\bin;%PATH%"
+example-dynamic-11.exe
diff --git a/examples/application/compile.sh b/examples/application/compile.sh
new file mode 100755
index 0000000..1ea1aa4
--- /dev/null
+++ b/examples/application/compile.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+FL_HOME="../../fuzzylite/"
+
+#Static Linking
+#--------------
+#For C++11
+g++ src/main.cpp -oexample-static-11 -I$FL_HOME -L$FL_HOME/release/bin -lfuzzylite-static -std=c++11
+
+#For C++98
+g++ src/main.cpp -oexample-static-98 -I$FL_HOME -L$FL_HOME/release/bin -lfuzzylite-static -DFL_CPP98=ON -Wno-non-literal-null-conversion
+
+
+#Dynamic Linking
+#---------------
+#For C++11
+g++ src/main.cpp -oexample-dynamic-11 -I$FL_HOME -L$FL_HOME/release/bin -lfuzzylite -std=c++11
+
+#For C++98
+g++ src/main.cpp -oexample-dynamic-98 -I$FL_HOME -L$FL_HOME/release/bin -lfuzzylite -DFL_CPP98=ON -Wno-non-literal-null-conversion
+
+#Note: when using dynamic linking, the path to fuzzylite libraries must be specified. For example, run from console the following:
+
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$FL_HOME/release/bin;
+./example-dynamic-11
diff --git a/examples/application/src/main.cpp b/examples/application/src/main.cpp
new file mode 100644
index 0000000..d547b72
--- /dev/null
+++ b/examples/application/src/main.cpp
@@ -0,0 +1,16 @@
+
+#include "fl/Headers.h"
+
+int main(int argc, char** argv){
+ FL_IUNUSED(argc);
+ FL_IUNUSED(argv);
+
+ using namespace fl;
+
+ Engine* hybrid = Console::hybrid();
+ FL_LOG("Hybrid Demo: FuzzyLite Dataset");
+ FL_LOG("===============================");
+ FL_LOG(FldExporter().toString(hybrid));
+ delete hybrid;
+
+} \ No newline at end of file
diff --git a/examples/examples.R b/examples/examples.R
new file mode 100644
index 0000000..7b905bf
--- /dev/null
+++ b/examples/examples.R
@@ -0,0 +1,16 @@
+directories = c("mamdani/", "mamdani/matlab/", "mamdani/octave/", "takagi-sugeno/", "takagi-sugeno/matlab/", "takagi-sugeno/octave/", "tsukamoto/", "hybrid")
+baseDirectory = getwd()
+
+for (directory in directories){
+ message("Processing directory: ", directory)
+ setwd(directory)
+ rScripts = list.files(".", pattern = ".R$")
+ for (i in seq(1, length(rScripts))){
+ rScript = rScripts[i]
+ message(sprintf("\tProcessing file %i/%i: %s", i, length(rScripts), rScript))
+ scriptEnvironment = new.env()
+ sys.source(rScript, scriptEnvironment)
+ rm(scriptEnvironment)
+ }
+ setwd(baseDirectory)
+}
diff --git a/examples/examples.mat b/examples/examples.mat
deleted file mode 100755
index 5955fbd..0000000
--- a/examples/examples.mat
+++ /dev/null
Binary files differ
diff --git a/examples/hybrid/ObstacleAvoidance.R b/examples/hybrid/ObstacleAvoidance.R
new file mode 100644
index 0000000..5a94543
--- /dev/null
+++ b/examples/hybrid/ObstacleAvoidance.R
@@ -0,0 +1,86 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "ObstacleAvoidance"
+engine.fll = "Engine: ObstacleAvoidance
+InputVariable: obstacle
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: mSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 100
+ default: nan
+ lock-previous: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: tsSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: left Constant 0.333
+ term: right Constant 0.666
+RuleBlock: mamdani
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: AlgebraicProduct
+ activation: General
+ rule: if obstacle is left then mSteer is right
+ rule: if obstacle is right then mSteer is left
+RuleBlock: takagiSugeno
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if obstacle is left then tsSteer is right
+ rule: if obstacle is right then tsSteer is left"
+
+engine.fldFile = "ObstacleAvoidance.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(obstacle, mSteer)) +
+ geom_line(aes(color=mSteer), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("obstacle vs mSteer")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(obstacle, mSteer)) +
+ geom_line(aes(color=mSteer), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("mSteer vs obstacle")
+
+engine.plot.i1_o2 = ggplot(engine.df, aes(obstacle, tsSteer)) +
+ geom_line(aes(color=tsSteer), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("obstacle vs tsSteer")
+
+engine.plot.o2_i1 = ggplot(engine.df, aes(obstacle, tsSteer)) +
+ geom_line(aes(color=tsSteer), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("tsSteer vs obstacle")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, engine.plot.i1_o2, engine.plot.o2_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/hybrid/ObstacleAvoidance.cpp b/examples/hybrid/ObstacleAvoidance.cpp
new file mode 100644
index 0000000..a5e42e1
--- /dev/null
+++ b/examples/hybrid/ObstacleAvoidance.cpp
@@ -0,0 +1,75 @@
+#include <fl/Headers.h>
+
+int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
+using namespace fl;
+
+Engine* engine = new Engine;
+engine->setName("ObstacleAvoidance");
+engine->setDescription("");
+
+InputVariable* obstacle = new InputVariable;
+obstacle->setName("obstacle");
+obstacle->setDescription("");
+obstacle->setEnabled(true);
+obstacle->setRange(0.000, 1.000);
+obstacle->setLockValueInRange(false);
+obstacle->addTerm(new Ramp("left", 1.000, 0.000));
+obstacle->addTerm(new Ramp("right", 0.000, 1.000));
+engine->addInputVariable(obstacle);
+
+OutputVariable* mSteer = new OutputVariable;
+mSteer->setName("mSteer");
+mSteer->setDescription("");
+mSteer->setEnabled(true);
+mSteer->setRange(0.000, 1.000);
+mSteer->setLockValueInRange(false);
+mSteer->setAggregation(new Maximum);
+mSteer->setDefuzzifier(new Centroid(100));
+mSteer->setDefaultValue(fl::nan);
+mSteer->setLockPreviousValue(false);
+mSteer->addTerm(new Ramp("left", 1.000, 0.000));
+mSteer->addTerm(new Ramp("right", 0.000, 1.000));
+engine->addOutputVariable(mSteer);
+
+OutputVariable* tsSteer = new OutputVariable;
+tsSteer->setName("tsSteer");
+tsSteer->setDescription("");
+tsSteer->setEnabled(true);
+tsSteer->setRange(0.000, 1.000);
+tsSteer->setLockValueInRange(false);
+tsSteer->setAggregation(new Maximum);
+tsSteer->setDefuzzifier(new WeightedAverage("Automatic"));
+tsSteer->setDefaultValue(fl::nan);
+tsSteer->setLockPreviousValue(false);
+tsSteer->addTerm(new Constant("left", 0.333));
+tsSteer->addTerm(new Constant("right", 0.666));
+engine->addOutputVariable(tsSteer);
+
+RuleBlock* mamdani = new RuleBlock;
+mamdani->setName("mamdani");
+mamdani->setDescription("");
+mamdani->setEnabled(true);
+mamdani->setConjunction(fl::null);
+mamdani->setDisjunction(fl::null);
+mamdani->setImplication(new AlgebraicProduct);
+mamdani->setActivation(new General);
+mamdani->addRule(Rule::parse("if obstacle is left then mSteer is right", engine));
+mamdani->addRule(Rule::parse("if obstacle is right then mSteer is left", engine));
+engine->addRuleBlock(mamdani);
+
+RuleBlock* takagiSugeno = new RuleBlock;
+takagiSugeno->setName("takagiSugeno");
+takagiSugeno->setDescription("");
+takagiSugeno->setEnabled(true);
+takagiSugeno->setConjunction(fl::null);
+takagiSugeno->setDisjunction(fl::null);
+takagiSugeno->setImplication(fl::null);
+takagiSugeno->setActivation(new General);
+takagiSugeno->addRule(Rule::parse("if obstacle is left then tsSteer is right", engine));
+takagiSugeno->addRule(Rule::parse("if obstacle is right then tsSteer is left", engine));
+engine->addRuleBlock(takagiSugeno);
+
+
+}
diff --git a/examples/hybrid/ObstacleAvoidance.fcl b/examples/hybrid/ObstacleAvoidance.fcl
new file mode 100644
index 0000000..81a30a7
--- /dev/null
+++ b/examples/hybrid/ObstacleAvoidance.fcl
@@ -0,0 +1,49 @@
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK ObstacleAvoidance
+
+VAR_INPUT
+ obstacle: REAL;
+END_VAR
+
+VAR_OUTPUT
+ mSteer: REAL;
+ tsSteer: REAL;
+END_VAR
+
+FUZZIFY obstacle
+ RANGE := (0.000 .. 1.000);
+ TERM left := Ramp 1.000 0.000;
+ TERM right := Ramp 0.000 1.000;
+END_FUZZIFY
+
+DEFUZZIFY mSteer
+ RANGE := (0.000 .. 1.000);
+ TERM left := Ramp 1.000 0.000;
+ TERM right := Ramp 0.000 1.000;
+ METHOD : COG;
+ ACCU : MAX;
+ DEFAULT := nan;
+END_DEFUZZIFY
+
+DEFUZZIFY tsSteer
+ RANGE := (0.000 .. 1.000);
+ TERM left := 0.333;
+ TERM right := 0.666;
+ METHOD : COGS;
+ ACCU : MAX;
+ DEFAULT := nan;
+END_DEFUZZIFY
+
+RULEBLOCK mamdani
+ ACT : PROD;
+ RULE 1 : if obstacle is left then mSteer is right
+ RULE 2 : if obstacle is right then mSteer is left
+END_RULEBLOCK
+
+RULEBLOCK takagiSugeno
+ RULE 1 : if obstacle is left then tsSteer is right
+ RULE 2 : if obstacle is right then tsSteer is left
+END_RULEBLOCK
+
+END_FUNCTION_BLOCK
diff --git a/examples/hybrid/ObstacleAvoidance.fis b/examples/hybrid/ObstacleAvoidance.fis
new file mode 100644
index 0000000..1bf0476
--- /dev/null
+++ b/examples/hybrid/ObstacleAvoidance.fis
@@ -0,0 +1,43 @@
+#Code automatically generated with fuzzylite 6.0.
+
+[System]
+Name='ObstacleAvoidance'
+Type='hybrid'
+Version=6.0
+NumInputs=1
+NumOutputs=2
+NumRules=4
+AndMethod='min'
+OrMethod='max'
+ImpMethod='prod'
+AggMethod='max'
+DefuzzMethod='centroid'
+
+[Input1]
+Name='obstacle'
+Range=[0.000 1.000]
+NumMFs=2
+MF1='left':'rampmf',[1.000 0.000]
+MF2='right':'rampmf',[0.000 1.000]
+
+[Output1]
+Name='mSteer'
+Range=[0.000 1.000]
+NumMFs=2
+MF1='left':'rampmf',[1.000 0.000]
+MF2='right':'rampmf',[0.000 1.000]
+
+[Output2]
+Name='tsSteer'
+Range=[0.000 1.000]
+NumMFs=2
+MF1='left':'constant',[0.333]
+MF2='right':'constant',[0.666]
+
+[Rules]
+# RuleBlock mamdani
+1.000 , 2.000 0.000 (1.000) : 1
+2.000 , 1.000 0.000 (1.000) : 1
+# RuleBlock takagiSugeno
+1.000 , 0.000 2.000 (1.000) : 1
+2.000 , 0.000 1.000 (1.000) : 1
diff --git a/examples/hybrid/ObstacleAvoidance.fld b/examples/hybrid/ObstacleAvoidance.fld
new file mode 100644
index 0000000..bd96696
--- /dev/null
+++ b/examples/hybrid/ObstacleAvoidance.fld
@@ -0,0 +1,1025 @@
+obstacle mSteer tsSteer
+0.000000000 0.666650000 0.666000000
+0.000977517 0.666650000 0.665674487
+0.001955034 0.666650000 0.665348974
+0.002932551 0.666650000 0.665023460
+0.003910068 0.666650000 0.664697947
+0.004887586 0.666650000 0.664372434
+0.005865103 0.666638485 0.664046921
+0.006842620 0.666625450 0.663721408
+0.007820137 0.666612389 0.663395894
+0.008797654 0.666599303 0.663070381
+0.009775171 0.666586193 0.662744868
+0.010752688 0.666573056 0.662419355
+0.011730205 0.666559894 0.662093842
+0.012707722 0.666546707 0.661768328
+0.013685239 0.666533494 0.661442815
+0.014662757 0.666520255 0.661117302
+0.015640274 0.666498518 0.660791789
+0.016617791 0.666472271 0.660466276
+0.017595308 0.666445974 0.660140762
+0.018572825 0.666419626 0.659815249
+0.019550342 0.666393229 0.659489736
+0.020527859 0.666366781 0.659164223
+0.021505376 0.666340282 0.658838710
+0.022482893 0.666313732 0.658513196
+0.023460411 0.666287131 0.658187683
+0.024437928 0.666260479 0.657862170
+0.025415445 0.666228313 0.657536657
+0.026392962 0.666188686 0.657211144
+0.027370479 0.666148986 0.656885630
+0.028347996 0.666109209 0.656560117
+0.029325513 0.666069358 0.656234604
+0.030303030 0.666029432 0.655909091
+0.031280547 0.665989429 0.655583578
+0.032258065 0.665949351 0.655258065
+0.033235582 0.665909196 0.654932551
+0.034213099 0.665868966 0.654607038
+0.035190616 0.665826169 0.654281525
+0.036168133 0.665773005 0.653956012
+0.037145650 0.665719742 0.653630499
+0.038123167 0.665666380 0.653304985
+0.039100684 0.665612917 0.652979472
+0.040078201 0.665559355 0.652653959
+0.041055718 0.665505693 0.652328446
+0.042033236 0.665451930 0.652002933
+0.043010753 0.665398066 0.651677419
+0.043988270 0.665344101 0.651351906
+0.044965787 0.665290034 0.651026393
+0.045943304 0.665223628 0.650700880
+0.046920821 0.665156655 0.650375367
+0.047898338 0.665089559 0.650049853
+0.048875855 0.665022339 0.649724340
+0.049853372 0.664954994 0.649398827
+0.050830890 0.664887525 0.649073314
+0.051808407 0.664819932 0.648747801
+0.052785924 0.664752213 0.648422287
+0.053763441 0.664684369 0.648096774
+0.054740958 0.664616398 0.647771261
+0.055718475 0.664539056 0.647445748
+0.056695992 0.664458237 0.647120235
+0.057673509 0.664377270 0.646794721
+0.058651026 0.664296156 0.646469208
+0.059628543 0.664214895 0.646143695
+0.060606061 0.664133485 0.645818182
+0.061583578 0.664051926 0.645492669
+0.062561095 0.663970218 0.645167155
+0.063538612 0.663888361 0.644841642
+0.064516129 0.663806354 0.644516129
+0.065493646 0.663717900 0.644190616
+0.066471163 0.663623109 0.643865103
+0.067448680 0.663528148 0.643539589
+0.068426197 0.663433016 0.643214076
+0.069403715 0.663337714 0.642888563
+0.070381232 0.663242240 0.642563050
+0.071358749 0.663146594 0.642237537
+0.072336266 0.663050776 0.641912023
+0.073313783 0.662954785 0.641586510
+0.074291300 0.662858620 0.641260997
+0.075268817 0.662758885 0.640935484
+0.076246334 0.662650011 0.640609971
+0.077223851 0.662540943 0.640284457
+0.078201369 0.662431683 0.639958944
+0.079178886 0.662322229 0.639633431
+0.080156403 0.662212581 0.639307918
+0.081133920 0.662102739 0.638982405
+0.082111437 0.661992701 0.638656891
+0.083088954 0.661882468 0.638331378
+0.084066471 0.661772039 0.638005865
+0.085043988 0.661660863 0.637680352
+0.086021505 0.661537806 0.637354839
+0.086999022 0.661414534 0.637029326
+0.087976540 0.661291048 0.636703812
+0.088954057 0.661167346 0.636378299
+0.089931574 0.661043428 0.636052786
+0.090909091 0.660919294 0.635727273
+0.091886608 0.660794942 0.635401760
+0.092864125 0.660670373 0.635076246
+0.093841642 0.660545585 0.634750733
+0.094819159 0.660420579 0.634425220
+0.095796676 0.660285492 0.634099707
+0.096774194 0.660147932 0.633774194
+0.097751711 0.660010136 0.633448680
+0.098729228 0.659872104 0.633123167
+0.099706745 0.659733835 0.632797654
+0.100684262 0.659595328 0.632472141
+0.101661779 0.659456582 0.632146628
+0.102639296 0.659317597 0.631821114
+0.103616813 0.659178373 0.631495601
+0.104594330 0.659038909 0.631170088
+0.105571848 0.658892208 0.630844575
+0.106549365 0.658740291 0.630519062
+0.107526882 0.658588119 0.630193548
+0.108504399 0.658435689 0.629868035
+0.109481916 0.658283002 0.629542522
+0.110459433 0.658130057 0.629217009
+0.111436950 0.657976852 0.628891496
+0.112414467 0.657823389 0.628565982
+0.113391984 0.657669665 0.628240469
+0.114369501 0.657515680 0.627914956
+0.115347019 0.657357242 0.627589443
+0.116324536 0.657190916 0.627263930
+0.117302053 0.657024315 0.626938416
+0.118279570 0.656857437 0.626612903
+0.119257087 0.656690282 0.626287390
+0.120234604 0.656522850 0.625961877
+0.121212121 0.656355139 0.625636364
+0.122189638 0.656187149 0.625310850
+0.123167155 0.656018879 0.624985337
+0.124144673 0.655850329 0.624659824
+0.125122190 0.655680041 0.624334311
+0.126099707 0.655499270 0.624008798
+0.127077224 0.655318205 0.623683284
+0.128054741 0.655136845 0.623357771
+0.129032258 0.654955190 0.623032258
+0.130009775 0.654773238 0.622706745
+0.130987292 0.654590990 0.622381232
+0.131964809 0.654408443 0.622055718
+0.132942326 0.654225598 0.621730205
+0.133919844 0.654042454 0.621404692
+0.134897361 0.653859010 0.621079179
+0.135874878 0.653664982 0.620753666
+0.136852395 0.653469436 0.620428152
+0.137829912 0.653273578 0.620102639
+0.138807429 0.653077407 0.619777126
+0.139784946 0.652880922 0.619451613
+0.140762463 0.652684123 0.619126100
+0.141739980 0.652487008 0.618800587
+0.142717498 0.652289577 0.618475073
+0.143695015 0.652091829 0.618149560
+0.144672532 0.651893763 0.617824047
+0.145650049 0.651687855 0.617498534
+0.146627566 0.651477831 0.617173021
+0.147605083 0.651267477 0.616847507
+0.148582600 0.651056794 0.616521994
+0.149560117 0.650845780 0.616196481
+0.150537634 0.650634436 0.615870968
+0.151515152 0.650422759 0.615545455
+0.152492669 0.650210750 0.615219941
+0.153470186 0.649998407 0.614894428
+0.154447703 0.649785731 0.614568915
+0.155425220 0.649567877 0.614243402
+0.156402737 0.649343393 0.613917889
+0.157380254 0.649118566 0.613592375
+0.158357771 0.648893393 0.613266862
+0.159335288 0.648667875 0.612941349
+0.160312805 0.648442011 0.612615836
+0.161290323 0.648215799 0.612290323
+0.162267840 0.647989239 0.611964809
+0.163245357 0.647762331 0.611639296
+0.164222874 0.647535073 0.611313783
+0.165200391 0.647305221 0.610988270
+0.166177908 0.647066320 0.610662757
+0.167155425 0.646827060 0.610337243
+0.168132942 0.646587441 0.610011730
+0.169110459 0.646347463 0.609686217
+0.170087977 0.646107124 0.609360704
+0.171065494 0.645866424 0.609035191
+0.172043011 0.645625361 0.608709677
+0.173020528 0.645383936 0.608384164
+0.173998045 0.645142147 0.608058651
+0.174975562 0.644899993 0.607733138
+0.175953079 0.644647002 0.607407625
+0.176930596 0.644393373 0.607082111
+0.177908113 0.644139372 0.606756598
+0.178885630 0.643884998 0.606431085
+0.179863148 0.643630251 0.606105572
+0.180840665 0.643375130 0.605780059
+0.181818182 0.643119633 0.605454545
+0.182795699 0.642863761 0.605129032
+0.183773216 0.642607513 0.604803519
+0.184750733 0.642350886 0.604478006
+0.185728250 0.642086038 0.604152493
+0.186705767 0.641818123 0.603826979
+0.187683284 0.641549824 0.603501466
+0.188660802 0.641281142 0.603175953
+0.189638319 0.641012074 0.602850440
+0.190615836 0.640742621 0.602524927
+0.191593353 0.640472782 0.602199413
+0.192570870 0.640202555 0.601873900
+0.193548387 0.639931940 0.601548387
+0.194525904 0.639660937 0.601222874
+0.195503421 0.639384233 0.600897361
+0.196480938 0.639102138 0.600571848
+0.197458456 0.638819650 0.600246334
+0.198435973 0.638536767 0.599920821
+0.199413490 0.638253490 0.599595308
+0.200391007 0.637969817 0.599269795
+0.201368524 0.637685747 0.598944282
+0.202346041 0.637401280 0.598618768
+0.203323558 0.637116415 0.598293255
+0.204301075 0.636831150 0.597967742
+0.205278592 0.636542613 0.597642229
+0.206256109 0.636246466 0.597316716
+0.207233627 0.635949918 0.596991202
+0.208211144 0.635652966 0.596665689
+0.209188661 0.635355612 0.596340176
+0.210166178 0.635057853 0.596014663
+0.211143695 0.634759688 0.595689150
+0.212121212 0.634461118 0.595363636
+0.213098729 0.634162142 0.595038123
+0.214076246 0.633862757 0.594712610
+0.215053763 0.633562423 0.594387097
+0.216031281 0.633252376 0.594061584
+0.217008798 0.632941920 0.593736070
+0.217986315 0.632631055 0.593410557
+0.218963832 0.632319779 0.593085044
+0.219941349 0.632008091 0.592759531
+0.220918866 0.631695992 0.592434018
+0.221896383 0.631383479 0.592108504
+0.222873900 0.631070553 0.591782991
+0.223851417 0.630757212 0.591457478
+0.224828935 0.630443455 0.591131965
+0.225806452 0.630121364 0.590806452
+0.226783969 0.629797178 0.590480938
+0.227761486 0.629472576 0.590155425
+0.228739003 0.629147559 0.589829912
+0.229716520 0.628822125 0.589504399
+0.230694037 0.628496272 0.589178886
+0.231671554 0.628170002 0.588853372
+0.232649071 0.627843312 0.588527859
+0.233626588 0.627516202 0.588202346
+0.234604106 0.627188671 0.587876833
+0.235581623 0.626855159 0.587551320
+0.236559140 0.626517443 0.587225806
+0.237536657 0.626179308 0.586900293
+0.238514174 0.625840753 0.586574780
+0.239491691 0.625501777 0.586249267
+0.240469208 0.625162379 0.585923754
+0.241446725 0.624822559 0.585598240
+0.242424242 0.624482316 0.585272727
+0.243401760 0.624141649 0.584947214
+0.244379277 0.623800557 0.584621701
+0.245356794 0.623455725 0.584296188
+0.246334311 0.623104704 0.583970674
+0.247311828 0.622753262 0.583645161
+0.248289345 0.622401397 0.583319648
+0.249266862 0.622049109 0.582994135
+0.250244379 0.621696398 0.582668622
+0.251221896 0.621343261 0.582343109
+0.252199413 0.620989700 0.582017595
+0.253176931 0.620635712 0.581692082
+0.254154448 0.620281297 0.581366569
+0.255131965 0.619925265 0.581041056
+0.256109482 0.619561189 0.580715543
+0.257086999 0.619196691 0.580390029
+0.258064516 0.618831769 0.580064516
+0.259042033 0.618466424 0.579739003
+0.260019550 0.618100655 0.579413490
+0.260997067 0.617734460 0.579087977
+0.261974585 0.617367839 0.578762463
+0.262952102 0.617000791 0.578436950
+0.263929619 0.616633316 0.578111437
+0.264907136 0.616265413 0.577785924
+0.265884653 0.615889366 0.577460411
+0.266862170 0.615512088 0.577134897
+0.267839687 0.615134387 0.576809384
+0.268817204 0.614756264 0.576483871
+0.269794721 0.614377718 0.576158358
+0.270772239 0.613998747 0.575832845
+0.271749756 0.613619351 0.575507331
+0.272727273 0.613239530 0.575181818
+0.273704790 0.612859282 0.574856305
+0.274682307 0.612478608 0.574530792
+0.275659824 0.612091947 0.574205279
+0.276637341 0.611702189 0.573879765
+0.277614858 0.611312012 0.573554252
+0.278592375 0.610921415 0.573228739
+0.279569892 0.610530398 0.572903226
+0.280547410 0.610138959 0.572577713
+0.281524927 0.609747097 0.572252199
+0.282502444 0.609354813 0.571926686
+0.283479961 0.608962106 0.571601173
+0.284457478 0.608568974 0.571275660
+0.285434995 0.608171886 0.570950147
+0.286412512 0.607769974 0.570624633
+0.287390029 0.607367648 0.570299120
+0.288367546 0.606964906 0.569973607
+0.289345064 0.606561748 0.569648094
+0.290322581 0.606158173 0.569322581
+0.291300098 0.605754180 0.568997067
+0.292277615 0.605349770 0.568671554
+0.293255132 0.604944940 0.568346041
+0.294232649 0.604539690 0.568020528
+0.295210166 0.604132380 0.567695015
+0.296187683 0.603718665 0.567369501
+0.297165200 0.603304542 0.567043988
+0.298142717 0.602890009 0.566718475
+0.299120235 0.602475066 0.566392962
+0.300097752 0.602059712 0.566067449
+0.301075269 0.601643947 0.565741935
+0.302052786 0.601227769 0.565416422
+0.303030303 0.600811179 0.565090909
+0.304007820 0.600394176 0.564765396
+0.304985337 0.599976759 0.564439883
+0.305962854 0.599551726 0.564114370
+0.306940371 0.599126182 0.563788856
+0.307917889 0.598700236 0.563463343
+0.308895406 0.598273888 0.563137830
+0.309872923 0.597847137 0.562812317
+0.310850440 0.597419982 0.562486804
+0.311827957 0.596992424 0.562161290
+0.312805474 0.596564460 0.561835777
+0.313782991 0.596136092 0.561510264
+0.314760508 0.595707318 0.561184751
+0.315738025 0.595272860 0.560859238
+0.316715543 0.594836296 0.560533724
+0.317693060 0.594399340 0.560208211
+0.318670577 0.593961991 0.559882698
+0.319648094 0.593524248 0.559557185
+0.320625611 0.593086112 0.559231672
+0.321603128 0.592647581 0.558906158
+0.322580645 0.592208655 0.558580645
+0.323558162 0.591769334 0.558255132
+0.324535679 0.591329617 0.557929619
+0.325513196 0.590886006 0.557604106
+0.326490714 0.590438847 0.557278592
+0.327468231 0.589991307 0.556953079
+0.328445748 0.589543385 0.556627566
+0.329423265 0.589095081 0.556302053
+0.330400782 0.588646394 0.555976540
+0.331378299 0.588197324 0.555651026
+0.332355816 0.587747870 0.555325513
+0.333333333 0.587298033 0.555000000
+0.334310850 0.586847811 0.554674487
+0.335288368 0.586395337 0.554348974
+0.336265885 0.585938031 0.554023460
+0.337243402 0.585480357 0.553697947
+0.338220919 0.585022313 0.553372434
+0.339198436 0.584563900 0.553046921
+0.340175953 0.584105117 0.552721408
+0.341153470 0.583645965 0.552395894
+0.342130987 0.583186441 0.552070381
+0.343108504 0.582726546 0.551744868
+0.344086022 0.582266280 0.551419355
+0.345063539 0.581805253 0.551093842
+0.346041056 0.581338270 0.550768328
+0.347018573 0.580870934 0.550442815
+0.347996090 0.580403243 0.550117302
+0.348973607 0.579935197 0.549791789
+0.349951124 0.579466795 0.549466276
+0.350928641 0.578998038 0.549140762
+0.351906158 0.578528925 0.548815249
+0.352883675 0.578059455 0.548489736
+0.353861193 0.577589628 0.548164223
+0.354838710 0.577119444 0.547838710
+0.355816227 0.576644207 0.547513196
+0.356793744 0.576167703 0.547187683
+0.357771261 0.575690860 0.546862170
+0.358748778 0.575213679 0.546536657
+0.359726295 0.574736158 0.546211144
+0.360703812 0.574258297 0.545885630
+0.361681329 0.573780096 0.545560117
+0.362658847 0.573301554 0.545234604
+0.363636364 0.572822672 0.544909091
+0.364613881 0.572343449 0.544583578
+0.365591398 0.571860698 0.544258065
+0.366568915 0.571375542 0.543932551
+0.367546432 0.570890065 0.543607038
+0.368523949 0.570404267 0.543281525
+0.369501466 0.569918146 0.542956012
+0.370478983 0.569431703 0.542630499
+0.371456500 0.568944938 0.542304985
+0.372434018 0.568457849 0.541979472
+0.373411535 0.567970438 0.541653959
+0.374389052 0.567482703 0.541328446
+0.375366569 0.566992805 0.541002933
+0.376344086 0.566499534 0.540677419
+0.377321603 0.566005960 0.540351906
+0.378299120 0.565512083 0.540026393
+0.379276637 0.565017903 0.539700880
+0.380254154 0.564523420 0.539375367
+0.381231672 0.564028633 0.539049853
+0.382209189 0.563533542 0.538724340
+0.383186706 0.563038147 0.538398827
+0.384164223 0.562542448 0.538073314
+0.385141740 0.562045786 0.537747801
+0.386119257 0.561544954 0.537422287
+0.387096774 0.561043840 0.537096774
+0.388074291 0.560542444 0.536771261
+0.389051808 0.560040764 0.536445748
+0.390029326 0.559538801 0.536120235
+0.391006843 0.559036555 0.535794721
+0.391984360 0.558534026 0.535469208
+0.392961877 0.558031212 0.535143695
+0.393939394 0.557528114 0.534818182
+0.394916911 0.557024732 0.534492669
+0.395894428 0.556517268 0.534167155
+0.396871945 0.556009189 0.533841642
+0.397849462 0.555500848 0.533516129
+0.398826979 0.554992247 0.533190616
+0.399804497 0.554483383 0.532865103
+0.400782014 0.553974258 0.532539589
+0.401759531 0.553464870 0.532214076
+0.402737048 0.552955221 0.531888563
+0.403714565 0.552445308 0.531563050
+0.404692082 0.551935134 0.531237537
+0.405669599 0.551422112 0.530912023
+0.406647116 0.550907660 0.530586510
+0.407624633 0.550392969 0.530260997
+0.408602151 0.549878039 0.529935484
+0.409579668 0.549362870 0.529609971
+0.410557185 0.548847462 0.529284457
+0.411534702 0.548331815 0.528958944
+0.412512219 0.547815928 0.528633431
+0.413489736 0.547299802 0.528307918
+0.414467253 0.546783436 0.527982405
+0.415444770 0.546265287 0.527656891
+0.416422287 0.545745069 0.527331378
+0.417399804 0.545224637 0.527005865
+0.418377322 0.544703989 0.526680352
+0.419354839 0.544183126 0.526354839
+0.420332356 0.543662048 0.526029326
+0.421309873 0.543140754 0.525703812
+0.422287390 0.542619244 0.525378299
+0.423264907 0.542097518 0.525052786
+0.424242424 0.541575577 0.524727273
+0.425219941 0.541052744 0.524401760
+0.426197458 0.540527383 0.524076246
+0.427174976 0.540001832 0.523750733
+0.428152493 0.539476090 0.523425220
+0.429130010 0.538950158 0.523099707
+0.430107527 0.538424035 0.522774194
+0.431085044 0.537897722 0.522448680
+0.432062561 0.537371217 0.522123167
+0.433040078 0.536844521 0.521797654
+0.434017595 0.536317635 0.521472141
+0.434995112 0.535790557 0.521146628
+0.435972630 0.535260701 0.520821114
+0.436950147 0.534730668 0.520495601
+0.437927664 0.534200469 0.520170088
+0.438905181 0.533670106 0.519844575
+0.439882698 0.533139577 0.519519062
+0.440860215 0.532608883 0.519193548
+0.441837732 0.532078024 0.518868035
+0.442815249 0.531546999 0.518542522
+0.443792766 0.531015810 0.518217009
+0.444770283 0.530484454 0.517891496
+0.445747801 0.529951246 0.517565982
+0.446725318 0.529417377 0.517240469
+0.447702835 0.528883370 0.516914956
+0.448680352 0.528349224 0.516589443
+0.449657869 0.527814939 0.516263930
+0.450635386 0.527280516 0.515938416
+0.451612903 0.526745953 0.515612903
+0.452590420 0.526211252 0.515287390
+0.453567937 0.525676412 0.514961877
+0.454545455 0.525141432 0.514636364
+0.455522972 0.524605346 0.514310850
+0.456500489 0.524068300 0.513985337
+0.457478006 0.523531142 0.513659824
+0.458455523 0.522993872 0.513334311
+0.459433040 0.522456490 0.513008798
+0.460410557 0.521918997 0.512683284
+0.461388074 0.521381392 0.512357771
+0.462365591 0.520843675 0.512032258
+0.463343109 0.520305846 0.511706745
+0.464320626 0.519767905 0.511381232
+0.465298143 0.519229421 0.511055718
+0.466275660 0.518689863 0.510730205
+0.467253177 0.518150220 0.510404692
+0.468230694 0.517610493 0.510079179
+0.469208211 0.517070682 0.509753666
+0.470185728 0.516530787 0.509428152
+0.471163245 0.515990807 0.509102639
+0.472140762 0.515450743 0.508777126
+0.473118280 0.514910594 0.508451613
+0.474095797 0.514370361 0.508126100
+0.475073314 0.513829968 0.507800587
+0.476050831 0.513288569 0.507475073
+0.477028348 0.512747115 0.507149560
+0.478005865 0.512205604 0.506824047
+0.478983382 0.511664036 0.506498534
+0.479960899 0.511122412 0.506173021
+0.480938416 0.510580732 0.505847507
+0.481915934 0.510038995 0.505521994
+0.482893451 0.509497202 0.505196481
+0.483870968 0.508955352 0.504870968
+0.484848485 0.508413446 0.504545455
+0.485826002 0.507870980 0.504219941
+0.486803519 0.507328390 0.503894428
+0.487781036 0.506785773 0.503568915
+0.488758553 0.506243127 0.503243402
+0.489736070 0.505700453 0.502917889
+0.490713587 0.505157751 0.502592375
+0.491691105 0.504615020 0.502266862
+0.492668622 0.504072261 0.501941349
+0.493646139 0.503529474 0.501615836
+0.494623656 0.502986658 0.501290323
+0.495601173 0.502443695 0.500964809
+0.496578690 0.501900652 0.500639296
+0.497556207 0.501357608 0.500313783
+0.498533724 0.500814565 0.499988270
+0.499511241 0.500271522 0.499662757
+0.500488759 0.499728478 0.499337243
+0.501466276 0.499185435 0.499011730
+0.502443793 0.498642392 0.498686217
+0.503421310 0.498099348 0.498360704
+0.504398827 0.497556305 0.498035191
+0.505376344 0.497013342 0.497709677
+0.506353861 0.496470526 0.497384164
+0.507331378 0.495927739 0.497058651
+0.508308895 0.495384980 0.496733138
+0.509286413 0.494842249 0.496407625
+0.510263930 0.494299547 0.496082111
+0.511241447 0.493756873 0.495756598
+0.512218964 0.493214227 0.495431085
+0.513196481 0.492671610 0.495105572
+0.514173998 0.492129020 0.494780059
+0.515151515 0.491586554 0.494454545
+0.516129032 0.491044648 0.494129032
+0.517106549 0.490502798 0.493803519
+0.518084066 0.489961005 0.493478006
+0.519061584 0.489419268 0.493152493
+0.520039101 0.488877588 0.492826979
+0.521016618 0.488335964 0.492501466
+0.521994135 0.487794396 0.492175953
+0.522971652 0.487252885 0.491850440
+0.523949169 0.486711431 0.491524927
+0.524926686 0.486170032 0.491199413
+0.525904203 0.485629639 0.490873900
+0.526881720 0.485089406 0.490548387
+0.527859238 0.484549257 0.490222874
+0.528836755 0.484009193 0.489897361
+0.529814272 0.483469213 0.489571848
+0.530791789 0.482929318 0.489246334
+0.531769306 0.482389507 0.488920821
+0.532746823 0.481849780 0.488595308
+0.533724340 0.481310137 0.488269795
+0.534701857 0.480770579 0.487944282
+0.535679374 0.480232095 0.487618768
+0.536656891 0.479694154 0.487293255
+0.537634409 0.479156325 0.486967742
+0.538611926 0.478618608 0.486642229
+0.539589443 0.478081003 0.486316716
+0.540566960 0.477543510 0.485991202
+0.541544477 0.477006128 0.485665689
+0.542521994 0.476468858 0.485340176
+0.543499511 0.475931700 0.485014663
+0.544477028 0.475394654 0.484689150
+0.545454545 0.474858568 0.484363636
+0.546432063 0.474323588 0.484038123
+0.547409580 0.473788748 0.483712610
+0.548387097 0.473254047 0.483387097
+0.549364614 0.472719484 0.483061584
+0.550342131 0.472185061 0.482736070
+0.551319648 0.471650776 0.482410557
+0.552297165 0.471116630 0.482085044
+0.553274682 0.470582623 0.481759531
+0.554252199 0.470048754 0.481434018
+0.555229717 0.469515546 0.481108504
+0.556207234 0.468984190 0.480782991
+0.557184751 0.468453001 0.480457478
+0.558162268 0.467921976 0.480131965
+0.559139785 0.467391117 0.479806452
+0.560117302 0.466860423 0.479480938
+0.561094819 0.466329894 0.479155425
+0.562072336 0.465799531 0.478829912
+0.563049853 0.465269332 0.478504399
+0.564027370 0.464739299 0.478178886
+0.565004888 0.464209443 0.477853372
+0.565982405 0.463682365 0.477527859
+0.566959922 0.463155479 0.477202346
+0.567937439 0.462628783 0.476876833
+0.568914956 0.462102278 0.476551320
+0.569892473 0.461575965 0.476225806
+0.570869990 0.461049842 0.475900293
+0.571847507 0.460523910 0.475574780
+0.572825024 0.459998168 0.475249267
+0.573802542 0.459472617 0.474923754
+0.574780059 0.458947256 0.474598240
+0.575757576 0.458424423 0.474272727
+0.576735093 0.457902482 0.473947214
+0.577712610 0.457380756 0.473621701
+0.578690127 0.456859246 0.473296188
+0.579667644 0.456337952 0.472970674
+0.580645161 0.455816874 0.472645161
+0.581622678 0.455296011 0.472319648
+0.582600196 0.454775363 0.471994135
+0.583577713 0.454254931 0.471668622
+0.584555230 0.453734713 0.471343109
+0.585532747 0.453216564 0.471017595
+0.586510264 0.452700198 0.470692082
+0.587487781 0.452184072 0.470366569
+0.588465298 0.451668185 0.470041056
+0.589442815 0.451152538 0.469715543
+0.590420332 0.450637130 0.469390029
+0.591397849 0.450121961 0.469064516
+0.592375367 0.449607031 0.468739003
+0.593352884 0.449092340 0.468413490
+0.594330401 0.448577888 0.468087977
+0.595307918 0.448064866 0.467762463
+0.596285435 0.447554692 0.467436950
+0.597262952 0.447044779 0.467111437
+0.598240469 0.446535130 0.466785924
+0.599217986 0.446025742 0.466460411
+0.600195503 0.445516617 0.466134897
+0.601173021 0.445007753 0.465809384
+0.602150538 0.444499152 0.465483871
+0.603128055 0.443990811 0.465158358
+0.604105572 0.443482732 0.464832845
+0.605083089 0.442975268 0.464507331
+0.606060606 0.442471886 0.464181818
+0.607038123 0.441968788 0.463856305
+0.608015640 0.441465974 0.463530792
+0.608993157 0.440963445 0.463205279
+0.609970674 0.440461199 0.462879765
+0.610948192 0.439959236 0.462554252
+0.611925709 0.439457556 0.462228739
+0.612903226 0.438956160 0.461903226
+0.613880743 0.438455046 0.461577713
+0.614858260 0.437954214 0.461252199
+0.615835777 0.437457552 0.460926686
+0.616813294 0.436961853 0.460601173
+0.617790811 0.436466458 0.460275660
+0.618768328 0.435971367 0.459950147
+0.619745846 0.435476580 0.459624633
+0.620723363 0.434982097 0.459299120
+0.621700880 0.434487917 0.458973607
+0.622678397 0.433994040 0.458648094
+0.623655914 0.433500466 0.458322581
+0.624633431 0.433007195 0.457997067
+0.625610948 0.432517297 0.457671554
+0.626588465 0.432029562 0.457346041
+0.627565982 0.431542151 0.457020528
+0.628543500 0.431055062 0.456695015
+0.629521017 0.430568297 0.456369501
+0.630498534 0.430081854 0.456043988
+0.631476051 0.429595733 0.455718475
+0.632453568 0.429109935 0.455392962
+0.633431085 0.428624458 0.455067449
+0.634408602 0.428139302 0.454741935
+0.635386119 0.427656551 0.454416422
+0.636363636 0.427177328 0.454090909
+0.637341153 0.426698446 0.453765396
+0.638318671 0.426219904 0.453439883
+0.639296188 0.425741703 0.453114370
+0.640273705 0.425263842 0.452788856
+0.641251222 0.424786321 0.452463343
+0.642228739 0.424309140 0.452137830
+0.643206256 0.423832297 0.451812317
+0.644183773 0.423355793 0.451486804
+0.645161290 0.422880556 0.451161290
+0.646138807 0.422410372 0.450835777
+0.647116325 0.421940545 0.450510264
+0.648093842 0.421471075 0.450184751
+0.649071359 0.421001962 0.449859238
+0.650048876 0.420533205 0.449533724
+0.651026393 0.420064803 0.449208211
+0.652003910 0.419596757 0.448882698
+0.652981427 0.419129066 0.448557185
+0.653958944 0.418661730 0.448231672
+0.654936461 0.418194747 0.447906158
+0.655913978 0.417733720 0.447580645
+0.656891496 0.417273454 0.447255132
+0.657869013 0.416813559 0.446929619
+0.658846530 0.416354035 0.446604106
+0.659824047 0.415894883 0.446278592
+0.660801564 0.415436100 0.445953079
+0.661779081 0.414977687 0.445627566
+0.662756598 0.414519643 0.445302053
+0.663734115 0.414061969 0.444976540
+0.664711632 0.413604663 0.444651026
+0.665689150 0.413152189 0.444325513
+0.666666667 0.412701967 0.444000000
+0.667644184 0.412252130 0.443674487
+0.668621701 0.411802676 0.443348974
+0.669599218 0.411353606 0.443023460
+0.670576735 0.410904919 0.442697947
+0.671554252 0.410456615 0.442372434
+0.672531769 0.410008693 0.442046921
+0.673509286 0.409561153 0.441721408
+0.674486804 0.409113994 0.441395894
+0.675464321 0.408670383 0.441070381
+0.676441838 0.408230666 0.440744868
+0.677419355 0.407791345 0.440419355
+0.678396872 0.407352419 0.440093842
+0.679374389 0.406913888 0.439768328
+0.680351906 0.406475752 0.439442815
+0.681329423 0.406038009 0.439117302
+0.682306940 0.405600660 0.438791789
+0.683284457 0.405163704 0.438466276
+0.684261975 0.404727140 0.438140762
+0.685239492 0.404292682 0.437815249
+0.686217009 0.403863908 0.437489736
+0.687194526 0.403435540 0.437164223
+0.688172043 0.403007576 0.436838710
+0.689149560 0.402580018 0.436513196
+0.690127077 0.402152863 0.436187683
+0.691104594 0.401726112 0.435862170
+0.692082111 0.401299764 0.435536657
+0.693059629 0.400873818 0.435211144
+0.694037146 0.400448274 0.434885630
+0.695014663 0.400023241 0.434560117
+0.695992180 0.399605824 0.434234604
+0.696969697 0.399188821 0.433909091
+0.697947214 0.398772231 0.433583578
+0.698924731 0.398356053 0.433258065
+0.699902248 0.397940288 0.432932551
+0.700879765 0.397524934 0.432607038
+0.701857283 0.397109991 0.432281525
+0.702834800 0.396695458 0.431956012
+0.703812317 0.396281335 0.431630499
+0.704789834 0.395867620 0.431304985
+0.705767351 0.395460310 0.430979472
+0.706744868 0.395055060 0.430653959
+0.707722385 0.394650230 0.430328446
+0.708699902 0.394245820 0.430002933
+0.709677419 0.393841827 0.429677419
+0.710654936 0.393438252 0.429351906
+0.711632454 0.393035094 0.429026393
+0.712609971 0.392632352 0.428700880
+0.713587488 0.392230026 0.428375367
+0.714565005 0.391828114 0.428049853
+0.715542522 0.391431026 0.427724340
+0.716520039 0.391037894 0.427398827
+0.717497556 0.390645187 0.427073314
+0.718475073 0.390252903 0.426747801
+0.719452590 0.389861041 0.426422287
+0.720430108 0.389469602 0.426096774
+0.721407625 0.389078585 0.425771261
+0.722385142 0.388687988 0.425445748
+0.723362659 0.388297811 0.425120235
+0.724340176 0.387908053 0.424794721
+0.725317693 0.387521392 0.424469208
+0.726295210 0.387140718 0.424143695
+0.727272727 0.386760470 0.423818182
+0.728250244 0.386380649 0.423492669
+0.729227761 0.386001253 0.423167155
+0.730205279 0.385622282 0.422841642
+0.731182796 0.385243736 0.422516129
+0.732160313 0.384865613 0.422190616
+0.733137830 0.384487912 0.421865103
+0.734115347 0.384110634 0.421539589
+0.735092864 0.383734587 0.421214076
+0.736070381 0.383366684 0.420888563
+0.737047898 0.382999209 0.420563050
+0.738025415 0.382632161 0.420237537
+0.739002933 0.382265540 0.419912023
+0.739980450 0.381899345 0.419586510
+0.740957967 0.381533576 0.419260997
+0.741935484 0.381168231 0.418935484
+0.742913001 0.380803309 0.418609971
+0.743890518 0.380438811 0.418284457
+0.744868035 0.380074735 0.417958944
+0.745845552 0.379718703 0.417633431
+0.746823069 0.379364288 0.417307918
+0.747800587 0.379010300 0.416982405
+0.748778104 0.378656739 0.416656891
+0.749755621 0.378303602 0.416331378
+0.750733138 0.377950891 0.416005865
+0.751710655 0.377598603 0.415680352
+0.752688172 0.377246738 0.415354839
+0.753665689 0.376895296 0.415029326
+0.754643206 0.376544275 0.414703812
+0.755620723 0.376199443 0.414378299
+0.756598240 0.375858351 0.414052786
+0.757575758 0.375517684 0.413727273
+0.758553275 0.375177441 0.413401760
+0.759530792 0.374837621 0.413076246
+0.760508309 0.374498223 0.412750733
+0.761485826 0.374159247 0.412425220
+0.762463343 0.373820692 0.412099707
+0.763440860 0.373482557 0.411774194
+0.764418377 0.373144841 0.411448680
+0.765395894 0.372811329 0.411123167
+0.766373412 0.372483798 0.410797654
+0.767350929 0.372156688 0.410472141
+0.768328446 0.371829998 0.410146628
+0.769305963 0.371503728 0.409821114
+0.770283480 0.371177875 0.409495601
+0.771260997 0.370852441 0.409170088
+0.772238514 0.370527424 0.408844575
+0.773216031 0.370202822 0.408519062
+0.774193548 0.369878636 0.408193548
+0.775171065 0.369556545 0.407868035
+0.776148583 0.369242788 0.407542522
+0.777126100 0.368929447 0.407217009
+0.778103617 0.368616521 0.406891496
+0.779081134 0.368304008 0.406565982
+0.780058651 0.367991909 0.406240469
+0.781036168 0.367680221 0.405914956
+0.782013685 0.367368945 0.405589443
+0.782991202 0.367058080 0.405263930
+0.783968719 0.366747624 0.404938416
+0.784946237 0.366437577 0.404612903
+0.785923754 0.366137243 0.404287390
+0.786901271 0.365837858 0.403961877
+0.787878788 0.365538882 0.403636364
+0.788856305 0.365240312 0.403310850
+0.789833822 0.364942147 0.402985337
+0.790811339 0.364644388 0.402659824
+0.791788856 0.364347034 0.402334311
+0.792766373 0.364050082 0.402008798
+0.793743891 0.363753534 0.401683284
+0.794721408 0.363457387 0.401357771
+0.795698925 0.363168850 0.401032258
+0.796676442 0.362883585 0.400706745
+0.797653959 0.362598720 0.400381232
+0.798631476 0.362314253 0.400055718
+0.799608993 0.362030183 0.399730205
+0.800586510 0.361746510 0.399404692
+0.801564027 0.361463233 0.399079179
+0.802541544 0.361180350 0.398753666
+0.803519062 0.360897862 0.398428152
+0.804496579 0.360615767 0.398102639
+0.805474096 0.360339063 0.397777126
+0.806451613 0.360068060 0.397451613
+0.807429130 0.359797445 0.397126100
+0.808406647 0.359527218 0.396800587
+0.809384164 0.359257379 0.396475073
+0.810361681 0.358987926 0.396149560
+0.811339198 0.358718858 0.395824047
+0.812316716 0.358450176 0.395498534
+0.813294233 0.358181877 0.395173021
+0.814271750 0.357913962 0.394847507
+0.815249267 0.357649114 0.394521994
+0.816226784 0.357392487 0.394196481
+0.817204301 0.357136239 0.393870968
+0.818181818 0.356880367 0.393545455
+0.819159335 0.356624870 0.393219941
+0.820136852 0.356369749 0.392894428
+0.821114370 0.356115002 0.392568915
+0.822091887 0.355860628 0.392243402
+0.823069404 0.355606627 0.391917889
+0.824046921 0.355352998 0.391592375
+0.825024438 0.355100007 0.391266862
+0.826001955 0.354857853 0.390941349
+0.826979472 0.354616064 0.390615836
+0.827956989 0.354374639 0.390290323
+0.828934506 0.354133576 0.389964809
+0.829912023 0.353892876 0.389639296
+0.830889541 0.353652537 0.389313783
+0.831867058 0.353412559 0.388988270
+0.832844575 0.353172940 0.388662757
+0.833822092 0.352933680 0.388337243
+0.834799609 0.352694779 0.388011730
+0.835777126 0.352464927 0.387686217
+0.836754643 0.352237669 0.387360704
+0.837732160 0.352010761 0.387035191
+0.838709677 0.351784201 0.386709677
+0.839687195 0.351557989 0.386384164
+0.840664712 0.351332125 0.386058651
+0.841642229 0.351106607 0.385733138
+0.842619746 0.350881434 0.385407625
+0.843597263 0.350656607 0.385082111
+0.844574780 0.350432123 0.384756598
+0.845552297 0.350214269 0.384431085
+0.846529814 0.350001593 0.384105572
+0.847507331 0.349789250 0.383780059
+0.848484848 0.349577241 0.383454545
+0.849462366 0.349365564 0.383129032
+0.850439883 0.349154220 0.382803519
+0.851417400 0.348943206 0.382478006
+0.852394917 0.348732523 0.382152493
+0.853372434 0.348522169 0.381826979
+0.854349951 0.348312145 0.381501466
+0.855327468 0.348106237 0.381175953
+0.856304985 0.347908171 0.380850440
+0.857282502 0.347710423 0.380524927
+0.858260020 0.347512992 0.380199413
+0.859237537 0.347315877 0.379873900
+0.860215054 0.347119078 0.379548387
+0.861192571 0.346922593 0.379222874
+0.862170088 0.346726422 0.378897361
+0.863147605 0.346530564 0.378571848
+0.864125122 0.346335018 0.378246334
+0.865102639 0.346140990 0.377920821
+0.866080156 0.345957546 0.377595308
+0.867057674 0.345774402 0.377269795
+0.868035191 0.345591557 0.376944282
+0.869012708 0.345409010 0.376618768
+0.869990225 0.345226762 0.376293255
+0.870967742 0.345044810 0.375967742
+0.871945259 0.344863155 0.375642229
+0.872922776 0.344681795 0.375316716
+0.873900293 0.344500730 0.374991202
+0.874877810 0.344319959 0.374665689
+0.875855327 0.344149671 0.374340176
+0.876832845 0.343981121 0.374014663
+0.877810362 0.343812851 0.373689150
+0.878787879 0.343644861 0.373363636
+0.879765396 0.343477150 0.373038123
+0.880742913 0.343309718 0.372712610
+0.881720430 0.343142563 0.372387097
+0.882697947 0.342975685 0.372061584
+0.883675464 0.342809084 0.371736070
+0.884652981 0.342642758 0.371410557
+0.885630499 0.342484320 0.371085044
+0.886608016 0.342330335 0.370759531
+0.887585533 0.342176611 0.370434018
+0.888563050 0.342023148 0.370108504
+0.889540567 0.341869943 0.369782991
+0.890518084 0.341716998 0.369457478
+0.891495601 0.341564311 0.369131965
+0.892473118 0.341411881 0.368806452
+0.893450635 0.341259709 0.368480938
+0.894428152 0.341107792 0.368155425
+0.895405670 0.340961091 0.367829912
+0.896383187 0.340821627 0.367504399
+0.897360704 0.340682403 0.367178886
+0.898338221 0.340543418 0.366853372
+0.899315738 0.340404672 0.366527859
+0.900293255 0.340266165 0.366202346
+0.901270772 0.340127896 0.365876833
+0.902248289 0.339989864 0.365551320
+0.903225806 0.339852068 0.365225806
+0.904203324 0.339714508 0.364900293
+0.905180841 0.339579421 0.364574780
+0.906158358 0.339454415 0.364249267
+0.907135875 0.339329627 0.363923754
+0.908113392 0.339205058 0.363598240
+0.909090909 0.339080706 0.363272727
+0.910068426 0.338956572 0.362947214
+0.911045943 0.338832654 0.362621701
+0.912023460 0.338708952 0.362296188
+0.913000978 0.338585466 0.361970674
+0.913978495 0.338462194 0.361645161
+0.914956012 0.338339137 0.361319648
+0.915933529 0.338227961 0.360994135
+0.916911046 0.338117532 0.360668622
+0.917888563 0.338007299 0.360343109
+0.918866080 0.337897261 0.360017595
+0.919843597 0.337787419 0.359692082
+0.920821114 0.337677771 0.359366569
+0.921798631 0.337568317 0.359041056
+0.922776149 0.337459057 0.358715543
+0.923753666 0.337349989 0.358390029
+0.924731183 0.337241115 0.358064516
+0.925708700 0.337141380 0.357739003
+0.926686217 0.337045215 0.357413490
+0.927663734 0.336949224 0.357087977
+0.928641251 0.336853406 0.356762463
+0.929618768 0.336757760 0.356436950
+0.930596285 0.336662286 0.356111437
+0.931573803 0.336566984 0.355785924
+0.932551320 0.336471852 0.355460411
+0.933528837 0.336376891 0.355134897
+0.934506354 0.336282100 0.354809384
+0.935483871 0.336193646 0.354483871
+0.936461388 0.336111639 0.354158358
+0.937438905 0.336029782 0.353832845
+0.938416422 0.335948074 0.353507331
+0.939393939 0.335866515 0.353181818
+0.940371457 0.335785105 0.352856305
+0.941348974 0.335703844 0.352530792
+0.942326491 0.335622730 0.352205279
+0.943304008 0.335541763 0.351879765
+0.944281525 0.335460944 0.351554252
+0.945259042 0.335383602 0.351228739
+0.946236559 0.335315631 0.350903226
+0.947214076 0.335247787 0.350577713
+0.948191593 0.335180068 0.350252199
+0.949169110 0.335112475 0.349926686
+0.950146628 0.335045006 0.349601173
+0.951124145 0.334977661 0.349275660
+0.952101662 0.334910441 0.348950147
+0.953079179 0.334843345 0.348624633
+0.954056696 0.334776372 0.348299120
+0.955034213 0.334709966 0.347973607
+0.956011730 0.334655899 0.347648094
+0.956989247 0.334601934 0.347322581
+0.957966764 0.334548070 0.346997067
+0.958944282 0.334494307 0.346671554
+0.959921799 0.334440645 0.346346041
+0.960899316 0.334387083 0.346020528
+0.961876833 0.334333620 0.345695015
+0.962854350 0.334280258 0.345369501
+0.963831867 0.334226995 0.345043988
+0.964809384 0.334173831 0.344718475
+0.965786901 0.334131034 0.344392962
+0.966764418 0.334090804 0.344067449
+0.967741935 0.334050649 0.343741935
+0.968719453 0.334010571 0.343416422
+0.969696970 0.333970568 0.343090909
+0.970674487 0.333930642 0.342765396
+0.971652004 0.333890791 0.342439883
+0.972629521 0.333851014 0.342114370
+0.973607038 0.333811314 0.341788856
+0.974584555 0.333771687 0.341463343
+0.975562072 0.333739521 0.341137830
+0.976539589 0.333712869 0.340812317
+0.977517107 0.333686268 0.340486804
+0.978494624 0.333659718 0.340161290
+0.979472141 0.333633219 0.339835777
+0.980449658 0.333606771 0.339510264
+0.981427175 0.333580374 0.339184751
+0.982404692 0.333554026 0.338859238
+0.983382209 0.333527729 0.338533724
+0.984359726 0.333501482 0.338208211
+0.985337243 0.333479745 0.337882698
+0.986314761 0.333466506 0.337557185
+0.987292278 0.333453293 0.337231672
+0.988269795 0.333440106 0.336906158
+0.989247312 0.333426944 0.336580645
+0.990224829 0.333413807 0.336255132
+0.991202346 0.333400697 0.335929619
+0.992179863 0.333387611 0.335604106
+0.993157380 0.333374550 0.335278592
+0.994134897 0.333361515 0.334953079
+0.995112414 0.333350000 0.334627566
+0.996089932 0.333350000 0.334302053
+0.997067449 0.333350000 0.333976540
+0.998044966 0.333350000 0.333651026
+0.999022483 0.333350000 0.333325513
+1.000000000 0.333350000 0.333000000
diff --git a/examples/hybrid/ObstacleAvoidance.fll b/examples/hybrid/ObstacleAvoidance.fll
new file mode 100644
index 0000000..970221b
--- /dev/null
+++ b/examples/hybrid/ObstacleAvoidance.fll
@@ -0,0 +1,43 @@
+Engine: ObstacleAvoidance
+InputVariable: obstacle
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: mSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 100
+ default: nan
+ lock-previous: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: tsSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: left Constant 0.333
+ term: right Constant 0.666
+RuleBlock: mamdani
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: AlgebraicProduct
+ activation: General
+ rule: if obstacle is left then mSteer is right
+ rule: if obstacle is right then mSteer is left
+RuleBlock: takagiSugeno
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if obstacle is left then tsSteer is right
+ rule: if obstacle is right then tsSteer is left \ No newline at end of file
diff --git a/examples/hybrid/ObstacleAvoidance.java b/examples/hybrid/ObstacleAvoidance.java
new file mode 100644
index 0000000..8196670
--- /dev/null
+++ b/examples/hybrid/ObstacleAvoidance.java
@@ -0,0 +1,86 @@
+import com.fuzzylite.*;
+import com.fuzzylite.activation.*
+import com.fuzzylite.defuzzifier.*;
+import com.fuzzylite.factory.*;
+import com.fuzzylite.hedge.*;
+import com.fuzzylite.imex.*;
+import com.fuzzylite.norm.*;
+import com.fuzzylite.norm.s.*;
+import com.fuzzylite.norm.t.*;
+import com.fuzzylite.rule.*;
+import com.fuzzylite.term.*;
+import com.fuzzylite.variable.*;
+
+public class ObstacleAvoidance{
+public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
+Engine engine = new Engine();
+engine.setName("ObstacleAvoidance");
+engine.setDescription("");
+
+InputVariable obstacle = new InputVariable();
+obstacle.setName("obstacle");
+obstacle.setDescription("");
+obstacle.setEnabled(true);
+obstacle.setRange(0.000, 1.000);
+obstacle.setLockValueInRange(false);
+obstacle.addTerm(new Ramp("left", 1.000, 0.000));
+obstacle.addTerm(new Ramp("right", 0.000, 1.000));
+engine.addInputVariable(obstacle);
+
+OutputVariable mSteer = new OutputVariable();
+mSteer.setName("mSteer");
+mSteer.setDescription("");
+mSteer.setEnabled(true);
+mSteer.setRange(0.000, 1.000);
+mSteer.setLockValueInRange(false);
+mSteer.setAggregation(new Maximum());
+mSteer.setDefuzzifier(new Centroid(100));
+mSteer.setDefaultValue(Double.NaN);
+mSteer.setLockPreviousValue(false);
+mSteer.addTerm(new Ramp("left", 1.000, 0.000));
+mSteer.addTerm(new Ramp("right", 0.000, 1.000));
+engine.addOutputVariable(mSteer);
+
+OutputVariable tsSteer = new OutputVariable();
+tsSteer.setName("tsSteer");
+tsSteer.setDescription("");
+tsSteer.setEnabled(true);
+tsSteer.setRange(0.000, 1.000);
+tsSteer.setLockValueInRange(false);
+tsSteer.setAggregation(new Maximum());
+tsSteer.setDefuzzifier(new WeightedAverage("Automatic"));
+tsSteer.setDefaultValue(Double.NaN);
+tsSteer.setLockPreviousValue(false);
+tsSteer.addTerm(new Constant("left", 0.333));
+tsSteer.addTerm(new Constant("right", 0.666));
+engine.addOutputVariable(tsSteer);
+
+RuleBlock mamdani = new RuleBlock();
+mamdani.setName("mamdani");
+mamdani.setDescription("");
+mamdani.setEnabled(true);
+mamdani.setConjunction(null);
+mamdani.setDisjunction(null);
+mamdani.setImplication(new AlgebraicProduct());
+mamdani.setActivation(new General());
+mamdani.addRule(Rule.parse("if obstacle is left then mSteer is right", engine));
+mamdani.addRule(Rule.parse("if obstacle is right then mSteer is left", engine));
+engine.addRuleBlock(mamdani);
+
+RuleBlock takagiSugeno = new RuleBlock();
+takagiSugeno.setName("takagiSugeno");
+takagiSugeno.setDescription("");
+takagiSugeno.setEnabled(true);
+takagiSugeno.setConjunction(null);
+takagiSugeno.setDisjunction(null);
+takagiSugeno.setImplication(null);
+takagiSugeno.setActivation(new General());
+takagiSugeno.addRule(Rule.parse("if obstacle is left then tsSteer is right", engine));
+takagiSugeno.addRule(Rule.parse("if obstacle is right then tsSteer is left", engine));
+engine.addRuleBlock(takagiSugeno);
+
+
+}
+}
diff --git a/examples/hybrid/ObstacleAvoidance.pdf b/examples/hybrid/ObstacleAvoidance.pdf
new file mode 100644
index 0000000..ad74e68
--- /dev/null
+++ b/examples/hybrid/ObstacleAvoidance.pdf
Binary files differ
diff --git a/examples/hybrid/tipper.R b/examples/hybrid/tipper.R
new file mode 100644
index 0000000..ba11351
--- /dev/null
+++ b/examples/hybrid/tipper.R
@@ -0,0 +1,109 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "tipper"
+engine.description = "(service and food) -> (tip)"
+engine.fll = "Engine: tipper
+description: (service and food) -> (tip)
+InputVariable: service
+ description: quality of service
+ enabled: true
+ range: 0.000 10.000
+ lock-range: true
+ term: poor Trapezoid 0.000 0.000 2.500 5.000
+ term: good Triangle 2.500 5.000 7.500
+ term: excellent Trapezoid 5.000 7.500 10.000 10.000
+InputVariable: food
+ description: quality of food
+ enabled: true
+ range: 0.000 10.000
+ lock-range: true
+ term: rancid Trapezoid 0.000 0.000 2.500 7.500
+ term: delicious Trapezoid 2.500 7.500 10.000 10.000
+OutputVariable: mTip
+ description: tip based on Mamdani inference
+ enabled: true
+ range: 0.000 30.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 100
+ default: nan
+ lock-previous: false
+ term: cheap Triangle 0.000 5.000 10.000
+ term: average Triangle 10.000 15.000 20.000
+ term: generous Triangle 20.000 25.000 30.000
+OutputVariable: tsTip
+ description: tip based on Takagi-Sugeno inference
+ enabled: true
+ range: 0.000 30.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: cheap Constant 5.000
+ term: average Constant 15.000
+ term: generous Constant 25.000
+RuleBlock: mamdani
+ description: Mamdani inference
+ enabled: true
+ conjunction: AlgebraicProduct
+ disjunction: AlgebraicSum
+ implication: Minimum
+ activation: General
+ rule: if service is poor or food is rancid then mTip is cheap
+ rule: if service is good then mTip is average
+ rule: if service is excellent or food is delicious then mTip is generous with 0.5
+ rule: if service is excellent and food is delicious then mTip is generous with 1.0
+RuleBlock: takagiSugeno
+ description: Takagi-Sugeno inference
+ enabled: true
+ conjunction: AlgebraicProduct
+ disjunction: AlgebraicSum
+ implication: none
+ activation: General
+ rule: if service is poor or food is rancid then tsTip is cheap
+ rule: if service is good then tsTip is average
+ rule: if service is excellent or food is delicious then tsTip is generous with 0.5
+ rule: if service is excellent and food is delicious then tsTip is generous with 1.0"
+
+engine.fldFile = "tipper.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1i2_o1 = ggplot(engine.df, aes(service, food)) +
+ geom_tile(aes(fill=mTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=service, y=food, z=mTip), color="black") +
+ ggtitle("(service, food) = mTip")
+
+engine.plot.i2i1_o1 = ggplot(engine.df, aes(food, service)) +
+ geom_tile(aes(fill=mTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=food, y=service, z=mTip), color="black") +
+ ggtitle("(food, service) = mTip")
+
+engine.plot.i1i2_o2 = ggplot(engine.df, aes(service, food)) +
+ geom_tile(aes(fill=tsTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=service, y=food, z=tsTip), color="black") +
+ ggtitle("(service, food) = tsTip")
+
+engine.plot.i2i1_o2 = ggplot(engine.df, aes(food, service)) +
+ geom_tile(aes(fill=tsTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=food, y=service, z=tsTip), color="black") +
+ ggtitle("(food, service) = tsTip")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1i2_o1, engine.plot.i2i1_o1, engine.plot.i1i2_o2, engine.plot.i2i1_o2, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/hybrid/tipper.cpp b/examples/hybrid/tipper.cpp
new file mode 100644
index 0000000..57bcc78
--- /dev/null
+++ b/examples/hybrid/tipper.cpp
@@ -0,0 +1,92 @@
+#include <fl/Headers.h>
+
+int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
+using namespace fl;
+
+Engine* engine = new Engine;
+engine->setName("tipper");
+engine->setDescription("(service and food) -> (tip)");
+
+InputVariable* service = new InputVariable;
+service->setName("service");
+service->setDescription("quality of service");
+service->setEnabled(true);
+service->setRange(0.000, 10.000);
+service->setLockValueInRange(true);
+service->addTerm(new Trapezoid("poor", 0.000, 0.000, 2.500, 5.000));
+service->addTerm(new Triangle("good", 2.500, 5.000, 7.500));
+service->addTerm(new Trapezoid("excellent", 5.000, 7.500, 10.000, 10.000));
+engine->addInputVariable(service);
+
+InputVariable* food = new InputVariable;
+food->setName("food");
+food->setDescription("quality of food");
+food->setEnabled(true);
+food->setRange(0.000, 10.000);
+food->setLockValueInRange(true);
+food->addTerm(new Trapezoid("rancid", 0.000, 0.000, 2.500, 7.500));
+food->addTerm(new Trapezoid("delicious", 2.500, 7.500, 10.000, 10.000));
+engine->addInputVariable(food);
+
+OutputVariable* mTip = new OutputVariable;
+mTip->setName("mTip");
+mTip->setDescription("tip based on Mamdani inference");
+mTip->setEnabled(true);
+mTip->setRange(0.000, 30.000);
+mTip->setLockValueInRange(false);
+mTip->setAggregation(new Maximum);
+mTip->setDefuzzifier(new Centroid(100));
+mTip->setDefaultValue(fl::nan);
+mTip->setLockPreviousValue(false);
+mTip->addTerm(new Triangle("cheap", 0.000, 5.000, 10.000));
+mTip->addTerm(new Triangle("average", 10.000, 15.000, 20.000));
+mTip->addTerm(new Triangle("generous", 20.000, 25.000, 30.000));
+engine->addOutputVariable(mTip);
+
+OutputVariable* tsTip = new OutputVariable;
+tsTip->setName("tsTip");
+tsTip->setDescription("tip based on Takagi-Sugeno inference");
+tsTip->setEnabled(true);
+tsTip->setRange(0.000, 30.000);
+tsTip->setLockValueInRange(false);
+tsTip->setAggregation(fl::null);
+tsTip->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+tsTip->setDefaultValue(fl::nan);
+tsTip->setLockPreviousValue(false);
+tsTip->addTerm(new Constant("cheap", 5.000));
+tsTip->addTerm(new Constant("average", 15.000));
+tsTip->addTerm(new Constant("generous", 25.000));
+engine->addOutputVariable(tsTip);
+
+RuleBlock* mamdani = new RuleBlock;
+mamdani->setName("mamdani");
+mamdani->setDescription("Mamdani inference");
+mamdani->setEnabled(true);
+mamdani->setConjunction(new AlgebraicProduct);
+mamdani->setDisjunction(new AlgebraicSum);
+mamdani->setImplication(new Minimum);
+mamdani->setActivation(new General);
+mamdani->addRule(Rule::parse("if service is poor or food is rancid then mTip is cheap", engine));
+mamdani->addRule(Rule::parse("if service is good then mTip is average", engine));
+mamdani->addRule(Rule::parse("if service is excellent or food is delicious then mTip is generous with 0.5", engine));
+mamdani->addRule(Rule::parse("if service is excellent and food is delicious then mTip is generous with 1.0", engine));
+engine->addRuleBlock(mamdani);
+
+RuleBlock* takagiSugeno = new RuleBlock;
+takagiSugeno->setName("takagiSugeno");
+takagiSugeno->setDescription("Takagi-Sugeno inference");
+takagiSugeno->setEnabled(true);
+takagiSugeno->setConjunction(new AlgebraicProduct);
+takagiSugeno->setDisjunction(new AlgebraicSum);
+takagiSugeno->setImplication(fl::null);
+takagiSugeno->setActivation(new General);
+takagiSugeno->addRule(Rule::parse("if service is poor or food is rancid then tsTip is cheap", engine));
+takagiSugeno->addRule(Rule::parse("if service is good then tsTip is average", engine));
+takagiSugeno->addRule(Rule::parse("if service is excellent or food is delicious then tsTip is generous with 0.5", engine));
+takagiSugeno->addRule(Rule::parse("if service is excellent and food is delicious then tsTip is generous with 1.0", engine));
+engine->addRuleBlock(takagiSugeno);
+
+
+}
diff --git a/examples/hybrid/tipper.fcl b/examples/hybrid/tipper.fcl
new file mode 100644
index 0000000..299dbb8
--- /dev/null
+++ b/examples/hybrid/tipper.fcl
@@ -0,0 +1,66 @@
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK tipper
+
+VAR_INPUT
+ service: REAL;
+ food: REAL;
+END_VAR
+
+VAR_OUTPUT
+ mTip: REAL;
+ tsTip: REAL;
+END_VAR
+
+FUZZIFY service
+ RANGE := (0.000 .. 10.000);
+ TERM poor := Trapezoid 0.000 0.000 2.500 5.000;
+ TERM good := Triangle 2.500 5.000 7.500;
+ TERM excellent := Trapezoid 5.000 7.500 10.000 10.000;
+END_FUZZIFY
+
+FUZZIFY food
+ RANGE := (0.000 .. 10.000);
+ TERM rancid := Trapezoid 0.000 0.000 2.500 7.500;
+ TERM delicious := Trapezoid 2.500 7.500 10.000 10.000;
+END_FUZZIFY
+
+DEFUZZIFY mTip
+ RANGE := (0.000 .. 30.000);
+ TERM cheap := Triangle 0.000 5.000 10.000;
+ TERM average := Triangle 10.000 15.000 20.000;
+ TERM generous := Triangle 20.000 25.000 30.000;
+ METHOD : COG;
+ ACCU : MAX;
+ DEFAULT := nan;
+END_DEFUZZIFY
+
+DEFUZZIFY tsTip
+ RANGE := (0.000 .. 30.000);
+ TERM cheap := 5.000;
+ TERM average := 15.000;
+ TERM generous := 25.000;
+ METHOD : COGS;
+ DEFAULT := nan;
+END_DEFUZZIFY
+
+RULEBLOCK mamdani
+ AND : PROD;
+ OR : ASUM;
+ ACT : MIN;
+ RULE 1 : if service is poor or food is rancid then mTip is cheap
+ RULE 2 : if service is good then mTip is average
+ RULE 3 : if service is excellent or food is delicious then mTip is generous with 0.5
+ RULE 4 : if service is excellent and food is delicious then mTip is generous with 1.0
+END_RULEBLOCK
+
+RULEBLOCK takagiSugeno
+ AND : PROD;
+ OR : ASUM;
+ RULE 1 : if service is poor or food is rancid then tsTip is cheap
+ RULE 2 : if service is good then tsTip is average
+ RULE 3 : if service is excellent or food is delicious then tsTip is generous with 0.5
+ RULE 4 : if service is excellent and food is delicious then tsTip is generous with 1.0
+END_RULEBLOCK
+
+END_FUNCTION_BLOCK
diff --git a/examples/hybrid/tipper.fis b/examples/hybrid/tipper.fis
new file mode 100644
index 0000000..abd850a
--- /dev/null
+++ b/examples/hybrid/tipper.fis
@@ -0,0 +1,57 @@
+#Code automatically generated with fuzzylite 6.0.
+
+[System]
+Name='tipper'
+Type='hybrid'
+Version=6.0
+NumInputs=2
+NumOutputs=2
+NumRules=8
+AndMethod='prod'
+OrMethod='probor'
+ImpMethod='min'
+AggMethod='max'
+DefuzzMethod='centroid'
+
+[Input1]
+Name='service'
+Range=[0.000 10.000]
+NumMFs=3
+MF1='poor':'trapmf',[0.000 0.000 2.500 5.000]
+MF2='good':'trimf',[2.500 5.000 7.500]
+MF3='excellent':'trapmf',[5.000 7.500 10.000 10.000]
+
+[Input2]
+Name='food'
+Range=[0.000 10.000]
+NumMFs=2
+MF1='rancid':'trapmf',[0.000 0.000 2.500 7.500]
+MF2='delicious':'trapmf',[2.500 7.500 10.000 10.000]
+
+[Output1]
+Name='mTip'
+Range=[0.000 30.000]
+NumMFs=3
+MF1='cheap':'trimf',[0.000 5.000 10.000]
+MF2='average':'trimf',[10.000 15.000 20.000]
+MF3='generous':'trimf',[20.000 25.000 30.000]
+
+[Output2]
+Name='tsTip'
+Range=[0.000 30.000]
+NumMFs=3
+MF1='cheap':'constant',[5.000]
+MF2='average':'constant',[15.000]
+MF3='generous':'constant',[25.000]
+
+[Rules]
+# RuleBlock mamdani
+1.000 1.000 , 1.000 0.000 (1.000) : 2
+2.000 0.000 , 2.000 0.000 (1.000) : 1
+3.000 2.000 , 3.000 0.000 (0.500) : 2
+3.000 2.000 , 3.000 0.000 (1.000) : 1
+# RuleBlock takagiSugeno
+1.000 1.000 , 0.000 1.000 (1.000) : 2
+2.000 0.000 , 0.000 2.000 (1.000) : 1
+3.000 2.000 , 0.000 3.000 (0.500) : 2
+3.000 2.000 , 0.000 3.000 (1.000) : 1
diff --git a/examples/hybrid/tipper.fld b/examples/hybrid/tipper.fld
new file mode 100644
index 0000000..7a8e29d
--- /dev/null
+++ b/examples/hybrid/tipper.fld
@@ -0,0 +1,1025 @@
+service food mTip tsTip
+0.000000000 0.000000000 4.998950210 5.000000000
+0.000000000 0.322580645 4.998950210 5.000000000
+0.000000000 0.645161290 4.998950210 5.000000000
+0.000000000 0.967741935 4.998950210 5.000000000
+0.000000000 1.290322581 4.998950210 5.000000000
+0.000000000 1.612903226 4.998950210 5.000000000
+0.000000000 1.935483871 4.998950210 5.000000000
+0.000000000 2.258064516 4.998950210 5.000000000
+0.000000000 2.580645161 5.314026132 5.160000000
+0.000000000 2.903225806 6.467756859 5.775193798
+0.000000000 3.225806452 7.452789474 6.353383459
+0.000000000 3.548387097 8.316896407 6.897810219
+0.000000000 3.870967742 9.067963620 7.411347518
+0.000000000 4.193548387 9.734585733 7.896551724
+0.000000000 4.516129032 10.322182298 8.355704698
+0.000000000 4.838709677 10.846060307 8.790849673
+0.000000000 5.161290323 11.316227524 9.203821656
+0.000000000 5.483870968 11.733949841 9.596273292
+0.000000000 5.806451613 12.115369655 9.969696970
+0.000000000 6.129032258 12.452152483 10.325443787
+0.000000000 6.451612903 12.762450565 10.664739884
+0.000000000 6.774193548 13.037607639 10.988700565
+0.000000000 7.096774194 13.291172539 11.298342541
+0.000000000 7.419354839 13.516499633 11.594594595
+0.000000000 7.741935484 13.570706205 11.666666667
+0.000000000 8.064516129 13.570706205 11.666666667
+0.000000000 8.387096774 13.570706205 11.666666667
+0.000000000 8.709677419 13.570706205 11.666666667
+0.000000000 9.032258065 13.570706205 11.666666667
+0.000000000 9.354838710 13.570706205 11.666666667
+0.000000000 9.677419355 13.570706205 11.666666667
+0.000000000 10.000000000 13.570706205 11.666666667
+0.322580645 0.000000000 4.998950210 5.000000000
+0.322580645 0.322580645 4.998950210 5.000000000
+0.322580645 0.645161290 4.998950210 5.000000000
+0.322580645 0.967741935 4.998950210 5.000000000
+0.322580645 1.290322581 4.998950210 5.000000000
+0.322580645 1.612903226 4.998950210 5.000000000
+0.322580645 1.935483871 4.998950210 5.000000000
+0.322580645 2.258064516 4.998950210 5.000000000
+0.322580645 2.580645161 5.314026132 5.160000000
+0.322580645 2.903225806 6.467756859 5.775193798
+0.322580645 3.225806452 7.452789474 6.353383459
+0.322580645 3.548387097 8.316896407 6.897810219
+0.322580645 3.870967742 9.067963620 7.411347518
+0.322580645 4.193548387 9.734585733 7.896551724
+0.322580645 4.516129032 10.322182298 8.355704698
+0.322580645 4.838709677 10.846060307 8.790849673
+0.322580645 5.161290323 11.316227524 9.203821656
+0.322580645 5.483870968 11.733949841 9.596273292
+0.322580645 5.806451613 12.115369655 9.969696970
+0.322580645 6.129032258 12.452152483 10.325443787
+0.322580645 6.451612903 12.762450565 10.664739884
+0.322580645 6.774193548 13.037607639 10.988700565
+0.322580645 7.096774194 13.291172539 11.298342541
+0.322580645 7.419354839 13.516499633 11.594594595
+0.322580645 7.741935484 13.570706205 11.666666667
+0.322580645 8.064516129 13.570706205 11.666666667
+0.322580645 8.387096774 13.570706205 11.666666667
+0.322580645 8.709677419 13.570706205 11.666666667
+0.322580645 9.032258065 13.570706205 11.666666667
+0.322580645 9.354838710 13.570706205 11.666666667
+0.322580645 9.677419355 13.570706205 11.666666667
+0.322580645 10.000000000 13.570706205 11.666666667
+0.645161290 0.000000000 4.998950210 5.000000000
+0.645161290 0.322580645 4.998950210 5.000000000
+0.645161290 0.645161290 4.998950210 5.000000000
+0.645161290 0.967741935 4.998950210 5.000000000
+0.645161290 1.290322581 4.998950210 5.000000000
+0.645161290 1.612903226 4.998950210 5.000000000
+0.645161290 1.935483871 4.998950210 5.000000000
+0.645161290 2.258064516 4.998950210 5.000000000
+0.645161290 2.580645161 5.314026132 5.160000000
+0.645161290 2.903225806 6.467756859 5.775193798
+0.645161290 3.225806452 7.452789474 6.353383459
+0.645161290 3.548387097 8.316896407 6.897810219
+0.645161290 3.870967742 9.067963620 7.411347518
+0.645161290 4.193548387 9.734585733 7.896551724
+0.645161290 4.516129032 10.322182298 8.355704698
+0.645161290 4.838709677 10.846060307 8.790849673
+0.645161290 5.161290323 11.316227524 9.203821656
+0.645161290 5.483870968 11.733949841 9.596273292
+0.645161290 5.806451613 12.115369655 9.969696970
+0.645161290 6.129032258 12.452152483 10.325443787
+0.645161290 6.451612903 12.762450565 10.664739884
+0.645161290 6.774193548 13.037607639 10.988700565
+0.645161290 7.096774194 13.291172539 11.298342541
+0.645161290 7.419354839 13.516499633 11.594594595
+0.645161290 7.741935484 13.570706205 11.666666667
+0.645161290 8.064516129 13.570706205 11.666666667
+0.645161290 8.387096774 13.570706205 11.666666667
+0.645161290 8.709677419 13.570706205 11.666666667
+0.645161290 9.032258065 13.570706205 11.666666667
+0.645161290 9.354838710 13.570706205 11.666666667
+0.645161290 9.677419355 13.570706205 11.666666667
+0.645161290 10.000000000 13.570706205 11.666666667
+0.967741935 0.000000000 4.998950210 5.000000000
+0.967741935 0.322580645 4.998950210 5.000000000
+0.967741935 0.645161290 4.998950210 5.000000000
+0.967741935 0.967741935 4.998950210 5.000000000
+0.967741935 1.290322581 4.998950210 5.000000000
+0.967741935 1.612903226 4.998950210 5.000000000
+0.967741935 1.935483871 4.998950210 5.000000000
+0.967741935 2.258064516 4.998950210 5.000000000
+0.967741935 2.580645161 5.314026132 5.160000000
+0.967741935 2.903225806 6.467756859 5.775193798
+0.967741935 3.225806452 7.452789474 6.353383459
+0.967741935 3.548387097 8.316896407 6.897810219
+0.967741935 3.870967742 9.067963620 7.411347518
+0.967741935 4.193548387 9.734585733 7.896551724
+0.967741935 4.516129032 10.322182298 8.355704698
+0.967741935 4.838709677 10.846060307 8.790849673
+0.967741935 5.161290323 11.316227524 9.203821656
+0.967741935 5.483870968 11.733949841 9.596273292
+0.967741935 5.806451613 12.115369655 9.969696970
+0.967741935 6.129032258 12.452152483 10.325443787
+0.967741935 6.451612903 12.762450565 10.664739884
+0.967741935 6.774193548 13.037607639 10.988700565
+0.967741935 7.096774194 13.291172539 11.298342541
+0.967741935 7.419354839 13.516499633 11.594594595
+0.967741935 7.741935484 13.570706205 11.666666667
+0.967741935 8.064516129 13.570706205 11.666666667
+0.967741935 8.387096774 13.570706205 11.666666667
+0.967741935 8.709677419 13.570706205 11.666666667
+0.967741935 9.032258065 13.570706205 11.666666667
+0.967741935 9.354838710 13.570706205 11.666666667
+0.967741935 9.677419355 13.570706205 11.666666667
+0.967741935 10.000000000 13.570706205 11.666666667
+1.290322581 0.000000000 4.998950210 5.000000000
+1.290322581 0.322580645 4.998950210 5.000000000
+1.290322581 0.645161290 4.998950210 5.000000000
+1.290322581 0.967741935 4.998950210 5.000000000
+1.290322581 1.290322581 4.998950210 5.000000000
+1.290322581 1.612903226 4.998950210 5.000000000
+1.290322581 1.935483871 4.998950210 5.000000000
+1.290322581 2.258064516 4.998950210 5.000000000
+1.290322581 2.580645161 5.314026132 5.160000000
+1.290322581 2.903225806 6.467756859 5.775193798
+1.290322581 3.225806452 7.452789474 6.353383459
+1.290322581 3.548387097 8.316896407 6.897810219
+1.290322581 3.870967742 9.067963620 7.411347518
+1.290322581 4.193548387 9.734585733 7.896551724
+1.290322581 4.516129032 10.322182298 8.355704698
+1.290322581 4.838709677 10.846060307 8.790849673
+1.290322581 5.161290323 11.316227524 9.203821656
+1.290322581 5.483870968 11.733949841 9.596273292
+1.290322581 5.806451613 12.115369655 9.969696970
+1.290322581 6.129032258 12.452152483 10.325443787
+1.290322581 6.451612903 12.762450565 10.664739884
+1.290322581 6.774193548 13.037607639 10.988700565
+1.290322581 7.096774194 13.291172539 11.298342541
+1.290322581 7.419354839 13.516499633 11.594594595
+1.290322581 7.741935484 13.570706205 11.666666667
+1.290322581 8.064516129 13.570706205 11.666666667
+1.290322581 8.387096774 13.570706205 11.666666667
+1.290322581 8.709677419 13.570706205 11.666666667
+1.290322581 9.032258065 13.570706205 11.666666667
+1.290322581 9.354838710 13.570706205 11.666666667
+1.290322581 9.677419355 13.570706205 11.666666667
+1.290322581 10.000000000 13.570706205 11.666666667
+1.612903226 0.000000000 4.998950210 5.000000000
+1.612903226 0.322580645 4.998950210 5.000000000
+1.612903226 0.645161290 4.998950210 5.000000000
+1.612903226 0.967741935 4.998950210 5.000000000
+1.612903226 1.290322581 4.998950210 5.000000000
+1.612903226 1.612903226 4.998950210 5.000000000
+1.612903226 1.935483871 4.998950210 5.000000000
+1.612903226 2.258064516 4.998950210 5.000000000
+1.612903226 2.580645161 5.314026132 5.160000000
+1.612903226 2.903225806 6.467756859 5.775193798
+1.612903226 3.225806452 7.452789474 6.353383459
+1.612903226 3.548387097 8.316896407 6.897810219
+1.612903226 3.870967742 9.067963620 7.411347518
+1.612903226 4.193548387 9.734585733 7.896551724
+1.612903226 4.516129032 10.322182298 8.355704698
+1.612903226 4.838709677 10.846060307 8.790849673
+1.612903226 5.161290323 11.316227524 9.203821656
+1.612903226 5.483870968 11.733949841 9.596273292
+1.612903226 5.806451613 12.115369655 9.969696970
+1.612903226 6.129032258 12.452152483 10.325443787
+1.612903226 6.451612903 12.762450565 10.664739884
+1.612903226 6.774193548 13.037607639 10.988700565
+1.612903226 7.096774194 13.291172539 11.298342541
+1.612903226 7.419354839 13.516499633 11.594594595
+1.612903226 7.741935484 13.570706205 11.666666667
+1.612903226 8.064516129 13.570706205 11.666666667
+1.612903226 8.387096774 13.570706205 11.666666667
+1.612903226 8.709677419 13.570706205 11.666666667
+1.612903226 9.032258065 13.570706205 11.666666667
+1.612903226 9.354838710 13.570706205 11.666666667
+1.612903226 9.677419355 13.570706205 11.666666667
+1.612903226 10.000000000 13.570706205 11.666666667
+1.935483871 0.000000000 4.998950210 5.000000000
+1.935483871 0.322580645 4.998950210 5.000000000
+1.935483871 0.645161290 4.998950210 5.000000000
+1.935483871 0.967741935 4.998950210 5.000000000
+1.935483871 1.290322581 4.998950210 5.000000000
+1.935483871 1.612903226 4.998950210 5.000000000
+1.935483871 1.935483871 4.998950210 5.000000000
+1.935483871 2.258064516 4.998950210 5.000000000
+1.935483871 2.580645161 5.314026132 5.160000000
+1.935483871 2.903225806 6.467756859 5.775193798
+1.935483871 3.225806452 7.452789474 6.353383459
+1.935483871 3.548387097 8.316896407 6.897810219
+1.935483871 3.870967742 9.067963620 7.411347518
+1.935483871 4.193548387 9.734585733 7.896551724
+1.935483871 4.516129032 10.322182298 8.355704698
+1.935483871 4.838709677 10.846060307 8.790849673
+1.935483871 5.161290323 11.316227524 9.203821656
+1.935483871 5.483870968 11.733949841 9.596273292
+1.935483871 5.806451613 12.115369655 9.969696970
+1.935483871 6.129032258 12.452152483 10.325443787
+1.935483871 6.451612903 12.762450565 10.664739884
+1.935483871 6.774193548 13.037607639 10.988700565
+1.935483871 7.096774194 13.291172539 11.298342541
+1.935483871 7.419354839 13.516499633 11.594594595
+1.935483871 7.741935484 13.570706205 11.666666667
+1.935483871 8.064516129 13.570706205 11.666666667
+1.935483871 8.387096774 13.570706205 11.666666667
+1.935483871 8.709677419 13.570706205 11.666666667
+1.935483871 9.032258065 13.570706205 11.666666667
+1.935483871 9.354838710 13.570706205 11.666666667
+1.935483871 9.677419355 13.570706205 11.666666667
+1.935483871 10.000000000 13.570706205 11.666666667
+2.258064516 0.000000000 4.998950210 5.000000000
+2.258064516 0.322580645 4.998950210 5.000000000
+2.258064516 0.645161290 4.998950210 5.000000000
+2.258064516 0.967741935 4.998950210 5.000000000
+2.258064516 1.290322581 4.998950210 5.000000000
+2.258064516 1.612903226 4.998950210 5.000000000
+2.258064516 1.935483871 4.998950210 5.000000000
+2.258064516 2.258064516 4.998950210 5.000000000
+2.258064516 2.580645161 5.314026132 5.160000000
+2.258064516 2.903225806 6.467756859 5.775193798
+2.258064516 3.225806452 7.452789474 6.353383459
+2.258064516 3.548387097 8.316896407 6.897810219
+2.258064516 3.870967742 9.067963620 7.411347518
+2.258064516 4.193548387 9.734585733 7.896551724
+2.258064516 4.516129032 10.322182298 8.355704698
+2.258064516 4.838709677 10.846060307 8.790849673
+2.258064516 5.161290323 11.316227524 9.203821656
+2.258064516 5.483870968 11.733949841 9.596273292
+2.258064516 5.806451613 12.115369655 9.969696970
+2.258064516 6.129032258 12.452152483 10.325443787
+2.258064516 6.451612903 12.762450565 10.664739884
+2.258064516 6.774193548 13.037607639 10.988700565
+2.258064516 7.096774194 13.291172539 11.298342541
+2.258064516 7.419354839 13.516499633 11.594594595
+2.258064516 7.741935484 13.570706205 11.666666667
+2.258064516 8.064516129 13.570706205 11.666666667
+2.258064516 8.387096774 13.570706205 11.666666667
+2.258064516 8.709677419 13.570706205 11.666666667
+2.258064516 9.032258065 13.570706205 11.666666667
+2.258064516 9.354838710 13.570706205 11.666666667
+2.258064516 9.677419355 13.570706205 11.666666667
+2.258064516 10.000000000 13.570706205 11.666666667
+2.580645161 0.000000000 5.592761972 5.312500000
+2.580645161 0.322580645 5.592761972 5.312500000
+2.580645161 0.645161290 5.592761972 5.312500000
+2.580645161 0.967741935 5.592761972 5.312500000
+2.580645161 1.290322581 5.592761972 5.312500000
+2.580645161 1.612903226 5.592761972 5.312500000
+2.580645161 1.935483871 5.592761972 5.312500000
+2.580645161 2.258064516 5.592761972 5.312500000
+2.580645161 2.580645161 5.880621907 5.465349012
+2.580645161 2.903225806 6.939232958 6.055190858
+2.580645161 3.225806452 7.848835301 6.612674391
+2.580645161 3.548387097 8.651174558 7.140391254
+2.580645161 3.870967742 9.351975577 7.640663528
+2.580645161 4.193548387 9.976796931 8.115577889
+2.580645161 4.516129032 10.530004073 8.567014703
+2.580645161 4.838709677 11.024934815 8.996672905
+2.580645161 5.161290323 11.470583404 9.406091371
+2.580645161 5.483870968 11.867640871 9.796667328
+2.580645161 5.806451613 12.231162308 10.169672290
+2.580645161 6.129032258 12.552900008 10.526265883
+2.580645161 6.451612903 12.849986938 10.867507886
+2.580645161 6.774193548 13.113962484 11.194368756
+2.580645161 7.096774194 13.357668633 11.507738837
+2.580645161 7.419354839 13.574618159 11.808436465
+2.580645161 7.741935484 13.626860714 11.881720430
+2.580645161 8.064516129 13.626860714 11.881720430
+2.580645161 8.387096774 13.626860714 11.881720430
+2.580645161 8.709677419 13.626860714 11.881720430
+2.580645161 9.032258065 13.626860714 11.881720430
+2.580645161 9.354838710 13.626860714 11.881720430
+2.580645161 9.677419355 13.626860714 11.881720430
+2.580645161 10.000000000 13.626860714 11.881720430
+2.903225806 0.000000000 7.283786709 6.388888889
+2.903225806 0.322580645 7.283786709 6.388888889
+2.903225806 0.645161290 7.283786709 6.388888889
+2.903225806 0.967741935 7.283786709 6.388888889
+2.903225806 1.290322581 7.283786709 6.388888889
+2.903225806 1.612903226 7.283786709 6.388888889
+2.903225806 1.935483871 7.283786709 6.388888889
+2.903225806 2.258064516 7.283786709 6.388888889
+2.903225806 2.580645161 7.499955755 6.520624303
+2.903225806 2.903225806 8.305212731 7.035456336
+2.903225806 3.225806452 9.011457616 7.531699979
+2.903225806 3.548387097 9.645097856 8.010344100
+2.903225806 3.870967742 10.207136722 8.472308650
+2.903225806 4.193548387 10.715739625 8.918450561
+2.903225806 4.516129032 11.172892280 9.349569052
+2.903225806 4.838709677 11.587921940 9.766410408
+2.903225806 5.161290323 11.967183067 10.169672290
+2.903225806 5.483870968 12.308758298 10.560007632
+2.903225806 5.806451613 12.624644763 10.938028169
+2.903225806 6.129032258 12.908650399 11.304307635
+2.903225806 6.451612903 13.174140812 11.659384671
+2.903225806 6.774193548 13.414725347 12.003765465
+2.903225806 7.096774194 13.639701953 12.337926161
+2.903225806 7.419354839 13.842390029 12.662315057
+2.903225806 7.741935484 13.891460681 12.741935484
+2.903225806 8.064516129 13.891460681 12.741935484
+2.903225806 8.387096774 13.891460681 12.741935484
+2.903225806 8.709677419 13.891460681 12.741935484
+2.903225806 9.032258065 13.891460681 12.741935484
+2.903225806 9.354838710 13.891460681 12.741935484
+2.903225806 9.677419355 13.891460681 12.741935484
+2.903225806 10.000000000 13.891460681 12.741935484
+3.225806452 0.000000000 8.314651325 7.250000000
+3.225806452 0.322580645 8.314651325 7.250000000
+3.225806452 0.645161290 8.314651325 7.250000000
+3.225806452 0.967741935 8.314651325 7.250000000
+3.225806452 1.290322581 8.314651325 7.250000000
+3.225806452 1.612903226 8.314651325 7.250000000
+3.225806452 1.935483871 8.314651325 7.250000000
+3.225806452 2.258064516 8.314651325 7.250000000
+3.225806452 2.580645161 8.491360774 7.368791474
+3.225806452 2.903225806 9.156409155 7.837810945
+3.225806452 3.225806452 9.746803244 8.297222769
+3.225806452 3.548387097 10.284138020 8.747319166
+3.225806452 3.870967742 10.769427894 9.188380622
+3.225806452 4.193548387 11.214534071 9.620676476
+3.225806452 4.516129032 11.619323393 10.044465468
+3.225806452 4.838709677 11.993033266 10.459996253
+3.225806452 5.161290323 12.340224927 10.867507886
+3.225806452 5.483870968 12.657043434 11.267230289
+3.225806452 5.806451613 12.956823683 11.659384671
+3.225806452 6.129032258 13.232890780 12.044183950
+3.225806452 6.451612903 13.493168128 12.421833125
+3.225806452 6.774193548 13.734211054 12.792529651
+3.225806452 7.096774194 13.966630648 13.156463778
+3.225806452 7.419354839 14.180445683 13.513818877
+3.225806452 7.741935484 14.232664470 13.602150538
+3.225806452 8.064516129 14.232664470 13.602150538
+3.225806452 8.387096774 14.232664470 13.602150538
+3.225806452 8.709677419 14.232664470 13.602150538
+3.225806452 9.032258065 14.232664470 13.602150538
+3.225806452 9.354838710 14.232664470 13.602150538
+3.225806452 9.677419355 14.232664470 13.602150538
+3.225806452 10.000000000 14.232664470 13.602150538
+3.548387097 0.000000000 8.985030201 7.954545455
+3.548387097 0.322580645 8.985030201 7.954545455
+3.548387097 0.645161290 8.985030201 7.954545455
+3.548387097 0.967741935 8.985030201 7.954545455
+3.548387097 1.290322581 8.985030201 7.954545455
+3.548387097 1.612903226 8.985030201 7.954545455
+3.548387097 1.935483871 8.985030201 7.954545455
+3.548387097 2.258064516 8.985030201 7.954545455
+3.548387097 2.580645161 9.137812976 8.065372642
+3.548387097 2.903225806 9.717703976 8.506659369
+3.548387097 3.225806452 10.238351404 8.944737320
+3.548387097 3.548387097 10.720683414 9.379641369
+3.548387097 3.870967742 11.160003933 9.811405883
+3.548387097 4.193548387 11.571126024 10.240064737
+3.548387097 4.516129032 11.950914620 10.665651317
+3.548387097 4.838709677 12.307875007 11.088198536
+3.548387097 5.161290323 12.645356184 11.507738837
+3.548387097 5.483870968 12.960313946 11.924304201
+3.548387097 5.806451613 13.266478726 12.337926161
+3.548387097 6.129032258 13.551156560 12.748635804
+3.548387097 6.451612903 13.831439195 13.156463778
+3.548387097 6.774193548 14.095225315 13.561440308
+3.548387097 7.096774194 14.356367336 13.963595192
+3.548387097 7.419354839 14.605377743 14.362957820
+3.548387097 7.741935484 14.667921566 14.462365591
+3.548387097 8.064516129 14.667921566 14.462365591
+3.548387097 8.387096774 14.667921566 14.462365591
+3.548387097 8.709677419 14.667921566 14.462365591
+3.548387097 9.032258065 14.667921566 14.462365591
+3.548387097 9.354838710 14.667921566 14.462365591
+3.548387097 9.677419355 14.667921566 14.462365591
+3.548387097 10.000000000 14.667921566 14.462365591
+3.870967742 0.000000000 9.432393054 8.541666667
+3.870967742 0.322580645 9.432393054 8.541666667
+3.870967742 0.645161290 9.432393054 8.541666667
+3.870967742 0.967741935 9.432393054 8.541666667
+3.870967742 1.290322581 9.432393054 8.541666667
+3.870967742 1.612903226 9.432393054 8.541666667
+3.870967742 1.935483871 9.432393054 8.541666667
+3.870967742 2.258064516 9.432393054 8.541666667
+3.870967742 2.580645161 9.569971811 8.647671878
+3.870967742 2.903225806 10.095984031 9.072764022
+3.870967742 3.225806452 10.575695895 9.499578059
+3.870967742 3.548387097 11.024096907 9.928124472
+3.870967742 3.870967742 11.442347059 10.358413828
+3.870967742 4.193548387 11.836700132 10.790456784
+3.870967742 4.516129032 12.211639878 11.224264080
+3.870967742 4.838709677 12.568786873 11.659846547
+3.870967742 5.161290323 12.913995839 12.097215103
+3.870967742 5.483870968 13.247084242 12.536380757
+3.870967742 5.806451613 13.573370226 12.977354606
+3.870967742 6.129032258 13.891165979 13.420147843
+3.870967742 6.451612903 14.206686830 13.864771748
+3.870967742 6.774193548 14.518152082 14.311237701
+3.870967742 7.096774194 14.833264590 14.759557170
+3.870967742 7.419354839 15.145455566 15.209741723
+3.870967742 7.741935484 15.224455159 15.322580645
+3.870967742 8.064516129 15.224455159 15.322580645
+3.870967742 8.387096774 15.224455159 15.322580645
+3.870967742 8.709677419 15.224455159 15.322580645
+3.870967742 9.032258065 15.224455159 15.322580645
+3.870967742 9.354838710 15.224455159 15.322580645
+3.870967742 9.677419355 15.224455159 15.322580645
+3.870967742 10.000000000 15.224455159 15.322580645
+4.193548387 0.000000000 9.724829800 9.038461538
+4.193548387 0.322580645 9.724829800 9.038461538
+4.193548387 0.645161290 9.724829800 9.038461538
+4.193548387 0.967741935 9.724829800 9.038461538
+4.193548387 1.290322581 9.724829800 9.038461538
+4.193548387 1.612903226 9.724829800 9.038461538
+4.193548387 1.935483871 9.724829800 9.038461538
+4.193548387 2.258064516 9.724829800 9.038461538
+4.193548387 2.580645161 9.852943138 9.141680907
+4.193548387 2.903225806 10.345918352 9.558110433
+4.193548387 3.225806452 10.802543542 9.980311860
+4.193548387 3.548387097 11.235827387 10.408406027
+4.193548387 3.870967742 11.644759742 10.842517170
+4.193548387 4.193548387 12.040733478 11.282773042
+4.193548387 4.516129032 12.424030547 11.729305038
+4.193548387 4.838709677 12.796980884 12.182248328
+4.193548387 5.161290323 13.166426475 12.641741988
+4.193548387 5.483870968 13.531922324 13.107929151
+4.193548387 5.806451613 13.901663971 13.580957145
+4.193548387 6.129032258 14.268117073 14.060977658
+4.193548387 6.451612903 14.647562125 14.548146895
+4.193548387 6.774193548 15.033372347 15.042625746
+4.193548387 7.096774194 15.433721197 15.544579969
+4.193548387 7.419354839 15.846288602 16.054180370
+4.193548387 7.741935484 15.954652850 16.182795699
+4.193548387 8.064516129 15.954652850 16.182795699
+4.193548387 8.387096774 15.954652850 16.182795699
+4.193548387 8.709677419 15.954652850 16.182795699
+4.193548387 9.032258065 15.954652850 16.182795699
+4.193548387 9.354838710 15.954652850 16.182795699
+4.193548387 9.677419355 15.954652850 16.182795699
+4.193548387 10.000000000 15.954652850 16.182795699
+4.516129032 0.000000000 9.902963105 9.464285714
+4.516129032 0.322580645 9.902963105 9.464285714
+4.516129032 0.645161290 9.902963105 9.464285714
+4.516129032 0.967741935 9.902963105 9.464285714
+4.516129032 1.290322581 9.902963105 9.464285714
+4.516129032 1.612903226 9.902963105 9.464285714
+4.516129032 1.935483871 9.902963105 9.464285714
+4.516129032 2.258064516 9.902963105 9.464285714
+4.516129032 2.580645161 10.025672736 9.566064982
+4.516129032 2.903225806 10.500507438 9.978829026
+4.516129032 3.225806452 10.946239871 10.400856341
+4.516129032 3.548387097 11.376703200 10.832462297
+4.516129032 3.870967742 11.792259146 11.273976741
+4.516129032 4.193548387 12.201356693 11.725744843
+4.516129032 4.516129032 12.604952096 12.188127995
+4.516129032 4.838709677 13.008602620 12.661504771
+4.516129032 5.161290323 13.417792712 13.146271965
+4.516129032 5.483870968 13.834555987 13.642845698
+4.516129032 5.806451613 14.267444692 14.151662612
+4.516129032 6.129032258 14.713512788 14.673181146
+4.516129032 6.451612903 15.186143246 15.207882920
+4.516129032 6.774193548 15.682677037 15.756274213
+4.516129032 7.096774194 16.216113014 16.318887562
+4.516129032 7.419354839 16.788339244 16.896283492
+4.516129032 7.741935484 16.942283864 17.043010753
+4.516129032 8.064516129 16.942283864 17.043010753
+4.516129032 8.387096774 16.942283864 17.043010753
+4.516129032 8.709677419 16.942283864 17.043010753
+4.516129032 9.032258065 16.942283864 17.043010753
+4.516129032 9.354838710 16.942283864 17.043010753
+4.516129032 9.677419355 16.942283864 17.043010753
+4.516129032 10.000000000 16.942283864 17.043010753
+4.838709677 0.000000000 9.987593227 9.833333333
+4.838709677 0.322580645 9.987593227 9.833333333
+4.838709677 0.645161290 9.987593227 9.833333333
+4.838709677 0.967741935 9.987593227 9.833333333
+4.838709677 1.290322581 9.987593227 9.833333333
+4.838709677 1.612903226 9.987593227 9.833333333
+4.838709677 1.935483871 9.987593227 9.833333333
+4.838709677 2.258064516 9.987593227 9.833333333
+4.838709677 2.580645161 10.107937367 9.934574396
+4.838709677 2.903225806 10.576746882 10.347022587
+4.838709677 3.225806452 11.023190342 10.771849382
+4.838709677 3.548387097 11.461860178 11.209620539
+4.838709677 3.870967742 11.892974885 11.660936829
+4.838709677 4.193548387 12.326836015 12.126436782
+4.838709677 4.516129032 12.765557275 12.606799704
+4.838709677 4.838709677 13.215984335 13.102748986
+4.838709677 5.161290323 13.685165434 13.615055734
+4.838709677 5.483870968 14.175297225 14.144542773
+4.838709677 5.806451613 14.699676483 14.692089057
+4.838709677 6.129032258 15.258066385 15.258634538
+4.838709677 6.451612903 15.868732072 15.845185548
+4.838709677 6.774193548 16.535753191 16.452820769
+4.838709677 7.096774194 17.280236196 17.082697848
+4.838709677 7.419354839 18.115344324 17.736060763
+4.838709677 7.741935484 18.343399565 17.903225806
+4.838709677 8.064516129 18.343399565 17.903225806
+4.838709677 8.387096774 18.343399565 17.903225806
+4.838709677 8.709677419 18.343399565 17.903225806
+4.838709677 9.032258065 18.343399565 17.903225806
+4.838709677 9.354838710 18.343399565 17.903225806
+4.838709677 9.677419355 18.343399565 17.903225806
+4.838709677 10.000000000 18.343399565 17.903225806
+5.161290323 0.000000000 10.453438845 10.081967213
+5.161290323 0.322580645 10.453438845 10.081967213
+5.161290323 0.645161290 10.453438845 10.081967213
+5.161290323 0.967741935 10.453438845 10.081967213
+5.161290323 1.290322581 10.453438845 10.081967213
+5.161290323 1.612903226 10.453438845 10.081967213
+5.161290323 1.935483871 10.453438845 10.081967213
+5.161290323 2.258064516 10.453438845 10.081967213
+5.161290323 2.580645161 10.555334150 10.189117452
+5.161290323 2.903225806 10.957766893 10.626095161
+5.161290323 3.225806452 11.358194134 11.076954676
+5.161290323 3.548387097 11.754612081 11.542368165
+5.161290323 3.870967742 12.159885021 12.023051902
+5.161290323 4.193548387 12.572343139 12.519769950
+5.161290323 4.516129032 13.004157242 13.033338207
+5.161290323 4.838709677 13.454843261 13.564628886
+5.161290323 5.161290323 13.937409133 14.114575450
+5.161290323 5.483870968 14.453623313 14.684178093
+5.161290323 5.806451613 15.017597606 15.274509804
+5.161290323 6.129032258 15.634903956 15.886723119
+5.161290323 6.451612903 16.324245881 16.522057627
+5.161290323 6.774193548 17.100135640 17.181848349
+5.161290323 7.096774194 17.987899976 17.867535104
+5.161290323 7.419354839 19.013798273 18.580672994
+5.161290323 7.741935484 19.297725710 18.763440860
+5.161290323 8.064516129 19.297725710 18.763440860
+5.161290323 8.387096774 19.297725710 18.763440860
+5.161290323 8.709677419 19.297725710 18.763440860
+5.161290323 9.032258065 19.297725710 18.763440860
+5.161290323 9.354838710 19.297725710 18.763440860
+5.161290323 9.677419355 19.297725710 18.763440860
+5.161290323 10.000000000 19.297725710 18.763440860
+5.483870968 0.000000000 11.200371425 10.254237288
+5.483870968 0.322580645 11.200371425 10.254237288
+5.483870968 0.645161290 11.200371425 10.254237288
+5.483870968 0.967741935 11.200371425 10.254237288
+5.483870968 1.290322581 11.200371425 10.254237288
+5.483870968 1.612903226 11.200371425 10.254237288
+5.483870968 1.935483871 11.200371425 10.254237288
+5.483870968 2.258064516 11.200371425 10.254237288
+5.483870968 2.580645161 11.275744351 10.373748457
+5.483870968 2.903225806 11.579276776 10.860102906
+5.483870968 3.225806452 11.893660170 11.360174870
+5.483870968 3.548387097 12.214119876 11.874552997
+5.483870968 3.870967742 12.553283322 12.403860107
+5.483870968 4.193548387 12.907426182 12.948755706
+5.483870968 4.516129032 13.285781482 13.509938724
+5.483870968 4.838709677 13.693069775 14.088150508
+5.483870968 5.161290323 14.133110626 14.684178093
+5.483870968 5.483870968 14.617921843 15.298857769
+5.483870968 5.806451613 15.149780175 15.933079002
+5.483870968 6.129032258 15.746811487 16.587788726
+5.483870968 6.451612903 16.415017186 17.263996060
+5.483870968 6.774193548 17.180595436 17.962777500
+5.483870968 7.096774194 18.063069240 18.685282635
+5.483870968 7.419354839 19.094026165 19.432740459
+5.483870968 7.741935484 19.380891828 19.623655914
+5.483870968 8.064516129 19.380891828 19.623655914
+5.483870968 8.387096774 19.380891828 19.623655914
+5.483870968 8.709677419 19.380891828 19.623655914
+5.483870968 9.032258065 19.380891828 19.623655914
+5.483870968 9.354838710 19.380891828 19.623655914
+5.483870968 9.677419355 19.380891828 19.623655914
+5.483870968 10.000000000 19.380891828 19.623655914
+5.806451613 0.000000000 11.792304026 10.438596491
+5.806451613 0.322580645 11.792304026 10.438596491
+5.806451613 0.645161290 11.792304026 10.438596491
+5.806451613 0.967741935 11.792304026 10.438596491
+5.806451613 1.290322581 11.792304026 10.438596491
+5.806451613 1.612903226 11.792304026 10.438596491
+5.806451613 1.935483871 11.792304026 10.438596491
+5.806451613 2.258064516 11.792304026 10.438596491
+5.806451613 2.580645161 11.848083932 10.571165035
+5.806451613 2.903225806 12.077812184 11.109435588
+5.806451613 3.225806452 12.327537589 11.660851868
+5.806451613 3.548387097 12.590635013 12.225901398
+5.806451613 3.870967742 12.875627326 12.805096111
+5.806451613 4.193548387 13.187716001 13.398973895
+5.806451613 4.516129032 13.525122531 14.008100260
+5.806451613 4.838709677 13.897938757 14.633070135
+5.806451613 5.161290323 14.310798618 15.274509804
+5.806451613 5.483870968 14.768759505 15.933079002
+5.806451613 5.806451613 15.285527581 16.609473175
+5.806451613 6.129032258 15.867812510 17.304425935
+5.806451613 6.451612903 16.531661050 18.018711707
+5.806451613 6.774193548 17.302903875 18.753148615
+5.806451613 7.096774194 18.198839735 19.508601601
+5.806451613 7.419354839 19.260035649 20.285985830
+5.806451613 7.741935484 19.557269007 20.483870968
+5.806451613 8.064516129 19.557269007 20.483870968
+5.806451613 8.387096774 19.557269007 20.483870968
+5.806451613 8.709677419 19.557269007 20.483870968
+5.806451613 9.032258065 19.557269007 20.483870968
+5.806451613 9.354838710 19.557269007 20.483870968
+5.806451613 9.677419355 19.557269007 20.483870968
+5.806451613 10.000000000 19.557269007 20.483870968
+6.129032258 0.000000000 12.272218993 10.636363636
+6.129032258 0.322580645 12.272218993 10.636363636
+6.129032258 0.645161290 12.272218993 10.636363636
+6.129032258 0.967741935 12.272218993 10.636363636
+6.129032258 1.290322581 12.272218993 10.636363636
+6.129032258 1.612903226 12.272218993 10.636363636
+6.129032258 1.935483871 12.272218993 10.636363636
+6.129032258 2.258064516 12.272218993 10.636363636
+6.129032258 2.580645161 12.312912957 10.782742908
+6.129032258 2.903225806 12.485719838 11.375649592
+6.129032258 3.225806452 12.683802558 11.980650967
+6.129032258 3.548387097 12.903346192 12.598120927
+6.129032258 3.870967742 13.148207675 13.228448936
+6.129032258 4.193548387 13.424397092 13.872040848
+6.129032258 4.516129032 13.734709260 14.529319781
+6.129032258 4.838709677 14.081175133 15.200727043
+6.129032258 5.161290323 14.472910716 15.886723119
+6.129032258 5.483870968 14.920581746 16.587788726
+6.129032258 5.806451613 15.427041299 17.304425935
+6.129032258 6.129032258 16.008438809 18.037159372
+6.129032258 6.451612903 16.684191565 18.786537498
+6.129032258 6.774193548 17.475450862 19.553133975
+6.129032258 7.096774194 18.410291448 20.337549137
+6.129032258 7.419354839 19.533529202 21.140411551
+6.129032258 7.741935484 19.850782228 21.344086022
+6.129032258 8.064516129 19.850782228 21.344086022
+6.129032258 8.387096774 19.850782228 21.344086022
+6.129032258 8.709677419 19.850782228 21.344086022
+6.129032258 9.032258065 19.850782228 21.344086022
+6.129032258 9.354838710 19.850782228 21.344086022
+6.129032258 9.677419355 19.850782228 21.344086022
+6.129032258 10.000000000 19.850782228 21.344086022
+6.451612903 0.000000000 12.667715960 10.849056604
+6.451612903 0.322580645 12.667715960 10.849056604
+6.451612903 0.645161290 12.667715960 10.849056604
+6.451612903 0.967741935 12.667715960 10.849056604
+6.451612903 1.290322581 12.667715960 10.849056604
+6.451612903 1.612903226 12.667715960 10.849056604
+6.451612903 1.935483871 12.667715960 10.849056604
+6.451612903 2.258064516 12.667715960 10.849056604
+6.451612903 2.580645161 12.695732249 11.010062510
+6.451612903 2.903225806 12.824135659 11.660519441
+6.451612903 3.225806452 12.981327533 12.321456235
+6.451612903 3.548387097 13.167148134 12.993128221
+6.451612903 3.870967742 13.381921080 13.675799087
+6.451612903 4.193548387 13.630079770 14.369741229
+6.451612903 4.516129032 13.917888750 15.075236113
+6.451612903 4.838709677 14.251097627 15.792574657
+6.451612903 5.161290323 14.632147614 16.522057627
+6.451612903 5.483870968 15.072735735 17.263996060
+6.451612903 5.806451613 15.583881738 18.018711707
+6.451612903 6.129032258 16.182136955 18.786537498
+6.451612903 6.451612903 16.899235777 19.567818029
+6.451612903 6.774193548 17.840675551 20.362910080
+6.451612903 7.096774194 18.923022827 21.172183159
+6.451612903 7.419354839 20.191498874 21.996020073
+6.451612903 7.741935484 20.543702253 22.204301075
+6.451612903 8.064516129 20.543702253 22.204301075
+6.451612903 8.387096774 20.543702253 22.204301075
+6.451612903 8.709677419 20.543702253 22.204301075
+6.451612903 9.032258065 20.543702253 22.204301075
+6.451612903 9.354838710 20.543702253 22.204301075
+6.451612903 9.677419355 20.543702253 22.204301075
+6.451612903 10.000000000 20.543702253 22.204301075
+6.774193548 0.000000000 12.998209351 11.078431373
+6.774193548 0.322580645 12.998209351 11.078431373
+6.774193548 0.645161290 12.998209351 11.078431373
+6.774193548 0.967741935 12.998209351 11.078431373
+6.774193548 1.290322581 12.998209351 11.078431373
+6.774193548 1.612903226 12.998209351 11.078431373
+6.774193548 1.935483871 12.998209351 11.078431373
+6.774193548 2.258064516 12.998209351 11.078431373
+6.774193548 2.580645161 13.016700861 11.254948535
+6.774193548 2.903225806 13.109051400 11.966077401
+6.774193548 3.225806452 13.233524203 12.685407657
+6.774193548 3.548387097 13.391742155 13.413082004
+6.774193548 3.870967742 13.584206097 14.149246475
+6.774193548 4.193548387 13.814318448 14.894050530
+6.774193548 4.516129032 14.087835159 15.647647155
+6.774193548 4.838709677 14.410179185 16.410192974
+6.774193548 5.161290323 14.791181858 17.181848349
+6.774193548 5.483870968 15.241218368 17.962777500
+6.774193548 5.806451613 15.875517713 18.753148615
+6.774193548 6.129032258 16.681146859 19.553133975
+6.774193548 6.451612903 17.569488681 20.362910080
+6.774193548 6.774193548 18.574163704 21.182657773
+6.774193548 7.096774194 19.734151545 22.012562382
+6.774193548 7.419354839 21.103510509 22.852813853
+6.774193548 7.741935484 21.487304165 23.064516129
+6.774193548 8.064516129 21.487304165 23.064516129
+6.774193548 8.387096774 21.487304165 23.064516129
+6.774193548 8.709677419 21.487304165 23.064516129
+6.774193548 9.032258065 21.487304165 23.064516129
+6.774193548 9.354838710 21.487304165 23.064516129
+6.774193548 9.677419355 21.487304165 23.064516129
+6.774193548 10.000000000 21.487304165 23.064516129
+7.096774194 0.000000000 13.277885841 11.326530612
+7.096774194 0.322580645 13.277885841 11.326530612
+7.096774194 0.645161290 13.277885841 11.326530612
+7.096774194 0.967741935 13.277885841 11.326530612
+7.096774194 1.290322581 13.277885841 11.326530612
+7.096774194 1.612903226 13.277885841 11.326530612
+7.096774194 1.935483871 13.277885841 11.326530612
+7.096774194 2.258064516 13.277885841 11.326530612
+7.096774194 2.580645161 13.288352640 11.519519025
+7.096774194 2.903225806 13.350771800 12.294662039
+7.096774194 3.225806452 13.448963305 13.074946112
+7.096774194 3.548387097 13.584671491 13.860422559
+7.096774194 3.870967742 13.760664445 14.651143382
+7.096774194 4.193548387 13.980902626 15.447161280
+7.096774194 4.516129032 14.249972519 16.248529659
+7.096774194 4.838709677 14.574475539 17.055302647
+7.096774194 5.161290323 14.966122630 17.867535104
+7.096774194 5.483870968 15.630163357 18.685282635
+7.096774194 5.806451613 16.437215216 19.508601601
+7.096774194 6.129032258 17.309323446 20.337549137
+7.096774194 6.451612903 18.275865243 21.172183159
+7.096774194 6.774193548 19.378378532 22.012562382
+7.096774194 7.096774194 20.668439101 22.858746331
+7.096774194 7.419354839 22.225144822 23.710795356
+7.096774194 7.741935484 22.668948283 23.924731183
+7.096774194 8.064516129 22.668948283 23.924731183
+7.096774194 8.387096774 22.668948283 23.924731183
+7.096774194 8.709677419 22.668948283 23.924731183
+7.096774194 9.032258065 22.668948283 23.924731183
+7.096774194 9.354838710 22.668948283 23.924731183
+7.096774194 9.677419355 22.668948283 23.924731183
+7.096774194 10.000000000 22.668948283 23.924731183
+7.419354839 0.000000000 13.515825784 11.595744681
+7.419354839 0.322580645 13.515825784 11.595744681
+7.419354839 0.645161290 13.515825784 11.595744681
+7.419354839 0.967741935 13.515825784 11.595744681
+7.419354839 1.290322581 13.515825784 11.595744681
+7.419354839 1.612903226 13.515825784 11.595744681
+7.419354839 1.935483871 13.515825784 11.595744681
+7.419354839 2.258064516 13.515825784 11.595744681
+7.419354839 2.580645161 13.519282293 11.806246782
+7.419354839 2.903225806 13.556279203 12.648978190
+7.419354839 3.225806452 13.633565239 13.492868190
+7.419354839 3.548387097 13.753168201 14.337919175
+7.419354839 3.870967742 13.918417774 15.184133540
+7.419354839 4.193548387 14.134193279 16.031513690
+7.419354839 4.516129032 14.407312339 16.880062037
+7.419354839 4.838709677 14.747121823 17.729780997
+7.419354839 5.161290323 15.312289393 18.580672994
+7.419354839 5.483870968 16.162307388 19.432740459
+7.419354839 5.806451613 17.055699946 20.285985830
+7.419354839 6.129032258 18.025108663 21.140411551
+7.419354839 6.451612903 19.112532086 21.996020073
+7.419354839 6.774193548 20.379272817 22.852813853
+7.419354839 7.096774194 21.908521849 23.710795356
+7.419354839 7.419354839 23.837396065 24.569967054
+7.419354839 7.741935484 24.406429743 24.784946237
+7.419354839 8.064516129 24.406429743 24.784946237
+7.419354839 8.387096774 24.406429743 24.784946237
+7.419354839 8.709677419 24.406429743 24.784946237
+7.419354839 9.032258065 24.406429743 24.784946237
+7.419354839 9.354838710 24.406429743 24.784946237
+7.419354839 9.677419355 24.406429743 24.784946237
+7.419354839 10.000000000 24.406429743 24.784946237
+7.741935484 0.000000000 13.570706205 11.666666667
+7.741935484 0.322580645 13.570706205 11.666666667
+7.741935484 0.645161290 13.570706205 11.666666667
+7.741935484 0.967741935 13.570706205 11.666666667
+7.741935484 1.290322581 13.570706205 11.666666667
+7.741935484 1.612903226 13.570706205 11.666666667
+7.741935484 1.935483871 13.570706205 11.666666667
+7.741935484 2.258064516 13.570706205 11.666666667
+7.741935484 2.580645161 13.572517919 11.881720430
+7.741935484 2.903225806 13.603707815 12.741935484
+7.741935484 3.225806452 13.676532623 13.602150538
+7.741935484 3.548387097 13.793124575 14.462365591
+7.741935484 3.870967742 13.957010447 15.322580645
+7.741935484 4.193548387 14.173387937 16.182795699
+7.741935484 4.516129032 14.449561083 17.043010753
+7.741935484 4.838709677 14.795606896 17.903225806
+7.741935484 5.161290323 15.430252399 18.763440860
+7.741935484 5.483870968 16.305345082 19.623655914
+7.741935484 5.806451613 17.225621817 20.483870968
+7.741935484 6.129032258 18.227035950 21.344086022
+7.741935484 6.451612903 19.356366279 22.204301075
+7.741935484 6.774193548 20.682807170 23.064516129
+7.741935484 7.096774194 22.303013754 23.924731183
+7.741935484 7.419354839 24.380408194 24.784946237
+7.741935484 7.741935484 25.001049790 25.000000000
+7.741935484 8.064516129 25.001049790 25.000000000
+7.741935484 8.387096774 25.001049790 25.000000000
+7.741935484 8.709677419 25.001049790 25.000000000
+7.741935484 9.032258065 25.001049790 25.000000000
+7.741935484 9.354838710 25.001049790 25.000000000
+7.741935484 9.677419355 25.001049790 25.000000000
+7.741935484 10.000000000 25.001049790 25.000000000
+8.064516129 0.000000000 13.570706205 11.666666667
+8.064516129 0.322580645 13.570706205 11.666666667
+8.064516129 0.645161290 13.570706205 11.666666667
+8.064516129 0.967741935 13.570706205 11.666666667
+8.064516129 1.290322581 13.570706205 11.666666667
+8.064516129 1.612903226 13.570706205 11.666666667
+8.064516129 1.935483871 13.570706205 11.666666667
+8.064516129 2.258064516 13.570706205 11.666666667
+8.064516129 2.580645161 13.572517919 11.881720430
+8.064516129 2.903225806 13.603707815 12.741935484
+8.064516129 3.225806452 13.676532623 13.602150538
+8.064516129 3.548387097 13.793124575 14.462365591
+8.064516129 3.870967742 13.957010447 15.322580645
+8.064516129 4.193548387 14.173387937 16.182795699
+8.064516129 4.516129032 14.449561083 17.043010753
+8.064516129 4.838709677 14.795606896 17.903225806
+8.064516129 5.161290323 15.430252399 18.763440860
+8.064516129 5.483870968 16.305345082 19.623655914
+8.064516129 5.806451613 17.225621817 20.483870968
+8.064516129 6.129032258 18.227035950 21.344086022
+8.064516129 6.451612903 19.356366279 22.204301075
+8.064516129 6.774193548 20.682807170 23.064516129
+8.064516129 7.096774194 22.303013754 23.924731183
+8.064516129 7.419354839 24.380408194 24.784946237
+8.064516129 7.741935484 25.001049790 25.000000000
+8.064516129 8.064516129 25.001049790 25.000000000
+8.064516129 8.387096774 25.001049790 25.000000000
+8.064516129 8.709677419 25.001049790 25.000000000
+8.064516129 9.032258065 25.001049790 25.000000000
+8.064516129 9.354838710 25.001049790 25.000000000
+8.064516129 9.677419355 25.001049790 25.000000000
+8.064516129 10.000000000 25.001049790 25.000000000
+8.387096774 0.000000000 13.570706205 11.666666667
+8.387096774 0.322580645 13.570706205 11.666666667
+8.387096774 0.645161290 13.570706205 11.666666667
+8.387096774 0.967741935 13.570706205 11.666666667
+8.387096774 1.290322581 13.570706205 11.666666667
+8.387096774 1.612903226 13.570706205 11.666666667
+8.387096774 1.935483871 13.570706205 11.666666667
+8.387096774 2.258064516 13.570706205 11.666666667
+8.387096774 2.580645161 13.572517919 11.881720430
+8.387096774 2.903225806 13.603707815 12.741935484
+8.387096774 3.225806452 13.676532623 13.602150538
+8.387096774 3.548387097 13.793124575 14.462365591
+8.387096774 3.870967742 13.957010447 15.322580645
+8.387096774 4.193548387 14.173387937 16.182795699
+8.387096774 4.516129032 14.449561083 17.043010753
+8.387096774 4.838709677 14.795606896 17.903225806
+8.387096774 5.161290323 15.430252399 18.763440860
+8.387096774 5.483870968 16.305345082 19.623655914
+8.387096774 5.806451613 17.225621817 20.483870968
+8.387096774 6.129032258 18.227035950 21.344086022
+8.387096774 6.451612903 19.356366279 22.204301075
+8.387096774 6.774193548 20.682807170 23.064516129
+8.387096774 7.096774194 22.303013754 23.924731183
+8.387096774 7.419354839 24.380408194 24.784946237
+8.387096774 7.741935484 25.001049790 25.000000000
+8.387096774 8.064516129 25.001049790 25.000000000
+8.387096774 8.387096774 25.001049790 25.000000000
+8.387096774 8.709677419 25.001049790 25.000000000
+8.387096774 9.032258065 25.001049790 25.000000000
+8.387096774 9.354838710 25.001049790 25.000000000
+8.387096774 9.677419355 25.001049790 25.000000000
+8.387096774 10.000000000 25.001049790 25.000000000
+8.709677419 0.000000000 13.570706205 11.666666667
+8.709677419 0.322580645 13.570706205 11.666666667
+8.709677419 0.645161290 13.570706205 11.666666667
+8.709677419 0.967741935 13.570706205 11.666666667
+8.709677419 1.290322581 13.570706205 11.666666667
+8.709677419 1.612903226 13.570706205 11.666666667
+8.709677419 1.935483871 13.570706205 11.666666667
+8.709677419 2.258064516 13.570706205 11.666666667
+8.709677419 2.580645161 13.572517919 11.881720430
+8.709677419 2.903225806 13.603707815 12.741935484
+8.709677419 3.225806452 13.676532623 13.602150538
+8.709677419 3.548387097 13.793124575 14.462365591
+8.709677419 3.870967742 13.957010447 15.322580645
+8.709677419 4.193548387 14.173387937 16.182795699
+8.709677419 4.516129032 14.449561083 17.043010753
+8.709677419 4.838709677 14.795606896 17.903225806
+8.709677419 5.161290323 15.430252399 18.763440860
+8.709677419 5.483870968 16.305345082 19.623655914
+8.709677419 5.806451613 17.225621817 20.483870968
+8.709677419 6.129032258 18.227035950 21.344086022
+8.709677419 6.451612903 19.356366279 22.204301075
+8.709677419 6.774193548 20.682807170 23.064516129
+8.709677419 7.096774194 22.303013754 23.924731183
+8.709677419 7.419354839 24.380408194 24.784946237
+8.709677419 7.741935484 25.001049790 25.000000000
+8.709677419 8.064516129 25.001049790 25.000000000
+8.709677419 8.387096774 25.001049790 25.000000000
+8.709677419 8.709677419 25.001049790 25.000000000
+8.709677419 9.032258065 25.001049790 25.000000000
+8.709677419 9.354838710 25.001049790 25.000000000
+8.709677419 9.677419355 25.001049790 25.000000000
+8.709677419 10.000000000 25.001049790 25.000000000
+9.032258065 0.000000000 13.570706205 11.666666667
+9.032258065 0.322580645 13.570706205 11.666666667
+9.032258065 0.645161290 13.570706205 11.666666667
+9.032258065 0.967741935 13.570706205 11.666666667
+9.032258065 1.290322581 13.570706205 11.666666667
+9.032258065 1.612903226 13.570706205 11.666666667
+9.032258065 1.935483871 13.570706205 11.666666667
+9.032258065 2.258064516 13.570706205 11.666666667
+9.032258065 2.580645161 13.572517919 11.881720430
+9.032258065 2.903225806 13.603707815 12.741935484
+9.032258065 3.225806452 13.676532623 13.602150538
+9.032258065 3.548387097 13.793124575 14.462365591
+9.032258065 3.870967742 13.957010447 15.322580645
+9.032258065 4.193548387 14.173387937 16.182795699
+9.032258065 4.516129032 14.449561083 17.043010753
+9.032258065 4.838709677 14.795606896 17.903225806
+9.032258065 5.161290323 15.430252399 18.763440860
+9.032258065 5.483870968 16.305345082 19.623655914
+9.032258065 5.806451613 17.225621817 20.483870968
+9.032258065 6.129032258 18.227035950 21.344086022
+9.032258065 6.451612903 19.356366279 22.204301075
+9.032258065 6.774193548 20.682807170 23.064516129
+9.032258065 7.096774194 22.303013754 23.924731183
+9.032258065 7.419354839 24.380408194 24.784946237
+9.032258065 7.741935484 25.001049790 25.000000000
+9.032258065 8.064516129 25.001049790 25.000000000
+9.032258065 8.387096774 25.001049790 25.000000000
+9.032258065 8.709677419 25.001049790 25.000000000
+9.032258065 9.032258065 25.001049790 25.000000000
+9.032258065 9.354838710 25.001049790 25.000000000
+9.032258065 9.677419355 25.001049790 25.000000000
+9.032258065 10.000000000 25.001049790 25.000000000
+9.354838710 0.000000000 13.570706205 11.666666667
+9.354838710 0.322580645 13.570706205 11.666666667
+9.354838710 0.645161290 13.570706205 11.666666667
+9.354838710 0.967741935 13.570706205 11.666666667
+9.354838710 1.290322581 13.570706205 11.666666667
+9.354838710 1.612903226 13.570706205 11.666666667
+9.354838710 1.935483871 13.570706205 11.666666667
+9.354838710 2.258064516 13.570706205 11.666666667
+9.354838710 2.580645161 13.572517919 11.881720430
+9.354838710 2.903225806 13.603707815 12.741935484
+9.354838710 3.225806452 13.676532623 13.602150538
+9.354838710 3.548387097 13.793124575 14.462365591
+9.354838710 3.870967742 13.957010447 15.322580645
+9.354838710 4.193548387 14.173387937 16.182795699
+9.354838710 4.516129032 14.449561083 17.043010753
+9.354838710 4.838709677 14.795606896 17.903225806
+9.354838710 5.161290323 15.430252399 18.763440860
+9.354838710 5.483870968 16.305345082 19.623655914
+9.354838710 5.806451613 17.225621817 20.483870968
+9.354838710 6.129032258 18.227035950 21.344086022
+9.354838710 6.451612903 19.356366279 22.204301075
+9.354838710 6.774193548 20.682807170 23.064516129
+9.354838710 7.096774194 22.303013754 23.924731183
+9.354838710 7.419354839 24.380408194 24.784946237
+9.354838710 7.741935484 25.001049790 25.000000000
+9.354838710 8.064516129 25.001049790 25.000000000
+9.354838710 8.387096774 25.001049790 25.000000000
+9.354838710 8.709677419 25.001049790 25.000000000
+9.354838710 9.032258065 25.001049790 25.000000000
+9.354838710 9.354838710 25.001049790 25.000000000
+9.354838710 9.677419355 25.001049790 25.000000000
+9.354838710 10.000000000 25.001049790 25.000000000
+9.677419355 0.000000000 13.570706205 11.666666667
+9.677419355 0.322580645 13.570706205 11.666666667
+9.677419355 0.645161290 13.570706205 11.666666667
+9.677419355 0.967741935 13.570706205 11.666666667
+9.677419355 1.290322581 13.570706205 11.666666667
+9.677419355 1.612903226 13.570706205 11.666666667
+9.677419355 1.935483871 13.570706205 11.666666667
+9.677419355 2.258064516 13.570706205 11.666666667
+9.677419355 2.580645161 13.572517919 11.881720430
+9.677419355 2.903225806 13.603707815 12.741935484
+9.677419355 3.225806452 13.676532623 13.602150538
+9.677419355 3.548387097 13.793124575 14.462365591
+9.677419355 3.870967742 13.957010447 15.322580645
+9.677419355 4.193548387 14.173387937 16.182795699
+9.677419355 4.516129032 14.449561083 17.043010753
+9.677419355 4.838709677 14.795606896 17.903225806
+9.677419355 5.161290323 15.430252399 18.763440860
+9.677419355 5.483870968 16.305345082 19.623655914
+9.677419355 5.806451613 17.225621817 20.483870968
+9.677419355 6.129032258 18.227035950 21.344086022
+9.677419355 6.451612903 19.356366279 22.204301075
+9.677419355 6.774193548 20.682807170 23.064516129
+9.677419355 7.096774194 22.303013754 23.924731183
+9.677419355 7.419354839 24.380408194 24.784946237
+9.677419355 7.741935484 25.001049790 25.000000000
+9.677419355 8.064516129 25.001049790 25.000000000
+9.677419355 8.387096774 25.001049790 25.000000000
+9.677419355 8.709677419 25.001049790 25.000000000
+9.677419355 9.032258065 25.001049790 25.000000000
+9.677419355 9.354838710 25.001049790 25.000000000
+9.677419355 9.677419355 25.001049790 25.000000000
+9.677419355 10.000000000 25.001049790 25.000000000
+10.000000000 0.000000000 13.570706205 11.666666667
+10.000000000 0.322580645 13.570706205 11.666666667
+10.000000000 0.645161290 13.570706205 11.666666667
+10.000000000 0.967741935 13.570706205 11.666666667
+10.000000000 1.290322581 13.570706205 11.666666667
+10.000000000 1.612903226 13.570706205 11.666666667
+10.000000000 1.935483871 13.570706205 11.666666667
+10.000000000 2.258064516 13.570706205 11.666666667
+10.000000000 2.580645161 13.572517919 11.881720430
+10.000000000 2.903225806 13.603707815 12.741935484
+10.000000000 3.225806452 13.676532623 13.602150538
+10.000000000 3.548387097 13.793124575 14.462365591
+10.000000000 3.870967742 13.957010447 15.322580645
+10.000000000 4.193548387 14.173387937 16.182795699
+10.000000000 4.516129032 14.449561083 17.043010753
+10.000000000 4.838709677 14.795606896 17.903225806
+10.000000000 5.161290323 15.430252399 18.763440860
+10.000000000 5.483870968 16.305345082 19.623655914
+10.000000000 5.806451613 17.225621817 20.483870968
+10.000000000 6.129032258 18.227035950 21.344086022
+10.000000000 6.451612903 19.356366279 22.204301075
+10.000000000 6.774193548 20.682807170 23.064516129
+10.000000000 7.096774194 22.303013754 23.924731183
+10.000000000 7.419354839 24.380408194 24.784946237
+10.000000000 7.741935484 25.001049790 25.000000000
+10.000000000 8.064516129 25.001049790 25.000000000
+10.000000000 8.387096774 25.001049790 25.000000000
+10.000000000 8.709677419 25.001049790 25.000000000
+10.000000000 9.032258065 25.001049790 25.000000000
+10.000000000 9.354838710 25.001049790 25.000000000
+10.000000000 9.677419355 25.001049790 25.000000000
+10.000000000 10.000000000 25.001049790 25.000000000
diff --git a/examples/hybrid/tipper.fll b/examples/hybrid/tipper.fll
new file mode 100644
index 0000000..cb8803f
--- /dev/null
+++ b/examples/hybrid/tipper.fll
@@ -0,0 +1,63 @@
+Engine: tipper
+description: (service and food) -> (tip)
+InputVariable: service
+ description: quality of service
+ enabled: true
+ range: 0.000 10.000
+ lock-range: true
+ term: poor Trapezoid 0.000 0.000 2.500 5.000
+ term: good Triangle 2.500 5.000 7.500
+ term: excellent Trapezoid 5.000 7.500 10.000 10.000
+InputVariable: food
+ description: quality of food
+ enabled: true
+ range: 0.000 10.000
+ lock-range: true
+ term: rancid Trapezoid 0.000 0.000 2.500 7.500
+ term: delicious Trapezoid 2.500 7.500 10.000 10.000
+OutputVariable: mTip
+ description: tip based on Mamdani inference
+ enabled: true
+ range: 0.000 30.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 100
+ default: nan
+ lock-previous: false
+ term: cheap Triangle 0.000 5.000 10.000
+ term: average Triangle 10.000 15.000 20.000
+ term: generous Triangle 20.000 25.000 30.000
+OutputVariable: tsTip
+ description: tip based on Takagi-Sugeno inference
+ enabled: true
+ range: 0.000 30.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: cheap Constant 5.000
+ term: average Constant 15.000
+ term: generous Constant 25.000
+RuleBlock: mamdani
+ description: Mamdani inference
+ enabled: true
+ conjunction: AlgebraicProduct
+ disjunction: AlgebraicSum
+ implication: Minimum
+ activation: General
+ rule: if service is poor or food is rancid then mTip is cheap
+ rule: if service is good then mTip is average
+ rule: if service is excellent or food is delicious then mTip is generous with 0.5
+ rule: if service is excellent and food is delicious then mTip is generous with 1.0
+RuleBlock: takagiSugeno
+ description: Takagi-Sugeno inference
+ enabled: true
+ conjunction: AlgebraicProduct
+ disjunction: AlgebraicSum
+ implication: none
+ activation: General
+ rule: if service is poor or food is rancid then tsTip is cheap
+ rule: if service is good then tsTip is average
+ rule: if service is excellent or food is delicious then tsTip is generous with 0.5
+ rule: if service is excellent and food is delicious then tsTip is generous with 1.0 \ No newline at end of file
diff --git a/examples/hybrid/tipper.java b/examples/hybrid/tipper.java
new file mode 100644
index 0000000..e0578ca
--- /dev/null
+++ b/examples/hybrid/tipper.java
@@ -0,0 +1,103 @@
+import com.fuzzylite.*;
+import com.fuzzylite.activation.*
+import com.fuzzylite.defuzzifier.*;
+import com.fuzzylite.factory.*;
+import com.fuzzylite.hedge.*;
+import com.fuzzylite.imex.*;
+import com.fuzzylite.norm.*;
+import com.fuzzylite.norm.s.*;
+import com.fuzzylite.norm.t.*;
+import com.fuzzylite.rule.*;
+import com.fuzzylite.term.*;
+import com.fuzzylite.variable.*;
+
+public class tipper{
+public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
+Engine engine = new Engine();
+engine.setName("tipper");
+engine.setDescription("(service and food) -> (tip)");
+
+InputVariable service = new InputVariable();
+service.setName("service");
+service.setDescription("quality of service");
+service.setEnabled(true);
+service.setRange(0.000, 10.000);
+service.setLockValueInRange(true);
+service.addTerm(new Trapezoid("poor", 0.000, 0.000, 2.500, 5.000));
+service.addTerm(new Triangle("good", 2.500, 5.000, 7.500));
+service.addTerm(new Trapezoid("excellent", 5.000, 7.500, 10.000, 10.000));
+engine.addInputVariable(service);
+
+InputVariable food = new InputVariable();
+food.setName("food");
+food.setDescription("quality of food");
+food.setEnabled(true);
+food.setRange(0.000, 10.000);
+food.setLockValueInRange(true);
+food.addTerm(new Trapezoid("rancid", 0.000, 0.000, 2.500, 7.500));
+food.addTerm(new Trapezoid("delicious", 2.500, 7.500, 10.000, 10.000));
+engine.addInputVariable(food);
+
+OutputVariable mTip = new OutputVariable();
+mTip.setName("mTip");
+mTip.setDescription("tip based on Mamdani inference");
+mTip.setEnabled(true);
+mTip.setRange(0.000, 30.000);
+mTip.setLockValueInRange(false);
+mTip.setAggregation(new Maximum());
+mTip.setDefuzzifier(new Centroid(100));
+mTip.setDefaultValue(Double.NaN);
+mTip.setLockPreviousValue(false);
+mTip.addTerm(new Triangle("cheap", 0.000, 5.000, 10.000));
+mTip.addTerm(new Triangle("average", 10.000, 15.000, 20.000));
+mTip.addTerm(new Triangle("generous", 20.000, 25.000, 30.000));
+engine.addOutputVariable(mTip);
+
+OutputVariable tsTip = new OutputVariable();
+tsTip.setName("tsTip");
+tsTip.setDescription("tip based on Takagi-Sugeno inference");
+tsTip.setEnabled(true);
+tsTip.setRange(0.000, 30.000);
+tsTip.setLockValueInRange(false);
+tsTip.setAggregation(null);
+tsTip.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+tsTip.setDefaultValue(Double.NaN);
+tsTip.setLockPreviousValue(false);
+tsTip.addTerm(new Constant("cheap", 5.000));
+tsTip.addTerm(new Constant("average", 15.000));
+tsTip.addTerm(new Constant("generous", 25.000));
+engine.addOutputVariable(tsTip);
+
+RuleBlock mamdani = new RuleBlock();
+mamdani.setName("mamdani");
+mamdani.setDescription("Mamdani inference");
+mamdani.setEnabled(true);
+mamdani.setConjunction(new AlgebraicProduct());
+mamdani.setDisjunction(new AlgebraicSum());
+mamdani.setImplication(new Minimum());
+mamdani.setActivation(new General());
+mamdani.addRule(Rule.parse("if service is poor or food is rancid then mTip is cheap", engine));
+mamdani.addRule(Rule.parse("if service is good then mTip is average", engine));
+mamdani.addRule(Rule.parse("if service is excellent or food is delicious then mTip is generous with 0.5", engine));
+mamdani.addRule(Rule.parse("if service is excellent and food is delicious then mTip is generous with 1.0", engine));
+engine.addRuleBlock(mamdani);
+
+RuleBlock takagiSugeno = new RuleBlock();
+takagiSugeno.setName("takagiSugeno");
+takagiSugeno.setDescription("Takagi-Sugeno inference");
+takagiSugeno.setEnabled(true);
+takagiSugeno.setConjunction(new AlgebraicProduct());
+takagiSugeno.setDisjunction(new AlgebraicSum());
+takagiSugeno.setImplication(null);
+takagiSugeno.setActivation(new General());
+takagiSugeno.addRule(Rule.parse("if service is poor or food is rancid then tsTip is cheap", engine));
+takagiSugeno.addRule(Rule.parse("if service is good then tsTip is average", engine));
+takagiSugeno.addRule(Rule.parse("if service is excellent or food is delicious then tsTip is generous with 0.5", engine));
+takagiSugeno.addRule(Rule.parse("if service is excellent and food is delicious then tsTip is generous with 1.0", engine));
+engine.addRuleBlock(takagiSugeno);
+
+
+}
+}
diff --git a/examples/hybrid/tipper.pdf b/examples/hybrid/tipper.pdf
new file mode 100644
index 0000000..482e9cc
--- /dev/null
+++ b/examples/hybrid/tipper.pdf
Binary files differ
diff --git a/examples/mamdani/AllTerms.R b/examples/mamdani/AllTerms.R
new file mode 100644
index 0000000..1b17463
--- /dev/null
+++ b/examples/mamdani/AllTerms.R
@@ -0,0 +1,111 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "AllTerms"
+engine.fll = "Engine: AllTerms
+InputVariable: AllInputTerms
+ enabled: true
+ range: 0.000 6.500
+ lock-range: false
+ term: A Sigmoid 0.500 -20.000
+ term: B ZShape 0.000 1.000
+ term: C Ramp 1.000 0.000
+ term: D Triangle 0.500 1.000 1.500
+ term: E Trapezoid 1.000 1.250 1.750 2.000
+ term: F Concave 0.850 0.250
+ term: G Rectangle 1.750 2.250
+ term: H Discrete 2.000 0.000 2.250 1.000 2.500 0.500 2.750 1.000 3.000 0.000
+ term: I Gaussian 3.000 0.200
+ term: J Cosine 3.250 0.650
+ term: K GaussianProduct 3.500 0.100 3.300 0.300
+ term: L Spike 3.640 1.040
+ term: M Bell 4.000 0.250 3.000
+ term: N PiShape 4.000 4.500 4.500 5.000
+ term: O Concave 5.650 6.250
+ term: P SigmoidDifference 4.750 10.000 30.000 5.250
+ term: Q SigmoidProduct 5.250 20.000 -10.000 5.750
+ term: R Ramp 5.500 6.500
+ term: S SShape 5.500 6.500
+ term: T Sigmoid 6.000 20.000
+OutputVariable: AllOutputTerms
+ enabled: true
+ range: 0.000 6.500
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: A Sigmoid 0.500 -20.000
+ term: B ZShape 0.000 1.000
+ term: C Ramp 1.000 0.000
+ term: D Triangle 0.500 1.000 1.500
+ term: E Trapezoid 1.000 1.250 1.750 2.000
+ term: F Concave 0.850 0.250
+ term: G Rectangle 1.750 2.250
+ term: H Discrete 2.000 0.000 2.250 1.000 2.500 0.500 2.750 1.000 3.000 0.000
+ term: I Gaussian 3.000 0.200
+ term: J Cosine 3.250 0.650
+ term: K GaussianProduct 3.500 0.100 3.300 0.300
+ term: L Spike 3.640 1.040
+ term: M Bell 4.000 0.250 3.000
+ term: N PiShape 4.000 4.500 4.500 5.000
+ term: O Concave 5.650 6.250
+ term: P SigmoidDifference 4.750 10.000 30.000 5.250
+ term: Q SigmoidProduct 5.250 20.000 -10.000 5.750
+ term: R Ramp 5.500 6.500
+ term: S SShape 5.500 6.500
+ term: T Sigmoid 6.000 20.000
+RuleBlock:
+ enabled: true
+ conjunction: Minimum
+ disjunction: Maximum
+ implication: Minimum
+ activation: General
+ rule: if AllInputTerms is A then AllOutputTerms is T
+ rule: if AllInputTerms is B then AllOutputTerms is S
+ rule: if AllInputTerms is C then AllOutputTerms is R
+ rule: if AllInputTerms is D then AllOutputTerms is Q
+ rule: if AllInputTerms is E then AllOutputTerms is P
+ rule: if AllInputTerms is F then AllOutputTerms is O
+ rule: if AllInputTerms is G then AllOutputTerms is N
+ rule: if AllInputTerms is H then AllOutputTerms is M
+ rule: if AllInputTerms is I then AllOutputTerms is L
+ rule: if AllInputTerms is J then AllOutputTerms is K
+ rule: if AllInputTerms is K then AllOutputTerms is J
+ rule: if AllInputTerms is L then AllOutputTerms is I
+ rule: if AllInputTerms is M then AllOutputTerms is H
+ rule: if AllInputTerms is N then AllOutputTerms is G
+ rule: if AllInputTerms is O then AllOutputTerms is F
+ rule: if AllInputTerms is P then AllOutputTerms is E
+ rule: if AllInputTerms is Q then AllOutputTerms is D
+ rule: if AllInputTerms is R then AllOutputTerms is C
+ rule: if AllInputTerms is S then AllOutputTerms is B
+ rule: if AllInputTerms is T then AllOutputTerms is A"
+
+engine.fldFile = "AllTerms.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(AllInputTerms, AllOutputTerms)) +
+ geom_line(aes(color=AllOutputTerms), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("AllInputTerms vs AllOutputTerms")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(AllInputTerms, AllOutputTerms)) +
+ geom_line(aes(color=AllOutputTerms), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("AllOutputTerms vs AllInputTerms")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/mamdani/AllTerms.cpp b/examples/mamdani/AllTerms.cpp
index 7bb1f31..3d96ef5 100644
--- a/examples/mamdani/AllTerms.cpp
+++ b/examples/mamdani/AllTerms.cpp
@@ -1,94 +1,102 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("qtfuzzylite");
+engine->setName("AllTerms");
+engine->setDescription("");
-InputVariable* inputVariable = new InputVariable;
-inputVariable->setEnabled(true);
-inputVariable->setName("AllInputTerms");
-inputVariable->setRange(0.000, 6.500);
-inputVariable->addTerm(new Sigmoid("A", 0.500, -20.000));
-inputVariable->addTerm(new ZShape("B", 0.000, 1.000));
-inputVariable->addTerm(new Ramp("C", 1.000, 0.000));
-inputVariable->addTerm(new Triangle("D", 0.500, 1.000, 1.500));
-inputVariable->addTerm(new Trapezoid("E", 1.000, 1.250, 1.750, 2.000));
-inputVariable->addTerm(new Concave("F", 0.850, 0.250));
-inputVariable->addTerm(new Rectangle("G", 1.750, 2.250));
-inputVariable->addTerm(Discrete::create("H", 10, 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000));
-inputVariable->addTerm(new Gaussian("I", 3.000, 0.200));
-inputVariable->addTerm(new Cosine("J", 3.250, 0.650));
-inputVariable->addTerm(new GaussianProduct("K", 3.500, 0.100, 3.300, 0.300));
-inputVariable->addTerm(new Spike("L", 3.640, 1.040));
-inputVariable->addTerm(new Bell("M", 4.000, 0.250, 3.000));
-inputVariable->addTerm(new PiShape("N", 4.000, 4.500, 4.500, 5.000));
-inputVariable->addTerm(new Concave("O", 5.650, 6.250));
-inputVariable->addTerm(new SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250));
-inputVariable->addTerm(new SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750));
-inputVariable->addTerm(new Ramp("R", 5.500, 6.500));
-inputVariable->addTerm(new SShape("S", 5.500, 6.500));
-inputVariable->addTerm(new Sigmoid("T", 6.000, 20.000));
-engine->addInputVariable(inputVariable);
+InputVariable* AllInputTerms = new InputVariable;
+AllInputTerms->setName("AllInputTerms");
+AllInputTerms->setDescription("");
+AllInputTerms->setEnabled(true);
+AllInputTerms->setRange(0.000, 6.500);
+AllInputTerms->setLockValueInRange(false);
+AllInputTerms->addTerm(new Sigmoid("A", 0.500, -20.000));
+AllInputTerms->addTerm(new ZShape("B", 0.000, 1.000));
+AllInputTerms->addTerm(new Ramp("C", 1.000, 0.000));
+AllInputTerms->addTerm(new Triangle("D", 0.500, 1.000, 1.500));
+AllInputTerms->addTerm(new Trapezoid("E", 1.000, 1.250, 1.750, 2.000));
+AllInputTerms->addTerm(new Concave("F", 0.850, 0.250));
+AllInputTerms->addTerm(new Rectangle("G", 1.750, 2.250));
+AllInputTerms->addTerm(Discrete::create("H", 10, 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000));
+AllInputTerms->addTerm(new Gaussian("I", 3.000, 0.200));
+AllInputTerms->addTerm(new Cosine("J", 3.250, 0.650));
+AllInputTerms->addTerm(new GaussianProduct("K", 3.500, 0.100, 3.300, 0.300));
+AllInputTerms->addTerm(new Spike("L", 3.640, 1.040));
+AllInputTerms->addTerm(new Bell("M", 4.000, 0.250, 3.000));
+AllInputTerms->addTerm(new PiShape("N", 4.000, 4.500, 4.500, 5.000));
+AllInputTerms->addTerm(new Concave("O", 5.650, 6.250));
+AllInputTerms->addTerm(new SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250));
+AllInputTerms->addTerm(new SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750));
+AllInputTerms->addTerm(new Ramp("R", 5.500, 6.500));
+AllInputTerms->addTerm(new SShape("S", 5.500, 6.500));
+AllInputTerms->addTerm(new Sigmoid("T", 6.000, 20.000));
+engine->addInputVariable(AllInputTerms);
-OutputVariable* outputVariable = new OutputVariable;
-outputVariable->setEnabled(true);
-outputVariable->setName("AllOutputTerms");
-outputVariable->setRange(0.000, 6.500);
-outputVariable->fuzzyOutput()->setAccumulation(new Maximum);
-outputVariable->setDefuzzifier(new Centroid(200));
-outputVariable->setDefaultValue(fl::nan);
-outputVariable->setLockPreviousOutputValue(false);
-outputVariable->setLockOutputValueInRange(false);
-outputVariable->addTerm(new Sigmoid("A", 0.500, -20.000));
-outputVariable->addTerm(new ZShape("B", 0.000, 1.000));
-outputVariable->addTerm(new Ramp("C", 1.000, 0.000));
-outputVariable->addTerm(new Triangle("D", 0.500, 1.000, 1.500));
-outputVariable->addTerm(new Trapezoid("E", 1.000, 1.250, 1.750, 2.000));
-outputVariable->addTerm(new Concave("F", 0.850, 0.250));
-outputVariable->addTerm(new Rectangle("G", 1.750, 2.250));
-outputVariable->addTerm(Discrete::create("H", 10, 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000));
-outputVariable->addTerm(new Gaussian("I", 3.000, 0.200));
-outputVariable->addTerm(new Cosine("J", 3.250, 0.650));
-outputVariable->addTerm(new GaussianProduct("K", 3.500, 0.100, 3.300, 0.300));
-outputVariable->addTerm(new Spike("L", 3.640, 1.040));
-outputVariable->addTerm(new Bell("M", 4.000, 0.250, 3.000));
-outputVariable->addTerm(new PiShape("N", 4.000, 4.500, 4.500, 5.000));
-outputVariable->addTerm(new Concave("O", 5.650, 6.250));
-outputVariable->addTerm(new SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250));
-outputVariable->addTerm(new SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750));
-outputVariable->addTerm(new Ramp("R", 5.500, 6.500));
-outputVariable->addTerm(new SShape("S", 5.500, 6.500));
-outputVariable->addTerm(new Sigmoid("T", 6.000, 20.000));
-engine->addOutputVariable(outputVariable);
+OutputVariable* AllOutputTerms = new OutputVariable;
+AllOutputTerms->setName("AllOutputTerms");
+AllOutputTerms->setDescription("");
+AllOutputTerms->setEnabled(true);
+AllOutputTerms->setRange(0.000, 6.500);
+AllOutputTerms->setLockValueInRange(false);
+AllOutputTerms->setAggregation(new Maximum);
+AllOutputTerms->setDefuzzifier(new Centroid(200));
+AllOutputTerms->setDefaultValue(fl::nan);
+AllOutputTerms->setLockPreviousValue(false);
+AllOutputTerms->addTerm(new Sigmoid("A", 0.500, -20.000));
+AllOutputTerms->addTerm(new ZShape("B", 0.000, 1.000));
+AllOutputTerms->addTerm(new Ramp("C", 1.000, 0.000));
+AllOutputTerms->addTerm(new Triangle("D", 0.500, 1.000, 1.500));
+AllOutputTerms->addTerm(new Trapezoid("E", 1.000, 1.250, 1.750, 2.000));
+AllOutputTerms->addTerm(new Concave("F", 0.850, 0.250));
+AllOutputTerms->addTerm(new Rectangle("G", 1.750, 2.250));
+AllOutputTerms->addTerm(Discrete::create("H", 10, 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000));
+AllOutputTerms->addTerm(new Gaussian("I", 3.000, 0.200));
+AllOutputTerms->addTerm(new Cosine("J", 3.250, 0.650));
+AllOutputTerms->addTerm(new GaussianProduct("K", 3.500, 0.100, 3.300, 0.300));
+AllOutputTerms->addTerm(new Spike("L", 3.640, 1.040));
+AllOutputTerms->addTerm(new Bell("M", 4.000, 0.250, 3.000));
+AllOutputTerms->addTerm(new PiShape("N", 4.000, 4.500, 4.500, 5.000));
+AllOutputTerms->addTerm(new Concave("O", 5.650, 6.250));
+AllOutputTerms->addTerm(new SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250));
+AllOutputTerms->addTerm(new SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750));
+AllOutputTerms->addTerm(new Ramp("R", 5.500, 6.500));
+AllOutputTerms->addTerm(new SShape("S", 5.500, 6.500));
+AllOutputTerms->addTerm(new Sigmoid("T", 6.000, 20.000));
+engine->addOutputVariable(AllOutputTerms);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(new Minimum);
ruleBlock->setDisjunction(new Maximum);
-ruleBlock->setActivation(new Minimum);
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is A then AllOutputTerms is T", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is B then AllOutputTerms is S", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is C then AllOutputTerms is R", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is D then AllOutputTerms is Q", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is E then AllOutputTerms is P", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is F then AllOutputTerms is O", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is G then AllOutputTerms is N", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is H then AllOutputTerms is M", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is I then AllOutputTerms is L", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is J then AllOutputTerms is K", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is K then AllOutputTerms is J", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is L then AllOutputTerms is I", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is M then AllOutputTerms is H", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is N then AllOutputTerms is G", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is O then AllOutputTerms is F", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is P then AllOutputTerms is E", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is Q then AllOutputTerms is D", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is R then AllOutputTerms is C", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is S then AllOutputTerms is B", engine));
-ruleBlock->addRule(fl::Rule::parse("if AllInputTerms is T then AllOutputTerms is A", engine));
+ruleBlock->setImplication(new Minimum);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if AllInputTerms is A then AllOutputTerms is T", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is B then AllOutputTerms is S", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is C then AllOutputTerms is R", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is D then AllOutputTerms is Q", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is E then AllOutputTerms is P", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is F then AllOutputTerms is O", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is G then AllOutputTerms is N", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is H then AllOutputTerms is M", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is I then AllOutputTerms is L", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is J then AllOutputTerms is K", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is K then AllOutputTerms is J", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is L then AllOutputTerms is I", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is M then AllOutputTerms is H", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is N then AllOutputTerms is G", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is O then AllOutputTerms is F", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is P then AllOutputTerms is E", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is Q then AllOutputTerms is D", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is R then AllOutputTerms is C", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is S then AllOutputTerms is B", engine));
+ruleBlock->addRule(Rule::parse("if AllInputTerms is T then AllOutputTerms is A", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/mamdani/AllTerms.fcl b/examples/mamdani/AllTerms.fcl
index ef08722..0c56fd6 100644
--- a/examples/mamdani/AllTerms.fcl
+++ b/examples/mamdani/AllTerms.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK qtfuzzylite
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK AllTerms
VAR_INPUT
AllInputTerms: REAL;
diff --git a/examples/mamdani/AllTerms.fis b/examples/mamdani/AllTerms.fis
index 61a6d18..d34e487 100644
--- a/examples/mamdani/AllTerms.fis
+++ b/examples/mamdani/AllTerms.fis
@@ -1,6 +1,9 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='qtfuzzylite'
+Name='AllTerms'
Type='mamdani'
+Version=6.0
NumInputs=1
NumOutputs=1
NumRules=20
diff --git a/examples/mamdani/AllTerms.fld b/examples/mamdani/AllTerms.fld
index 95116fa..b765a5b 100644
--- a/examples/mamdani/AllTerms.fld
+++ b/examples/mamdani/AllTerms.fld
@@ -1,1026 +1,1025 @@
-#@Engine: qtfuzzylite;
-#@InputVariable: AllInputTerms; @OutputVariable: AllOutputTerms;
-0.00000000 4.59989528
-0.00635386 4.59989528
-0.01270772 4.59989528
-0.01906158 4.59989215
-0.02541544 4.59988508
-0.03176931 4.59987800
-0.03812317 4.59987091
-0.04447703 4.59986380
-0.05083089 4.59985436
-0.05718475 4.59984014
-0.06353861 4.59982589
-0.06989247 4.59981161
-0.07624633 4.59979731
-0.08260020 4.59978148
-0.08895406 4.59976002
-0.09530792 4.59973853
-0.10166178 4.59971699
-0.10801564 4.59969542
-0.11436950 4.59967311
-0.12072336 4.59964434
-0.12707722 4.59961551
-0.13343109 4.59958663
-0.13978495 4.59955769
-0.14613881 4.59952871
-0.15249267 4.59949265
-0.15884653 4.59945641
-0.16520039 4.59942010
-0.17155425 4.59938372
-0.17790811 4.59934727
-0.18426197 4.59930456
-0.19061584 4.59926081
-0.19696970 4.59921698
-0.20332356 4.59917307
-0.20967742 4.59912907
-0.21603128 4.59907961
-0.22238514 4.59902827
-0.22873900 4.59897684
-0.23509286 4.59892531
-0.24144673 4.59887368
-0.24780059 4.59881738
-0.25415445 4.59691917
-0.26050831 4.59649344
-0.26686217 4.59613763
-0.27321603 4.59574220
-0.27956989 4.59527472
-0.28592375 4.59472722
-0.29227761 4.59411601
-0.29863148 4.59343292
-0.30498534 4.59266881
-0.31133920 4.59177691
-0.31769306 4.59072170
-0.32404692 4.58953931
-0.33040078 4.58821415
-0.33675464 4.58672898
-0.34310850 4.58501913
-0.34946237 4.58298678
-0.35581623 4.58071110
-0.36217009 4.57816482
-0.36852395 4.57531844
-0.37487781 4.57209253
-0.38123167 4.56826124
-0.38758553 4.56399478
-0.39393939 4.55925255
-0.40029326 4.55399273
-0.40664712 4.54814499
-0.41300098 4.54124963
-0.41935484 4.53365966
-0.42570870 4.52533306
-0.43206256 4.51623220
-0.43841642 4.50632570
-0.44477028 4.49679479
-0.45112414 4.49371013
-0.45747801 4.49066211
-0.46383187 4.48765002
-0.47018573 4.48467321
-0.47653959 4.48157929
-0.48289345 4.47849013
-0.48924731 4.47543574
-0.49560117 4.47241549
-0.50195503 4.46942878
-0.50830890 4.46635382
-0.51466276 4.46326454
-0.52101662 4.46020827
-0.52737048 4.45718444
-0.53372434 4.45419251
-0.54007820 4.45113732
-0.54643206 4.44805138
-0.55278592 4.44499678
-0.55913978 4.44197300
-0.56549365 4.43897956
-0.57184751 4.43594462
-0.57820137 4.43286470
-0.58455523 4.42981456
-0.59090909 4.42679371
-0.59726295 4.42380172
-0.60361681 4.42078721
-0.60997067 4.41771542
-0.61632454 4.41467191
-0.62267840 4.41165627
-0.62903226 4.40866808
-0.63538612 4.40567398
-0.64173998 4.40261191
-0.64809384 4.39957674
-0.65444770 4.39656808
-0.66080156 4.39358555
-0.66715543 4.39061167
-0.67350929 4.38756054
-0.67986315 4.38453499
-0.68621701 4.38153468
-0.69257087 4.37880303
-0.69892473 4.37647513
-0.70527859 4.37447251
-0.71163245 4.37287629
-0.71798631 4.37166784
-0.72434018 4.37088208
-0.73069404 4.37049511
-0.73704790 4.37038886
-0.74340176 4.37064262
-0.74975562 4.37108759
-0.75610948 4.37180971
-0.76246334 4.37286007
-0.76881720 4.37417270
-0.77517107 4.37551934
-0.78152493 4.37694454
-0.78787879 4.37839069
-0.79423265 4.37985711
-0.80058651 4.38133785
-0.80694037 4.38282570
-0.81329423 4.38399523
-0.81964809 4.38518475
-0.82600196 4.38627238
-0.83235582 4.38726315
-0.83870968 4.38827040
-0.84506354 4.38921872
-0.85141740 4.38993199
-0.85777126 4.39066514
-0.86412512 4.39141423
-0.87047898 4.39217807
-0.87683284 4.39292534
-0.88318671 4.39340549
-0.88954057 4.39376844
-0.89589443 4.39404783
-0.90224829 4.39434112
-0.90860215 4.39441413
-0.91495601 4.39443473
-0.92130987 4.39447393
-0.92766373 4.39445587
-0.93401760 4.39402302
-0.94037146 4.39356564
-0.94672532 4.39297918
-0.95307918 4.39226487
-0.95943304 4.39119401
-0.96578690 4.38989115
-0.97214076 4.38796712
-0.97849462 4.38600893
-0.98484848 4.38407835
-0.99120235 4.38215966
-0.99755621 4.38024519
-1.00391007 4.37834225
-1.01026393 4.37645076
-1.01661779 4.37457058
-1.02297165 4.37270159
-1.02932551 4.37083696
-1.03567937 4.36877780
-1.04203324 4.36610094
-1.04838710 4.36313118
-1.05474096 4.35990289
-1.06109482 4.35644500
-1.06744868 4.35289881
-1.07380254 4.34968954
-1.08015640 4.34716128
-1.08651026 4.34611783
-1.09286413 4.34663860
-1.09921799 4.34758866
-1.10557185 4.34836750
-1.11192571 4.34914531
-1.11827957 4.34958039
-1.12463343 4.35003899
-1.13098729 4.35014697
-1.13734115 4.35002141
-1.14369501 4.34987408
-1.15004888 4.34973832
-1.15640274 4.34945577
-1.16275660 4.34879209
-1.16911046 4.34814083
-1.17546432 4.34731869
-1.18181818 4.34624489
-1.18817204 4.34469651
-1.19452590 4.34288533
-1.20087977 4.34082275
-1.20723363 4.33851027
-1.21358749 4.33615665
-1.21994135 4.33335536
-1.22629521 4.33013730
-1.23264907 4.32664160
-1.23900293 4.32198901
-1.24535679 4.31616989
-1.25171065 4.31025501
-1.25806452 4.30433460
-1.26441838 4.29837199
-1.27077224 4.29236663
-1.27712610 4.28609815
-1.28347996 4.27962801
-1.28983382 4.27309980
-1.29618768 4.26651947
-1.30254154 4.25988662
-1.30889541 4.25320051
-1.31524927 4.24629927
-1.32160313 4.24005945
-1.32795699 4.23795316
-1.33431085 4.23585513
-1.34066471 4.23376527
-1.34701857 4.23168350
-1.35337243 4.22960435
-1.35972630 4.22753110
-1.36608016 4.22546570
-1.37243402 4.22340809
-1.37878788 4.22135819
-1.38514174 4.21931137
-1.39149560 4.21726922
-1.39784946 4.21523454
-1.40420332 4.21320729
-1.41055718 4.21118737
-1.41691105 4.20917103
-1.42326491 4.20715813
-1.42961877 4.20515236
-1.43597263 4.20315365
-1.44232649 4.20116193
-1.44868035 4.19917429
-1.45503421 4.19718890
-1.46138807 4.19521029
-1.46774194 4.19323841
-1.47409580 4.19127319
-1.48044966 4.18931257
-1.48680352 4.18735301
-1.49315738 4.18539991
-1.49951124 4.18345322
-1.50586510 4.18151287
-1.51221896 4.17957767
-1.51857283 4.17764235
-1.52492669 4.17571319
-1.53128055 4.17379013
-1.53763441 4.17187310
-1.54398827 4.16996178
-1.55034213 4.16804919
-1.55669599 4.16614246
-1.56304985 4.16424153
-1.56940371 4.16234634
-1.57575758 4.16045686
-1.58211144 4.15856612
-1.58846530 4.15668038
-1.59481916 4.15480017
-1.60117302 4.15292542
-1.60752688 4.15105609
-1.61388074 4.14918610
-1.62023460 4.14731998
-1.62658847 4.14545912
-1.63294233 4.14360345
-1.63929619 4.14175295
-1.64565005 4.13990238
-1.65200391 4.13805457
-1.65835777 4.13621175
-1.66471163 4.13437388
-1.67106549 4.13254091
-1.67741935 4.13070850
-1.68377322 4.12887773
-1.69012708 4.12705172
-1.69648094 4.12523040
-1.70283480 4.12341375
-1.70918866 4.12159827
-1.71554252 4.11978336
-1.72189638 4.11797295
-1.72825024 4.11616701
-1.73460411 4.11436550
-1.74095797 4.11256579
-1.74731183 4.11076557
-1.75366569 4.16815388
-1.76001955 4.16667554
-1.76637341 4.16410645
-1.77272727 4.16043775
-1.77908113 4.15638598
-1.78543500 4.15183330
-1.79178886 4.14667777
-1.79814272 4.14136638
-1.80449658 4.13570068
-1.81085044 4.12992982
-1.81720430 4.12387456
-1.82355816 4.11726659
-1.82991202 4.11042338
-1.83626588 4.10317095
-1.84261975 4.09581886
-1.84897361 4.08832336
-1.85532747 4.08042629
-1.86168133 4.07241751
-1.86803519 4.06429132
-1.87438905 4.05568572
-1.88074291 4.04633694
-1.88709677 4.03689612
-1.89345064 4.02761208
-1.89980450 4.01817993
-1.90615836 4.00859076
-1.91251222 3.99884449
-1.91886608 3.98920625
-1.92521994 3.97958231
-1.93157380 3.96973063
-1.93792766 3.96399899
-1.94428152 3.96201550
-1.95063539 3.96003562
-1.95698925 3.95805933
-1.96334311 3.95608658
-1.96969697 3.95411363
-1.97605083 3.95214101
-1.98240469 3.95017184
-1.98875855 3.94820607
-1.99511241 3.94624368
-2.00146628 3.94428172
-2.00782014 3.94231916
-2.01417400 3.94035987
-2.02052786 3.93840382
-2.02688172 3.93645098
-2.03323558 3.93449920
-2.03958944 3.93254591
-2.04594330 3.93059572
-2.05229717 3.92832105
-2.05865103 3.92627635
-2.06500489 3.92447527
-2.07135875 3.92277481
-2.07771261 3.92110473
-2.08406647 3.91946430
-2.09042033 3.91801074
-2.09677419 3.91668068
-2.10312805 3.91536878
-2.10948192 3.91408031
-2.11583578 3.91281472
-2.12218964 3.91172397
-2.12854350 3.91066873
-2.13489736 3.90968063
-2.14125122 3.90866978
-2.14760508 3.90758799
-2.15395894 3.90652395
-2.16031281 3.90547728
-2.16666667 3.90444268
-2.17302053 3.90342393
-2.17937439 3.90242153
-2.18572825 3.90148645
-2.19208211 3.90044592
-2.19843597 3.89939315
-2.20478983 3.89835323
-2.21114370 3.89732738
-2.21749756 3.89631533
-2.22385142 3.89532342
-2.23020528 3.89423978
-2.23655914 3.89316626
-2.24291300 3.89208563
-2.24926686 3.89092119
-2.25562072 3.76337314
-2.26197458 3.76081058
-2.26832845 3.75822085
-2.27468231 3.75551510
-2.28103617 3.75278784
-2.28739003 3.75004999
-2.29374389 3.74729617
-2.30009775 3.74452493
-2.30645161 3.74170572
-2.31280547 3.73878316
-2.31915934 3.73582261
-2.32551320 3.73283947
-2.33186706 3.72983299
-2.33822092 3.72680713
-2.34457478 3.72376166
-2.35092864 3.72069632
-2.35728250 3.71760993
-2.36363636 3.71449828
-2.36999022 3.71136598
-2.37634409 3.70821278
-2.38269795 3.70489596
-2.38905181 3.70154910
-2.39540567 3.69815149
-2.40175953 3.69472082
-2.40811339 3.69126224
-2.41446725 3.68777534
-2.42082111 3.68425972
-2.42717498 3.68070953
-2.43352884 3.67712936
-2.43988270 3.67351920
-2.44623656 3.66987859
-2.45259042 3.66620712
-2.45894428 3.66249957
-2.46529814 3.65875916
-2.47165200 3.65498647
-2.47800587 3.65104597
-2.48435973 3.64701800
-2.49071359 3.64293652
-2.49706745 3.63878867
-2.50342131 3.63659673
-2.50977517 3.63611399
-2.51612903 3.63561093
-2.52248289 3.63510324
-2.52883675 3.63453444
-2.53519062 3.63385004
-2.54154448 3.63317427
-2.54789834 3.63250700
-2.55425220 3.63184550
-2.56060606 3.63118938
-2.56695992 3.63054136
-2.57331378 3.62990130
-2.57966764 3.62926907
-2.58602151 3.62864268
-2.59237537 3.62802052
-2.59872923 3.62740583
-2.60508309 3.62679849
-2.61143695 3.62618413
-2.61779081 3.62554215
-2.62414467 3.62488392
-2.63049853 3.62406075
-2.63685239 3.62318956
-2.64320626 3.62232742
-2.64956012 3.62147802
-2.65591398 3.62064524
-2.66226784 3.61982108
-2.66862170 3.61902917
-2.67497556 3.61825984
-2.68132942 3.61749945
-2.68768328 3.61673378
-2.69403715 3.61592994
-2.70039101 3.61501009
-2.70674487 3.61408072
-2.71309873 3.61321512
-2.71945259 3.61235895
-2.72580645 3.61151329
-2.73216031 3.61064326
-2.73851417 3.60961746
-2.74486804 3.60859393
-2.75122190 3.60702762
-2.75757576 3.60351398
-2.76392962 3.59960789
-2.77028348 3.59555467
-2.77663734 3.59147098
-2.78299120 3.58703970
-2.78934506 3.58242764
-2.79569892 3.57776988
-2.80205279 3.57306558
-2.80840665 3.56829409
-2.81476051 3.56334023
-2.82111437 3.55802164
-2.82746823 3.55251633
-2.83382209 3.54693068
-2.84017595 3.54126260
-2.84652981 3.53550824
-2.85288368 3.52966479
-2.85923754 3.52373194
-2.86559140 3.51744075
-2.87194526 3.51081525
-2.87829912 3.50398168
-2.88465298 3.49701812
-2.89100684 3.48987377
-2.89736070 3.48252541
-2.90371457 3.47502794
-2.91006843 3.46722539
-2.91642229 3.45888634
-2.92277615 3.45055564
-2.92913001 3.44204877
-2.93548387 3.43336011
-2.94183773 3.42460297
-2.94819159 3.41528161
-2.95454545 3.40565175
-2.96089932 3.40300714
-2.96725318 3.40043451
-2.97360704 3.39786239
-2.97996090 3.39528792
-2.98631476 3.39271389
-2.99266862 3.39014036
-2.99902248 3.38756888
-3.00537634 3.38500034
-3.01173021 3.38243001
-3.01808407 3.38007765
-3.02443793 3.37787501
-3.03079179 3.37552494
-3.03714565 3.37340204
-3.04349951 3.37111671
-3.04985337 3.36882418
-3.05620723 3.36662318
-3.06256109 3.36450384
-3.06891496 3.36240980
-3.07526882 3.36033602
-3.08162268 3.35835345
-3.08797654 3.35647890
-3.09433040 3.35462247
-3.10068426 3.35277157
-3.10703812 3.35090734
-3.11339198 3.34899388
-3.11974585 3.34690989
-3.12609971 3.34481953
-3.13245357 3.34259889
-3.13880743 3.34027538
-3.14516129 3.33788302
-3.15151515 3.33541209
-3.15786901 3.33287539
-3.16422287 3.33020839
-3.17057674 3.32753274
-3.17693060 3.32484854
-3.18328446 3.32215720
-3.18963832 3.31945931
-3.19599218 3.31667743
-3.20234604 3.31378377
-3.20869990 3.31088178
-3.21505376 3.30797303
-3.22140762 3.30519492
-3.22776149 3.30243306
-3.23411535 3.29966916
-3.24046921 3.29698360
-3.24682307 3.29438892
-3.25317693 3.29169494
-3.25953079 3.28891268
-3.26588465 3.28630351
-3.27223851 3.28369610
-3.27859238 3.28109052
-3.28494624 3.27860857
-3.29130010 3.27619341
-3.29765396 3.27372222
-3.30400782 3.27116176
-3.31036168 3.26874774
-3.31671554 3.26596679
-3.32306940 3.26308532
-3.32942326 3.26019945
-3.33577713 3.25734721
-3.34213099 3.25458122
-3.34848485 3.25172732
-3.35483871 3.24879215
-3.36119257 3.24576566
-3.36754643 3.24271852
-3.37390029 3.23961927
-3.38025415 3.23641405
-3.38660802 3.23321121
-3.39296188 3.22976019
-3.39931574 3.22637810
-3.40566960 3.22279662
-3.41202346 3.21915441
-3.41837732 3.21527248
-3.42473118 3.21129762
-3.43108504 3.20713137
-3.43743891 3.20292699
-3.44379277 3.19841827
-3.45014663 3.19381075
-3.45650049 3.18886054
-3.46285435 3.18335924
-3.46920821 3.17702423
-3.47556207 3.17049682
-3.48191593 3.16377804
-3.48826979 3.15683580
-3.49462366 3.15177725
-3.50097752 3.14803572
-3.50733138 3.14419775
-3.51368524 3.14044671
-3.52003910 3.13665574
-3.52639296 3.13280620
-3.53274682 3.12889965
-3.53910068 3.12512947
-3.54545455 3.12126138
-3.55180841 3.11732325
-3.55816227 3.11337877
-3.56451613 3.10955691
-3.57086999 3.10568995
-3.57722385 3.10181269
-3.58357771 3.09811330
-3.58993157 3.09438699
-3.59628543 3.09086132
-3.60263930 3.08751561
-3.60899316 3.08415516
-3.61534702 3.08099062
-3.62170088 3.07776100
-3.62805474 3.07468958
-3.63440860 3.07176252
-3.64076246 3.06907851
-3.64711632 3.06688891
-3.65347019 3.06484834
-3.65982405 3.06284108
-3.66617791 3.06094316
-3.67253177 3.05894665
-3.67888563 3.05703324
-3.68523949 3.05164677
-3.69159335 3.04363857
-3.69794721 3.03471641
-3.70430108 3.02543208
-3.71065494 3.01589929
-3.71700880 3.00553223
-3.72336266 2.99463175
-3.72971652 2.98325797
-3.73607038 2.97164536
-3.74242424 2.95913845
-3.74877810 2.94665618
-3.75513196 2.93476834
-3.76148583 2.92401169
-3.76783969 2.91397295
-3.77419355 2.90500583
-3.78054741 2.89739564
-3.78690127 2.89023994
-3.79325513 2.88386471
-3.79960899 2.87814643
-3.80596285 2.87333892
-3.81231672 2.86877440
-3.81867058 2.86469132
-3.82502444 2.86094168
-3.83137830 2.85747363
-3.83773216 2.85439583
-3.84408602 2.85144970
-3.85043988 2.84854948
-3.85679374 2.84569551
-3.86314761 2.84293338
-3.86950147 2.84039038
-3.87585533 2.83818725
-3.88220919 2.83628229
-3.88856305 2.83439521
-3.89491691 2.83251336
-3.90127077 2.83063091
-3.90762463 2.82874730
-3.91397849 2.82686252
-3.92033236 2.82497962
-3.92668622 2.82309721
-3.93304008 2.82121357
-3.93939394 2.81932867
-3.94574780 2.81744251
-3.95210166 2.81555763
-3.95845552 2.81367374
-3.96480938 2.81178852
-3.97116325 2.80990194
-3.97751711 2.80801400
-3.98387097 2.80612671
-3.99022483 2.80424094
-3.99657869 2.80235372
-4.00293255 2.80046506
-4.00928641 2.79857491
-4.01564027 2.79668478
-4.02199413 2.79479670
-4.02834800 2.79290707
-4.03470186 2.79101588
-4.04105572 2.78912311
-4.04740958 2.78722967
-4.05376344 2.78533883
-4.06011730 2.78344635
-4.06647116 2.78155219
-4.07282502 2.77965634
-4.07917889 2.77775913
-4.08553275 2.77586508
-4.09188661 2.77396927
-4.09824047 2.77207168
-4.10459433 2.77017228
-4.11094819 2.76827109
-4.11730205 2.76637434
-4.12365591 2.76447607
-4.13000978 2.76259577
-4.13636364 2.76075882
-4.14271750 2.75893517
-4.14907136 2.75713151
-4.15542522 2.75534631
-4.16177908 2.75358066
-4.16813294 2.75148207
-4.17448680 2.74737957
-4.18084066 2.74328575
-4.18719453 2.73904082
-4.19354839 2.73500045
-4.19990225 2.73095663
-4.20625611 2.72730610
-4.21260997 2.72385368
-4.21896383 2.72065040
-4.22531769 2.71721572
-4.23167155 2.71426493
-4.23802542 2.71137767
-4.24437928 2.70845631
-4.25073314 2.70550205
-4.25708700 2.69996380
-4.26344086 2.69440475
-4.26979472 2.68881807
-4.27614858 2.68315293
-4.28250244 2.67735284
-4.28885630 2.67153447
-4.29521017 2.66571019
-4.30156403 2.65989453
-4.30791789 2.65390481
-4.31427175 2.64708228
-4.32062561 2.64037670
-4.32697947 2.63438347
-4.33333333 2.62861133
-4.33968719 2.62304526
-4.34604106 2.61768259
-4.35239492 2.61251066
-4.35874878 2.60752294
-4.36510264 2.60271328
-4.37145650 2.59807611
-4.37781036 2.59361216
-4.38416422 2.58930980
-4.39051808 2.58516418
-4.39687195 2.58117070
-4.40322581 2.57732505
-4.40957967 2.57362922
-4.41593353 2.57007381
-4.42228739 2.56665466
-4.42864125 2.56336836
-4.43499511 2.56021170
-4.44134897 2.55718697
-4.44770283 2.55428733
-4.45405670 2.55150882
-4.46041056 2.54884895
-4.46676442 2.54630540
-4.47311828 2.54388055
-4.47947214 2.54156989
-4.48582600 2.53936947
-4.49217986 2.53727757
-4.49853372 2.53529258
-4.50488759 2.53341685
-4.51124145 2.53164806
-4.51759531 2.52998217
-4.52394917 2.52841809
-4.53030303 2.52695485
-4.53665689 2.52559467
-4.54301075 2.52433737
-4.54936461 2.52317872
-4.55571848 2.52211823
-4.56207234 2.52115550
-4.56842620 2.52029257
-4.57478006 2.51953144
-4.58113392 2.51886761
-4.58748778 2.51830117
-4.59384164 2.51783230
-4.60019550 2.51746288
-4.60654936 2.51719708
-4.61290323 2.51703018
-4.61925709 2.51696285
-4.62561095 2.51699591
-4.63196481 2.51713108
-4.63831867 2.51737487
-4.64467253 2.51772231
-4.65102639 2.51817478
-4.65738025 2.51365912
-4.66373412 2.50812539
-4.67008798 2.50254117
-4.67644184 2.49690585
-4.68279570 2.49122666
-4.68914956 2.48551165
-4.69550342 2.48013193
-4.70185728 2.47482314
-4.70821114 2.46951049
-4.71456500 2.46420298
-4.72091887 2.45891090
-4.72727273 2.45364485
-4.73362659 2.44842132
-4.73998045 2.44324745
-4.74633431 2.43829931
-4.75268817 2.43276374
-4.75904203 2.42594901
-4.76539589 2.41929175
-4.77174976 2.41266990
-4.77810362 2.40605558
-4.78445748 2.39925032
-4.79081134 2.39250730
-4.79716520 2.38586294
-4.80351906 2.37967484
-4.80987292 2.37356953
-4.81622678 2.36760890
-4.82258065 2.36164133
-4.82893451 2.35521881
-4.83528837 2.34873027
-4.84164223 2.34243033
-4.84799609 2.33632066
-4.85434995 2.33039904
-4.86070381 2.32481692
-4.86705767 2.31953567
-4.87341153 2.31441875
-4.87976540 2.30946679
-4.88611926 2.30477217
-4.89247312 2.30022466
-4.89882698 2.29582445
-4.90518084 2.29156138
-4.91153470 2.28743097
-4.91788856 2.28342860
-4.92424242 2.27955015
-4.93059629 2.27579688
-4.93695015 2.27215754
-4.94330401 2.26862746
-4.94965787 2.26530921
-4.95601173 2.26211366
-4.96236559 2.25901275
-4.96871945 2.25599608
-4.97507331 2.25305960
-4.98142717 2.25019972
-4.98778104 2.24741298
-4.99413490 2.24474210
-5.00048876 2.24213855
-5.00684262 2.23959626
-5.01319648 2.23711290
-5.01955034 2.23468644
-5.02590420 2.23232023
-5.03225806 2.23000972
-5.03861193 2.22775220
-5.04496579 2.22554726
-5.05131965 2.22339513
-5.05767351 2.22130091
-5.06402737 2.21926461
-5.07038123 2.21728613
-5.07673509 2.21536907
-5.08308895 2.21351825
-5.08944282 2.21174342
-5.09579668 2.21005250
-5.10215054 2.20845203
-5.10850440 2.20695434
-5.11485826 2.20557445
-5.12121212 2.20433321
-5.12756598 2.20325400
-5.13391984 2.20235861
-5.14027370 2.20167781
-5.14662757 2.20124760
-5.15298143 2.20111168
-5.15933529 2.20132119
-5.16568915 2.20193404
-5.17204301 2.20307241
-5.17839687 2.20475357
-5.18475073 2.20726794
-5.19110459 2.21067269
-5.19745846 2.21491846
-5.20381232 2.22008426
-5.21016618 2.22646298
-5.21652004 2.23442174
-5.22287390 2.24385294
-5.22922776 2.24551921
-5.23558162 2.24815352
-5.24193548 2.25200556
-5.24828935 2.25714357
-5.25464321 2.25724236
-5.26099707 2.25616649
-5.26735093 2.25520784
-5.27370479 2.25248810
-5.28005865 2.24548917
-5.28641251 2.23618077
-5.29276637 2.22750996
-5.29912023 2.21983090
-5.30547410 2.21317646
-5.31182796 2.20715601
-5.31818182 2.20179151
-5.32453568 2.19721742
-5.33088954 2.19294220
-5.33724340 2.18926362
-5.34359726 2.18576371
-5.34995112 2.18274758
-5.35630499 2.17987881
-5.36265885 2.17713283
-5.36901271 2.17468567
-5.37536657 2.17233874
-5.38172043 2.17006553
-5.38807429 2.16786008
-5.39442815 2.16579907
-5.40078201 2.16380630
-5.40713587 2.16184094
-5.41348974 2.15990253
-5.41984360 2.15799046
-5.42619746 2.15609712
-5.43255132 2.15422018
-5.43890518 2.15235753
-5.44525904 2.15050915
-5.45161290 2.14867742
-5.45796676 2.14685502
-5.46432063 2.14504070
-5.47067449 2.14323338
-5.47702835 2.14143305
-5.48338221 2.13964470
-5.48973607 2.13786091
-5.49608993 2.13608110
-5.50244379 2.13432811
-5.50879765 2.13264953
-5.51515152 2.13098914
-5.52150538 2.12933904
-5.52785924 2.12769901
-5.53421310 2.12606893
-5.54056696 2.12444872
-5.54692082 2.12297169
-5.55327468 2.12151101
-5.55962854 2.12000896
-5.56598240 2.11852374
-5.57233627 2.11705545
-5.57869013 2.11576567
-5.58504399 2.11453786
-5.59139785 2.11333588
-5.59775171 2.11220915
-5.60410557 2.11125442
-5.61045943 2.11033818
-5.61681329 2.10945768
-5.62316716 2.10879468
-5.62952102 2.10825077
-5.63587488 2.10774775
-5.64222874 2.10752398
-5.64858260 2.10735134
-5.65493646 2.10726066
-5.66129032 2.10750332
-5.66764418 2.10779560
-5.67399804 2.10835799
-5.68035191 2.10902043
-5.68670577 2.10984600
-5.69305963 2.11097904
-5.69941349 2.11222876
-5.70576735 2.11373651
-5.71212121 2.11528838
-5.71847507 2.11718851
-5.72482893 2.11914029
-5.73118280 2.12140684
-5.73753666 2.12370922
-5.74389052 2.12586442
-5.75024438 2.12753370
-5.75659824 2.12895198
-5.76295210 2.12981477
-5.76930596 2.13011125
-5.77565982 2.12994191
-5.78201369 2.12933282
-5.78836755 2.12820110
-5.79472141 2.12646697
-5.80107527 2.12412333
-5.80742913 2.12143814
-5.81378299 2.11846532
-5.82013685 2.11546501
-5.82649071 2.11243946
-5.83284457 2.10938833
-5.83919844 2.10641445
-5.84555230 2.10343192
-5.85190616 2.10042326
-5.85826002 2.09738809
-5.86461388 2.09432602
-5.87096774 2.09133192
-5.87732160 2.08834373
-5.88367546 2.08532809
-5.89002933 2.08228458
-5.89638319 2.07921279
-5.90273705 2.07619828
-5.90909091 2.07320629
-5.91544477 2.07018544
-5.92179863 2.06713530
-5.92815249 2.06405538
-5.93450635 2.06102044
-5.94086022 2.05802700
-5.94721408 2.05500322
-5.95356794 2.05194862
-5.95992180 2.04886268
-5.96627566 2.04580749
-5.97262952 2.04281556
-5.97898338 2.03979173
-5.98533724 2.03673546
-5.99169110 2.03364618
-5.99804497 2.03057122
-6.00439883 2.02758451
-6.01075269 2.02456426
-6.01710655 2.02150987
-6.02346041 2.01842071
-6.02981427 2.01532679
-6.03616813 2.01234998
-6.04252199 2.00933789
-6.04887586 2.00628987
-6.05522972 2.00320521
-6.06158358 1.99367430
-6.06793744 1.98376780
-6.07429130 1.97466694
-6.08064516 1.96634034
-6.08699902 1.95875037
-6.09335288 1.95185501
-6.09970674 1.94600727
-6.10606061 1.94074745
-6.11241447 1.93600522
-6.11876833 1.93173876
-6.12512219 1.92790747
-6.13147605 1.92468156
-6.13782991 1.92183518
-6.14418377 1.91928890
-6.15053763 1.91701322
-6.15689150 1.91498087
-6.16324536 1.91327102
-6.16959922 1.91178585
-6.17595308 1.91046069
-6.18230694 1.90927830
-6.18866080 1.90822309
-6.19501466 1.90733119
-6.20136852 1.90656708
-6.20772239 1.90588399
-6.21407625 1.90527278
-6.22043011 1.90472528
-6.22678397 1.90425780
-6.23313783 1.90386237
-6.23949169 1.90350656
-6.24584555 1.90308083
-6.25219941 1.90118262
-6.25855327 1.90112632
-6.26490714 1.90107469
-6.27126100 1.90102316
-6.27761486 1.90097173
-6.28396872 1.90092039
-6.29032258 1.90087093
-6.29667644 1.90082693
-6.30303030 1.90078302
-6.30938416 1.90073919
-6.31573803 1.90069544
-6.32209189 1.90065273
-6.32844575 1.90061628
-6.33479961 1.90057990
-6.34115347 1.90054359
-6.34750733 1.90050735
-6.35386119 1.90047129
-6.36021505 1.90044231
-6.36656891 1.90041337
-6.37292278 1.90038449
-6.37927664 1.90035566
-6.38563050 1.90032689
-6.39198436 1.90030458
-6.39833822 1.90028301
-6.40469208 1.90026147
-6.41104594 1.90023998
-6.41739980 1.90021852
-6.42375367 1.90020269
-6.43010753 1.90018839
-6.43646139 1.90017411
-6.44281525 1.90015986
-6.44916911 1.90014564
-6.45552297 1.90013620
-6.46187683 1.90012909
-6.46823069 1.90012200
-6.47458456 1.90011492
-6.48093842 1.90010785
-6.48729228 1.90010472
-6.49364614 1.90010472
-6.50000000 1.90010472
+AllInputTerms AllOutputTerms
+0.000000000 4.599895277
+0.006353861 4.599895277
+0.012707722 4.599895277
+0.019061584 4.599892153
+0.025415445 4.599885084
+0.031769306 4.599878001
+0.038123167 4.599870905
+0.044477028 4.599863796
+0.050830890 4.599854356
+0.057184751 4.599840135
+0.063538612 4.599825888
+0.069892473 4.599811614
+0.076246334 4.599797313
+0.082600196 4.599781479
+0.088954057 4.599760024
+0.095307918 4.599738529
+0.101661779 4.599716994
+0.108015640 4.599695418
+0.114369501 4.599673109
+0.120723363 4.599644337
+0.127077224 4.599615510
+0.133431085 4.599586630
+0.139784946 4.599557695
+0.146138807 4.599528705
+0.152492669 4.599492655
+0.158846530 4.599456412
+0.165200391 4.599420101
+0.171554252 4.599383721
+0.177908113 4.599347272
+0.184261975 4.599304555
+0.190615836 4.599260809
+0.196969697 4.599216981
+0.203323558 4.599173070
+0.209677419 4.599129075
+0.216031281 4.599079607
+0.222385142 4.599028272
+0.228739003 4.598976839
+0.235092864 4.598925308
+0.241446725 4.598873679
+0.247800587 4.598817377
+0.254154448 4.596919174
+0.260508309 4.596493440
+0.266862170 4.596137632
+0.273216031 4.595742200
+0.279569892 4.595274723
+0.285923754 4.594727219
+0.292277615 4.594116008
+0.298631476 4.593432922
+0.304985337 4.592668807
+0.311339198 4.591776911
+0.317693060 4.590721701
+0.324046921 4.589539310
+0.330400782 4.588214154
+0.336754643 4.586728981
+0.343108504 4.585019129
+0.349462366 4.582986784
+0.355816227 4.580711102
+0.362170088 4.578164818
+0.368523949 4.575318436
+0.374877810 4.572092534
+0.381231672 4.568261237
+0.387585533 4.563994780
+0.393939394 4.559252552
+0.400293255 4.553992732
+0.406647116 4.548144994
+0.413000978 4.541249632
+0.419354839 4.533659657
+0.425708700 4.525333057
+0.432062561 4.516232199
+0.438416422 4.506325696
+0.444770283 4.496794792
+0.451124145 4.493710135
+0.457478006 4.490662106
+0.463831867 4.487650020
+0.470185728 4.484673209
+0.476539589 4.481579293
+0.482893451 4.478490131
+0.489247312 4.475435736
+0.495601173 4.472415487
+0.501955034 4.469428781
+0.508308895 4.466353820
+0.514662757 4.463264545
+0.521016618 4.460208273
+0.527370479 4.457184444
+0.533724340 4.454192506
+0.540078201 4.451137323
+0.546432063 4.448051381
+0.552785924 4.444996778
+0.559139785 4.441973003
+0.565493646 4.438979556
+0.571847507 4.435944616
+0.578201369 4.432864702
+0.584555230 4.429814557
+0.590909091 4.426793715
+0.597262952 4.423801721
+0.603616813 4.420787213
+0.609970674 4.417715418
+0.616324536 4.414671913
+0.622678397 4.411656273
+0.629032258 4.408668084
+0.635386119 4.405673984
+0.641739980 4.402611914
+0.648093842 4.399576742
+0.654447703 4.396568080
+0.660801564 4.393585550
+0.667155425 4.390611667
+0.673509286 4.387560536
+0.679863148 4.384534993
+0.686217009 4.381534685
+0.692570870 4.378803034
+0.698924731 4.376475128
+0.705278592 4.374472509
+0.711632454 4.372876293
+0.717986315 4.371667843
+0.724340176 4.370882078
+0.730694037 4.370495109
+0.737047898 4.370388857
+0.743401760 4.370642624
+0.749755621 4.371087594
+0.756109482 4.371809708
+0.762463343 4.372860066
+0.768817204 4.374172697
+0.775171065 4.375519338
+0.781524927 4.376944539
+0.787878788 4.378390691
+0.794232649 4.379857111
+0.800586510 4.381337853
+0.806940371 4.382825703
+0.813294233 4.383995232
+0.819648094 4.385184747
+0.826001955 4.386272381
+0.832355816 4.387263153
+0.838709677 4.388270397
+0.845063539 4.389218723
+0.851417400 4.389931993
+0.857771261 4.390665144
+0.864125122 4.391414233
+0.870478983 4.392178065
+0.876832845 4.392925336
+0.883186706 4.393405489
+0.889540567 4.393768439
+0.895894428 4.394047827
+0.902248289 4.394341121
+0.908602151 4.394414128
+0.914956012 4.394434726
+0.921309873 4.394473933
+0.927663734 4.394455866
+0.934017595 4.394023022
+0.940371457 4.393565645
+0.946725318 4.392979180
+0.953079179 4.392264873
+0.959433040 4.391194008
+0.965786901 4.389891155
+0.972140762 4.387967116
+0.978494624 4.386008929
+0.984848485 4.384078347
+0.991202346 4.382159658
+0.997556207 4.380245187
+1.003910068 4.378342248
+1.010263930 4.376450758
+1.016617791 4.374570582
+1.022971652 4.372701585
+1.029325513 4.370836957
+1.035679374 4.368777798
+1.042033236 4.366100940
+1.048387097 4.363131178
+1.054740958 4.359902890
+1.061094819 4.356444999
+1.067448680 4.352898808
+1.073802542 4.349689538
+1.080156403 4.347161282
+1.086510264 4.346117831
+1.092864125 4.346638603
+1.099217986 4.347588660
+1.105571848 4.348367496
+1.111925709 4.349145305
+1.118279570 4.349580392
+1.124633431 4.350038990
+1.130987292 4.350146966
+1.137341153 4.350021415
+1.143695015 4.349874085
+1.150048876 4.349738316
+1.156402737 4.349455770
+1.162756598 4.348792090
+1.169110459 4.348140830
+1.175464321 4.347318692
+1.181818182 4.346244887
+1.188172043 4.344696513
+1.194525904 4.342885325
+1.200879765 4.340822753
+1.207233627 4.338510265
+1.213587488 4.336156649
+1.219941349 4.333355362
+1.226295210 4.330137299
+1.232649071 4.326641602
+1.239002933 4.321989008
+1.245356794 4.316169893
+1.251710655 4.310255005
+1.258064516 4.304334601
+1.264418377 4.298371995
+1.270772239 4.292366629
+1.277126100 4.286098146
+1.283479961 4.279628008
+1.289833822 4.273099795
+1.296187683 4.266519469
+1.302541544 4.259886618
+1.308895406 4.253200509
+1.315249267 4.246299266
+1.321603128 4.240059447
+1.327956989 4.237953162
+1.334310850 4.235855128
+1.340664712 4.233765267
+1.347018573 4.231683504
+1.353372434 4.229604349
+1.359726295 4.227531097
+1.366080156 4.225465702
+1.372434018 4.223408091
+1.378787879 4.221358193
+1.385141740 4.219311371
+1.391495601 4.217269217
+1.397849462 4.215234545
+1.404203324 4.213207286
+1.410557185 4.211187374
+1.416911046 4.209171028
+1.423264907 4.207158130
+1.429618768 4.205152358
+1.435972630 4.203153647
+1.442326491 4.201161932
+1.448680352 4.199174293
+1.455034213 4.197188899
+1.461388074 4.195210291
+1.467741935 4.193238408
+1.474095797 4.191273188
+1.480449658 4.189312571
+1.486803519 4.187353011
+1.493157380 4.185399915
+1.499511241 4.183453221
+1.505865103 4.181512872
+1.512218964 4.179577670
+1.518572825 4.177642355
+1.524926686 4.175713192
+1.531280547 4.173790126
+1.537634409 4.171873100
+1.543988270 4.169961779
+1.550342131 4.168049188
+1.556695992 4.166142455
+1.563049853 4.164241525
+1.569403715 4.162346345
+1.575757576 4.160456860
+1.582111437 4.158566124
+1.588465298 4.156680384
+1.594819159 4.154800166
+1.601173021 4.152925419
+1.607526882 4.151056092
+1.613880743 4.149186104
+1.620234604 4.147319983
+1.626588465 4.145459116
+1.632942326 4.143603453
+1.639296188 4.141752946
+1.645650049 4.139902380
+1.652003910 4.138054566
+1.658357771 4.136211747
+1.664711632 4.134373878
+1.671065494 4.132540910
+1.677419355 4.130708496
+1.683773216 4.128877732
+1.690127077 4.127051717
+1.696480938 4.125230405
+1.702834800 4.123413751
+1.709188661 4.121598273
+1.715542522 4.119783356
+1.721896383 4.117972950
+1.728250244 4.116167012
+1.734604106 4.114365499
+1.740957967 4.112565790
+1.747311828 4.110765567
+1.753665689 4.168153884
+1.760019550 4.166675537
+1.766373412 4.164106453
+1.772727273 4.160437753
+1.779081134 4.156385975
+1.785434995 4.151833303
+1.791788856 4.146677771
+1.798142717 4.141366376
+1.804496579 4.135700681
+1.810850440 4.129929818
+1.817204301 4.123874560
+1.823558162 4.117266592
+1.829912023 4.110423379
+1.836265885 4.103170947
+1.842619746 4.095818864
+1.848973607 4.088323358
+1.855327468 4.080426295
+1.861681329 4.072417514
+1.868035191 4.064291322
+1.874389052 4.055685721
+1.880742913 4.046336936
+1.887096774 4.036896117
+1.893450635 4.027612078
+1.899804497 4.018179925
+1.906158358 4.008590765
+1.912512219 3.998844491
+1.918866080 3.989206249
+1.925219941 3.979582314
+1.931573803 3.969730626
+1.937927664 3.963998992
+1.944281525 3.962015501
+1.950635386 3.960035623
+1.956989247 3.958059326
+1.963343109 3.956086577
+1.969696970 3.954113625
+1.976050831 3.952141011
+1.982404692 3.950171837
+1.988758553 3.948206070
+1.995112414 3.946243679
+2.001466276 3.944281718
+2.007820137 3.942319159
+2.014173998 3.940359871
+2.020527859 3.938403822
+2.026881720 3.936450982
+2.033235582 3.934499204
+2.039589443 3.932545907
+2.045943304 3.930595717
+2.052297165 3.928321055
+2.058651026 3.926276349
+2.065004888 3.924475266
+2.071358749 3.922774809
+2.077712610 3.921104727
+2.084066471 3.919464304
+2.090420332 3.918010740
+2.096774194 3.916680680
+2.103128055 3.915368777
+2.109481916 3.914080307
+2.115835777 3.912814724
+2.122189638 3.911723968
+2.128543500 3.910668734
+2.134897361 3.909680634
+2.141251222 3.908669775
+2.147605083 3.907587992
+2.153958944 3.906523952
+2.160312805 3.905477277
+2.166666667 3.904442682
+2.173020528 3.903423931
+2.179374389 3.902421528
+2.185728250 3.901486449
+2.192082111 3.900445921
+2.198435973 3.899393150
+2.204789834 3.898353233
+2.211143695 3.897327377
+2.217497556 3.896315330
+2.223851417 3.895323424
+2.230205279 3.894239779
+2.236559140 3.893166259
+2.242913001 3.892085629
+2.249266862 3.890921186
+2.255620723 3.763373136
+2.261974585 3.760810581
+2.268328446 3.758220845
+2.274682307 3.755515096
+2.281036168 3.752787836
+2.287390029 3.750049993
+2.293743891 3.747296167
+2.300097752 3.744524926
+2.306451613 3.741705721
+2.312805474 3.738783159
+2.319159335 3.735822614
+2.325513196 3.732839473
+2.331867058 3.729832989
+2.338220919 3.726807130
+2.344574780 3.723761656
+2.350928641 3.720696322
+2.357282502 3.717609935
+2.363636364 3.714498281
+2.369990225 3.711365982
+2.376344086 3.708212779
+2.382697947 3.704895960
+2.389051808 3.701549104
+2.395405670 3.698151488
+2.401759531 3.694720822
+2.408113392 3.691262237
+2.414467253 3.687775337
+2.420821114 3.684259719
+2.427174976 3.680709529
+2.433528837 3.677129365
+2.439882698 3.673519197
+2.446236559 3.669878595
+2.452590420 3.666207121
+2.458944282 3.662499570
+2.465298143 3.658759155
+2.471652004 3.654986475
+2.478005865 3.651045967
+2.484359726 3.647017997
+2.490713587 3.642936519
+2.497067449 3.638788673
+2.503421310 3.636596731
+2.509775171 3.636113994
+2.516129032 3.635610934
+2.522482893 3.635103238
+2.528836755 3.634534439
+2.535190616 3.633850040
+2.541544477 3.633174274
+2.547898338 3.632506997
+2.554252199 3.631845503
+2.560606061 3.631189380
+2.566959922 3.630541357
+2.573313783 3.629901299
+2.579667644 3.629269072
+2.586021505 3.628642677
+2.592375367 3.628020518
+2.598729228 3.627405830
+2.605083089 3.626798488
+2.611436950 3.626184131
+2.617790811 3.625542149
+2.624144673 3.624883923
+2.630498534 3.624060753
+2.636852395 3.623189558
+2.643206256 3.622327417
+2.649560117 3.621478017
+2.655913978 3.620645245
+2.662267840 3.619821076
+2.668621701 3.619029171
+2.674975562 3.618259835
+2.681329423 3.617499446
+2.687683284 3.616733785
+2.694037146 3.615929936
+2.700391007 3.615010095
+2.706744868 3.614080723
+2.713098729 3.613215121
+2.719452590 3.612358954
+2.725806452 3.611513289
+2.732160313 3.610643258
+2.738514174 3.609617457
+2.744868035 3.608593932
+2.751221896 3.607027619
+2.757575758 3.603513978
+2.763929619 3.599607885
+2.770283480 3.595554668
+2.776637341 3.591470975
+2.782991202 3.587039699
+2.789345064 3.582427638
+2.795698925 3.577769876
+2.802052786 3.573065578
+2.808406647 3.568294094
+2.814760508 3.563340228
+2.821114370 3.558021643
+2.827468231 3.552516327
+2.833822092 3.546930677
+2.840175953 3.541262601
+2.846529814 3.535508239
+2.852883675 3.529664792
+2.859237537 3.523731944
+2.865591398 3.517440754
+2.871945259 3.510815250
+2.878299120 3.503981681
+2.884652981 3.497018115
+2.891006843 3.489873772
+2.897360704 3.482525406
+2.903714565 3.475027943
+2.910068426 3.467225386
+2.916422287 3.458886336
+2.922776149 3.450555637
+2.929130010 3.442048766
+2.935483871 3.433360109
+2.941837732 3.424602968
+2.948191593 3.415281614
+2.954545455 3.405651752
+2.960899316 3.403007137
+2.967253177 3.400434512
+2.973607038 3.397862391
+2.979960899 3.395287917
+2.986314761 3.392713887
+2.992668622 3.390140357
+2.999022483 3.387568883
+3.005376344 3.385000338
+3.011730205 3.382430013
+3.018084066 3.380077653
+3.024437928 3.377875015
+3.030791789 3.375524943
+3.037145650 3.373402036
+3.043499511 3.371116711
+3.049853372 3.368824184
+3.056207234 3.366623179
+3.062561095 3.364503845
+3.068914956 3.362409804
+3.075268817 3.360336018
+3.081622678 3.358353454
+3.087976540 3.356478896
+3.094330401 3.354622474
+3.100684262 3.352771569
+3.107038123 3.350907341
+3.113391984 3.348993885
+3.119745846 3.346909885
+3.126099707 3.344819531
+3.132453568 3.342598890
+3.138807429 3.340275375
+3.145161290 3.337883015
+3.151515152 3.335412086
+3.157869013 3.332875386
+3.164222874 3.330208393
+3.170576735 3.327532743
+3.176930596 3.324848544
+3.183284457 3.322157198
+3.189638319 3.319459305
+3.195992180 3.316677427
+3.202346041 3.313783765
+3.208699902 3.310881781
+3.215053763 3.307973034
+3.221407625 3.305194923
+3.227761486 3.302433058
+3.234115347 3.299669163
+3.240469208 3.296983598
+3.246823069 3.294388917
+3.253176931 3.291694941
+3.259530792 3.288912681
+3.265884653 3.286303511
+3.272238514 3.283696099
+3.278592375 3.281090518
+3.284946237 3.278608571
+3.291300098 3.276193408
+3.297653959 3.273722220
+3.304007820 3.271161759
+3.310361681 3.268747744
+3.316715543 3.265966787
+3.323069404 3.263085323
+3.329423265 3.260199447
+3.335777126 3.257347210
+3.342130987 3.254581221
+3.348484848 3.251727316
+3.354838710 3.248792146
+3.361192571 3.245765662
+3.367546432 3.242718518
+3.373900293 3.239619271
+3.380254154 3.236414055
+3.386608016 3.233211207
+3.392961877 3.229760188
+3.399315738 3.226378097
+3.405669599 3.222796617
+3.412023460 3.219154408
+3.418377322 3.215272481
+3.424731183 3.211297617
+3.431085044 3.207131367
+3.437438905 3.202926988
+3.443792766 3.198418272
+3.450146628 3.193810749
+3.456500489 3.188860538
+3.462854350 3.183359238
+3.469208211 3.177024226
+3.475562072 3.170496818
+3.481915934 3.163778038
+3.488269795 3.156835795
+3.494623656 3.151777246
+3.500977517 3.148035721
+3.507331378 3.144197746
+3.513685239 3.140446705
+3.520039101 3.136655740
+3.526392962 3.132806200
+3.532746823 3.128899648
+3.539100684 3.125129471
+3.545454545 3.121261384
+3.551808407 3.117323246
+3.558162268 3.113378774
+3.564516129 3.109556905
+3.570869990 3.105689954
+3.577223851 3.101812687
+3.583577713 3.098113304
+3.589931574 3.094386990
+3.596285435 3.090861319
+3.602639296 3.087515615
+3.608993157 3.084155158
+3.615347019 3.080990618
+3.621700880 3.077760997
+3.628054741 3.074689575
+3.634408602 3.071762524
+3.640762463 3.069078509
+3.647116325 3.066888906
+3.653470186 3.064848343
+3.659824047 3.062841076
+3.666177908 3.060943162
+3.672531769 3.058946649
+3.678885630 3.057033237
+3.685239492 3.051646773
+3.691593353 3.043638574
+3.697947214 3.034716407
+3.704301075 3.025432082
+3.710654936 3.015899291
+3.717008798 3.005532233
+3.723362659 2.994631745
+3.729716520 2.983257966
+3.736070381 2.971645362
+3.742424242 2.959138446
+3.748778104 2.946656184
+3.755131965 2.934768336
+3.761485826 2.924011690
+3.767839687 2.913972946
+3.774193548 2.905005829
+3.780547410 2.897395635
+3.786901271 2.890239940
+3.793255132 2.883864707
+3.799608993 2.878146427
+3.805962854 2.873338916
+3.812316716 2.868774397
+3.818670577 2.864691316
+3.825024438 2.860941683
+3.831378299 2.857473629
+3.837732160 2.854395833
+3.844086022 2.851449698
+3.850439883 2.848549478
+3.856793744 2.845695513
+3.863147605 2.842933383
+3.869501466 2.840390382
+3.875855327 2.838187245
+3.882209189 2.836282288
+3.888563050 2.834395205
+3.894916911 2.832513363
+3.901270772 2.830630910
+3.907624633 2.828747302
+3.913978495 2.826862520
+3.920332356 2.824979616
+3.926686217 2.823097208
+3.933040078 2.821213567
+3.939393939 2.819328674
+3.945747801 2.817442508
+3.952101662 2.815557626
+3.958455523 2.813673739
+3.964809384 2.811788518
+3.971163245 2.809901944
+3.977517107 2.808013996
+3.983870968 2.806126709
+3.990224829 2.804240935
+3.996578690 2.802353725
+4.002932551 2.800465058
+4.009286413 2.798574913
+4.015640274 2.796684781
+4.021994135 2.794796696
+4.028347996 2.792907069
+4.034701857 2.791015880
+4.041055718 2.789123106
+4.047409580 2.787229672
+4.053763441 2.785338834
+4.060117302 2.783446347
+4.066471163 2.781552188
+4.072825024 2.779656337
+4.079178886 2.777759126
+4.085532747 2.775865077
+4.091886608 2.773969268
+4.098240469 2.772071676
+4.104594330 2.770172279
+4.110948192 2.768271094
+4.117302053 2.766374342
+4.123655914 2.764476074
+4.130009775 2.762595767
+4.136363636 2.760758819
+4.142717498 2.758935172
+4.149071359 2.757131514
+4.155425220 2.755346309
+4.161779081 2.753580657
+4.168132942 2.751482072
+4.174486804 2.747379566
+4.180840665 2.743285748
+4.187194526 2.739040821
+4.193548387 2.735000453
+4.199902248 2.730956631
+4.206256109 2.727306104
+4.212609971 2.723853682
+4.218963832 2.720650398
+4.225317693 2.717215725
+4.231671554 2.714264925
+4.238025415 2.711377668
+4.244379277 2.708456312
+4.250733138 2.705502047
+4.257086999 2.699963796
+4.263440860 2.694404754
+4.269794721 2.688818075
+4.276148583 2.683152932
+4.282502444 2.677352841
+4.288856305 2.671534472
+4.295210166 2.665710188
+4.301564027 2.659894532
+4.307917889 2.653904808
+4.314271750 2.647082281
+4.320625611 2.640376703
+4.326979472 2.634383466
+4.333333333 2.628611333
+4.339687195 2.623045257
+4.346041056 2.617682590
+4.352394917 2.612510659
+4.358748778 2.607522940
+4.365102639 2.602713283
+4.371456500 2.598076108
+4.377810362 2.593612156
+4.384164223 2.589309799
+4.390518084 2.585164176
+4.396871945 2.581170702
+4.403225806 2.577325054
+4.409579668 2.573629224
+4.415933529 2.570073814
+4.422287390 2.566654660
+4.428641251 2.563368355
+4.434995112 2.560211698
+4.441348974 2.557186973
+4.447702835 2.554287333
+4.454056696 2.551508820
+4.460410557 2.548848951
+4.466764418 2.546305402
+4.473118280 2.543880553
+4.479472141 2.541569889
+4.485826002 2.539369471
+4.492179863 2.537277567
+4.498533724 2.535292581
+4.504887586 2.533416848
+4.511241447 2.531648061
+4.517595308 2.529982170
+4.523949169 2.528418089
+4.530303030 2.526954850
+4.536656891 2.525594665
+4.543010753 2.524337371
+4.549364614 2.523178724
+4.555718475 2.522118228
+4.562072336 2.521155495
+4.568426197 2.520292572
+4.574780059 2.519531438
+4.581133920 2.518867611
+4.587487781 2.518301166
+4.593841642 2.517832298
+4.600195503 2.517462875
+4.606549365 2.517197081
+4.612903226 2.517030180
+4.619257087 2.516962853
+4.625610948 2.516995911
+4.631964809 2.517131080
+4.638318671 2.517374868
+4.644672532 2.517722312
+4.651026393 2.518174779
+4.657380254 2.513659123
+4.663734115 2.508125388
+4.670087977 2.502541173
+4.676441838 2.496905848
+4.682795699 2.491226658
+4.689149560 2.485511648
+4.695503421 2.480131931
+4.701857283 2.474823139
+4.708211144 2.469510489
+4.714565005 2.464202984
+4.720918866 2.458910899
+4.727272727 2.453644854
+4.733626588 2.448421318
+4.739980450 2.443247453
+4.746334311 2.438299314
+4.752688172 2.432763745
+4.759042033 2.425949005
+4.765395894 2.419291750
+4.771749756 2.412669897
+4.778103617 2.406055580
+4.784457478 2.399250324
+4.790811339 2.392507300
+4.797165200 2.385862943
+4.803519062 2.379674845
+4.809872923 2.373569532
+4.816226784 2.367608901
+4.822580645 2.361641330
+4.828934506 2.355218813
+4.835288368 2.348730271
+4.841642229 2.342430330
+4.847996090 2.336320662
+4.854349951 2.330399039
+4.860703812 2.324816922
+4.867057674 2.319535672
+4.873411535 2.314418752
+4.879765396 2.309466791
+4.886119257 2.304772174
+4.892473118 2.300224661
+4.898826979 2.295824445
+4.905180841 2.291561381
+4.911534702 2.287430967
+4.917888563 2.283428598
+4.924242424 2.279550153
+4.930596285 2.275796879
+4.936950147 2.272157536
+4.943304008 2.268627457
+4.949657869 2.265309212
+4.956011730 2.262113657
+4.962365591 2.259012750
+4.968719453 2.255996077
+4.975073314 2.253059604
+4.981427175 2.250199716
+4.987781036 2.247412981
+4.994134897 2.244742103
+5.000488759 2.242138547
+5.006842620 2.239596260
+5.013196481 2.237112902
+5.019550342 2.234686436
+5.025904203 2.232320228
+5.032258065 2.230009725
+5.038611926 2.227752196
+5.044965787 2.225547264
+5.051319648 2.223395128
+5.057673509 2.221300911
+5.064027370 2.219264613
+5.070381232 2.217286135
+5.076735093 2.215369071
+5.083088954 2.213518254
+5.089442815 2.211743418
+5.095796676 2.210052495
+5.102150538 2.208452035
+5.108504399 2.206954343
+5.114858260 2.205574451
+5.121212121 2.204333209
+5.127565982 2.203253997
+5.133919844 2.202358615
+5.140273705 2.201677808
+5.146627566 2.201247601
+5.152981427 2.201111684
+5.159335288 2.201321192
+5.165689150 2.201934041
+5.172043011 2.203072413
+5.178396872 2.204753575
+5.184750733 2.207267944
+5.191104594 2.210672693
+5.197458456 2.214918459
+5.203812317 2.220084262
+5.210166178 2.226462979
+5.216520039 2.234421744
+5.222873900 2.243852944
+5.229227761 2.245519207
+5.235581623 2.248153515
+5.241935484 2.252005561
+5.248289345 2.257143573
+5.254643206 2.257242365
+5.260997067 2.256166494
+5.267350929 2.255207844
+5.273704790 2.252488099
+5.280058651 2.245489169
+5.286412512 2.236180770
+5.292766373 2.227509962
+5.299120235 2.219830899
+5.305474096 2.213176464
+5.311827957 2.207156013
+5.318181818 2.201791510
+5.324535679 2.197217425
+5.330889541 2.192942201
+5.337243402 2.189263625
+5.343597263 2.185763709
+5.349951124 2.182747581
+5.356304985 2.179878809
+5.362658847 2.177132825
+5.369012708 2.174685668
+5.375366569 2.172338745
+5.381720430 2.170065527
+5.388074291 2.167860085
+5.394428152 2.165799070
+5.400782014 2.163806303
+5.407135875 2.161840938
+5.413489736 2.159902531
+5.419843597 2.157990461
+5.426197458 2.156097125
+5.432551320 2.154220179
+5.438905181 2.152357531
+5.445259042 2.150509149
+5.451612903 2.148677415
+5.457966764 2.146855019
+5.464320626 2.145040704
+5.470674487 2.143233382
+5.477028348 2.141433054
+5.483382209 2.139644701
+5.489736070 2.137860906
+5.496089932 2.136081099
+5.502443793 2.134328107
+5.508797654 2.132649534
+5.515151515 2.130989142
+5.521505376 2.129339036
+5.527859238 2.127699011
+5.534213099 2.126068931
+5.540566960 2.124448719
+5.546920821 2.122971692
+5.553274682 2.121511010
+5.559628543 2.120008961
+5.565982405 2.118523744
+5.572336266 2.117055449
+5.578690127 2.115765674
+5.585043988 2.114537858
+5.591397849 2.113335881
+5.597751711 2.112209154
+5.604105572 2.111254423
+5.610459433 2.110338185
+5.616813294 2.109457677
+5.623167155 2.108794683
+5.629521017 2.108250774
+5.635874878 2.107747754
+5.642228739 2.107523978
+5.648582600 2.107351345
+5.654936461 2.107260660
+5.661290323 2.107503323
+5.667644184 2.107795601
+5.673998045 2.108357990
+5.680351906 2.109020431
+5.686705767 2.109846004
+5.693059629 2.110979040
+5.699413490 2.112228755
+5.705767351 2.113736512
+5.712121212 2.115288377
+5.718475073 2.117188508
+5.724828935 2.119140287
+5.731182796 2.121406844
+5.737536657 2.123709219
+5.743890518 2.125864421
+5.750244379 2.127533697
+5.756598240 2.128951976
+5.762952102 2.129814768
+5.769305963 2.130111253
+5.775659824 2.129941914
+5.782013685 2.129332824
+5.788367546 2.128201102
+5.794721408 2.126466974
+5.801075269 2.124123331
+5.807429130 2.121438142
+5.813782991 2.118465315
+5.820136852 2.115465007
+5.826490714 2.112439464
+5.832844575 2.109388333
+5.839198436 2.106414450
+5.845552297 2.103431920
+5.851906158 2.100423258
+5.858260020 2.097388086
+5.864613881 2.094326016
+5.870967742 2.091331916
+5.877321603 2.088343727
+5.883675464 2.085328087
+5.890029326 2.082284582
+5.896383187 2.079212787
+5.902737048 2.076198279
+5.909090909 2.073206285
+5.915444770 2.070185443
+5.921798631 2.067135298
+5.928152493 2.064055384
+5.934506354 2.061020444
+5.940860215 2.058026997
+5.947214076 2.055003222
+5.953567937 2.051948619
+5.959921799 2.048862677
+5.966275660 2.045807494
+5.972629521 2.042815556
+5.978983382 2.039791727
+5.985337243 2.036735455
+5.991691105 2.033646180
+5.998044966 2.030571219
+6.004398827 2.027584513
+6.010752688 2.024564264
+6.017106549 2.021509869
+6.023460411 2.018420707
+6.029814272 2.015326791
+6.036168133 2.012349980
+6.042521994 2.009337894
+6.048875855 2.006289865
+6.055229717 2.003205208
+6.061583578 1.993674304
+6.067937439 1.983767801
+6.074291300 1.974666943
+6.080645161 1.966340343
+6.086999022 1.958750368
+6.093352884 1.951855006
+6.099706745 1.946007268
+6.106060606 1.940747448
+6.112414467 1.936005220
+6.118768328 1.931738763
+6.125122190 1.927907466
+6.131476051 1.924681564
+6.137829912 1.921835182
+6.144183773 1.919288898
+6.150537634 1.917013216
+6.156891496 1.914980871
+6.163245357 1.913271019
+6.169599218 1.911785846
+6.175953079 1.910460690
+6.182306940 1.909278299
+6.188660802 1.908223089
+6.195014663 1.907331193
+6.201368524 1.906567078
+6.207722385 1.905883992
+6.214076246 1.905272781
+6.220430108 1.904725277
+6.226783969 1.904257800
+6.233137830 1.903862368
+6.239491691 1.903506560
+6.245845552 1.903080826
+6.252199413 1.901182623
+6.258553275 1.901126321
+6.264907136 1.901074692
+6.271260997 1.901023161
+6.277614858 1.900971728
+6.283968719 1.900920393
+6.290322581 1.900870925
+6.296676442 1.900826930
+6.303030303 1.900783019
+6.309384164 1.900739191
+6.315738025 1.900695445
+6.322091887 1.900652728
+6.328445748 1.900616279
+6.334799609 1.900579899
+6.341153470 1.900543588
+6.347507331 1.900507345
+6.353861193 1.900471295
+6.360215054 1.900442305
+6.366568915 1.900413370
+6.372922776 1.900384490
+6.379276637 1.900355663
+6.385630499 1.900326891
+6.391984360 1.900304582
+6.398338221 1.900283006
+6.404692082 1.900261471
+6.411045943 1.900239976
+6.417399804 1.900218521
+6.423753666 1.900202687
+6.430107527 1.900188386
+6.436461388 1.900174112
+6.442815249 1.900159865
+6.449169110 1.900145644
+6.455522972 1.900136204
+6.461876833 1.900129095
+6.468230694 1.900121999
+6.474584555 1.900114916
+6.480938416 1.900107847
+6.487292278 1.900104723
+6.493646139 1.900104723
+6.500000000 1.900104723
diff --git a/examples/mamdani/AllTerms.fll b/examples/mamdani/AllTerms.fll
index 58d5705..4db1b32 100644
--- a/examples/mamdani/AllTerms.fll
+++ b/examples/mamdani/AllTerms.fll
@@ -1,7 +1,8 @@
-Engine: qtfuzzylite
+Engine: AllTerms
InputVariable: AllInputTerms
enabled: true
range: 0.000 6.500
+ lock-range: false
term: A Sigmoid 0.500 -20.000
term: B ZShape 0.000 1.000
term: C Ramp 1.000 0.000
@@ -25,11 +26,11 @@ InputVariable: AllInputTerms
OutputVariable: AllOutputTerms
enabled: true
range: 0.000 6.500
- accumulation: Maximum
+ lock-range: false
+ aggregation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
- lock-range: false
term: A Sigmoid 0.500 -20.000
term: B ZShape 0.000 1.000
term: C Ramp 1.000 0.000
@@ -54,7 +55,8 @@ RuleBlock:
enabled: true
conjunction: Minimum
disjunction: Maximum
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if AllInputTerms is A then AllOutputTerms is T
rule: if AllInputTerms is B then AllOutputTerms is S
rule: if AllInputTerms is C then AllOutputTerms is R
diff --git a/examples/mamdani/AllTerms.java b/examples/mamdani/AllTerms.java
index c59f9a1..6d4651d 100644
--- a/examples/mamdani/AllTerms.java
+++ b/examples/mamdani/AllTerms.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,72 +13,80 @@ import com.fuzzylite.variable.*;
public class AllTerms{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("qtfuzzylite");
+engine.setName("AllTerms");
+engine.setDescription("");
-InputVariable inputVariable = new InputVariable();
-inputVariable.setEnabled(true);
-inputVariable.setName("AllInputTerms");
-inputVariable.setRange(0.000, 6.500);
-inputVariable.addTerm(new Sigmoid("A", 0.500, -20.000));
-inputVariable.addTerm(new ZShape("B", 0.000, 1.000));
-inputVariable.addTerm(new Ramp("C", 1.000, 0.000));
-inputVariable.addTerm(new Triangle("D", 0.500, 1.000, 1.500));
-inputVariable.addTerm(new Trapezoid("E", 1.000, 1.250, 1.750, 2.000));
-inputVariable.addTerm(new Concave("F", 0.850, 0.250));
-inputVariable.addTerm(new Rectangle("G", 1.750, 2.250));
-inputVariable.addTerm(Discrete.create("H", 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000));
-inputVariable.addTerm(new Gaussian("I", 3.000, 0.200));
-inputVariable.addTerm(new Cosine("J", 3.250, 0.650));
-inputVariable.addTerm(new GaussianProduct("K", 3.500, 0.100, 3.300, 0.300));
-inputVariable.addTerm(new Spike("L", 3.640, 1.040));
-inputVariable.addTerm(new Bell("M", 4.000, 0.250, 3.000));
-inputVariable.addTerm(new PiShape("N", 4.000, 4.500, 4.500, 5.000));
-inputVariable.addTerm(new Concave("O", 5.650, 6.250));
-inputVariable.addTerm(new SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250));
-inputVariable.addTerm(new SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750));
-inputVariable.addTerm(new Ramp("R", 5.500, 6.500));
-inputVariable.addTerm(new SShape("S", 5.500, 6.500));
-inputVariable.addTerm(new Sigmoid("T", 6.000, 20.000));
-engine.addInputVariable(inputVariable);
+InputVariable AllInputTerms = new InputVariable();
+AllInputTerms.setName("AllInputTerms");
+AllInputTerms.setDescription("");
+AllInputTerms.setEnabled(true);
+AllInputTerms.setRange(0.000, 6.500);
+AllInputTerms.setLockValueInRange(false);
+AllInputTerms.addTerm(new Sigmoid("A", 0.500, -20.000));
+AllInputTerms.addTerm(new ZShape("B", 0.000, 1.000));
+AllInputTerms.addTerm(new Ramp("C", 1.000, 0.000));
+AllInputTerms.addTerm(new Triangle("D", 0.500, 1.000, 1.500));
+AllInputTerms.addTerm(new Trapezoid("E", 1.000, 1.250, 1.750, 2.000));
+AllInputTerms.addTerm(new Concave("F", 0.850, 0.250));
+AllInputTerms.addTerm(new Rectangle("G", 1.750, 2.250));
+AllInputTerms.addTerm(Discrete.create("H", 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000));
+AllInputTerms.addTerm(new Gaussian("I", 3.000, 0.200));
+AllInputTerms.addTerm(new Cosine("J", 3.250, 0.650));
+AllInputTerms.addTerm(new GaussianProduct("K", 3.500, 0.100, 3.300, 0.300));
+AllInputTerms.addTerm(new Spike("L", 3.640, 1.040));
+AllInputTerms.addTerm(new Bell("M", 4.000, 0.250, 3.000));
+AllInputTerms.addTerm(new PiShape("N", 4.000, 4.500, 4.500, 5.000));
+AllInputTerms.addTerm(new Concave("O", 5.650, 6.250));
+AllInputTerms.addTerm(new SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250));
+AllInputTerms.addTerm(new SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750));
+AllInputTerms.addTerm(new Ramp("R", 5.500, 6.500));
+AllInputTerms.addTerm(new SShape("S", 5.500, 6.500));
+AllInputTerms.addTerm(new Sigmoid("T", 6.000, 20.000));
+engine.addInputVariable(AllInputTerms);
-OutputVariable outputVariable = new OutputVariable();
-outputVariable.setEnabled(true);
-outputVariable.setName("AllOutputTerms");
-outputVariable.setRange(0.000, 6.500);
-outputVariable.fuzzyOutput().setAccumulation(new Maximum());
-outputVariable.setDefuzzifier(new Centroid(200));
-outputVariable.setDefaultValue(Double.NaN);
-outputVariable.setLockPreviousOutputValue(false);
-outputVariable.setLockOutputValueInRange(false);
-outputVariable.addTerm(new Sigmoid("A", 0.500, -20.000));
-outputVariable.addTerm(new ZShape("B", 0.000, 1.000));
-outputVariable.addTerm(new Ramp("C", 1.000, 0.000));
-outputVariable.addTerm(new Triangle("D", 0.500, 1.000, 1.500));
-outputVariable.addTerm(new Trapezoid("E", 1.000, 1.250, 1.750, 2.000));
-outputVariable.addTerm(new Concave("F", 0.850, 0.250));
-outputVariable.addTerm(new Rectangle("G", 1.750, 2.250));
-outputVariable.addTerm(Discrete.create("H", 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000));
-outputVariable.addTerm(new Gaussian("I", 3.000, 0.200));
-outputVariable.addTerm(new Cosine("J", 3.250, 0.650));
-outputVariable.addTerm(new GaussianProduct("K", 3.500, 0.100, 3.300, 0.300));
-outputVariable.addTerm(new Spike("L", 3.640, 1.040));
-outputVariable.addTerm(new Bell("M", 4.000, 0.250, 3.000));
-outputVariable.addTerm(new PiShape("N", 4.000, 4.500, 4.500, 5.000));
-outputVariable.addTerm(new Concave("O", 5.650, 6.250));
-outputVariable.addTerm(new SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250));
-outputVariable.addTerm(new SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750));
-outputVariable.addTerm(new Ramp("R", 5.500, 6.500));
-outputVariable.addTerm(new SShape("S", 5.500, 6.500));
-outputVariable.addTerm(new Sigmoid("T", 6.000, 20.000));
-engine.addOutputVariable(outputVariable);
+OutputVariable AllOutputTerms = new OutputVariable();
+AllOutputTerms.setName("AllOutputTerms");
+AllOutputTerms.setDescription("");
+AllOutputTerms.setEnabled(true);
+AllOutputTerms.setRange(0.000, 6.500);
+AllOutputTerms.setLockValueInRange(false);
+AllOutputTerms.setAggregation(new Maximum());
+AllOutputTerms.setDefuzzifier(new Centroid(200));
+AllOutputTerms.setDefaultValue(Double.NaN);
+AllOutputTerms.setLockPreviousValue(false);
+AllOutputTerms.addTerm(new Sigmoid("A", 0.500, -20.000));
+AllOutputTerms.addTerm(new ZShape("B", 0.000, 1.000));
+AllOutputTerms.addTerm(new Ramp("C", 1.000, 0.000));
+AllOutputTerms.addTerm(new Triangle("D", 0.500, 1.000, 1.500));
+AllOutputTerms.addTerm(new Trapezoid("E", 1.000, 1.250, 1.750, 2.000));
+AllOutputTerms.addTerm(new Concave("F", 0.850, 0.250));
+AllOutputTerms.addTerm(new Rectangle("G", 1.750, 2.250));
+AllOutputTerms.addTerm(Discrete.create("H", 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000));
+AllOutputTerms.addTerm(new Gaussian("I", 3.000, 0.200));
+AllOutputTerms.addTerm(new Cosine("J", 3.250, 0.650));
+AllOutputTerms.addTerm(new GaussianProduct("K", 3.500, 0.100, 3.300, 0.300));
+AllOutputTerms.addTerm(new Spike("L", 3.640, 1.040));
+AllOutputTerms.addTerm(new Bell("M", 4.000, 0.250, 3.000));
+AllOutputTerms.addTerm(new PiShape("N", 4.000, 4.500, 4.500, 5.000));
+AllOutputTerms.addTerm(new Concave("O", 5.650, 6.250));
+AllOutputTerms.addTerm(new SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250));
+AllOutputTerms.addTerm(new SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750));
+AllOutputTerms.addTerm(new Ramp("R", 5.500, 6.500));
+AllOutputTerms.addTerm(new SShape("S", 5.500, 6.500));
+AllOutputTerms.addTerm(new Sigmoid("T", 6.000, 20.000));
+engine.addOutputVariable(AllOutputTerms);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(new Minimum());
ruleBlock.setDisjunction(new Maximum());
-ruleBlock.setActivation(new Minimum());
+ruleBlock.setImplication(new Minimum());
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if AllInputTerms is A then AllOutputTerms is T", engine));
ruleBlock.addRule(Rule.parse("if AllInputTerms is B then AllOutputTerms is S", engine));
ruleBlock.addRule(Rule.parse("if AllInputTerms is C then AllOutputTerms is R", engine));
diff --git a/examples/mamdani/AllTerms.pdf b/examples/mamdani/AllTerms.pdf
new file mode 100644
index 0000000..ed71111
--- /dev/null
+++ b/examples/mamdani/AllTerms.pdf
Binary files differ
diff --git a/examples/mamdani/Laundry.R b/examples/mamdani/Laundry.R
new file mode 100644
index 0000000..ca7d73d
--- /dev/null
+++ b/examples/mamdani/Laundry.R
@@ -0,0 +1,91 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "Laundry"
+engine.fll = "Engine: Laundry
+InputVariable: Load
+ enabled: true
+ range: 0.000 6.000
+ lock-range: false
+ term: small Discrete 0.000 1.000 1.000 1.000 2.000 0.800 5.000 0.000
+ term: normal Discrete 3.000 0.000 4.000 1.000 6.000 0.000
+InputVariable: Dirt
+ enabled: true
+ range: 0.000 6.000
+ lock-range: false
+ term: low Discrete 0.000 1.000 2.000 0.800 5.000 0.000
+ term: high Discrete 1.000 0.000 2.000 0.200 4.000 0.800 6.000 1.000
+OutputVariable: Detergent
+ enabled: true
+ range: 0.000 80.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: MeanOfMaximum 500
+ default: nan
+ lock-previous: false
+ term: less_than_usual Discrete 10.000 0.000 40.000 1.000 50.000 0.000
+ term: usual Discrete 40.000 0.000 50.000 1.000 60.000 1.000 80.000 0.000
+ term: more_than_usual Discrete 50.000 0.000 80.000 1.000
+OutputVariable: Cycle
+ enabled: true
+ range: 0.000 20.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: MeanOfMaximum 500
+ default: nan
+ lock-previous: false
+ term: short Discrete 0.000 1.000 10.000 1.000 20.000 0.000
+ term: long Discrete 10.000 0.000 20.000 1.000
+RuleBlock:
+ enabled: true
+ conjunction: Minimum
+ disjunction: Maximum
+ implication: Minimum
+ activation: General
+ rule: if Load is small and Dirt is not high then Detergent is less_than_usual
+ rule: if Load is small and Dirt is high then Detergent is usual
+ rule: if Load is normal and Dirt is low then Detergent is less_than_usual
+ rule: if Load is normal and Dirt is high then Detergent is more_than_usual
+ rule: if Detergent is usual or Detergent is less_than_usual then Cycle is short
+ rule: if Detergent is more_than_usual then Cycle is long"
+
+engine.fldFile = "Laundry.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1i2_o1 = ggplot(engine.df, aes(Load, Dirt)) +
+ geom_tile(aes(fill=Detergent)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Load, y=Dirt, z=Detergent), color="black") +
+ ggtitle("(Load, Dirt) = Detergent")
+
+engine.plot.i2i1_o1 = ggplot(engine.df, aes(Dirt, Load)) +
+ geom_tile(aes(fill=Detergent)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Dirt, y=Load, z=Detergent), color="black") +
+ ggtitle("(Dirt, Load) = Detergent")
+
+engine.plot.i1i2_o2 = ggplot(engine.df, aes(Load, Dirt)) +
+ geom_tile(aes(fill=Cycle)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Load, y=Dirt, z=Cycle), color="black") +
+ ggtitle("(Load, Dirt) = Cycle")
+
+engine.plot.i2i1_o2 = ggplot(engine.df, aes(Dirt, Load)) +
+ geom_tile(aes(fill=Cycle)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Dirt, y=Load, z=Cycle), color="black") +
+ ggtitle("(Dirt, Load) = Cycle")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1i2_o1, engine.plot.i2i1_o1, engine.plot.i1i2_o2, engine.plot.i2i1_o2, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/mamdani/Laundry.cpp b/examples/mamdani/Laundry.cpp
index 7fbcb11..cc7492c 100644
--- a/examples/mamdani/Laundry.cpp
+++ b/examples/mamdani/Laundry.cpp
@@ -1,66 +1,77 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
engine->setName("Laundry");
+engine->setDescription("");
-InputVariable* inputVariable1 = new InputVariable;
-inputVariable1->setEnabled(true);
-inputVariable1->setName("Load");
-inputVariable1->setRange(0.000, 6.000);
-inputVariable1->addTerm(Discrete::create("small", 8, 0.000, 1.000, 1.000, 1.000, 2.000, 0.800, 5.000, 0.000));
-inputVariable1->addTerm(Discrete::create("normal", 6, 3.000, 0.000, 4.000, 1.000, 6.000, 0.000));
-engine->addInputVariable(inputVariable1);
+InputVariable* Load = new InputVariable;
+Load->setName("Load");
+Load->setDescription("");
+Load->setEnabled(true);
+Load->setRange(0.000, 6.000);
+Load->setLockValueInRange(false);
+Load->addTerm(Discrete::create("small", 8, 0.000, 1.000, 1.000, 1.000, 2.000, 0.800, 5.000, 0.000));
+Load->addTerm(Discrete::create("normal", 6, 3.000, 0.000, 4.000, 1.000, 6.000, 0.000));
+engine->addInputVariable(Load);
-InputVariable* inputVariable2 = new InputVariable;
-inputVariable2->setEnabled(true);
-inputVariable2->setName("Dirt");
-inputVariable2->setRange(0.000, 6.000);
-inputVariable2->addTerm(Discrete::create("low", 6, 0.000, 1.000, 2.000, 0.800, 5.000, 0.000));
-inputVariable2->addTerm(Discrete::create("high", 8, 1.000, 0.000, 2.000, 0.200, 4.000, 0.800, 6.000, 1.000));
-engine->addInputVariable(inputVariable2);
+InputVariable* Dirt = new InputVariable;
+Dirt->setName("Dirt");
+Dirt->setDescription("");
+Dirt->setEnabled(true);
+Dirt->setRange(0.000, 6.000);
+Dirt->setLockValueInRange(false);
+Dirt->addTerm(Discrete::create("low", 6, 0.000, 1.000, 2.000, 0.800, 5.000, 0.000));
+Dirt->addTerm(Discrete::create("high", 8, 1.000, 0.000, 2.000, 0.200, 4.000, 0.800, 6.000, 1.000));
+engine->addInputVariable(Dirt);
-OutputVariable* outputVariable1 = new OutputVariable;
-outputVariable1->setEnabled(true);
-outputVariable1->setName("Detergent");
-outputVariable1->setRange(0.000, 80.000);
-outputVariable1->fuzzyOutput()->setAccumulation(new Maximum);
-outputVariable1->setDefuzzifier(new MeanOfMaximum(500));
-outputVariable1->setDefaultValue(fl::nan);
-outputVariable1->setLockPreviousOutputValue(false);
-outputVariable1->setLockOutputValueInRange(false);
-outputVariable1->addTerm(Discrete::create("less", 6, 10.000, 0.000, 40.000, 1.000, 50.000, 0.000));
-outputVariable1->addTerm(Discrete::create("normal", 8, 40.000, 0.000, 50.000, 1.000, 60.000, 1.000, 80.000, 0.000));
-outputVariable1->addTerm(Discrete::create("more", 4, 50.000, 0.000, 80.000, 1.000));
-engine->addOutputVariable(outputVariable1);
+OutputVariable* Detergent = new OutputVariable;
+Detergent->setName("Detergent");
+Detergent->setDescription("");
+Detergent->setEnabled(true);
+Detergent->setRange(0.000, 80.000);
+Detergent->setLockValueInRange(false);
+Detergent->setAggregation(new Maximum);
+Detergent->setDefuzzifier(new MeanOfMaximum(500));
+Detergent->setDefaultValue(fl::nan);
+Detergent->setLockPreviousValue(false);
+Detergent->addTerm(Discrete::create("less_than_usual", 6, 10.000, 0.000, 40.000, 1.000, 50.000, 0.000));
+Detergent->addTerm(Discrete::create("usual", 8, 40.000, 0.000, 50.000, 1.000, 60.000, 1.000, 80.000, 0.000));
+Detergent->addTerm(Discrete::create("more_than_usual", 4, 50.000, 0.000, 80.000, 1.000));
+engine->addOutputVariable(Detergent);
-OutputVariable* outputVariable2 = new OutputVariable;
-outputVariable2->setEnabled(true);
-outputVariable2->setName("Cycle");
-outputVariable2->setRange(0.000, 20.000);
-outputVariable2->fuzzyOutput()->setAccumulation(new Maximum);
-outputVariable2->setDefuzzifier(new MeanOfMaximum(500));
-outputVariable2->setDefaultValue(fl::nan);
-outputVariable2->setLockPreviousOutputValue(false);
-outputVariable2->setLockOutputValueInRange(false);
-outputVariable2->addTerm(Discrete::create("short", 6, 0.000, 1.000, 10.000, 1.000, 20.000, 0.000));
-outputVariable2->addTerm(Discrete::create("long", 4, 10.000, 0.000, 20.000, 1.000));
-engine->addOutputVariable(outputVariable2);
+OutputVariable* Cycle = new OutputVariable;
+Cycle->setName("Cycle");
+Cycle->setDescription("");
+Cycle->setEnabled(true);
+Cycle->setRange(0.000, 20.000);
+Cycle->setLockValueInRange(false);
+Cycle->setAggregation(new Maximum);
+Cycle->setDefuzzifier(new MeanOfMaximum(500));
+Cycle->setDefaultValue(fl::nan);
+Cycle->setLockPreviousValue(false);
+Cycle->addTerm(Discrete::create("short", 6, 0.000, 1.000, 10.000, 1.000, 20.000, 0.000));
+Cycle->addTerm(Discrete::create("long", 4, 10.000, 0.000, 20.000, 1.000));
+engine->addOutputVariable(Cycle);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(new Minimum);
ruleBlock->setDisjunction(new Maximum);
-ruleBlock->setActivation(new Minimum);
-ruleBlock->addRule(fl::Rule::parse("if Load is small and Dirt is not high then Detergent is less", engine));
-ruleBlock->addRule(fl::Rule::parse("if Load is small and Dirt is high then Detergent is normal", engine));
-ruleBlock->addRule(fl::Rule::parse("if Load is normal and Dirt is low then Detergent is less", engine));
-ruleBlock->addRule(fl::Rule::parse("if Load is normal and Dirt is high then Detergent is more", engine));
-ruleBlock->addRule(fl::Rule::parse("if Detergent is normal or Detergent is less then Cycle is short", engine));
-ruleBlock->addRule(fl::Rule::parse("if Detergent is more then Cycle is long", engine));
+ruleBlock->setImplication(new Minimum);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if Load is small and Dirt is not high then Detergent is less_than_usual", engine));
+ruleBlock->addRule(Rule::parse("if Load is small and Dirt is high then Detergent is usual", engine));
+ruleBlock->addRule(Rule::parse("if Load is normal and Dirt is low then Detergent is less_than_usual", engine));
+ruleBlock->addRule(Rule::parse("if Load is normal and Dirt is high then Detergent is more_than_usual", engine));
+ruleBlock->addRule(Rule::parse("if Detergent is usual or Detergent is less_than_usual then Cycle is short", engine));
+ruleBlock->addRule(Rule::parse("if Detergent is more_than_usual then Cycle is long", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/mamdani/Laundry.fcl b/examples/mamdani/Laundry.fcl
index a5d5380..9a34532 100644
--- a/examples/mamdani/Laundry.fcl
+++ b/examples/mamdani/Laundry.fcl
@@ -1,3 +1,5 @@
+//Code automatically generated with fuzzylite 6.0.
+
FUNCTION_BLOCK Laundry
VAR_INPUT
@@ -24,9 +26,9 @@ END_FUZZIFY
DEFUZZIFY Detergent
RANGE := (0.000 .. 80.000);
- TERM less := (10.000, 0.000) (40.000, 1.000) (50.000, 0.000);
- TERM normal := (40.000, 0.000) (50.000, 1.000) (60.000, 1.000) (80.000, 0.000);
- TERM more := (50.000, 0.000) (80.000, 1.000);
+ TERM less_than_usual := (10.000, 0.000) (40.000, 1.000) (50.000, 0.000);
+ TERM usual := (40.000, 0.000) (50.000, 1.000) (60.000, 1.000) (80.000, 0.000);
+ TERM more_than_usual := (50.000, 0.000) (80.000, 1.000);
METHOD : MM;
ACCU : MAX;
DEFAULT := nan;
@@ -45,12 +47,12 @@ RULEBLOCK
AND : MIN;
OR : MAX;
ACT : MIN;
- RULE 1 : if Load is small and Dirt is not high then Detergent is less
- RULE 2 : if Load is small and Dirt is high then Detergent is normal
- RULE 3 : if Load is normal and Dirt is low then Detergent is less
- RULE 4 : if Load is normal and Dirt is high then Detergent is more
- RULE 5 : if Detergent is normal or Detergent is less then Cycle is short
- RULE 6 : if Detergent is more then Cycle is long
+ RULE 1 : if Load is small and Dirt is not high then Detergent is less_than_usual
+ RULE 2 : if Load is small and Dirt is high then Detergent is usual
+ RULE 3 : if Load is normal and Dirt is low then Detergent is less_than_usual
+ RULE 4 : if Load is normal and Dirt is high then Detergent is more_than_usual
+ RULE 5 : if Detergent is usual or Detergent is less_than_usual then Cycle is short
+ RULE 6 : if Detergent is more_than_usual then Cycle is long
END_RULEBLOCK
END_FUNCTION_BLOCK
diff --git a/examples/mamdani/Laundry.fis b/examples/mamdani/Laundry.fis
new file mode 100644
index 0000000..7f1c31d
--- /dev/null
+++ b/examples/mamdani/Laundry.fis
@@ -0,0 +1,51 @@
+#Code automatically generated with fuzzylite 6.0.
+
+[System]
+Name='Laundry'
+Type='mamdani'
+Version=6.0
+NumInputs=2
+NumOutputs=2
+NumRules=6
+AndMethod='min'
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
+DefuzzMethod='mom'
+
+[Input1]
+Name='Load'
+Range=[0.000 6.000]
+NumMFs=2
+MF1='small':'discretemf',[0.000 1.000 1.000 1.000 2.000 0.800 5.000 0.000]
+MF2='normal':'discretemf',[3.000 0.000 4.000 1.000 6.000 0.000]
+
+[Input2]
+Name='Dirt'
+Range=[0.000 6.000]
+NumMFs=2
+MF1='low':'discretemf',[0.000 1.000 2.000 0.800 5.000 0.000]
+MF2='high':'discretemf',[1.000 0.000 2.000 0.200 4.000 0.800 6.000 1.000]
+
+[Output1]
+Name='Detergent'
+Range=[0.000 80.000]
+NumMFs=3
+MF1='less_than_usual':'discretemf',[10.000 0.000 40.000 1.000 50.000 0.000]
+MF2='usual':'discretemf',[40.000 0.000 50.000 1.000 60.000 1.000 80.000 0.000]
+MF3='more_than_usual':'discretemf',[50.000 0.000 80.000 1.000]
+
+[Output2]
+Name='Cycle'
+Range=[0.000 20.000]
+NumMFs=2
+MF1='short':'discretemf',[0.000 1.000 10.000 1.000 20.000 0.000]
+MF2='long':'discretemf',[10.000 0.000 20.000 1.000]
+
+[Rules]
+1.000 -2.000 , 1.000 0.000 (1.000) : 1
+1.000 2.000 , 2.000 0.000 (1.000) : 1
+2.000 1.000 , 1.000 0.000 (1.000) : 1
+2.000 2.000 , 3.000 0.000 (1.000) : 1
+0.000 0.000 , 0.000 1.000 (1.000) : 2
+0.000 0.000 , 0.000 2.000 (1.000) : 1
diff --git a/examples/mamdani/Laundry.fld b/examples/mamdani/Laundry.fld
index f72dfb6..a8f27dd 100644
--- a/examples/mamdani/Laundry.fld
+++ b/examples/mamdani/Laundry.fld
@@ -1,1026 +1,1025 @@
-#@Engine: Laundry;
-#@InputVariable: Load; @InputVariable: Dirt; @OutputVariable: Detergent; @OutputVariable: Cycle;
-0.00000000 0.00000000 39.92000000 5.00000000
-0.00000000 0.19354839 39.92000000 5.00000000
-0.00000000 0.38709677 39.92000000 5.00000000
-0.00000000 0.58064516 39.92000000 5.00000000
-0.00000000 0.77419355 39.92000000 5.00000000
-0.00000000 0.96774194 39.92000000 5.00000000
-0.00000000 1.16129032 39.68000000 5.16000000
-0.00000000 1.35483871 39.28000000 5.36000000
-0.00000000 1.54838710 38.88000000 5.54000000
-0.00000000 1.74193548 38.48000000 5.74000000
-0.00000000 1.93548387 38.16000000 5.94000000
-0.00000000 2.12903226 37.60000000 6.20000000
-0.00000000 2.32258065 37.04000000 6.48000000
-0.00000000 2.51612903 36.40000000 6.78000000
-0.00000000 2.70967742 35.92000000 7.06000000
-0.00000000 2.90322581 35.28000000 7.36000000
-0.00000000 3.09677419 57.36000000 7.36000000
-0.00000000 3.29032258 57.12000000 7.06000000
-0.00000000 3.48387097 56.72000000 6.78000000
-0.00000000 3.67741935 56.48000000 6.48000000
-0.00000000 3.87096774 56.24000000 6.20000000
-0.00000000 4.06451613 55.92000000 5.96000000
-0.00000000 4.25806452 55.92000000 5.88000000
-0.00000000 4.45161290 55.76000000 5.78000000
-0.00000000 4.64516129 55.68000000 5.68000000
-0.00000000 4.83870968 55.60000000 5.58000000
-0.00000000 5.03225806 55.44000000 5.48000000
-0.00000000 5.22580645 55.44000000 5.38000000
-0.00000000 5.41935484 55.28000000 5.30000000
-0.00000000 5.61290323 55.20000000 5.20000000
-0.00000000 5.80645161 55.04000000 5.10000000
-0.00000000 6.00000000 54.96000000 5.00000000
-0.19354839 0.00000000 39.92000000 5.00000000
-0.19354839 0.19354839 39.92000000 5.00000000
-0.19354839 0.38709677 39.92000000 5.00000000
-0.19354839 0.58064516 39.92000000 5.00000000
-0.19354839 0.77419355 39.92000000 5.00000000
-0.19354839 0.96774194 39.92000000 5.00000000
-0.19354839 1.16129032 39.68000000 5.16000000
-0.19354839 1.35483871 39.28000000 5.36000000
-0.19354839 1.54838710 38.88000000 5.54000000
-0.19354839 1.74193548 38.48000000 5.74000000
-0.19354839 1.93548387 38.16000000 5.94000000
-0.19354839 2.12903226 37.60000000 6.20000000
-0.19354839 2.32258065 37.04000000 6.48000000
-0.19354839 2.51612903 36.40000000 6.78000000
-0.19354839 2.70967742 35.92000000 7.06000000
-0.19354839 2.90322581 35.28000000 7.36000000
-0.19354839 3.09677419 57.36000000 7.36000000
-0.19354839 3.29032258 57.12000000 7.06000000
-0.19354839 3.48387097 56.72000000 6.78000000
-0.19354839 3.67741935 56.48000000 6.48000000
-0.19354839 3.87096774 56.24000000 6.20000000
-0.19354839 4.06451613 55.92000000 5.96000000
-0.19354839 4.25806452 55.92000000 5.88000000
-0.19354839 4.45161290 55.76000000 5.78000000
-0.19354839 4.64516129 55.68000000 5.68000000
-0.19354839 4.83870968 55.60000000 5.58000000
-0.19354839 5.03225806 55.44000000 5.48000000
-0.19354839 5.22580645 55.44000000 5.38000000
-0.19354839 5.41935484 55.28000000 5.30000000
-0.19354839 5.61290323 55.20000000 5.20000000
-0.19354839 5.80645161 55.04000000 5.10000000
-0.19354839 6.00000000 54.96000000 5.00000000
-0.38709677 0.00000000 39.92000000 5.00000000
-0.38709677 0.19354839 39.92000000 5.00000000
-0.38709677 0.38709677 39.92000000 5.00000000
-0.38709677 0.58064516 39.92000000 5.00000000
-0.38709677 0.77419355 39.92000000 5.00000000
-0.38709677 0.96774194 39.92000000 5.00000000
-0.38709677 1.16129032 39.68000000 5.16000000
-0.38709677 1.35483871 39.28000000 5.36000000
-0.38709677 1.54838710 38.88000000 5.54000000
-0.38709677 1.74193548 38.48000000 5.74000000
-0.38709677 1.93548387 38.16000000 5.94000000
-0.38709677 2.12903226 37.60000000 6.20000000
-0.38709677 2.32258065 37.04000000 6.48000000
-0.38709677 2.51612903 36.40000000 6.78000000
-0.38709677 2.70967742 35.92000000 7.06000000
-0.38709677 2.90322581 35.28000000 7.36000000
-0.38709677 3.09677419 57.36000000 7.36000000
-0.38709677 3.29032258 57.12000000 7.06000000
-0.38709677 3.48387097 56.72000000 6.78000000
-0.38709677 3.67741935 56.48000000 6.48000000
-0.38709677 3.87096774 56.24000000 6.20000000
-0.38709677 4.06451613 55.92000000 5.96000000
-0.38709677 4.25806452 55.92000000 5.88000000
-0.38709677 4.45161290 55.76000000 5.78000000
-0.38709677 4.64516129 55.68000000 5.68000000
-0.38709677 4.83870968 55.60000000 5.58000000
-0.38709677 5.03225806 55.44000000 5.48000000
-0.38709677 5.22580645 55.44000000 5.38000000
-0.38709677 5.41935484 55.28000000 5.30000000
-0.38709677 5.61290323 55.20000000 5.20000000
-0.38709677 5.80645161 55.04000000 5.10000000
-0.38709677 6.00000000 54.96000000 5.00000000
-0.58064516 0.00000000 39.92000000 5.00000000
-0.58064516 0.19354839 39.92000000 5.00000000
-0.58064516 0.38709677 39.92000000 5.00000000
-0.58064516 0.58064516 39.92000000 5.00000000
-0.58064516 0.77419355 39.92000000 5.00000000
-0.58064516 0.96774194 39.92000000 5.00000000
-0.58064516 1.16129032 39.68000000 5.16000000
-0.58064516 1.35483871 39.28000000 5.36000000
-0.58064516 1.54838710 38.88000000 5.54000000
-0.58064516 1.74193548 38.48000000 5.74000000
-0.58064516 1.93548387 38.16000000 5.94000000
-0.58064516 2.12903226 37.60000000 6.20000000
-0.58064516 2.32258065 37.04000000 6.48000000
-0.58064516 2.51612903 36.40000000 6.78000000
-0.58064516 2.70967742 35.92000000 7.06000000
-0.58064516 2.90322581 35.28000000 7.36000000
-0.58064516 3.09677419 57.36000000 7.36000000
-0.58064516 3.29032258 57.12000000 7.06000000
-0.58064516 3.48387097 56.72000000 6.78000000
-0.58064516 3.67741935 56.48000000 6.48000000
-0.58064516 3.87096774 56.24000000 6.20000000
-0.58064516 4.06451613 55.92000000 5.96000000
-0.58064516 4.25806452 55.92000000 5.88000000
-0.58064516 4.45161290 55.76000000 5.78000000
-0.58064516 4.64516129 55.68000000 5.68000000
-0.58064516 4.83870968 55.60000000 5.58000000
-0.58064516 5.03225806 55.44000000 5.48000000
-0.58064516 5.22580645 55.44000000 5.38000000
-0.58064516 5.41935484 55.28000000 5.30000000
-0.58064516 5.61290323 55.20000000 5.20000000
-0.58064516 5.80645161 55.04000000 5.10000000
-0.58064516 6.00000000 54.96000000 5.00000000
-0.77419355 0.00000000 39.92000000 5.00000000
-0.77419355 0.19354839 39.92000000 5.00000000
-0.77419355 0.38709677 39.92000000 5.00000000
-0.77419355 0.58064516 39.92000000 5.00000000
-0.77419355 0.77419355 39.92000000 5.00000000
-0.77419355 0.96774194 39.92000000 5.00000000
-0.77419355 1.16129032 39.68000000 5.16000000
-0.77419355 1.35483871 39.28000000 5.36000000
-0.77419355 1.54838710 38.88000000 5.54000000
-0.77419355 1.74193548 38.48000000 5.74000000
-0.77419355 1.93548387 38.16000000 5.94000000
-0.77419355 2.12903226 37.60000000 6.20000000
-0.77419355 2.32258065 37.04000000 6.48000000
-0.77419355 2.51612903 36.40000000 6.78000000
-0.77419355 2.70967742 35.92000000 7.06000000
-0.77419355 2.90322581 35.28000000 7.36000000
-0.77419355 3.09677419 57.36000000 7.36000000
-0.77419355 3.29032258 57.12000000 7.06000000
-0.77419355 3.48387097 56.72000000 6.78000000
-0.77419355 3.67741935 56.48000000 6.48000000
-0.77419355 3.87096774 56.24000000 6.20000000
-0.77419355 4.06451613 55.92000000 5.96000000
-0.77419355 4.25806452 55.92000000 5.88000000
-0.77419355 4.45161290 55.76000000 5.78000000
-0.77419355 4.64516129 55.68000000 5.68000000
-0.77419355 4.83870968 55.60000000 5.58000000
-0.77419355 5.03225806 55.44000000 5.48000000
-0.77419355 5.22580645 55.44000000 5.38000000
-0.77419355 5.41935484 55.28000000 5.30000000
-0.77419355 5.61290323 55.20000000 5.20000000
-0.77419355 5.80645161 55.04000000 5.10000000
-0.77419355 6.00000000 54.96000000 5.00000000
-0.96774194 0.00000000 39.92000000 5.00000000
-0.96774194 0.19354839 39.92000000 5.00000000
-0.96774194 0.38709677 39.92000000 5.00000000
-0.96774194 0.58064516 39.92000000 5.00000000
-0.96774194 0.77419355 39.92000000 5.00000000
-0.96774194 0.96774194 39.92000000 5.00000000
-0.96774194 1.16129032 39.68000000 5.16000000
-0.96774194 1.35483871 39.28000000 5.36000000
-0.96774194 1.54838710 38.88000000 5.54000000
-0.96774194 1.74193548 38.48000000 5.74000000
-0.96774194 1.93548387 38.16000000 5.94000000
-0.96774194 2.12903226 37.60000000 6.20000000
-0.96774194 2.32258065 37.04000000 6.48000000
-0.96774194 2.51612903 36.40000000 6.78000000
-0.96774194 2.70967742 35.92000000 7.06000000
-0.96774194 2.90322581 35.28000000 7.36000000
-0.96774194 3.09677419 57.36000000 7.36000000
-0.96774194 3.29032258 57.12000000 7.06000000
-0.96774194 3.48387097 56.72000000 6.78000000
-0.96774194 3.67741935 56.48000000 6.48000000
-0.96774194 3.87096774 56.24000000 6.20000000
-0.96774194 4.06451613 55.92000000 5.96000000
-0.96774194 4.25806452 55.92000000 5.88000000
-0.96774194 4.45161290 55.76000000 5.78000000
-0.96774194 4.64516129 55.68000000 5.68000000
-0.96774194 4.83870968 55.60000000 5.58000000
-0.96774194 5.03225806 55.44000000 5.48000000
-0.96774194 5.22580645 55.44000000 5.38000000
-0.96774194 5.41935484 55.28000000 5.30000000
-0.96774194 5.61290323 55.20000000 5.20000000
-0.96774194 5.80645161 55.04000000 5.10000000
-0.96774194 6.00000000 54.96000000 5.00000000
-1.16129032 0.00000000 39.68000000 5.16000000
-1.16129032 0.19354839 39.68000000 5.16000000
-1.16129032 0.38709677 39.68000000 5.16000000
-1.16129032 0.58064516 39.68000000 5.16000000
-1.16129032 0.77419355 39.68000000 5.16000000
-1.16129032 0.96774194 39.68000000 5.16000000
-1.16129032 1.16129032 39.68000000 5.16000000
-1.16129032 1.35483871 39.28000000 5.36000000
-1.16129032 1.54838710 38.88000000 5.54000000
-1.16129032 1.74193548 38.48000000 5.74000000
-1.16129032 1.93548387 38.16000000 5.94000000
-1.16129032 2.12903226 37.60000000 6.20000000
-1.16129032 2.32258065 37.04000000 6.48000000
-1.16129032 2.51612903 36.40000000 6.78000000
-1.16129032 2.70967742 35.92000000 7.06000000
-1.16129032 2.90322581 35.28000000 7.36000000
-1.16129032 3.09677419 57.36000000 7.36000000
-1.16129032 3.29032258 57.12000000 7.06000000
-1.16129032 3.48387097 56.72000000 6.78000000
-1.16129032 3.67741935 56.48000000 6.48000000
-1.16129032 3.87096774 56.24000000 6.20000000
-1.16129032 4.06451613 55.92000000 5.96000000
-1.16129032 4.25806452 55.92000000 5.88000000
-1.16129032 4.45161290 55.76000000 5.78000000
-1.16129032 4.64516129 55.68000000 5.68000000
-1.16129032 4.83870968 55.60000000 5.58000000
-1.16129032 5.03225806 55.44000000 5.48000000
-1.16129032 5.22580645 55.44000000 5.38000000
-1.16129032 5.41935484 55.28000000 5.30000000
-1.16129032 5.61290323 55.20000000 5.20000000
-1.16129032 5.80645161 55.12000000 5.16000000
-1.16129032 6.00000000 55.12000000 5.16000000
-1.35483871 0.00000000 39.28000000 5.36000000
-1.35483871 0.19354839 39.28000000 5.36000000
-1.35483871 0.38709677 39.28000000 5.36000000
-1.35483871 0.58064516 39.28000000 5.36000000
-1.35483871 0.77419355 39.28000000 5.36000000
-1.35483871 0.96774194 39.28000000 5.36000000
-1.35483871 1.16129032 39.28000000 5.36000000
-1.35483871 1.35483871 39.28000000 5.36000000
-1.35483871 1.54838710 38.88000000 5.54000000
-1.35483871 1.74193548 38.48000000 5.74000000
-1.35483871 1.93548387 38.16000000 5.94000000
-1.35483871 2.12903226 37.60000000 6.20000000
-1.35483871 2.32258065 37.04000000 6.48000000
-1.35483871 2.51612903 36.40000000 6.78000000
-1.35483871 2.70967742 35.92000000 7.06000000
-1.35483871 2.90322581 35.28000000 7.36000000
-1.35483871 3.09677419 57.36000000 7.36000000
-1.35483871 3.29032258 57.12000000 7.06000000
-1.35483871 3.48387097 56.72000000 6.78000000
-1.35483871 3.67741935 56.48000000 6.48000000
-1.35483871 3.87096774 56.24000000 6.20000000
-1.35483871 4.06451613 55.92000000 5.96000000
-1.35483871 4.25806452 55.92000000 5.88000000
-1.35483871 4.45161290 55.76000000 5.78000000
-1.35483871 4.64516129 55.68000000 5.68000000
-1.35483871 4.83870968 55.60000000 5.58000000
-1.35483871 5.03225806 55.44000000 5.48000000
-1.35483871 5.22580645 55.44000000 5.38000000
-1.35483871 5.41935484 55.36000000 5.36000000
-1.35483871 5.61290323 55.36000000 5.36000000
-1.35483871 5.80645161 55.36000000 5.36000000
-1.35483871 6.00000000 55.36000000 5.36000000
-1.54838710 0.00000000 38.88000000 5.54000000
-1.54838710 0.19354839 38.88000000 5.54000000
-1.54838710 0.38709677 38.88000000 5.54000000
-1.54838710 0.58064516 38.88000000 5.54000000
-1.54838710 0.77419355 38.88000000 5.54000000
-1.54838710 0.96774194 38.88000000 5.54000000
-1.54838710 1.16129032 38.88000000 5.54000000
-1.54838710 1.35483871 38.88000000 5.54000000
-1.54838710 1.54838710 38.88000000 5.54000000
-1.54838710 1.74193548 38.48000000 5.74000000
-1.54838710 1.93548387 38.16000000 5.94000000
-1.54838710 2.12903226 37.60000000 6.20000000
-1.54838710 2.32258065 37.04000000 6.48000000
-1.54838710 2.51612903 36.40000000 6.78000000
-1.54838710 2.70967742 35.92000000 7.06000000
-1.54838710 2.90322581 35.28000000 7.36000000
-1.54838710 3.09677419 57.36000000 7.36000000
-1.54838710 3.29032258 57.12000000 7.06000000
-1.54838710 3.48387097 56.72000000 6.78000000
-1.54838710 3.67741935 56.48000000 6.48000000
-1.54838710 3.87096774 56.24000000 6.20000000
-1.54838710 4.06451613 55.92000000 5.96000000
-1.54838710 4.25806452 55.92000000 5.88000000
-1.54838710 4.45161290 55.76000000 5.78000000
-1.54838710 4.64516129 55.68000000 5.68000000
-1.54838710 4.83870968 55.60000000 5.58000000
-1.54838710 5.03225806 55.60000000 5.54000000
-1.54838710 5.22580645 55.60000000 5.54000000
-1.54838710 5.41935484 55.60000000 5.54000000
-1.54838710 5.61290323 55.60000000 5.54000000
-1.54838710 5.80645161 55.60000000 5.54000000
-1.54838710 6.00000000 55.60000000 5.54000000
-1.74193548 0.00000000 38.48000000 5.74000000
-1.74193548 0.19354839 38.48000000 5.74000000
-1.74193548 0.38709677 38.48000000 5.74000000
-1.74193548 0.58064516 38.48000000 5.74000000
-1.74193548 0.77419355 38.48000000 5.74000000
-1.74193548 0.96774194 38.48000000 5.74000000
-1.74193548 1.16129032 38.48000000 5.74000000
-1.74193548 1.35483871 38.48000000 5.74000000
-1.74193548 1.54838710 38.48000000 5.74000000
-1.74193548 1.74193548 38.48000000 5.74000000
-1.74193548 1.93548387 38.16000000 5.94000000
-1.74193548 2.12903226 37.60000000 6.20000000
-1.74193548 2.32258065 37.04000000 6.48000000
-1.74193548 2.51612903 36.40000000 6.78000000
-1.74193548 2.70967742 35.92000000 7.06000000
-1.74193548 2.90322581 35.28000000 7.36000000
-1.74193548 3.09677419 57.36000000 7.36000000
-1.74193548 3.29032258 57.12000000 7.06000000
-1.74193548 3.48387097 56.72000000 6.78000000
-1.74193548 3.67741935 56.48000000 6.48000000
-1.74193548 3.87096774 56.24000000 6.20000000
-1.74193548 4.06451613 55.92000000 5.96000000
-1.74193548 4.25806452 55.92000000 5.88000000
-1.74193548 4.45161290 55.76000000 5.78000000
-1.74193548 4.64516129 55.76000000 5.74000000
-1.74193548 4.83870968 55.76000000 5.74000000
-1.74193548 5.03225806 55.76000000 5.74000000
-1.74193548 5.22580645 55.76000000 5.74000000
-1.74193548 5.41935484 55.76000000 5.74000000
-1.74193548 5.61290323 55.76000000 5.74000000
-1.74193548 5.80645161 55.76000000 5.74000000
-1.74193548 6.00000000 55.76000000 5.74000000
-1.93548387 0.00000000 38.16000000 5.94000000
-1.93548387 0.19354839 38.16000000 5.94000000
-1.93548387 0.38709677 38.16000000 5.94000000
-1.93548387 0.58064516 38.16000000 5.94000000
-1.93548387 0.77419355 38.16000000 5.94000000
-1.93548387 0.96774194 38.16000000 5.94000000
-1.93548387 1.16129032 38.16000000 5.94000000
-1.93548387 1.35483871 38.16000000 5.94000000
-1.93548387 1.54838710 38.16000000 5.94000000
-1.93548387 1.74193548 38.16000000 5.94000000
-1.93548387 1.93548387 38.16000000 5.94000000
-1.93548387 2.12903226 37.60000000 6.20000000
-1.93548387 2.32258065 37.04000000 6.48000000
-1.93548387 2.51612903 36.40000000 6.78000000
-1.93548387 2.70967742 35.92000000 7.06000000
-1.93548387 2.90322581 35.28000000 7.36000000
-1.93548387 3.09677419 57.36000000 7.36000000
-1.93548387 3.29032258 57.12000000 7.06000000
-1.93548387 3.48387097 56.72000000 6.78000000
-1.93548387 3.67741935 56.48000000 6.48000000
-1.93548387 3.87096774 56.24000000 6.20000000
-1.93548387 4.06451613 55.92000000 5.96000000
-1.93548387 4.25806452 55.92000000 5.94000000
-1.93548387 4.45161290 55.92000000 5.94000000
-1.93548387 4.64516129 55.92000000 5.94000000
-1.93548387 4.83870968 55.92000000 5.94000000
-1.93548387 5.03225806 55.92000000 5.94000000
-1.93548387 5.22580645 55.92000000 5.94000000
-1.93548387 5.41935484 55.92000000 5.94000000
-1.93548387 5.61290323 55.92000000 5.94000000
-1.93548387 5.80645161 55.92000000 5.94000000
-1.93548387 6.00000000 55.92000000 5.94000000
-2.12903226 0.00000000 37.68000000 6.18000000
-2.12903226 0.19354839 37.68000000 6.18000000
-2.12903226 0.38709677 37.68000000 6.18000000
-2.12903226 0.58064516 37.68000000 6.18000000
-2.12903226 0.77419355 37.68000000 6.18000000
-2.12903226 0.96774194 37.68000000 6.18000000
-2.12903226 1.16129032 37.68000000 6.18000000
-2.12903226 1.35483871 37.68000000 6.18000000
-2.12903226 1.54838710 37.68000000 6.18000000
-2.12903226 1.74193548 37.68000000 6.18000000
-2.12903226 1.93548387 37.68000000 6.18000000
-2.12903226 2.12903226 37.60000000 6.20000000
-2.12903226 2.32258065 37.04000000 6.48000000
-2.12903226 2.51612903 36.40000000 6.78000000
-2.12903226 2.70967742 35.92000000 7.06000000
-2.12903226 2.90322581 35.28000000 7.36000000
-2.12903226 3.09677419 57.36000000 7.36000000
-2.12903226 3.29032258 57.12000000 7.06000000
-2.12903226 3.48387097 56.72000000 6.78000000
-2.12903226 3.67741935 56.48000000 6.48000000
-2.12903226 3.87096774 56.24000000 6.20000000
-2.12903226 4.06451613 56.16000000 6.18000000
-2.12903226 4.25806452 56.16000000 6.18000000
-2.12903226 4.45161290 56.16000000 6.18000000
-2.12903226 4.64516129 56.16000000 6.18000000
-2.12903226 4.83870968 56.16000000 6.18000000
-2.12903226 5.03225806 56.16000000 6.18000000
-2.12903226 5.22580645 56.16000000 6.18000000
-2.12903226 5.41935484 56.16000000 6.18000000
-2.12903226 5.61290323 56.16000000 6.18000000
-2.12903226 5.80645161 56.16000000 6.18000000
-2.12903226 6.00000000 56.16000000 6.18000000
-2.32258065 0.00000000 37.12000000 6.44000000
-2.32258065 0.19354839 37.12000000 6.44000000
-2.32258065 0.38709677 37.12000000 6.44000000
-2.32258065 0.58064516 37.12000000 6.44000000
-2.32258065 0.77419355 37.12000000 6.44000000
-2.32258065 0.96774194 37.12000000 6.44000000
-2.32258065 1.16129032 37.12000000 6.44000000
-2.32258065 1.35483871 37.12000000 6.44000000
-2.32258065 1.54838710 37.12000000 6.44000000
-2.32258065 1.74193548 37.12000000 6.44000000
-2.32258065 1.93548387 37.12000000 6.44000000
-2.32258065 2.12903226 37.12000000 6.44000000
-2.32258065 2.32258065 37.04000000 6.48000000
-2.32258065 2.51612903 36.40000000 6.78000000
-2.32258065 2.70967742 35.92000000 7.06000000
-2.32258065 2.90322581 35.28000000 7.36000000
-2.32258065 3.09677419 57.36000000 7.36000000
-2.32258065 3.29032258 57.12000000 7.06000000
-2.32258065 3.48387097 56.72000000 6.78000000
-2.32258065 3.67741935 56.48000000 6.48000000
-2.32258065 3.87096774 56.48000000 6.44000000
-2.32258065 4.06451613 56.48000000 6.44000000
-2.32258065 4.25806452 56.48000000 6.44000000
-2.32258065 4.45161290 56.48000000 6.44000000
-2.32258065 4.64516129 56.48000000 6.44000000
-2.32258065 4.83870968 56.48000000 6.44000000
-2.32258065 5.03225806 56.48000000 6.44000000
-2.32258065 5.22580645 56.48000000 6.44000000
-2.32258065 5.41935484 56.48000000 6.44000000
-2.32258065 5.61290323 56.48000000 6.44000000
-2.32258065 5.80645161 56.48000000 6.44000000
-2.32258065 6.00000000 56.48000000 6.44000000
-2.51612903 0.00000000 36.64000000 6.68000000
-2.51612903 0.19354839 36.64000000 6.68000000
-2.51612903 0.38709677 36.64000000 6.68000000
-2.51612903 0.58064516 36.64000000 6.68000000
-2.51612903 0.77419355 36.64000000 6.68000000
-2.51612903 0.96774194 36.64000000 6.68000000
-2.51612903 1.16129032 36.64000000 6.68000000
-2.51612903 1.35483871 36.64000000 6.68000000
-2.51612903 1.54838710 36.64000000 6.68000000
-2.51612903 1.74193548 36.64000000 6.68000000
-2.51612903 1.93548387 36.64000000 6.68000000
-2.51612903 2.12903226 36.64000000 6.68000000
-2.51612903 2.32258065 36.64000000 6.68000000
-2.51612903 2.51612903 36.40000000 6.78000000
-2.51612903 2.70967742 35.92000000 7.06000000
-2.51612903 2.90322581 35.28000000 7.36000000
-2.51612903 3.09677419 57.36000000 7.36000000
-2.51612903 3.29032258 57.12000000 7.06000000
-2.51612903 3.48387097 56.72000000 6.78000000
-2.51612903 3.67741935 56.64000000 6.68000000
-2.51612903 3.87096774 56.64000000 6.68000000
-2.51612903 4.06451613 56.64000000 6.68000000
-2.51612903 4.25806452 56.64000000 6.68000000
-2.51612903 4.45161290 56.64000000 6.68000000
-2.51612903 4.64516129 56.64000000 6.68000000
-2.51612903 4.83870968 56.64000000 6.68000000
-2.51612903 5.03225806 56.64000000 6.68000000
-2.51612903 5.22580645 56.64000000 6.68000000
-2.51612903 5.41935484 56.64000000 6.68000000
-2.51612903 5.61290323 56.64000000 6.68000000
-2.51612903 5.80645161 56.64000000 6.68000000
-2.51612903 6.00000000 56.64000000 6.68000000
-2.70967742 0.00000000 36.08000000 6.94000000
-2.70967742 0.19354839 36.08000000 6.94000000
-2.70967742 0.38709677 36.08000000 6.94000000
-2.70967742 0.58064516 36.08000000 6.94000000
-2.70967742 0.77419355 36.08000000 6.94000000
-2.70967742 0.96774194 36.08000000 6.94000000
-2.70967742 1.16129032 36.08000000 6.94000000
-2.70967742 1.35483871 36.08000000 6.94000000
-2.70967742 1.54838710 36.08000000 6.94000000
-2.70967742 1.74193548 36.08000000 6.94000000
-2.70967742 1.93548387 36.08000000 6.94000000
-2.70967742 2.12903226 36.08000000 6.94000000
-2.70967742 2.32258065 36.08000000 6.94000000
-2.70967742 2.51612903 36.08000000 6.94000000
-2.70967742 2.70967742 35.92000000 7.06000000
-2.70967742 2.90322581 35.28000000 7.36000000
-2.70967742 3.09677419 57.36000000 7.36000000
-2.70967742 3.29032258 57.12000000 7.06000000
-2.70967742 3.48387097 56.96000000 6.94000000
-2.70967742 3.67741935 56.96000000 6.94000000
-2.70967742 3.87096774 56.96000000 6.94000000
-2.70967742 4.06451613 56.96000000 6.94000000
-2.70967742 4.25806452 56.96000000 6.94000000
-2.70967742 4.45161290 56.96000000 6.94000000
-2.70967742 4.64516129 56.96000000 6.94000000
-2.70967742 4.83870968 56.96000000 6.94000000
-2.70967742 5.03225806 56.96000000 6.94000000
-2.70967742 5.22580645 56.96000000 6.94000000
-2.70967742 5.41935484 56.96000000 6.94000000
-2.70967742 5.61290323 56.96000000 6.94000000
-2.70967742 5.80645161 56.96000000 6.94000000
-2.70967742 6.00000000 56.96000000 6.94000000
-2.90322581 0.00000000 35.60000000 7.20000000
-2.90322581 0.19354839 35.60000000 7.20000000
-2.90322581 0.38709677 35.60000000 7.20000000
-2.90322581 0.58064516 35.60000000 7.20000000
-2.90322581 0.77419355 35.60000000 7.20000000
-2.90322581 0.96774194 35.60000000 7.20000000
-2.90322581 1.16129032 35.60000000 7.20000000
-2.90322581 1.35483871 35.60000000 7.20000000
-2.90322581 1.54838710 35.60000000 7.20000000
-2.90322581 1.74193548 35.60000000 7.20000000
-2.90322581 1.93548387 35.60000000 7.20000000
-2.90322581 2.12903226 35.60000000 7.20000000
-2.90322581 2.32258065 35.60000000 7.20000000
-2.90322581 2.51612903 35.60000000 7.20000000
-2.90322581 2.70967742 35.60000000 7.20000000
-2.90322581 2.90322581 35.28000000 7.36000000
-2.90322581 3.09677419 57.36000000 7.36000000
-2.90322581 3.29032258 57.20000000 7.20000000
-2.90322581 3.48387097 57.20000000 7.20000000
-2.90322581 3.67741935 57.20000000 7.20000000
-2.90322581 3.87096774 57.20000000 7.20000000
-2.90322581 4.06451613 57.20000000 7.20000000
-2.90322581 4.25806452 57.20000000 7.20000000
-2.90322581 4.45161290 57.20000000 7.20000000
-2.90322581 4.64516129 57.20000000 7.20000000
-2.90322581 4.83870968 57.20000000 7.20000000
-2.90322581 5.03225806 57.20000000 7.20000000
-2.90322581 5.22580645 57.20000000 7.20000000
-2.90322581 5.41935484 57.20000000 7.20000000
-2.90322581 5.61290323 57.20000000 7.20000000
-2.90322581 5.80645161 57.20000000 7.20000000
-2.90322581 6.00000000 57.20000000 7.20000000
-3.09677419 0.00000000 35.12000000 7.46000000
-3.09677419 0.19354839 35.12000000 7.46000000
-3.09677419 0.38709677 35.12000000 7.46000000
-3.09677419 0.58064516 35.12000000 7.46000000
-3.09677419 0.77419355 35.12000000 7.46000000
-3.09677419 0.96774194 35.12000000 7.46000000
-3.09677419 1.16129032 35.12000000 7.46000000
-3.09677419 1.35483871 35.12000000 7.46000000
-3.09677419 1.54838710 35.12000000 7.46000000
-3.09677419 1.74193548 35.12000000 7.46000000
-3.09677419 1.93548387 35.12000000 7.46000000
-3.09677419 2.12903226 35.12000000 7.46000000
-3.09677419 2.32258065 35.12000000 7.46000000
-3.09677419 2.51612903 35.12000000 7.46000000
-3.09677419 2.70967742 35.12000000 7.46000000
-3.09677419 2.90322581 35.12000000 7.46000000
-3.09677419 3.09677419 57.52000000 7.46000000
-3.09677419 3.29032258 57.52000000 7.46000000
-3.09677419 3.48387097 57.52000000 7.46000000
-3.09677419 3.67741935 57.52000000 7.46000000
-3.09677419 3.87096774 57.52000000 7.46000000
-3.09677419 4.06451613 57.52000000 7.46000000
-3.09677419 4.25806452 57.52000000 7.46000000
-3.09677419 4.45161290 57.52000000 7.46000000
-3.09677419 4.64516129 57.52000000 7.46000000
-3.09677419 4.83870968 57.52000000 7.46000000
-3.09677419 5.03225806 57.52000000 7.46000000
-3.09677419 5.22580645 57.52000000 7.46000000
-3.09677419 5.41935484 57.52000000 7.46000000
-3.09677419 5.61290323 57.52000000 7.46000000
-3.09677419 5.80645161 57.52000000 7.46000000
-3.09677419 6.00000000 57.52000000 7.46000000
-3.29032258 0.00000000 34.56000000 7.72000000
-3.29032258 0.19354839 34.56000000 7.72000000
-3.29032258 0.38709677 34.56000000 7.72000000
-3.29032258 0.58064516 34.56000000 7.72000000
-3.29032258 0.77419355 34.56000000 7.72000000
-3.29032258 0.96774194 34.56000000 7.72000000
-3.29032258 1.16129032 34.56000000 7.72000000
-3.29032258 1.35483871 34.56000000 7.72000000
-3.29032258 1.54838710 34.56000000 7.72000000
-3.29032258 1.74193548 34.56000000 7.72000000
-3.29032258 1.93548387 34.56000000 7.72000000
-3.29032258 2.12903226 34.56000000 7.72000000
-3.29032258 2.32258065 34.56000000 7.72000000
-3.29032258 2.51612903 34.56000000 7.72000000
-3.29032258 2.70967742 34.56000000 7.72000000
-3.29032258 2.90322581 47.28000000 7.72000000
-3.29032258 3.09677419 47.28000000 7.72000000
-3.29032258 3.29032258 57.68000000 7.72000000
-3.29032258 3.48387097 57.68000000 7.72000000
-3.29032258 3.67741935 57.68000000 7.72000000
-3.29032258 3.87096774 57.68000000 7.72000000
-3.29032258 4.06451613 57.68000000 7.72000000
-3.29032258 4.25806452 57.68000000 7.72000000
-3.29032258 4.45161290 57.68000000 7.72000000
-3.29032258 4.64516129 57.68000000 7.72000000
-3.29032258 4.83870968 57.68000000 7.72000000
-3.29032258 5.03225806 57.68000000 7.72000000
-3.29032258 5.22580645 57.68000000 7.72000000
-3.29032258 5.41935484 57.68000000 7.72000000
-3.29032258 5.61290323 57.68000000 7.72000000
-3.29032258 5.80645161 57.68000000 7.72000000
-3.29032258 6.00000000 57.68000000 7.72000000
-3.48387097 0.00000000 34.80000000 7.58000000
-3.48387097 0.19354839 34.80000000 7.58000000
-3.48387097 0.38709677 34.80000000 7.58000000
-3.48387097 0.58064516 34.80000000 7.58000000
-3.48387097 0.77419355 34.80000000 7.58000000
-3.48387097 0.96774194 34.80000000 7.58000000
-3.48387097 1.16129032 34.80000000 7.58000000
-3.48387097 1.35483871 34.80000000 7.58000000
-3.48387097 1.54838710 34.80000000 7.58000000
-3.48387097 1.74193548 34.80000000 7.58000000
-3.48387097 1.93548387 34.80000000 7.58000000
-3.48387097 2.12903226 34.80000000 7.58000000
-3.48387097 2.32258065 34.80000000 7.58000000
-3.48387097 2.51612903 34.80000000 7.58000000
-3.48387097 2.70967742 34.80000000 7.58000000
-3.48387097 2.90322581 34.80000000 7.58000000
-3.48387097 3.09677419 34.80000000 10.00000000
-3.48387097 3.29032258 72.24000000 17.42000000
-3.48387097 3.48387097 72.24000000 17.42000000
-3.48387097 3.67741935 72.24000000 17.42000000
-3.48387097 3.87096774 72.24000000 17.42000000
-3.48387097 4.06451613 72.24000000 17.42000000
-3.48387097 4.25806452 72.24000000 17.42000000
-3.48387097 4.45161290 72.24000000 17.42000000
-3.48387097 4.64516129 72.24000000 17.42000000
-3.48387097 4.83870968 72.24000000 17.42000000
-3.48387097 5.03225806 72.24000000 17.42000000
-3.48387097 5.22580645 72.24000000 17.42000000
-3.48387097 5.41935484 72.24000000 17.42000000
-3.48387097 5.61290323 72.24000000 17.42000000
-3.48387097 5.80645161 72.24000000 17.42000000
-3.48387097 6.00000000 72.24000000 17.42000000
-3.67741935 0.00000000 36.80000000 6.62000000
-3.67741935 0.19354839 36.80000000 6.62000000
-3.67741935 0.38709677 36.80000000 6.62000000
-3.67741935 0.58064516 36.80000000 6.62000000
-3.67741935 0.77419355 36.80000000 6.62000000
-3.67741935 0.96774194 36.80000000 6.62000000
-3.67741935 1.16129032 36.80000000 6.62000000
-3.67741935 1.35483871 36.80000000 6.62000000
-3.67741935 1.54838710 36.80000000 6.62000000
-3.67741935 1.74193548 36.80000000 6.62000000
-3.67741935 1.93548387 36.80000000 6.62000000
-3.67741935 2.12903226 36.80000000 6.62000000
-3.67741935 2.32258065 36.80000000 6.62000000
-3.67741935 2.51612903 36.64000000 6.68000000
-3.67741935 2.70967742 36.08000000 6.94000000
-3.67741935 2.90322581 35.60000000 7.20000000
-3.67741935 3.09677419 72.96000000 17.64000000
-3.67741935 3.29032258 73.84000000 17.94000000
-3.67741935 3.48387097 74.64000000 18.22000000
-3.67741935 3.67741935 75.20000000 18.38000000
-3.67741935 3.87096774 75.20000000 18.38000000
-3.67741935 4.06451613 75.20000000 18.38000000
-3.67741935 4.25806452 75.20000000 18.38000000
-3.67741935 4.45161290 75.20000000 18.38000000
-3.67741935 4.64516129 75.20000000 18.38000000
-3.67741935 4.83870968 75.20000000 18.38000000
-3.67741935 5.03225806 75.20000000 18.38000000
-3.67741935 5.22580645 75.20000000 18.38000000
-3.67741935 5.41935484 75.20000000 18.38000000
-3.67741935 5.61290323 75.20000000 18.38000000
-3.67741935 5.80645161 75.20000000 18.38000000
-3.67741935 6.00000000 75.20000000 18.38000000
-3.87096774 0.00000000 38.72000000 5.64000000
-3.87096774 0.19354839 38.72000000 5.64000000
-3.87096774 0.38709677 38.72000000 5.64000000
-3.87096774 0.58064516 38.72000000 5.64000000
-3.87096774 0.77419355 38.72000000 5.64000000
-3.87096774 0.96774194 38.72000000 5.64000000
-3.87096774 1.16129032 38.72000000 5.64000000
-3.87096774 1.35483871 38.64000000 5.68000000
-3.87096774 1.54838710 38.48000000 5.78000000
-3.87096774 1.74193548 38.24000000 5.88000000
-3.87096774 1.93548387 38.08000000 5.96000000
-3.87096774 2.12903226 37.68000000 6.18000000
-3.87096774 2.32258065 37.12000000 6.44000000
-3.87096774 2.51612903 36.64000000 6.68000000
-3.87096774 2.70967742 36.08000000 6.94000000
-3.87096774 2.90322581 35.60000000 7.20000000
-3.87096774 3.09677419 72.96000000 17.64000000
-3.87096774 3.29032258 73.84000000 17.94000000
-3.87096774 3.48387097 74.64000000 18.22000000
-3.87096774 3.67741935 75.52000000 18.52000000
-3.87096774 3.87096774 76.40000000 18.80000000
-3.87096774 4.06451613 77.12000000 19.04000000
-3.87096774 4.25806452 77.36000000 19.12000000
-3.87096774 4.45161290 77.68000000 19.22000000
-3.87096774 4.64516129 78.00000000 19.32000000
-3.87096774 4.83870968 78.08000000 19.36000000
-3.87096774 5.03225806 78.08000000 19.36000000
-3.87096774 5.22580645 78.08000000 19.36000000
-3.87096774 5.41935484 78.08000000 19.36000000
-3.87096774 5.61290323 78.08000000 19.36000000
-3.87096774 5.80645161 78.08000000 19.36000000
-3.87096774 6.00000000 78.08000000 19.36000000
-4.06451613 0.00000000 39.68000000 5.16000000
-4.06451613 0.19354839 39.68000000 5.16000000
-4.06451613 0.38709677 39.60000000 5.20000000
-4.06451613 0.58064516 39.44000000 5.30000000
-4.06451613 0.77419355 39.20000000 5.38000000
-4.06451613 0.96774194 39.04000000 5.48000000
-4.06451613 1.16129032 38.80000000 5.58000000
-4.06451613 1.35483871 38.64000000 5.68000000
-4.06451613 1.54838710 38.48000000 5.78000000
-4.06451613 1.74193548 38.24000000 5.88000000
-4.06451613 1.93548387 38.08000000 5.96000000
-4.06451613 2.12903226 37.68000000 6.18000000
-4.06451613 2.32258065 37.12000000 6.44000000
-4.06451613 2.51612903 36.64000000 6.68000000
-4.06451613 2.70967742 36.08000000 6.94000000
-4.06451613 2.90322581 35.60000000 7.20000000
-4.06451613 3.09677419 72.96000000 17.64000000
-4.06451613 3.29032258 73.84000000 17.94000000
-4.06451613 3.48387097 74.64000000 18.22000000
-4.06451613 3.67741935 75.52000000 18.52000000
-4.06451613 3.87096774 76.40000000 18.80000000
-4.06451613 4.06451613 77.12000000 19.04000000
-4.06451613 4.25806452 77.36000000 19.12000000
-4.06451613 4.45161290 77.68000000 19.22000000
-4.06451613 4.64516129 78.00000000 19.32000000
-4.06451613 4.83870968 78.24000000 19.42000000
-4.06451613 5.03225806 78.56000000 19.52000000
-4.06451613 5.22580645 78.80000000 19.62000000
-4.06451613 5.41935484 79.12000000 19.70000000
-4.06451613 5.61290323 79.44000000 19.80000000
-4.06451613 5.80645161 79.52000000 19.84000000
-4.06451613 6.00000000 79.52000000 19.84000000
-4.25806452 0.00000000 38.72000000 5.64000000
-4.25806452 0.19354839 38.72000000 5.64000000
-4.25806452 0.38709677 38.72000000 5.64000000
-4.25806452 0.58064516 38.72000000 5.64000000
-4.25806452 0.77419355 38.72000000 5.64000000
-4.25806452 0.96774194 38.72000000 5.64000000
-4.25806452 1.16129032 38.72000000 5.64000000
-4.25806452 1.35483871 38.64000000 5.68000000
-4.25806452 1.54838710 38.48000000 5.78000000
-4.25806452 1.74193548 38.24000000 5.88000000
-4.25806452 1.93548387 38.08000000 5.96000000
-4.25806452 2.12903226 37.68000000 6.18000000
-4.25806452 2.32258065 37.12000000 6.44000000
-4.25806452 2.51612903 36.64000000 6.68000000
-4.25806452 2.70967742 36.08000000 6.94000000
-4.25806452 2.90322581 35.60000000 7.20000000
-4.25806452 3.09677419 72.96000000 17.64000000
-4.25806452 3.29032258 73.84000000 17.94000000
-4.25806452 3.48387097 74.64000000 18.22000000
-4.25806452 3.67741935 75.52000000 18.52000000
-4.25806452 3.87096774 76.40000000 18.80000000
-4.25806452 4.06451613 77.12000000 19.04000000
-4.25806452 4.25806452 77.36000000 19.12000000
-4.25806452 4.45161290 77.68000000 19.22000000
-4.25806452 4.64516129 78.00000000 19.32000000
-4.25806452 4.83870968 78.08000000 19.36000000
-4.25806452 5.03225806 78.08000000 19.36000000
-4.25806452 5.22580645 78.08000000 19.36000000
-4.25806452 5.41935484 78.08000000 19.36000000
-4.25806452 5.61290323 78.08000000 19.36000000
-4.25806452 5.80645161 78.08000000 19.36000000
-4.25806452 6.00000000 78.08000000 19.36000000
-4.45161290 0.00000000 37.76000000 6.12000000
-4.45161290 0.19354839 37.76000000 6.12000000
-4.45161290 0.38709677 37.76000000 6.12000000
-4.45161290 0.58064516 37.76000000 6.12000000
-4.45161290 0.77419355 37.76000000 6.12000000
-4.45161290 0.96774194 37.76000000 6.12000000
-4.45161290 1.16129032 37.76000000 6.12000000
-4.45161290 1.35483871 37.76000000 6.12000000
-4.45161290 1.54838710 37.76000000 6.12000000
-4.45161290 1.74193548 37.76000000 6.12000000
-4.45161290 1.93548387 37.76000000 6.12000000
-4.45161290 2.12903226 37.68000000 6.18000000
-4.45161290 2.32258065 37.12000000 6.44000000
-4.45161290 2.51612903 36.64000000 6.68000000
-4.45161290 2.70967742 36.08000000 6.94000000
-4.45161290 2.90322581 35.60000000 7.20000000
-4.45161290 3.09677419 72.96000000 17.64000000
-4.45161290 3.29032258 73.84000000 17.94000000
-4.45161290 3.48387097 74.64000000 18.22000000
-4.45161290 3.67741935 75.52000000 18.52000000
-4.45161290 3.87096774 76.40000000 18.80000000
-4.45161290 4.06451613 76.64000000 18.88000000
-4.45161290 4.25806452 76.64000000 18.88000000
-4.45161290 4.45161290 76.64000000 18.88000000
-4.45161290 4.64516129 76.64000000 18.88000000
-4.45161290 4.83870968 76.64000000 18.88000000
-4.45161290 5.03225806 76.64000000 18.88000000
-4.45161290 5.22580645 76.64000000 18.88000000
-4.45161290 5.41935484 76.64000000 18.88000000
-4.45161290 5.61290323 76.64000000 18.88000000
-4.45161290 5.80645161 76.64000000 18.88000000
-4.45161290 6.00000000 76.64000000 18.88000000
-4.64516129 0.00000000 36.80000000 6.62000000
-4.64516129 0.19354839 36.80000000 6.62000000
-4.64516129 0.38709677 36.80000000 6.62000000
-4.64516129 0.58064516 36.80000000 6.62000000
-4.64516129 0.77419355 36.80000000 6.62000000
-4.64516129 0.96774194 36.80000000 6.62000000
-4.64516129 1.16129032 36.80000000 6.62000000
-4.64516129 1.35483871 36.80000000 6.62000000
-4.64516129 1.54838710 36.80000000 6.62000000
-4.64516129 1.74193548 36.80000000 6.62000000
-4.64516129 1.93548387 36.80000000 6.62000000
-4.64516129 2.12903226 36.80000000 6.62000000
-4.64516129 2.32258065 36.80000000 6.62000000
-4.64516129 2.51612903 36.64000000 6.68000000
-4.64516129 2.70967742 36.08000000 6.94000000
-4.64516129 2.90322581 35.60000000 7.20000000
-4.64516129 3.09677419 72.96000000 17.64000000
-4.64516129 3.29032258 73.84000000 17.94000000
-4.64516129 3.48387097 74.64000000 18.22000000
-4.64516129 3.67741935 75.20000000 18.38000000
-4.64516129 3.87096774 75.20000000 18.38000000
-4.64516129 4.06451613 75.20000000 18.38000000
-4.64516129 4.25806452 75.20000000 18.38000000
-4.64516129 4.45161290 75.20000000 18.38000000
-4.64516129 4.64516129 75.20000000 18.38000000
-4.64516129 4.83870968 75.20000000 18.38000000
-4.64516129 5.03225806 75.20000000 18.38000000
-4.64516129 5.22580645 75.20000000 18.38000000
-4.64516129 5.41935484 75.20000000 18.38000000
-4.64516129 5.61290323 75.20000000 18.38000000
-4.64516129 5.80645161 75.20000000 18.38000000
-4.64516129 6.00000000 75.20000000 18.38000000
-4.83870968 0.00000000 35.76000000 7.10000000
-4.83870968 0.19354839 35.76000000 7.10000000
-4.83870968 0.38709677 35.76000000 7.10000000
-4.83870968 0.58064516 35.76000000 7.10000000
-4.83870968 0.77419355 35.76000000 7.10000000
-4.83870968 0.96774194 35.76000000 7.10000000
-4.83870968 1.16129032 35.76000000 7.10000000
-4.83870968 1.35483871 35.76000000 7.10000000
-4.83870968 1.54838710 35.76000000 7.10000000
-4.83870968 1.74193548 35.76000000 7.10000000
-4.83870968 1.93548387 35.76000000 7.10000000
-4.83870968 2.12903226 35.76000000 7.10000000
-4.83870968 2.32258065 35.76000000 7.10000000
-4.83870968 2.51612903 35.76000000 7.10000000
-4.83870968 2.70967742 35.76000000 7.10000000
-4.83870968 2.90322581 35.60000000 7.20000000
-4.83870968 3.09677419 72.96000000 17.64000000
-4.83870968 3.29032258 73.68000000 17.90000000
-4.83870968 3.48387097 73.68000000 17.90000000
-4.83870968 3.67741935 73.68000000 17.90000000
-4.83870968 3.87096774 73.68000000 17.90000000
-4.83870968 4.06451613 73.68000000 17.90000000
-4.83870968 4.25806452 73.68000000 17.90000000
-4.83870968 4.45161290 73.68000000 17.90000000
-4.83870968 4.64516129 73.68000000 17.90000000
-4.83870968 4.83870968 73.68000000 17.90000000
-4.83870968 5.03225806 73.68000000 17.90000000
-4.83870968 5.22580645 73.68000000 17.90000000
-4.83870968 5.41935484 73.68000000 17.90000000
-4.83870968 5.61290323 73.68000000 17.90000000
-4.83870968 5.80645161 73.68000000 17.90000000
-4.83870968 6.00000000 73.68000000 17.90000000
-5.03225806 0.00000000 34.80000000 7.58000000
-5.03225806 0.19354839 34.80000000 7.58000000
-5.03225806 0.38709677 34.80000000 7.58000000
-5.03225806 0.58064516 34.80000000 7.58000000
-5.03225806 0.77419355 34.80000000 7.58000000
-5.03225806 0.96774194 34.80000000 7.58000000
-5.03225806 1.16129032 34.80000000 7.58000000
-5.03225806 1.35483871 34.80000000 7.58000000
-5.03225806 1.54838710 34.80000000 7.58000000
-5.03225806 1.74193548 34.80000000 7.58000000
-5.03225806 1.93548387 34.80000000 7.58000000
-5.03225806 2.12903226 34.80000000 7.58000000
-5.03225806 2.32258065 34.80000000 7.58000000
-5.03225806 2.51612903 34.80000000 7.58000000
-5.03225806 2.70967742 34.80000000 7.58000000
-5.03225806 2.90322581 34.80000000 7.58000000
-5.03225806 3.09677419 34.80000000 10.00000000
-5.03225806 3.29032258 72.24000000 17.42000000
-5.03225806 3.48387097 72.24000000 17.42000000
-5.03225806 3.67741935 72.24000000 17.42000000
-5.03225806 3.87096774 72.24000000 17.42000000
-5.03225806 4.06451613 72.24000000 17.42000000
-5.03225806 4.25806452 72.24000000 17.42000000
-5.03225806 4.45161290 72.24000000 17.42000000
-5.03225806 4.64516129 72.24000000 17.42000000
-5.03225806 4.83870968 72.24000000 17.42000000
-5.03225806 5.03225806 72.24000000 17.42000000
-5.03225806 5.22580645 72.24000000 17.42000000
-5.03225806 5.41935484 72.24000000 17.42000000
-5.03225806 5.61290323 72.24000000 17.42000000
-5.03225806 5.80645161 72.24000000 17.42000000
-5.03225806 6.00000000 72.24000000 17.42000000
-5.22580645 0.00000000 33.84000000 8.06000000
-5.22580645 0.19354839 33.84000000 8.06000000
-5.22580645 0.38709677 33.84000000 8.06000000
-5.22580645 0.58064516 33.84000000 8.06000000
-5.22580645 0.77419355 33.84000000 8.06000000
-5.22580645 0.96774194 33.84000000 8.06000000
-5.22580645 1.16129032 33.84000000 8.06000000
-5.22580645 1.35483871 33.84000000 8.06000000
-5.22580645 1.54838710 33.84000000 8.06000000
-5.22580645 1.74193548 33.84000000 8.06000000
-5.22580645 1.93548387 33.84000000 8.06000000
-5.22580645 2.12903226 33.84000000 8.06000000
-5.22580645 2.32258065 33.84000000 8.06000000
-5.22580645 2.51612903 33.84000000 8.06000000
-5.22580645 2.70967742 33.84000000 10.00000000
-5.22580645 2.90322581 33.84000000 10.00000000
-5.22580645 3.09677419 33.84000000 10.00000000
-5.22580645 3.29032258 33.84000000 10.00000000
-5.22580645 3.48387097 33.84000000 10.00000000
-5.22580645 3.67741935 70.80000000 16.94000000
-5.22580645 3.87096774 70.80000000 16.94000000
-5.22580645 4.06451613 70.80000000 16.94000000
-5.22580645 4.25806452 70.80000000 16.94000000
-5.22580645 4.45161290 70.80000000 16.94000000
-5.22580645 4.64516129 70.80000000 16.94000000
-5.22580645 4.83870968 70.80000000 16.94000000
-5.22580645 5.03225806 70.80000000 16.94000000
-5.22580645 5.22580645 70.80000000 16.94000000
-5.22580645 5.41935484 70.80000000 16.94000000
-5.22580645 5.61290323 70.80000000 16.94000000
-5.22580645 5.80645161 70.80000000 16.94000000
-5.22580645 6.00000000 70.80000000 16.94000000
-5.41935484 0.00000000 32.88000000 8.54000000
-5.41935484 0.19354839 32.88000000 8.54000000
-5.41935484 0.38709677 32.88000000 8.54000000
-5.41935484 0.58064516 32.88000000 8.54000000
-5.41935484 0.77419355 32.88000000 8.54000000
-5.41935484 0.96774194 32.88000000 8.54000000
-5.41935484 1.16129032 32.88000000 8.54000000
-5.41935484 1.35483871 32.88000000 8.54000000
-5.41935484 1.54838710 32.88000000 8.54000000
-5.41935484 1.74193548 32.88000000 8.54000000
-5.41935484 1.93548387 32.88000000 8.54000000
-5.41935484 2.12903226 32.88000000 8.54000000
-5.41935484 2.32258065 32.88000000 10.00000000
-5.41935484 2.51612903 32.88000000 10.00000000
-5.41935484 2.70967742 32.88000000 10.00000000
-5.41935484 2.90322581 32.88000000 10.00000000
-5.41935484 3.09677419 32.88000000 10.00000000
-5.41935484 3.29032258 32.88000000 10.00000000
-5.41935484 3.48387097 32.88000000 10.00000000
-5.41935484 3.67741935 32.88000000 10.00000000
-5.41935484 3.87096774 32.88000000 10.00000000
-5.41935484 4.06451613 69.36000000 16.46000000
-5.41935484 4.25806452 69.36000000 16.46000000
-5.41935484 4.45161290 69.36000000 16.46000000
-5.41935484 4.64516129 69.36000000 16.46000000
-5.41935484 4.83870968 69.36000000 16.46000000
-5.41935484 5.03225806 69.36000000 16.46000000
-5.41935484 5.22580645 69.36000000 16.46000000
-5.41935484 5.41935484 69.36000000 16.46000000
-5.41935484 5.61290323 69.36000000 16.46000000
-5.41935484 5.80645161 69.36000000 16.46000000
-5.41935484 6.00000000 69.36000000 16.46000000
-5.61290323 0.00000000 31.92000000 9.04000000
-5.61290323 0.19354839 31.92000000 9.04000000
-5.61290323 0.38709677 31.92000000 9.04000000
-5.61290323 0.58064516 31.92000000 9.04000000
-5.61290323 0.77419355 31.92000000 9.04000000
-5.61290323 0.96774194 31.92000000 9.04000000
-5.61290323 1.16129032 31.92000000 9.04000000
-5.61290323 1.35483871 31.92000000 9.04000000
-5.61290323 1.54838710 31.92000000 9.04000000
-5.61290323 1.74193548 31.92000000 9.04000000
-5.61290323 1.93548387 31.92000000 9.04000000
-5.61290323 2.12903226 31.92000000 10.00000000
-5.61290323 2.32258065 31.92000000 10.00000000
-5.61290323 2.51612903 31.92000000 10.00000000
-5.61290323 2.70967742 31.92000000 10.00000000
-5.61290323 2.90322581 31.92000000 10.00000000
-5.61290323 3.09677419 31.92000000 10.00000000
-5.61290323 3.29032258 31.92000000 10.00000000
-5.61290323 3.48387097 31.92000000 10.00000000
-5.61290323 3.67741935 31.92000000 10.00000000
-5.61290323 3.87096774 31.92000000 10.00000000
-5.61290323 4.06451613 31.92000000 10.00000000
-5.61290323 4.25806452 31.92000000 10.00000000
-5.61290323 4.45161290 67.92000000 15.96000000
-5.61290323 4.64516129 67.92000000 15.96000000
-5.61290323 4.83870968 67.92000000 15.96000000
-5.61290323 5.03225806 67.92000000 15.96000000
-5.61290323 5.22580645 67.92000000 15.96000000
-5.61290323 5.41935484 67.92000000 15.96000000
-5.61290323 5.61290323 67.92000000 15.96000000
-5.61290323 5.80645161 67.92000000 15.96000000
-5.61290323 6.00000000 67.92000000 15.96000000
-5.80645161 0.00000000 30.96000000 9.52000000
-5.80645161 0.19354839 30.96000000 9.52000000
-5.80645161 0.38709677 30.96000000 9.52000000
-5.80645161 0.58064516 30.96000000 9.52000000
-5.80645161 0.77419355 30.96000000 9.52000000
-5.80645161 0.96774194 30.96000000 9.52000000
-5.80645161 1.16129032 30.96000000 9.52000000
-5.80645161 1.35483871 30.96000000 9.52000000
-5.80645161 1.54838710 30.96000000 10.00000000
-5.80645161 1.74193548 30.96000000 10.00000000
-5.80645161 1.93548387 30.96000000 10.00000000
-5.80645161 2.12903226 30.96000000 10.00000000
-5.80645161 2.32258065 30.96000000 10.00000000
-5.80645161 2.51612903 30.96000000 10.00000000
-5.80645161 2.70967742 30.96000000 10.00000000
-5.80645161 2.90322581 30.96000000 10.00000000
-5.80645161 3.09677419 30.96000000 10.00000000
-5.80645161 3.29032258 30.96000000 10.00000000
-5.80645161 3.48387097 30.96000000 10.00000000
-5.80645161 3.67741935 30.96000000 10.00000000
-5.80645161 3.87096774 30.96000000 10.00000000
-5.80645161 4.06451613 30.96000000 10.00000000
-5.80645161 4.25806452 30.96000000 10.00000000
-5.80645161 4.45161290 30.96000000 10.00000000
-5.80645161 4.64516129 66.48000000 15.48000000
-5.80645161 4.83870968 66.48000000 15.48000000
-5.80645161 5.03225806 66.48000000 15.48000000
-5.80645161 5.22580645 66.48000000 15.48000000
-5.80645161 5.41935484 66.48000000 15.48000000
-5.80645161 5.61290323 66.48000000 15.48000000
-5.80645161 5.80645161 66.48000000 15.48000000
-5.80645161 6.00000000 66.48000000 15.48000000
-6.00000000 0.00000000 nan nan
-6.00000000 0.19354839 nan nan
-6.00000000 0.38709677 nan nan
-6.00000000 0.58064516 nan nan
-6.00000000 0.77419355 nan nan
-6.00000000 0.96774194 nan nan
-6.00000000 1.16129032 nan nan
-6.00000000 1.35483871 nan nan
-6.00000000 1.54838710 nan nan
-6.00000000 1.74193548 nan nan
-6.00000000 1.93548387 nan nan
-6.00000000 2.12903226 nan nan
-6.00000000 2.32258065 nan nan
-6.00000000 2.51612903 nan nan
-6.00000000 2.70967742 nan nan
-6.00000000 2.90322581 nan nan
-6.00000000 3.09677419 nan nan
-6.00000000 3.29032258 nan nan
-6.00000000 3.48387097 nan nan
-6.00000000 3.67741935 nan nan
-6.00000000 3.87096774 nan nan
-6.00000000 4.06451613 nan nan
-6.00000000 4.25806452 nan nan
-6.00000000 4.45161290 nan nan
-6.00000000 4.64516129 nan nan
-6.00000000 4.83870968 nan nan
-6.00000000 5.03225806 nan nan
-6.00000000 5.22580645 nan nan
-6.00000000 5.41935484 nan nan
-6.00000000 5.61290323 nan nan
-6.00000000 5.80645161 nan nan
-6.00000000 6.00000000 nan nan
+Load Dirt Detergent Cycle
+0.000000000 0.000000000 39.920000000 5.000000000
+0.000000000 0.193548387 39.920000000 5.000000000
+0.000000000 0.387096774 39.920000000 5.000000000
+0.000000000 0.580645161 39.920000000 5.000000000
+0.000000000 0.774193548 39.920000000 5.000000000
+0.000000000 0.967741935 39.920000000 5.000000000
+0.000000000 1.161290323 39.680000000 5.160000000
+0.000000000 1.354838710 39.280000000 5.360000000
+0.000000000 1.548387097 38.880000000 5.540000000
+0.000000000 1.741935484 38.480000000 5.740000000
+0.000000000 1.935483871 38.160000000 5.940000000
+0.000000000 2.129032258 37.600000000 6.200000000
+0.000000000 2.322580645 37.040000000 6.480000000
+0.000000000 2.516129032 36.400000000 6.780000000
+0.000000000 2.709677419 35.920000000 7.060000000
+0.000000000 2.903225806 35.280000000 7.360000000
+0.000000000 3.096774194 57.360000000 7.360000000
+0.000000000 3.290322581 57.120000000 7.060000000
+0.000000000 3.483870968 56.720000000 6.780000000
+0.000000000 3.677419355 56.480000000 6.480000000
+0.000000000 3.870967742 56.240000000 6.200000000
+0.000000000 4.064516129 55.920000000 5.960000000
+0.000000000 4.258064516 55.920000000 5.880000000
+0.000000000 4.451612903 55.760000000 5.780000000
+0.000000000 4.645161290 55.680000000 5.680000000
+0.000000000 4.838709677 55.600000000 5.580000000
+0.000000000 5.032258065 55.440000000 5.480000000
+0.000000000 5.225806452 55.440000000 5.380000000
+0.000000000 5.419354839 55.280000000 5.300000000
+0.000000000 5.612903226 55.200000000 5.200000000
+0.000000000 5.806451613 55.040000000 5.100000000
+0.000000000 6.000000000 54.960000000 5.000000000
+0.193548387 0.000000000 39.920000000 5.000000000
+0.193548387 0.193548387 39.920000000 5.000000000
+0.193548387 0.387096774 39.920000000 5.000000000
+0.193548387 0.580645161 39.920000000 5.000000000
+0.193548387 0.774193548 39.920000000 5.000000000
+0.193548387 0.967741935 39.920000000 5.000000000
+0.193548387 1.161290323 39.680000000 5.160000000
+0.193548387 1.354838710 39.280000000 5.360000000
+0.193548387 1.548387097 38.880000000 5.540000000
+0.193548387 1.741935484 38.480000000 5.740000000
+0.193548387 1.935483871 38.160000000 5.940000000
+0.193548387 2.129032258 37.600000000 6.200000000
+0.193548387 2.322580645 37.040000000 6.480000000
+0.193548387 2.516129032 36.400000000 6.780000000
+0.193548387 2.709677419 35.920000000 7.060000000
+0.193548387 2.903225806 35.280000000 7.360000000
+0.193548387 3.096774194 57.360000000 7.360000000
+0.193548387 3.290322581 57.120000000 7.060000000
+0.193548387 3.483870968 56.720000000 6.780000000
+0.193548387 3.677419355 56.480000000 6.480000000
+0.193548387 3.870967742 56.240000000 6.200000000
+0.193548387 4.064516129 55.920000000 5.960000000
+0.193548387 4.258064516 55.920000000 5.880000000
+0.193548387 4.451612903 55.760000000 5.780000000
+0.193548387 4.645161290 55.680000000 5.680000000
+0.193548387 4.838709677 55.600000000 5.580000000
+0.193548387 5.032258065 55.440000000 5.480000000
+0.193548387 5.225806452 55.440000000 5.380000000
+0.193548387 5.419354839 55.280000000 5.300000000
+0.193548387 5.612903226 55.200000000 5.200000000
+0.193548387 5.806451613 55.040000000 5.100000000
+0.193548387 6.000000000 54.960000000 5.000000000
+0.387096774 0.000000000 39.920000000 5.000000000
+0.387096774 0.193548387 39.920000000 5.000000000
+0.387096774 0.387096774 39.920000000 5.000000000
+0.387096774 0.580645161 39.920000000 5.000000000
+0.387096774 0.774193548 39.920000000 5.000000000
+0.387096774 0.967741935 39.920000000 5.000000000
+0.387096774 1.161290323 39.680000000 5.160000000
+0.387096774 1.354838710 39.280000000 5.360000000
+0.387096774 1.548387097 38.880000000 5.540000000
+0.387096774 1.741935484 38.480000000 5.740000000
+0.387096774 1.935483871 38.160000000 5.940000000
+0.387096774 2.129032258 37.600000000 6.200000000
+0.387096774 2.322580645 37.040000000 6.480000000
+0.387096774 2.516129032 36.400000000 6.780000000
+0.387096774 2.709677419 35.920000000 7.060000000
+0.387096774 2.903225806 35.280000000 7.360000000
+0.387096774 3.096774194 57.360000000 7.360000000
+0.387096774 3.290322581 57.120000000 7.060000000
+0.387096774 3.483870968 56.720000000 6.780000000
+0.387096774 3.677419355 56.480000000 6.480000000
+0.387096774 3.870967742 56.240000000 6.200000000
+0.387096774 4.064516129 55.920000000 5.960000000
+0.387096774 4.258064516 55.920000000 5.880000000
+0.387096774 4.451612903 55.760000000 5.780000000
+0.387096774 4.645161290 55.680000000 5.680000000
+0.387096774 4.838709677 55.600000000 5.580000000
+0.387096774 5.032258065 55.440000000 5.480000000
+0.387096774 5.225806452 55.440000000 5.380000000
+0.387096774 5.419354839 55.280000000 5.300000000
+0.387096774 5.612903226 55.200000000 5.200000000
+0.387096774 5.806451613 55.040000000 5.100000000
+0.387096774 6.000000000 54.960000000 5.000000000
+0.580645161 0.000000000 39.920000000 5.000000000
+0.580645161 0.193548387 39.920000000 5.000000000
+0.580645161 0.387096774 39.920000000 5.000000000
+0.580645161 0.580645161 39.920000000 5.000000000
+0.580645161 0.774193548 39.920000000 5.000000000
+0.580645161 0.967741935 39.920000000 5.000000000
+0.580645161 1.161290323 39.680000000 5.160000000
+0.580645161 1.354838710 39.280000000 5.360000000
+0.580645161 1.548387097 38.880000000 5.540000000
+0.580645161 1.741935484 38.480000000 5.740000000
+0.580645161 1.935483871 38.160000000 5.940000000
+0.580645161 2.129032258 37.600000000 6.200000000
+0.580645161 2.322580645 37.040000000 6.480000000
+0.580645161 2.516129032 36.400000000 6.780000000
+0.580645161 2.709677419 35.920000000 7.060000000
+0.580645161 2.903225806 35.280000000 7.360000000
+0.580645161 3.096774194 57.360000000 7.360000000
+0.580645161 3.290322581 57.120000000 7.060000000
+0.580645161 3.483870968 56.720000000 6.780000000
+0.580645161 3.677419355 56.480000000 6.480000000
+0.580645161 3.870967742 56.240000000 6.200000000
+0.580645161 4.064516129 55.920000000 5.960000000
+0.580645161 4.258064516 55.920000000 5.880000000
+0.580645161 4.451612903 55.760000000 5.780000000
+0.580645161 4.645161290 55.680000000 5.680000000
+0.580645161 4.838709677 55.600000000 5.580000000
+0.580645161 5.032258065 55.440000000 5.480000000
+0.580645161 5.225806452 55.440000000 5.380000000
+0.580645161 5.419354839 55.280000000 5.300000000
+0.580645161 5.612903226 55.200000000 5.200000000
+0.580645161 5.806451613 55.040000000 5.100000000
+0.580645161 6.000000000 54.960000000 5.000000000
+0.774193548 0.000000000 39.920000000 5.000000000
+0.774193548 0.193548387 39.920000000 5.000000000
+0.774193548 0.387096774 39.920000000 5.000000000
+0.774193548 0.580645161 39.920000000 5.000000000
+0.774193548 0.774193548 39.920000000 5.000000000
+0.774193548 0.967741935 39.920000000 5.000000000
+0.774193548 1.161290323 39.680000000 5.160000000
+0.774193548 1.354838710 39.280000000 5.360000000
+0.774193548 1.548387097 38.880000000 5.540000000
+0.774193548 1.741935484 38.480000000 5.740000000
+0.774193548 1.935483871 38.160000000 5.940000000
+0.774193548 2.129032258 37.600000000 6.200000000
+0.774193548 2.322580645 37.040000000 6.480000000
+0.774193548 2.516129032 36.400000000 6.780000000
+0.774193548 2.709677419 35.920000000 7.060000000
+0.774193548 2.903225806 35.280000000 7.360000000
+0.774193548 3.096774194 57.360000000 7.360000000
+0.774193548 3.290322581 57.120000000 7.060000000
+0.774193548 3.483870968 56.720000000 6.780000000
+0.774193548 3.677419355 56.480000000 6.480000000
+0.774193548 3.870967742 56.240000000 6.200000000
+0.774193548 4.064516129 55.920000000 5.960000000
+0.774193548 4.258064516 55.920000000 5.880000000
+0.774193548 4.451612903 55.760000000 5.780000000
+0.774193548 4.645161290 55.680000000 5.680000000
+0.774193548 4.838709677 55.600000000 5.580000000
+0.774193548 5.032258065 55.440000000 5.480000000
+0.774193548 5.225806452 55.440000000 5.380000000
+0.774193548 5.419354839 55.280000000 5.300000000
+0.774193548 5.612903226 55.200000000 5.200000000
+0.774193548 5.806451613 55.040000000 5.100000000
+0.774193548 6.000000000 54.960000000 5.000000000
+0.967741935 0.000000000 39.920000000 5.000000000
+0.967741935 0.193548387 39.920000000 5.000000000
+0.967741935 0.387096774 39.920000000 5.000000000
+0.967741935 0.580645161 39.920000000 5.000000000
+0.967741935 0.774193548 39.920000000 5.000000000
+0.967741935 0.967741935 39.920000000 5.000000000
+0.967741935 1.161290323 39.680000000 5.160000000
+0.967741935 1.354838710 39.280000000 5.360000000
+0.967741935 1.548387097 38.880000000 5.540000000
+0.967741935 1.741935484 38.480000000 5.740000000
+0.967741935 1.935483871 38.160000000 5.940000000
+0.967741935 2.129032258 37.600000000 6.200000000
+0.967741935 2.322580645 37.040000000 6.480000000
+0.967741935 2.516129032 36.400000000 6.780000000
+0.967741935 2.709677419 35.920000000 7.060000000
+0.967741935 2.903225806 35.280000000 7.360000000
+0.967741935 3.096774194 57.360000000 7.360000000
+0.967741935 3.290322581 57.120000000 7.060000000
+0.967741935 3.483870968 56.720000000 6.780000000
+0.967741935 3.677419355 56.480000000 6.480000000
+0.967741935 3.870967742 56.240000000 6.200000000
+0.967741935 4.064516129 55.920000000 5.960000000
+0.967741935 4.258064516 55.920000000 5.880000000
+0.967741935 4.451612903 55.760000000 5.780000000
+0.967741935 4.645161290 55.680000000 5.680000000
+0.967741935 4.838709677 55.600000000 5.580000000
+0.967741935 5.032258065 55.440000000 5.480000000
+0.967741935 5.225806452 55.440000000 5.380000000
+0.967741935 5.419354839 55.280000000 5.300000000
+0.967741935 5.612903226 55.200000000 5.200000000
+0.967741935 5.806451613 55.040000000 5.100000000
+0.967741935 6.000000000 54.960000000 5.000000000
+1.161290323 0.000000000 39.680000000 5.160000000
+1.161290323 0.193548387 39.680000000 5.160000000
+1.161290323 0.387096774 39.680000000 5.160000000
+1.161290323 0.580645161 39.680000000 5.160000000
+1.161290323 0.774193548 39.680000000 5.160000000
+1.161290323 0.967741935 39.680000000 5.160000000
+1.161290323 1.161290323 39.680000000 5.160000000
+1.161290323 1.354838710 39.280000000 5.360000000
+1.161290323 1.548387097 38.880000000 5.540000000
+1.161290323 1.741935484 38.480000000 5.740000000
+1.161290323 1.935483871 38.160000000 5.940000000
+1.161290323 2.129032258 37.600000000 6.200000000
+1.161290323 2.322580645 37.040000000 6.480000000
+1.161290323 2.516129032 36.400000000 6.780000000
+1.161290323 2.709677419 35.920000000 7.060000000
+1.161290323 2.903225806 35.280000000 7.360000000
+1.161290323 3.096774194 57.360000000 7.360000000
+1.161290323 3.290322581 57.120000000 7.060000000
+1.161290323 3.483870968 56.720000000 6.780000000
+1.161290323 3.677419355 56.480000000 6.480000000
+1.161290323 3.870967742 56.240000000 6.200000000
+1.161290323 4.064516129 55.920000000 5.960000000
+1.161290323 4.258064516 55.920000000 5.880000000
+1.161290323 4.451612903 55.760000000 5.780000000
+1.161290323 4.645161290 55.680000000 5.680000000
+1.161290323 4.838709677 55.600000000 5.580000000
+1.161290323 5.032258065 55.440000000 5.480000000
+1.161290323 5.225806452 55.440000000 5.380000000
+1.161290323 5.419354839 55.280000000 5.300000000
+1.161290323 5.612903226 55.200000000 5.200000000
+1.161290323 5.806451613 55.120000000 5.160000000
+1.161290323 6.000000000 55.120000000 5.160000000
+1.354838710 0.000000000 39.280000000 5.360000000
+1.354838710 0.193548387 39.280000000 5.360000000
+1.354838710 0.387096774 39.280000000 5.360000000
+1.354838710 0.580645161 39.280000000 5.360000000
+1.354838710 0.774193548 39.280000000 5.360000000
+1.354838710 0.967741935 39.280000000 5.360000000
+1.354838710 1.161290323 39.280000000 5.360000000
+1.354838710 1.354838710 39.280000000 5.360000000
+1.354838710 1.548387097 38.880000000 5.540000000
+1.354838710 1.741935484 38.480000000 5.740000000
+1.354838710 1.935483871 38.160000000 5.940000000
+1.354838710 2.129032258 37.600000000 6.200000000
+1.354838710 2.322580645 37.040000000 6.480000000
+1.354838710 2.516129032 36.400000000 6.780000000
+1.354838710 2.709677419 35.920000000 7.060000000
+1.354838710 2.903225806 35.280000000 7.360000000
+1.354838710 3.096774194 57.360000000 7.360000000
+1.354838710 3.290322581 57.120000000 7.060000000
+1.354838710 3.483870968 56.720000000 6.780000000
+1.354838710 3.677419355 56.480000000 6.480000000
+1.354838710 3.870967742 56.240000000 6.200000000
+1.354838710 4.064516129 55.920000000 5.960000000
+1.354838710 4.258064516 55.920000000 5.880000000
+1.354838710 4.451612903 55.760000000 5.780000000
+1.354838710 4.645161290 55.680000000 5.680000000
+1.354838710 4.838709677 55.600000000 5.580000000
+1.354838710 5.032258065 55.440000000 5.480000000
+1.354838710 5.225806452 55.440000000 5.380000000
+1.354838710 5.419354839 55.360000000 5.360000000
+1.354838710 5.612903226 55.360000000 5.360000000
+1.354838710 5.806451613 55.360000000 5.360000000
+1.354838710 6.000000000 55.360000000 5.360000000
+1.548387097 0.000000000 38.880000000 5.540000000
+1.548387097 0.193548387 38.880000000 5.540000000
+1.548387097 0.387096774 38.880000000 5.540000000
+1.548387097 0.580645161 38.880000000 5.540000000
+1.548387097 0.774193548 38.880000000 5.540000000
+1.548387097 0.967741935 38.880000000 5.540000000
+1.548387097 1.161290323 38.880000000 5.540000000
+1.548387097 1.354838710 38.880000000 5.540000000
+1.548387097 1.548387097 38.880000000 5.540000000
+1.548387097 1.741935484 38.480000000 5.740000000
+1.548387097 1.935483871 38.160000000 5.940000000
+1.548387097 2.129032258 37.600000000 6.200000000
+1.548387097 2.322580645 37.040000000 6.480000000
+1.548387097 2.516129032 36.400000000 6.780000000
+1.548387097 2.709677419 35.920000000 7.060000000
+1.548387097 2.903225806 35.280000000 7.360000000
+1.548387097 3.096774194 57.360000000 7.360000000
+1.548387097 3.290322581 57.120000000 7.060000000
+1.548387097 3.483870968 56.720000000 6.780000000
+1.548387097 3.677419355 56.480000000 6.480000000
+1.548387097 3.870967742 56.240000000 6.200000000
+1.548387097 4.064516129 55.920000000 5.960000000
+1.548387097 4.258064516 55.920000000 5.880000000
+1.548387097 4.451612903 55.760000000 5.780000000
+1.548387097 4.645161290 55.680000000 5.680000000
+1.548387097 4.838709677 55.600000000 5.580000000
+1.548387097 5.032258065 55.600000000 5.540000000
+1.548387097 5.225806452 55.600000000 5.540000000
+1.548387097 5.419354839 55.600000000 5.540000000
+1.548387097 5.612903226 55.600000000 5.540000000
+1.548387097 5.806451613 55.600000000 5.540000000
+1.548387097 6.000000000 55.600000000 5.540000000
+1.741935484 0.000000000 38.480000000 5.740000000
+1.741935484 0.193548387 38.480000000 5.740000000
+1.741935484 0.387096774 38.480000000 5.740000000
+1.741935484 0.580645161 38.480000000 5.740000000
+1.741935484 0.774193548 38.480000000 5.740000000
+1.741935484 0.967741935 38.480000000 5.740000000
+1.741935484 1.161290323 38.480000000 5.740000000
+1.741935484 1.354838710 38.480000000 5.740000000
+1.741935484 1.548387097 38.480000000 5.740000000
+1.741935484 1.741935484 38.480000000 5.740000000
+1.741935484 1.935483871 38.160000000 5.940000000
+1.741935484 2.129032258 37.600000000 6.200000000
+1.741935484 2.322580645 37.040000000 6.480000000
+1.741935484 2.516129032 36.400000000 6.780000000
+1.741935484 2.709677419 35.920000000 7.060000000
+1.741935484 2.903225806 35.280000000 7.360000000
+1.741935484 3.096774194 57.360000000 7.360000000
+1.741935484 3.290322581 57.120000000 7.060000000
+1.741935484 3.483870968 56.720000000 6.780000000
+1.741935484 3.677419355 56.480000000 6.480000000
+1.741935484 3.870967742 56.240000000 6.200000000
+1.741935484 4.064516129 55.920000000 5.960000000
+1.741935484 4.258064516 55.920000000 5.880000000
+1.741935484 4.451612903 55.760000000 5.780000000
+1.741935484 4.645161290 55.760000000 5.740000000
+1.741935484 4.838709677 55.760000000 5.740000000
+1.741935484 5.032258065 55.760000000 5.740000000
+1.741935484 5.225806452 55.760000000 5.740000000
+1.741935484 5.419354839 55.760000000 5.740000000
+1.741935484 5.612903226 55.760000000 5.740000000
+1.741935484 5.806451613 55.760000000 5.740000000
+1.741935484 6.000000000 55.760000000 5.740000000
+1.935483871 0.000000000 38.160000000 5.940000000
+1.935483871 0.193548387 38.160000000 5.940000000
+1.935483871 0.387096774 38.160000000 5.940000000
+1.935483871 0.580645161 38.160000000 5.940000000
+1.935483871 0.774193548 38.160000000 5.940000000
+1.935483871 0.967741935 38.160000000 5.940000000
+1.935483871 1.161290323 38.160000000 5.940000000
+1.935483871 1.354838710 38.160000000 5.940000000
+1.935483871 1.548387097 38.160000000 5.940000000
+1.935483871 1.741935484 38.160000000 5.940000000
+1.935483871 1.935483871 38.160000000 5.940000000
+1.935483871 2.129032258 37.600000000 6.200000000
+1.935483871 2.322580645 37.040000000 6.480000000
+1.935483871 2.516129032 36.400000000 6.780000000
+1.935483871 2.709677419 35.920000000 7.060000000
+1.935483871 2.903225806 35.280000000 7.360000000
+1.935483871 3.096774194 57.360000000 7.360000000
+1.935483871 3.290322581 57.120000000 7.060000000
+1.935483871 3.483870968 56.720000000 6.780000000
+1.935483871 3.677419355 56.480000000 6.480000000
+1.935483871 3.870967742 56.240000000 6.200000000
+1.935483871 4.064516129 55.920000000 5.960000000
+1.935483871 4.258064516 55.920000000 5.940000000
+1.935483871 4.451612903 55.920000000 5.940000000
+1.935483871 4.645161290 55.920000000 5.940000000
+1.935483871 4.838709677 55.920000000 5.940000000
+1.935483871 5.032258065 55.920000000 5.940000000
+1.935483871 5.225806452 55.920000000 5.940000000
+1.935483871 5.419354839 55.920000000 5.940000000
+1.935483871 5.612903226 55.920000000 5.940000000
+1.935483871 5.806451613 55.920000000 5.940000000
+1.935483871 6.000000000 55.920000000 5.940000000
+2.129032258 0.000000000 37.680000000 6.180000000
+2.129032258 0.193548387 37.680000000 6.180000000
+2.129032258 0.387096774 37.680000000 6.180000000
+2.129032258 0.580645161 37.680000000 6.180000000
+2.129032258 0.774193548 37.680000000 6.180000000
+2.129032258 0.967741935 37.680000000 6.180000000
+2.129032258 1.161290323 37.680000000 6.180000000
+2.129032258 1.354838710 37.680000000 6.180000000
+2.129032258 1.548387097 37.680000000 6.180000000
+2.129032258 1.741935484 37.680000000 6.180000000
+2.129032258 1.935483871 37.680000000 6.180000000
+2.129032258 2.129032258 37.600000000 6.200000000
+2.129032258 2.322580645 37.040000000 6.480000000
+2.129032258 2.516129032 36.400000000 6.780000000
+2.129032258 2.709677419 35.920000000 7.060000000
+2.129032258 2.903225806 35.280000000 7.360000000
+2.129032258 3.096774194 57.360000000 7.360000000
+2.129032258 3.290322581 57.120000000 7.060000000
+2.129032258 3.483870968 56.720000000 6.780000000
+2.129032258 3.677419355 56.480000000 6.480000000
+2.129032258 3.870967742 56.240000000 6.200000000
+2.129032258 4.064516129 56.160000000 6.180000000
+2.129032258 4.258064516 56.160000000 6.180000000
+2.129032258 4.451612903 56.160000000 6.180000000
+2.129032258 4.645161290 56.160000000 6.180000000
+2.129032258 4.838709677 56.160000000 6.180000000
+2.129032258 5.032258065 56.160000000 6.180000000
+2.129032258 5.225806452 56.160000000 6.180000000
+2.129032258 5.419354839 56.160000000 6.180000000
+2.129032258 5.612903226 56.160000000 6.180000000
+2.129032258 5.806451613 56.160000000 6.180000000
+2.129032258 6.000000000 56.160000000 6.180000000
+2.322580645 0.000000000 37.120000000 6.440000000
+2.322580645 0.193548387 37.120000000 6.440000000
+2.322580645 0.387096774 37.120000000 6.440000000
+2.322580645 0.580645161 37.120000000 6.440000000
+2.322580645 0.774193548 37.120000000 6.440000000
+2.322580645 0.967741935 37.120000000 6.440000000
+2.322580645 1.161290323 37.120000000 6.440000000
+2.322580645 1.354838710 37.120000000 6.440000000
+2.322580645 1.548387097 37.120000000 6.440000000
+2.322580645 1.741935484 37.120000000 6.440000000
+2.322580645 1.935483871 37.120000000 6.440000000
+2.322580645 2.129032258 37.120000000 6.440000000
+2.322580645 2.322580645 37.040000000 6.480000000
+2.322580645 2.516129032 36.400000000 6.780000000
+2.322580645 2.709677419 35.920000000 7.060000000
+2.322580645 2.903225806 35.280000000 7.360000000
+2.322580645 3.096774194 57.360000000 7.360000000
+2.322580645 3.290322581 57.120000000 7.060000000
+2.322580645 3.483870968 56.720000000 6.780000000
+2.322580645 3.677419355 56.480000000 6.480000000
+2.322580645 3.870967742 56.480000000 6.440000000
+2.322580645 4.064516129 56.480000000 6.440000000
+2.322580645 4.258064516 56.480000000 6.440000000
+2.322580645 4.451612903 56.480000000 6.440000000
+2.322580645 4.645161290 56.480000000 6.440000000
+2.322580645 4.838709677 56.480000000 6.440000000
+2.322580645 5.032258065 56.480000000 6.440000000
+2.322580645 5.225806452 56.480000000 6.440000000
+2.322580645 5.419354839 56.480000000 6.440000000
+2.322580645 5.612903226 56.480000000 6.440000000
+2.322580645 5.806451613 56.480000000 6.440000000
+2.322580645 6.000000000 56.480000000 6.440000000
+2.516129032 0.000000000 36.640000000 6.680000000
+2.516129032 0.193548387 36.640000000 6.680000000
+2.516129032 0.387096774 36.640000000 6.680000000
+2.516129032 0.580645161 36.640000000 6.680000000
+2.516129032 0.774193548 36.640000000 6.680000000
+2.516129032 0.967741935 36.640000000 6.680000000
+2.516129032 1.161290323 36.640000000 6.680000000
+2.516129032 1.354838710 36.640000000 6.680000000
+2.516129032 1.548387097 36.640000000 6.680000000
+2.516129032 1.741935484 36.640000000 6.680000000
+2.516129032 1.935483871 36.640000000 6.680000000
+2.516129032 2.129032258 36.640000000 6.680000000
+2.516129032 2.322580645 36.640000000 6.680000000
+2.516129032 2.516129032 36.400000000 6.780000000
+2.516129032 2.709677419 35.920000000 7.060000000
+2.516129032 2.903225806 35.280000000 7.360000000
+2.516129032 3.096774194 57.360000000 7.360000000
+2.516129032 3.290322581 57.120000000 7.060000000
+2.516129032 3.483870968 56.720000000 6.780000000
+2.516129032 3.677419355 56.640000000 6.680000000
+2.516129032 3.870967742 56.640000000 6.680000000
+2.516129032 4.064516129 56.640000000 6.680000000
+2.516129032 4.258064516 56.640000000 6.680000000
+2.516129032 4.451612903 56.640000000 6.680000000
+2.516129032 4.645161290 56.640000000 6.680000000
+2.516129032 4.838709677 56.640000000 6.680000000
+2.516129032 5.032258065 56.640000000 6.680000000
+2.516129032 5.225806452 56.640000000 6.680000000
+2.516129032 5.419354839 56.640000000 6.680000000
+2.516129032 5.612903226 56.640000000 6.680000000
+2.516129032 5.806451613 56.640000000 6.680000000
+2.516129032 6.000000000 56.640000000 6.680000000
+2.709677419 0.000000000 36.080000000 6.940000000
+2.709677419 0.193548387 36.080000000 6.940000000
+2.709677419 0.387096774 36.080000000 6.940000000
+2.709677419 0.580645161 36.080000000 6.940000000
+2.709677419 0.774193548 36.080000000 6.940000000
+2.709677419 0.967741935 36.080000000 6.940000000
+2.709677419 1.161290323 36.080000000 6.940000000
+2.709677419 1.354838710 36.080000000 6.940000000
+2.709677419 1.548387097 36.080000000 6.940000000
+2.709677419 1.741935484 36.080000000 6.940000000
+2.709677419 1.935483871 36.080000000 6.940000000
+2.709677419 2.129032258 36.080000000 6.940000000
+2.709677419 2.322580645 36.080000000 6.940000000
+2.709677419 2.516129032 36.080000000 6.940000000
+2.709677419 2.709677419 35.920000000 7.060000000
+2.709677419 2.903225806 35.280000000 7.360000000
+2.709677419 3.096774194 57.360000000 7.360000000
+2.709677419 3.290322581 57.120000000 7.060000000
+2.709677419 3.483870968 56.960000000 6.940000000
+2.709677419 3.677419355 56.960000000 6.940000000
+2.709677419 3.870967742 56.960000000 6.940000000
+2.709677419 4.064516129 56.960000000 6.940000000
+2.709677419 4.258064516 56.960000000 6.940000000
+2.709677419 4.451612903 56.960000000 6.940000000
+2.709677419 4.645161290 56.960000000 6.940000000
+2.709677419 4.838709677 56.960000000 6.940000000
+2.709677419 5.032258065 56.960000000 6.940000000
+2.709677419 5.225806452 56.960000000 6.940000000
+2.709677419 5.419354839 56.960000000 6.940000000
+2.709677419 5.612903226 56.960000000 6.940000000
+2.709677419 5.806451613 56.960000000 6.940000000
+2.709677419 6.000000000 56.960000000 6.940000000
+2.903225806 0.000000000 35.600000000 7.200000000
+2.903225806 0.193548387 35.600000000 7.200000000
+2.903225806 0.387096774 35.600000000 7.200000000
+2.903225806 0.580645161 35.600000000 7.200000000
+2.903225806 0.774193548 35.600000000 7.200000000
+2.903225806 0.967741935 35.600000000 7.200000000
+2.903225806 1.161290323 35.600000000 7.200000000
+2.903225806 1.354838710 35.600000000 7.200000000
+2.903225806 1.548387097 35.600000000 7.200000000
+2.903225806 1.741935484 35.600000000 7.200000000
+2.903225806 1.935483871 35.600000000 7.200000000
+2.903225806 2.129032258 35.600000000 7.200000000
+2.903225806 2.322580645 35.600000000 7.200000000
+2.903225806 2.516129032 35.600000000 7.200000000
+2.903225806 2.709677419 35.600000000 7.200000000
+2.903225806 2.903225806 35.280000000 7.360000000
+2.903225806 3.096774194 57.360000000 7.360000000
+2.903225806 3.290322581 57.200000000 7.200000000
+2.903225806 3.483870968 57.200000000 7.200000000
+2.903225806 3.677419355 57.200000000 7.200000000
+2.903225806 3.870967742 57.200000000 7.200000000
+2.903225806 4.064516129 57.200000000 7.200000000
+2.903225806 4.258064516 57.200000000 7.200000000
+2.903225806 4.451612903 57.200000000 7.200000000
+2.903225806 4.645161290 57.200000000 7.200000000
+2.903225806 4.838709677 57.200000000 7.200000000
+2.903225806 5.032258065 57.200000000 7.200000000
+2.903225806 5.225806452 57.200000000 7.200000000
+2.903225806 5.419354839 57.200000000 7.200000000
+2.903225806 5.612903226 57.200000000 7.200000000
+2.903225806 5.806451613 57.200000000 7.200000000
+2.903225806 6.000000000 57.200000000 7.200000000
+3.096774194 0.000000000 35.120000000 7.460000000
+3.096774194 0.193548387 35.120000000 7.460000000
+3.096774194 0.387096774 35.120000000 7.460000000
+3.096774194 0.580645161 35.120000000 7.460000000
+3.096774194 0.774193548 35.120000000 7.460000000
+3.096774194 0.967741935 35.120000000 7.460000000
+3.096774194 1.161290323 35.120000000 7.460000000
+3.096774194 1.354838710 35.120000000 7.460000000
+3.096774194 1.548387097 35.120000000 7.460000000
+3.096774194 1.741935484 35.120000000 7.460000000
+3.096774194 1.935483871 35.120000000 7.460000000
+3.096774194 2.129032258 35.120000000 7.460000000
+3.096774194 2.322580645 35.120000000 7.460000000
+3.096774194 2.516129032 35.120000000 7.460000000
+3.096774194 2.709677419 35.120000000 7.460000000
+3.096774194 2.903225806 35.120000000 7.460000000
+3.096774194 3.096774194 57.520000000 7.460000000
+3.096774194 3.290322581 57.520000000 7.460000000
+3.096774194 3.483870968 57.520000000 7.460000000
+3.096774194 3.677419355 57.520000000 7.460000000
+3.096774194 3.870967742 57.520000000 7.460000000
+3.096774194 4.064516129 57.520000000 7.460000000
+3.096774194 4.258064516 57.520000000 7.460000000
+3.096774194 4.451612903 57.520000000 7.460000000
+3.096774194 4.645161290 57.520000000 7.460000000
+3.096774194 4.838709677 57.520000000 7.460000000
+3.096774194 5.032258065 57.520000000 7.460000000
+3.096774194 5.225806452 57.520000000 7.460000000
+3.096774194 5.419354839 57.520000000 7.460000000
+3.096774194 5.612903226 57.520000000 7.460000000
+3.096774194 5.806451613 57.520000000 7.460000000
+3.096774194 6.000000000 57.520000000 7.460000000
+3.290322581 0.000000000 34.560000000 7.720000000
+3.290322581 0.193548387 34.560000000 7.720000000
+3.290322581 0.387096774 34.560000000 7.720000000
+3.290322581 0.580645161 34.560000000 7.720000000
+3.290322581 0.774193548 34.560000000 7.720000000
+3.290322581 0.967741935 34.560000000 7.720000000
+3.290322581 1.161290323 34.560000000 7.720000000
+3.290322581 1.354838710 34.560000000 7.720000000
+3.290322581 1.548387097 34.560000000 7.720000000
+3.290322581 1.741935484 34.560000000 7.720000000
+3.290322581 1.935483871 34.560000000 7.720000000
+3.290322581 2.129032258 34.560000000 7.720000000
+3.290322581 2.322580645 34.560000000 7.720000000
+3.290322581 2.516129032 34.560000000 7.720000000
+3.290322581 2.709677419 34.560000000 7.720000000
+3.290322581 2.903225806 47.280000000 7.720000000
+3.290322581 3.096774194 47.280000000 7.720000000
+3.290322581 3.290322581 57.680000000 7.720000000
+3.290322581 3.483870968 57.680000000 7.720000000
+3.290322581 3.677419355 57.680000000 7.720000000
+3.290322581 3.870967742 57.680000000 7.720000000
+3.290322581 4.064516129 57.680000000 7.720000000
+3.290322581 4.258064516 57.680000000 7.720000000
+3.290322581 4.451612903 57.680000000 7.720000000
+3.290322581 4.645161290 57.680000000 7.720000000
+3.290322581 4.838709677 57.680000000 7.720000000
+3.290322581 5.032258065 57.680000000 7.720000000
+3.290322581 5.225806452 57.680000000 7.720000000
+3.290322581 5.419354839 57.680000000 7.720000000
+3.290322581 5.612903226 57.680000000 7.720000000
+3.290322581 5.806451613 57.680000000 7.720000000
+3.290322581 6.000000000 57.680000000 7.720000000
+3.483870968 0.000000000 34.800000000 7.580000000
+3.483870968 0.193548387 34.800000000 7.580000000
+3.483870968 0.387096774 34.800000000 7.580000000
+3.483870968 0.580645161 34.800000000 7.580000000
+3.483870968 0.774193548 34.800000000 7.580000000
+3.483870968 0.967741935 34.800000000 7.580000000
+3.483870968 1.161290323 34.800000000 7.580000000
+3.483870968 1.354838710 34.800000000 7.580000000
+3.483870968 1.548387097 34.800000000 7.580000000
+3.483870968 1.741935484 34.800000000 7.580000000
+3.483870968 1.935483871 34.800000000 7.580000000
+3.483870968 2.129032258 34.800000000 7.580000000
+3.483870968 2.322580645 34.800000000 7.580000000
+3.483870968 2.516129032 34.800000000 7.580000000
+3.483870968 2.709677419 34.800000000 7.580000000
+3.483870968 2.903225806 34.800000000 7.580000000
+3.483870968 3.096774194 34.800000000 10.000000000
+3.483870968 3.290322581 72.240000000 17.420000000
+3.483870968 3.483870968 72.240000000 17.420000000
+3.483870968 3.677419355 72.240000000 17.420000000
+3.483870968 3.870967742 72.240000000 17.420000000
+3.483870968 4.064516129 72.240000000 17.420000000
+3.483870968 4.258064516 72.240000000 17.420000000
+3.483870968 4.451612903 72.240000000 17.420000000
+3.483870968 4.645161290 72.240000000 17.420000000
+3.483870968 4.838709677 72.240000000 17.420000000
+3.483870968 5.032258065 72.240000000 17.420000000
+3.483870968 5.225806452 72.240000000 17.420000000
+3.483870968 5.419354839 72.240000000 17.420000000
+3.483870968 5.612903226 72.240000000 17.420000000
+3.483870968 5.806451613 72.240000000 17.420000000
+3.483870968 6.000000000 72.240000000 17.420000000
+3.677419355 0.000000000 36.800000000 6.620000000
+3.677419355 0.193548387 36.800000000 6.620000000
+3.677419355 0.387096774 36.800000000 6.620000000
+3.677419355 0.580645161 36.800000000 6.620000000
+3.677419355 0.774193548 36.800000000 6.620000000
+3.677419355 0.967741935 36.800000000 6.620000000
+3.677419355 1.161290323 36.800000000 6.620000000
+3.677419355 1.354838710 36.800000000 6.620000000
+3.677419355 1.548387097 36.800000000 6.620000000
+3.677419355 1.741935484 36.800000000 6.620000000
+3.677419355 1.935483871 36.800000000 6.620000000
+3.677419355 2.129032258 36.800000000 6.620000000
+3.677419355 2.322580645 36.800000000 6.620000000
+3.677419355 2.516129032 36.640000000 6.680000000
+3.677419355 2.709677419 36.080000000 6.940000000
+3.677419355 2.903225806 35.600000000 7.200000000
+3.677419355 3.096774194 72.960000000 17.640000000
+3.677419355 3.290322581 73.840000000 17.940000000
+3.677419355 3.483870968 74.640000000 18.220000000
+3.677419355 3.677419355 75.200000000 18.380000000
+3.677419355 3.870967742 75.200000000 18.380000000
+3.677419355 4.064516129 75.200000000 18.380000000
+3.677419355 4.258064516 75.200000000 18.380000000
+3.677419355 4.451612903 75.200000000 18.380000000
+3.677419355 4.645161290 75.200000000 18.380000000
+3.677419355 4.838709677 75.200000000 18.380000000
+3.677419355 5.032258065 75.200000000 18.380000000
+3.677419355 5.225806452 75.200000000 18.380000000
+3.677419355 5.419354839 75.200000000 18.380000000
+3.677419355 5.612903226 75.200000000 18.380000000
+3.677419355 5.806451613 75.200000000 18.380000000
+3.677419355 6.000000000 75.200000000 18.380000000
+3.870967742 0.000000000 38.720000000 5.640000000
+3.870967742 0.193548387 38.720000000 5.640000000
+3.870967742 0.387096774 38.720000000 5.640000000
+3.870967742 0.580645161 38.720000000 5.640000000
+3.870967742 0.774193548 38.720000000 5.640000000
+3.870967742 0.967741935 38.720000000 5.640000000
+3.870967742 1.161290323 38.720000000 5.640000000
+3.870967742 1.354838710 38.640000000 5.680000000
+3.870967742 1.548387097 38.480000000 5.780000000
+3.870967742 1.741935484 38.240000000 5.880000000
+3.870967742 1.935483871 38.080000000 5.960000000
+3.870967742 2.129032258 37.680000000 6.180000000
+3.870967742 2.322580645 37.120000000 6.440000000
+3.870967742 2.516129032 36.640000000 6.680000000
+3.870967742 2.709677419 36.080000000 6.940000000
+3.870967742 2.903225806 35.600000000 7.200000000
+3.870967742 3.096774194 72.960000000 17.640000000
+3.870967742 3.290322581 73.840000000 17.940000000
+3.870967742 3.483870968 74.640000000 18.220000000
+3.870967742 3.677419355 75.520000000 18.520000000
+3.870967742 3.870967742 76.400000000 18.800000000
+3.870967742 4.064516129 77.120000000 19.040000000
+3.870967742 4.258064516 77.360000000 19.120000000
+3.870967742 4.451612903 77.680000000 19.220000000
+3.870967742 4.645161290 78.000000000 19.320000000
+3.870967742 4.838709677 78.080000000 19.360000000
+3.870967742 5.032258065 78.080000000 19.360000000
+3.870967742 5.225806452 78.080000000 19.360000000
+3.870967742 5.419354839 78.080000000 19.360000000
+3.870967742 5.612903226 78.080000000 19.360000000
+3.870967742 5.806451613 78.080000000 19.360000000
+3.870967742 6.000000000 78.080000000 19.360000000
+4.064516129 0.000000000 39.680000000 5.160000000
+4.064516129 0.193548387 39.680000000 5.160000000
+4.064516129 0.387096774 39.600000000 5.200000000
+4.064516129 0.580645161 39.440000000 5.300000000
+4.064516129 0.774193548 39.200000000 5.380000000
+4.064516129 0.967741935 39.040000000 5.480000000
+4.064516129 1.161290323 38.800000000 5.580000000
+4.064516129 1.354838710 38.640000000 5.680000000
+4.064516129 1.548387097 38.480000000 5.780000000
+4.064516129 1.741935484 38.240000000 5.880000000
+4.064516129 1.935483871 38.080000000 5.960000000
+4.064516129 2.129032258 37.680000000 6.180000000
+4.064516129 2.322580645 37.120000000 6.440000000
+4.064516129 2.516129032 36.640000000 6.680000000
+4.064516129 2.709677419 36.080000000 6.940000000
+4.064516129 2.903225806 35.600000000 7.200000000
+4.064516129 3.096774194 72.960000000 17.640000000
+4.064516129 3.290322581 73.840000000 17.940000000
+4.064516129 3.483870968 74.640000000 18.220000000
+4.064516129 3.677419355 75.520000000 18.520000000
+4.064516129 3.870967742 76.400000000 18.800000000
+4.064516129 4.064516129 77.120000000 19.040000000
+4.064516129 4.258064516 77.360000000 19.120000000
+4.064516129 4.451612903 77.680000000 19.220000000
+4.064516129 4.645161290 78.000000000 19.320000000
+4.064516129 4.838709677 78.240000000 19.420000000
+4.064516129 5.032258065 78.560000000 19.520000000
+4.064516129 5.225806452 78.800000000 19.620000000
+4.064516129 5.419354839 79.120000000 19.700000000
+4.064516129 5.612903226 79.440000000 19.800000000
+4.064516129 5.806451613 79.520000000 19.840000000
+4.064516129 6.000000000 79.520000000 19.840000000
+4.258064516 0.000000000 38.720000000 5.640000000
+4.258064516 0.193548387 38.720000000 5.640000000
+4.258064516 0.387096774 38.720000000 5.640000000
+4.258064516 0.580645161 38.720000000 5.640000000
+4.258064516 0.774193548 38.720000000 5.640000000
+4.258064516 0.967741935 38.720000000 5.640000000
+4.258064516 1.161290323 38.720000000 5.640000000
+4.258064516 1.354838710 38.640000000 5.680000000
+4.258064516 1.548387097 38.480000000 5.780000000
+4.258064516 1.741935484 38.240000000 5.880000000
+4.258064516 1.935483871 38.080000000 5.960000000
+4.258064516 2.129032258 37.680000000 6.180000000
+4.258064516 2.322580645 37.120000000 6.440000000
+4.258064516 2.516129032 36.640000000 6.680000000
+4.258064516 2.709677419 36.080000000 6.940000000
+4.258064516 2.903225806 35.600000000 7.200000000
+4.258064516 3.096774194 72.960000000 17.640000000
+4.258064516 3.290322581 73.840000000 17.940000000
+4.258064516 3.483870968 74.640000000 18.220000000
+4.258064516 3.677419355 75.520000000 18.520000000
+4.258064516 3.870967742 76.400000000 18.800000000
+4.258064516 4.064516129 77.120000000 19.040000000
+4.258064516 4.258064516 77.360000000 19.120000000
+4.258064516 4.451612903 77.680000000 19.220000000
+4.258064516 4.645161290 78.000000000 19.320000000
+4.258064516 4.838709677 78.080000000 19.360000000
+4.258064516 5.032258065 78.080000000 19.360000000
+4.258064516 5.225806452 78.080000000 19.360000000
+4.258064516 5.419354839 78.080000000 19.360000000
+4.258064516 5.612903226 78.080000000 19.360000000
+4.258064516 5.806451613 78.080000000 19.360000000
+4.258064516 6.000000000 78.080000000 19.360000000
+4.451612903 0.000000000 37.760000000 6.120000000
+4.451612903 0.193548387 37.760000000 6.120000000
+4.451612903 0.387096774 37.760000000 6.120000000
+4.451612903 0.580645161 37.760000000 6.120000000
+4.451612903 0.774193548 37.760000000 6.120000000
+4.451612903 0.967741935 37.760000000 6.120000000
+4.451612903 1.161290323 37.760000000 6.120000000
+4.451612903 1.354838710 37.760000000 6.120000000
+4.451612903 1.548387097 37.760000000 6.120000000
+4.451612903 1.741935484 37.760000000 6.120000000
+4.451612903 1.935483871 37.760000000 6.120000000
+4.451612903 2.129032258 37.680000000 6.180000000
+4.451612903 2.322580645 37.120000000 6.440000000
+4.451612903 2.516129032 36.640000000 6.680000000
+4.451612903 2.709677419 36.080000000 6.940000000
+4.451612903 2.903225806 35.600000000 7.200000000
+4.451612903 3.096774194 72.960000000 17.640000000
+4.451612903 3.290322581 73.840000000 17.940000000
+4.451612903 3.483870968 74.640000000 18.220000000
+4.451612903 3.677419355 75.520000000 18.520000000
+4.451612903 3.870967742 76.400000000 18.800000000
+4.451612903 4.064516129 76.640000000 18.880000000
+4.451612903 4.258064516 76.640000000 18.880000000
+4.451612903 4.451612903 76.640000000 18.880000000
+4.451612903 4.645161290 76.640000000 18.880000000
+4.451612903 4.838709677 76.640000000 18.880000000
+4.451612903 5.032258065 76.640000000 18.880000000
+4.451612903 5.225806452 76.640000000 18.880000000
+4.451612903 5.419354839 76.640000000 18.880000000
+4.451612903 5.612903226 76.640000000 18.880000000
+4.451612903 5.806451613 76.640000000 18.880000000
+4.451612903 6.000000000 76.640000000 18.880000000
+4.645161290 0.000000000 36.800000000 6.620000000
+4.645161290 0.193548387 36.800000000 6.620000000
+4.645161290 0.387096774 36.800000000 6.620000000
+4.645161290 0.580645161 36.800000000 6.620000000
+4.645161290 0.774193548 36.800000000 6.620000000
+4.645161290 0.967741935 36.800000000 6.620000000
+4.645161290 1.161290323 36.800000000 6.620000000
+4.645161290 1.354838710 36.800000000 6.620000000
+4.645161290 1.548387097 36.800000000 6.620000000
+4.645161290 1.741935484 36.800000000 6.620000000
+4.645161290 1.935483871 36.800000000 6.620000000
+4.645161290 2.129032258 36.800000000 6.620000000
+4.645161290 2.322580645 36.800000000 6.620000000
+4.645161290 2.516129032 36.640000000 6.680000000
+4.645161290 2.709677419 36.080000000 6.940000000
+4.645161290 2.903225806 35.600000000 7.200000000
+4.645161290 3.096774194 72.960000000 17.640000000
+4.645161290 3.290322581 73.840000000 17.940000000
+4.645161290 3.483870968 74.640000000 18.220000000
+4.645161290 3.677419355 75.200000000 18.380000000
+4.645161290 3.870967742 75.200000000 18.380000000
+4.645161290 4.064516129 75.200000000 18.380000000
+4.645161290 4.258064516 75.200000000 18.380000000
+4.645161290 4.451612903 75.200000000 18.380000000
+4.645161290 4.645161290 75.200000000 18.380000000
+4.645161290 4.838709677 75.200000000 18.380000000
+4.645161290 5.032258065 75.200000000 18.380000000
+4.645161290 5.225806452 75.200000000 18.380000000
+4.645161290 5.419354839 75.200000000 18.380000000
+4.645161290 5.612903226 75.200000000 18.380000000
+4.645161290 5.806451613 75.200000000 18.380000000
+4.645161290 6.000000000 75.200000000 18.380000000
+4.838709677 0.000000000 35.760000000 7.100000000
+4.838709677 0.193548387 35.760000000 7.100000000
+4.838709677 0.387096774 35.760000000 7.100000000
+4.838709677 0.580645161 35.760000000 7.100000000
+4.838709677 0.774193548 35.760000000 7.100000000
+4.838709677 0.967741935 35.760000000 7.100000000
+4.838709677 1.161290323 35.760000000 7.100000000
+4.838709677 1.354838710 35.760000000 7.100000000
+4.838709677 1.548387097 35.760000000 7.100000000
+4.838709677 1.741935484 35.760000000 7.100000000
+4.838709677 1.935483871 35.760000000 7.100000000
+4.838709677 2.129032258 35.760000000 7.100000000
+4.838709677 2.322580645 35.760000000 7.100000000
+4.838709677 2.516129032 35.760000000 7.100000000
+4.838709677 2.709677419 35.760000000 7.100000000
+4.838709677 2.903225806 35.600000000 7.200000000
+4.838709677 3.096774194 72.960000000 17.640000000
+4.838709677 3.290322581 73.680000000 17.900000000
+4.838709677 3.483870968 73.680000000 17.900000000
+4.838709677 3.677419355 73.680000000 17.900000000
+4.838709677 3.870967742 73.680000000 17.900000000
+4.838709677 4.064516129 73.680000000 17.900000000
+4.838709677 4.258064516 73.680000000 17.900000000
+4.838709677 4.451612903 73.680000000 17.900000000
+4.838709677 4.645161290 73.680000000 17.900000000
+4.838709677 4.838709677 73.680000000 17.900000000
+4.838709677 5.032258065 73.680000000 17.900000000
+4.838709677 5.225806452 73.680000000 17.900000000
+4.838709677 5.419354839 73.680000000 17.900000000
+4.838709677 5.612903226 73.680000000 17.900000000
+4.838709677 5.806451613 73.680000000 17.900000000
+4.838709677 6.000000000 73.680000000 17.900000000
+5.032258065 0.000000000 34.800000000 7.580000000
+5.032258065 0.193548387 34.800000000 7.580000000
+5.032258065 0.387096774 34.800000000 7.580000000
+5.032258065 0.580645161 34.800000000 7.580000000
+5.032258065 0.774193548 34.800000000 7.580000000
+5.032258065 0.967741935 34.800000000 7.580000000
+5.032258065 1.161290323 34.800000000 7.580000000
+5.032258065 1.354838710 34.800000000 7.580000000
+5.032258065 1.548387097 34.800000000 7.580000000
+5.032258065 1.741935484 34.800000000 7.580000000
+5.032258065 1.935483871 34.800000000 7.580000000
+5.032258065 2.129032258 34.800000000 7.580000000
+5.032258065 2.322580645 34.800000000 7.580000000
+5.032258065 2.516129032 34.800000000 7.580000000
+5.032258065 2.709677419 34.800000000 7.580000000
+5.032258065 2.903225806 34.800000000 7.580000000
+5.032258065 3.096774194 34.800000000 10.000000000
+5.032258065 3.290322581 72.240000000 17.420000000
+5.032258065 3.483870968 72.240000000 17.420000000
+5.032258065 3.677419355 72.240000000 17.420000000
+5.032258065 3.870967742 72.240000000 17.420000000
+5.032258065 4.064516129 72.240000000 17.420000000
+5.032258065 4.258064516 72.240000000 17.420000000
+5.032258065 4.451612903 72.240000000 17.420000000
+5.032258065 4.645161290 72.240000000 17.420000000
+5.032258065 4.838709677 72.240000000 17.420000000
+5.032258065 5.032258065 72.240000000 17.420000000
+5.032258065 5.225806452 72.240000000 17.420000000
+5.032258065 5.419354839 72.240000000 17.420000000
+5.032258065 5.612903226 72.240000000 17.420000000
+5.032258065 5.806451613 72.240000000 17.420000000
+5.032258065 6.000000000 72.240000000 17.420000000
+5.225806452 0.000000000 33.840000000 8.060000000
+5.225806452 0.193548387 33.840000000 8.060000000
+5.225806452 0.387096774 33.840000000 8.060000000
+5.225806452 0.580645161 33.840000000 8.060000000
+5.225806452 0.774193548 33.840000000 8.060000000
+5.225806452 0.967741935 33.840000000 8.060000000
+5.225806452 1.161290323 33.840000000 8.060000000
+5.225806452 1.354838710 33.840000000 8.060000000
+5.225806452 1.548387097 33.840000000 8.060000000
+5.225806452 1.741935484 33.840000000 8.060000000
+5.225806452 1.935483871 33.840000000 8.060000000
+5.225806452 2.129032258 33.840000000 8.060000000
+5.225806452 2.322580645 33.840000000 8.060000000
+5.225806452 2.516129032 33.840000000 8.060000000
+5.225806452 2.709677419 33.840000000 10.000000000
+5.225806452 2.903225806 33.840000000 10.000000000
+5.225806452 3.096774194 33.840000000 10.000000000
+5.225806452 3.290322581 33.840000000 10.000000000
+5.225806452 3.483870968 33.840000000 10.000000000
+5.225806452 3.677419355 70.800000000 16.940000000
+5.225806452 3.870967742 70.800000000 16.940000000
+5.225806452 4.064516129 70.800000000 16.940000000
+5.225806452 4.258064516 70.800000000 16.940000000
+5.225806452 4.451612903 70.800000000 16.940000000
+5.225806452 4.645161290 70.800000000 16.940000000
+5.225806452 4.838709677 70.800000000 16.940000000
+5.225806452 5.032258065 70.800000000 16.940000000
+5.225806452 5.225806452 70.800000000 16.940000000
+5.225806452 5.419354839 70.800000000 16.940000000
+5.225806452 5.612903226 70.800000000 16.940000000
+5.225806452 5.806451613 70.800000000 16.940000000
+5.225806452 6.000000000 70.800000000 16.940000000
+5.419354839 0.000000000 32.880000000 8.540000000
+5.419354839 0.193548387 32.880000000 8.540000000
+5.419354839 0.387096774 32.880000000 8.540000000
+5.419354839 0.580645161 32.880000000 8.540000000
+5.419354839 0.774193548 32.880000000 8.540000000
+5.419354839 0.967741935 32.880000000 8.540000000
+5.419354839 1.161290323 32.880000000 8.540000000
+5.419354839 1.354838710 32.880000000 8.540000000
+5.419354839 1.548387097 32.880000000 8.540000000
+5.419354839 1.741935484 32.880000000 8.540000000
+5.419354839 1.935483871 32.880000000 8.540000000
+5.419354839 2.129032258 32.880000000 8.540000000
+5.419354839 2.322580645 32.880000000 10.000000000
+5.419354839 2.516129032 32.880000000 10.000000000
+5.419354839 2.709677419 32.880000000 10.000000000
+5.419354839 2.903225806 32.880000000 10.000000000
+5.419354839 3.096774194 32.880000000 10.000000000
+5.419354839 3.290322581 32.880000000 10.000000000
+5.419354839 3.483870968 32.880000000 10.000000000
+5.419354839 3.677419355 32.880000000 10.000000000
+5.419354839 3.870967742 32.880000000 10.000000000
+5.419354839 4.064516129 69.360000000 16.460000000
+5.419354839 4.258064516 69.360000000 16.460000000
+5.419354839 4.451612903 69.360000000 16.460000000
+5.419354839 4.645161290 69.360000000 16.460000000
+5.419354839 4.838709677 69.360000000 16.460000000
+5.419354839 5.032258065 69.360000000 16.460000000
+5.419354839 5.225806452 69.360000000 16.460000000
+5.419354839 5.419354839 69.360000000 16.460000000
+5.419354839 5.612903226 69.360000000 16.460000000
+5.419354839 5.806451613 69.360000000 16.460000000
+5.419354839 6.000000000 69.360000000 16.460000000
+5.612903226 0.000000000 31.920000000 9.040000000
+5.612903226 0.193548387 31.920000000 9.040000000
+5.612903226 0.387096774 31.920000000 9.040000000
+5.612903226 0.580645161 31.920000000 9.040000000
+5.612903226 0.774193548 31.920000000 9.040000000
+5.612903226 0.967741935 31.920000000 9.040000000
+5.612903226 1.161290323 31.920000000 9.040000000
+5.612903226 1.354838710 31.920000000 9.040000000
+5.612903226 1.548387097 31.920000000 9.040000000
+5.612903226 1.741935484 31.920000000 9.040000000
+5.612903226 1.935483871 31.920000000 9.040000000
+5.612903226 2.129032258 31.920000000 10.000000000
+5.612903226 2.322580645 31.920000000 10.000000000
+5.612903226 2.516129032 31.920000000 10.000000000
+5.612903226 2.709677419 31.920000000 10.000000000
+5.612903226 2.903225806 31.920000000 10.000000000
+5.612903226 3.096774194 31.920000000 10.000000000
+5.612903226 3.290322581 31.920000000 10.000000000
+5.612903226 3.483870968 31.920000000 10.000000000
+5.612903226 3.677419355 31.920000000 10.000000000
+5.612903226 3.870967742 31.920000000 10.000000000
+5.612903226 4.064516129 31.920000000 10.000000000
+5.612903226 4.258064516 31.920000000 10.000000000
+5.612903226 4.451612903 67.920000000 15.960000000
+5.612903226 4.645161290 67.920000000 15.960000000
+5.612903226 4.838709677 67.920000000 15.960000000
+5.612903226 5.032258065 67.920000000 15.960000000
+5.612903226 5.225806452 67.920000000 15.960000000
+5.612903226 5.419354839 67.920000000 15.960000000
+5.612903226 5.612903226 67.920000000 15.960000000
+5.612903226 5.806451613 67.920000000 15.960000000
+5.612903226 6.000000000 67.920000000 15.960000000
+5.806451613 0.000000000 30.960000000 9.520000000
+5.806451613 0.193548387 30.960000000 9.520000000
+5.806451613 0.387096774 30.960000000 9.520000000
+5.806451613 0.580645161 30.960000000 9.520000000
+5.806451613 0.774193548 30.960000000 9.520000000
+5.806451613 0.967741935 30.960000000 9.520000000
+5.806451613 1.161290323 30.960000000 9.520000000
+5.806451613 1.354838710 30.960000000 9.520000000
+5.806451613 1.548387097 30.960000000 10.000000000
+5.806451613 1.741935484 30.960000000 10.000000000
+5.806451613 1.935483871 30.960000000 10.000000000
+5.806451613 2.129032258 30.960000000 10.000000000
+5.806451613 2.322580645 30.960000000 10.000000000
+5.806451613 2.516129032 30.960000000 10.000000000
+5.806451613 2.709677419 30.960000000 10.000000000
+5.806451613 2.903225806 30.960000000 10.000000000
+5.806451613 3.096774194 30.960000000 10.000000000
+5.806451613 3.290322581 30.960000000 10.000000000
+5.806451613 3.483870968 30.960000000 10.000000000
+5.806451613 3.677419355 30.960000000 10.000000000
+5.806451613 3.870967742 30.960000000 10.000000000
+5.806451613 4.064516129 30.960000000 10.000000000
+5.806451613 4.258064516 30.960000000 10.000000000
+5.806451613 4.451612903 30.960000000 10.000000000
+5.806451613 4.645161290 66.480000000 15.480000000
+5.806451613 4.838709677 66.480000000 15.480000000
+5.806451613 5.032258065 66.480000000 15.480000000
+5.806451613 5.225806452 66.480000000 15.480000000
+5.806451613 5.419354839 66.480000000 15.480000000
+5.806451613 5.612903226 66.480000000 15.480000000
+5.806451613 5.806451613 66.480000000 15.480000000
+5.806451613 6.000000000 66.480000000 15.480000000
+6.000000000 0.000000000 nan nan
+6.000000000 0.193548387 nan nan
+6.000000000 0.387096774 nan nan
+6.000000000 0.580645161 nan nan
+6.000000000 0.774193548 nan nan
+6.000000000 0.967741935 nan nan
+6.000000000 1.161290323 nan nan
+6.000000000 1.354838710 nan nan
+6.000000000 1.548387097 nan nan
+6.000000000 1.741935484 nan nan
+6.000000000 1.935483871 nan nan
+6.000000000 2.129032258 nan nan
+6.000000000 2.322580645 nan nan
+6.000000000 2.516129032 nan nan
+6.000000000 2.709677419 nan nan
+6.000000000 2.903225806 nan nan
+6.000000000 3.096774194 nan nan
+6.000000000 3.290322581 nan nan
+6.000000000 3.483870968 nan nan
+6.000000000 3.677419355 nan nan
+6.000000000 3.870967742 nan nan
+6.000000000 4.064516129 nan nan
+6.000000000 4.258064516 nan nan
+6.000000000 4.451612903 nan nan
+6.000000000 4.645161290 nan nan
+6.000000000 4.838709677 nan nan
+6.000000000 5.032258065 nan nan
+6.000000000 5.225806452 nan nan
+6.000000000 5.419354839 nan nan
+6.000000000 5.612903226 nan nan
+6.000000000 5.806451613 nan nan
+6.000000000 6.000000000 nan nan
diff --git a/examples/mamdani/Laundry.fll b/examples/mamdani/Laundry.fll
index ef6fd44..6abf2df 100644
--- a/examples/mamdani/Laundry.fll
+++ b/examples/mamdani/Laundry.fll
@@ -2,42 +2,45 @@ Engine: Laundry
InputVariable: Load
enabled: true
range: 0.000 6.000
+ lock-range: false
term: small Discrete 0.000 1.000 1.000 1.000 2.000 0.800 5.000 0.000
term: normal Discrete 3.000 0.000 4.000 1.000 6.000 0.000
InputVariable: Dirt
enabled: true
range: 0.000 6.000
+ lock-range: false
term: low Discrete 0.000 1.000 2.000 0.800 5.000 0.000
term: high Discrete 1.000 0.000 2.000 0.200 4.000 0.800 6.000 1.000
OutputVariable: Detergent
enabled: true
range: 0.000 80.000
- accumulation: Maximum
+ lock-range: false
+ aggregation: Maximum
defuzzifier: MeanOfMaximum 500
default: nan
lock-previous: false
- lock-range: false
- term: less Discrete 10.000 0.000 40.000 1.000 50.000 0.000
- term: normal Discrete 40.000 0.000 50.000 1.000 60.000 1.000 80.000 0.000
- term: more Discrete 50.000 0.000 80.000 1.000
+ term: less_than_usual Discrete 10.000 0.000 40.000 1.000 50.000 0.000
+ term: usual Discrete 40.000 0.000 50.000 1.000 60.000 1.000 80.000 0.000
+ term: more_than_usual Discrete 50.000 0.000 80.000 1.000
OutputVariable: Cycle
enabled: true
range: 0.000 20.000
- accumulation: Maximum
+ lock-range: false
+ aggregation: Maximum
defuzzifier: MeanOfMaximum 500
default: nan
lock-previous: false
- lock-range: false
term: short Discrete 0.000 1.000 10.000 1.000 20.000 0.000
term: long Discrete 10.000 0.000 20.000 1.000
RuleBlock:
enabled: true
conjunction: Minimum
disjunction: Maximum
- activation: Minimum
- rule: if Load is small and Dirt is not high then Detergent is less
- rule: if Load is small and Dirt is high then Detergent is normal
- rule: if Load is normal and Dirt is low then Detergent is less
- rule: if Load is normal and Dirt is high then Detergent is more
- rule: if Detergent is normal or Detergent is less then Cycle is short
- rule: if Detergent is more then Cycle is long \ No newline at end of file
+ implication: Minimum
+ activation: General
+ rule: if Load is small and Dirt is not high then Detergent is less_than_usual
+ rule: if Load is small and Dirt is high then Detergent is usual
+ rule: if Load is normal and Dirt is low then Detergent is less_than_usual
+ rule: if Load is normal and Dirt is high then Detergent is more_than_usual
+ rule: if Detergent is usual or Detergent is less_than_usual then Cycle is short
+ rule: if Detergent is more_than_usual then Cycle is long \ No newline at end of file
diff --git a/examples/mamdani/Laundry.java b/examples/mamdani/Laundry.java
index d45e77e..95cbe7c 100644
--- a/examples/mamdani/Laundry.java
+++ b/examples/mamdani/Laundry.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,64 +13,75 @@ import com.fuzzylite.variable.*;
public class Laundry{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
engine.setName("Laundry");
+engine.setDescription("");
-InputVariable inputVariable1 = new InputVariable();
-inputVariable1.setEnabled(true);
-inputVariable1.setName("Load");
-inputVariable1.setRange(0.000, 6.000);
-inputVariable1.addTerm(Discrete.create("small", 0.000, 1.000, 1.000, 1.000, 2.000, 0.800, 5.000, 0.000));
-inputVariable1.addTerm(Discrete.create("normal", 3.000, 0.000, 4.000, 1.000, 6.000, 0.000));
-engine.addInputVariable(inputVariable1);
+InputVariable Load = new InputVariable();
+Load.setName("Load");
+Load.setDescription("");
+Load.setEnabled(true);
+Load.setRange(0.000, 6.000);
+Load.setLockValueInRange(false);
+Load.addTerm(Discrete.create("small", 0.000, 1.000, 1.000, 1.000, 2.000, 0.800, 5.000, 0.000));
+Load.addTerm(Discrete.create("normal", 3.000, 0.000, 4.000, 1.000, 6.000, 0.000));
+engine.addInputVariable(Load);
-InputVariable inputVariable2 = new InputVariable();
-inputVariable2.setEnabled(true);
-inputVariable2.setName("Dirt");
-inputVariable2.setRange(0.000, 6.000);
-inputVariable2.addTerm(Discrete.create("low", 0.000, 1.000, 2.000, 0.800, 5.000, 0.000));
-inputVariable2.addTerm(Discrete.create("high", 1.000, 0.000, 2.000, 0.200, 4.000, 0.800, 6.000, 1.000));
-engine.addInputVariable(inputVariable2);
+InputVariable Dirt = new InputVariable();
+Dirt.setName("Dirt");
+Dirt.setDescription("");
+Dirt.setEnabled(true);
+Dirt.setRange(0.000, 6.000);
+Dirt.setLockValueInRange(false);
+Dirt.addTerm(Discrete.create("low", 0.000, 1.000, 2.000, 0.800, 5.000, 0.000));
+Dirt.addTerm(Discrete.create("high", 1.000, 0.000, 2.000, 0.200, 4.000, 0.800, 6.000, 1.000));
+engine.addInputVariable(Dirt);
-OutputVariable outputVariable1 = new OutputVariable();
-outputVariable1.setEnabled(true);
-outputVariable1.setName("Detergent");
-outputVariable1.setRange(0.000, 80.000);
-outputVariable1.fuzzyOutput().setAccumulation(new Maximum());
-outputVariable1.setDefuzzifier(new MeanOfMaximum(500));
-outputVariable1.setDefaultValue(Double.NaN);
-outputVariable1.setLockPreviousOutputValue(false);
-outputVariable1.setLockOutputValueInRange(false);
-outputVariable1.addTerm(Discrete.create("less", 10.000, 0.000, 40.000, 1.000, 50.000, 0.000));
-outputVariable1.addTerm(Discrete.create("normal", 40.000, 0.000, 50.000, 1.000, 60.000, 1.000, 80.000, 0.000));
-outputVariable1.addTerm(Discrete.create("more", 50.000, 0.000, 80.000, 1.000));
-engine.addOutputVariable(outputVariable1);
+OutputVariable Detergent = new OutputVariable();
+Detergent.setName("Detergent");
+Detergent.setDescription("");
+Detergent.setEnabled(true);
+Detergent.setRange(0.000, 80.000);
+Detergent.setLockValueInRange(false);
+Detergent.setAggregation(new Maximum());
+Detergent.setDefuzzifier(new MeanOfMaximum(500));
+Detergent.setDefaultValue(Double.NaN);
+Detergent.setLockPreviousValue(false);
+Detergent.addTerm(Discrete.create("less_than_usual", 10.000, 0.000, 40.000, 1.000, 50.000, 0.000));
+Detergent.addTerm(Discrete.create("usual", 40.000, 0.000, 50.000, 1.000, 60.000, 1.000, 80.000, 0.000));
+Detergent.addTerm(Discrete.create("more_than_usual", 50.000, 0.000, 80.000, 1.000));
+engine.addOutputVariable(Detergent);
-OutputVariable outputVariable2 = new OutputVariable();
-outputVariable2.setEnabled(true);
-outputVariable2.setName("Cycle");
-outputVariable2.setRange(0.000, 20.000);
-outputVariable2.fuzzyOutput().setAccumulation(new Maximum());
-outputVariable2.setDefuzzifier(new MeanOfMaximum(500));
-outputVariable2.setDefaultValue(Double.NaN);
-outputVariable2.setLockPreviousOutputValue(false);
-outputVariable2.setLockOutputValueInRange(false);
-outputVariable2.addTerm(Discrete.create("short", 0.000, 1.000, 10.000, 1.000, 20.000, 0.000));
-outputVariable2.addTerm(Discrete.create("long", 10.000, 0.000, 20.000, 1.000));
-engine.addOutputVariable(outputVariable2);
+OutputVariable Cycle = new OutputVariable();
+Cycle.setName("Cycle");
+Cycle.setDescription("");
+Cycle.setEnabled(true);
+Cycle.setRange(0.000, 20.000);
+Cycle.setLockValueInRange(false);
+Cycle.setAggregation(new Maximum());
+Cycle.setDefuzzifier(new MeanOfMaximum(500));
+Cycle.setDefaultValue(Double.NaN);
+Cycle.setLockPreviousValue(false);
+Cycle.addTerm(Discrete.create("short", 0.000, 1.000, 10.000, 1.000, 20.000, 0.000));
+Cycle.addTerm(Discrete.create("long", 10.000, 0.000, 20.000, 1.000));
+engine.addOutputVariable(Cycle);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(new Minimum());
ruleBlock.setDisjunction(new Maximum());
-ruleBlock.setActivation(new Minimum());
-ruleBlock.addRule(Rule.parse("if Load is small and Dirt is not high then Detergent is less", engine));
-ruleBlock.addRule(Rule.parse("if Load is small and Dirt is high then Detergent is normal", engine));
-ruleBlock.addRule(Rule.parse("if Load is normal and Dirt is low then Detergent is less", engine));
-ruleBlock.addRule(Rule.parse("if Load is normal and Dirt is high then Detergent is more", engine));
-ruleBlock.addRule(Rule.parse("if Detergent is normal or Detergent is less then Cycle is short", engine));
-ruleBlock.addRule(Rule.parse("if Detergent is more then Cycle is long", engine));
+ruleBlock.setImplication(new Minimum());
+ruleBlock.setActivation(new General());
+ruleBlock.addRule(Rule.parse("if Load is small and Dirt is not high then Detergent is less_than_usual", engine));
+ruleBlock.addRule(Rule.parse("if Load is small and Dirt is high then Detergent is usual", engine));
+ruleBlock.addRule(Rule.parse("if Load is normal and Dirt is low then Detergent is less_than_usual", engine));
+ruleBlock.addRule(Rule.parse("if Load is normal and Dirt is high then Detergent is more_than_usual", engine));
+ruleBlock.addRule(Rule.parse("if Detergent is usual or Detergent is less_than_usual then Cycle is short", engine));
+ruleBlock.addRule(Rule.parse("if Detergent is more_than_usual then Cycle is long", engine));
engine.addRuleBlock(ruleBlock);
diff --git a/examples/mamdani/Laundry.pdf b/examples/mamdani/Laundry.pdf
new file mode 100644
index 0000000..42df3cf
--- /dev/null
+++ b/examples/mamdani/Laundry.pdf
Binary files differ
diff --git a/examples/mamdani/ObstacleAvoidance.R b/examples/mamdani/ObstacleAvoidance.R
new file mode 100644
index 0000000..5533d26
--- /dev/null
+++ b/examples/mamdani/ObstacleAvoidance.R
@@ -0,0 +1,57 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "ObstacleAvoidance"
+engine.fll = "Engine: ObstacleAvoidance
+InputVariable: obstacle
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: mSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 100
+ default: nan
+ lock-previous: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+RuleBlock: mamdani
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: AlgebraicProduct
+ activation: General
+ rule: if obstacle is left then mSteer is right
+ rule: if obstacle is right then mSteer is left"
+
+engine.fldFile = "ObstacleAvoidance.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(obstacle, mSteer)) +
+ geom_line(aes(color=mSteer), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("obstacle vs mSteer")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(obstacle, mSteer)) +
+ geom_line(aes(color=mSteer), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("mSteer vs obstacle")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/mamdani/ObstacleAvoidance.cpp b/examples/mamdani/ObstacleAvoidance.cpp
new file mode 100644
index 0000000..341ffe5
--- /dev/null
+++ b/examples/mamdani/ObstacleAvoidance.cpp
@@ -0,0 +1,49 @@
+#include <fl/Headers.h>
+
+int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
+using namespace fl;
+
+Engine* engine = new Engine;
+engine->setName("ObstacleAvoidance");
+engine->setDescription("");
+
+InputVariable* obstacle = new InputVariable;
+obstacle->setName("obstacle");
+obstacle->setDescription("");
+obstacle->setEnabled(true);
+obstacle->setRange(0.000, 1.000);
+obstacle->setLockValueInRange(false);
+obstacle->addTerm(new Ramp("left", 1.000, 0.000));
+obstacle->addTerm(new Ramp("right", 0.000, 1.000));
+engine->addInputVariable(obstacle);
+
+OutputVariable* mSteer = new OutputVariable;
+mSteer->setName("mSteer");
+mSteer->setDescription("");
+mSteer->setEnabled(true);
+mSteer->setRange(0.000, 1.000);
+mSteer->setLockValueInRange(false);
+mSteer->setAggregation(new Maximum);
+mSteer->setDefuzzifier(new Centroid(100));
+mSteer->setDefaultValue(fl::nan);
+mSteer->setLockPreviousValue(false);
+mSteer->addTerm(new Ramp("left", 1.000, 0.000));
+mSteer->addTerm(new Ramp("right", 0.000, 1.000));
+engine->addOutputVariable(mSteer);
+
+RuleBlock* mamdani = new RuleBlock;
+mamdani->setName("mamdani");
+mamdani->setDescription("");
+mamdani->setEnabled(true);
+mamdani->setConjunction(fl::null);
+mamdani->setDisjunction(fl::null);
+mamdani->setImplication(new AlgebraicProduct);
+mamdani->setActivation(new General);
+mamdani->addRule(Rule::parse("if obstacle is left then mSteer is right", engine));
+mamdani->addRule(Rule::parse("if obstacle is right then mSteer is left", engine));
+engine->addRuleBlock(mamdani);
+
+
+}
diff --git a/examples/mamdani/ObstacleAvoidance.fcl b/examples/mamdani/ObstacleAvoidance.fcl
new file mode 100644
index 0000000..1f2bac0
--- /dev/null
+++ b/examples/mamdani/ObstacleAvoidance.fcl
@@ -0,0 +1,34 @@
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK ObstacleAvoidance
+
+VAR_INPUT
+ obstacle: REAL;
+END_VAR
+
+VAR_OUTPUT
+ mSteer: REAL;
+END_VAR
+
+FUZZIFY obstacle
+ RANGE := (0.000 .. 1.000);
+ TERM left := Ramp 1.000 0.000;
+ TERM right := Ramp 0.000 1.000;
+END_FUZZIFY
+
+DEFUZZIFY mSteer
+ RANGE := (0.000 .. 1.000);
+ TERM left := Ramp 1.000 0.000;
+ TERM right := Ramp 0.000 1.000;
+ METHOD : COG;
+ ACCU : MAX;
+ DEFAULT := nan;
+END_DEFUZZIFY
+
+RULEBLOCK mamdani
+ ACT : PROD;
+ RULE 1 : if obstacle is left then mSteer is right
+ RULE 2 : if obstacle is right then mSteer is left
+END_RULEBLOCK
+
+END_FUNCTION_BLOCK
diff --git a/examples/mamdani/ObstacleAvoidance.fis b/examples/mamdani/ObstacleAvoidance.fis
new file mode 100644
index 0000000..f938ec0
--- /dev/null
+++ b/examples/mamdani/ObstacleAvoidance.fis
@@ -0,0 +1,32 @@
+#Code automatically generated with fuzzylite 6.0.
+
+[System]
+Name='ObstacleAvoidance'
+Type='mamdani'
+Version=6.0
+NumInputs=1
+NumOutputs=1
+NumRules=2
+AndMethod='min'
+OrMethod='max'
+ImpMethod='prod'
+AggMethod='max'
+DefuzzMethod='centroid'
+
+[Input1]
+Name='obstacle'
+Range=[0.000 1.000]
+NumMFs=2
+MF1='left':'rampmf',[1.000 0.000]
+MF2='right':'rampmf',[0.000 1.000]
+
+[Output1]
+Name='mSteer'
+Range=[0.000 1.000]
+NumMFs=2
+MF1='left':'rampmf',[1.000 0.000]
+MF2='right':'rampmf',[0.000 1.000]
+
+[Rules]
+1.000 , 2.000 (1.000) : 1
+2.000 , 1.000 (1.000) : 1
diff --git a/examples/mamdani/ObstacleAvoidance.fld b/examples/mamdani/ObstacleAvoidance.fld
new file mode 100644
index 0000000..ec259dd
--- /dev/null
+++ b/examples/mamdani/ObstacleAvoidance.fld
@@ -0,0 +1,1025 @@
+obstacle mSteer
+0.000000000 0.666650000
+0.000977517 0.666650000
+0.001955034 0.666650000
+0.002932551 0.666650000
+0.003910068 0.666650000
+0.004887586 0.666650000
+0.005865103 0.666638485
+0.006842620 0.666625450
+0.007820137 0.666612389
+0.008797654 0.666599303
+0.009775171 0.666586193
+0.010752688 0.666573056
+0.011730205 0.666559894
+0.012707722 0.666546707
+0.013685239 0.666533494
+0.014662757 0.666520255
+0.015640274 0.666498518
+0.016617791 0.666472271
+0.017595308 0.666445974
+0.018572825 0.666419626
+0.019550342 0.666393229
+0.020527859 0.666366781
+0.021505376 0.666340282
+0.022482893 0.666313732
+0.023460411 0.666287131
+0.024437928 0.666260479
+0.025415445 0.666228313
+0.026392962 0.666188686
+0.027370479 0.666148986
+0.028347996 0.666109209
+0.029325513 0.666069358
+0.030303030 0.666029432
+0.031280547 0.665989429
+0.032258065 0.665949351
+0.033235582 0.665909196
+0.034213099 0.665868966
+0.035190616 0.665826169
+0.036168133 0.665773005
+0.037145650 0.665719742
+0.038123167 0.665666380
+0.039100684 0.665612917
+0.040078201 0.665559355
+0.041055718 0.665505693
+0.042033236 0.665451930
+0.043010753 0.665398066
+0.043988270 0.665344101
+0.044965787 0.665290034
+0.045943304 0.665223628
+0.046920821 0.665156655
+0.047898338 0.665089559
+0.048875855 0.665022339
+0.049853372 0.664954994
+0.050830890 0.664887525
+0.051808407 0.664819932
+0.052785924 0.664752213
+0.053763441 0.664684369
+0.054740958 0.664616398
+0.055718475 0.664539056
+0.056695992 0.664458237
+0.057673509 0.664377270
+0.058651026 0.664296156
+0.059628543 0.664214895
+0.060606061 0.664133485
+0.061583578 0.664051926
+0.062561095 0.663970218
+0.063538612 0.663888361
+0.064516129 0.663806354
+0.065493646 0.663717900
+0.066471163 0.663623109
+0.067448680 0.663528148
+0.068426197 0.663433016
+0.069403715 0.663337714
+0.070381232 0.663242240
+0.071358749 0.663146594
+0.072336266 0.663050776
+0.073313783 0.662954785
+0.074291300 0.662858620
+0.075268817 0.662758885
+0.076246334 0.662650011
+0.077223851 0.662540943
+0.078201369 0.662431683
+0.079178886 0.662322229
+0.080156403 0.662212581
+0.081133920 0.662102739
+0.082111437 0.661992701
+0.083088954 0.661882468
+0.084066471 0.661772039
+0.085043988 0.661660863
+0.086021505 0.661537806
+0.086999022 0.661414534
+0.087976540 0.661291048
+0.088954057 0.661167346
+0.089931574 0.661043428
+0.090909091 0.660919294
+0.091886608 0.660794942
+0.092864125 0.660670373
+0.093841642 0.660545585
+0.094819159 0.660420579
+0.095796676 0.660285492
+0.096774194 0.660147932
+0.097751711 0.660010136
+0.098729228 0.659872104
+0.099706745 0.659733835
+0.100684262 0.659595328
+0.101661779 0.659456582
+0.102639296 0.659317597
+0.103616813 0.659178373
+0.104594330 0.659038909
+0.105571848 0.658892208
+0.106549365 0.658740291
+0.107526882 0.658588119
+0.108504399 0.658435689
+0.109481916 0.658283002
+0.110459433 0.658130057
+0.111436950 0.657976852
+0.112414467 0.657823389
+0.113391984 0.657669665
+0.114369501 0.657515680
+0.115347019 0.657357242
+0.116324536 0.657190916
+0.117302053 0.657024315
+0.118279570 0.656857437
+0.119257087 0.656690282
+0.120234604 0.656522850
+0.121212121 0.656355139
+0.122189638 0.656187149
+0.123167155 0.656018879
+0.124144673 0.655850329
+0.125122190 0.655680041
+0.126099707 0.655499270
+0.127077224 0.655318205
+0.128054741 0.655136845
+0.129032258 0.654955190
+0.130009775 0.654773238
+0.130987292 0.654590990
+0.131964809 0.654408443
+0.132942326 0.654225598
+0.133919844 0.654042454
+0.134897361 0.653859010
+0.135874878 0.653664982
+0.136852395 0.653469436
+0.137829912 0.653273578
+0.138807429 0.653077407
+0.139784946 0.652880922
+0.140762463 0.652684123
+0.141739980 0.652487008
+0.142717498 0.652289577
+0.143695015 0.652091829
+0.144672532 0.651893763
+0.145650049 0.651687855
+0.146627566 0.651477831
+0.147605083 0.651267477
+0.148582600 0.651056794
+0.149560117 0.650845780
+0.150537634 0.650634436
+0.151515152 0.650422759
+0.152492669 0.650210750
+0.153470186 0.649998407
+0.154447703 0.649785731
+0.155425220 0.649567877
+0.156402737 0.649343393
+0.157380254 0.649118566
+0.158357771 0.648893393
+0.159335288 0.648667875
+0.160312805 0.648442011
+0.161290323 0.648215799
+0.162267840 0.647989239
+0.163245357 0.647762331
+0.164222874 0.647535073
+0.165200391 0.647305221
+0.166177908 0.647066320
+0.167155425 0.646827060
+0.168132942 0.646587441
+0.169110459 0.646347463
+0.170087977 0.646107124
+0.171065494 0.645866424
+0.172043011 0.645625361
+0.173020528 0.645383936
+0.173998045 0.645142147
+0.174975562 0.644899993
+0.175953079 0.644647002
+0.176930596 0.644393373
+0.177908113 0.644139372
+0.178885630 0.643884998
+0.179863148 0.643630251
+0.180840665 0.643375130
+0.181818182 0.643119633
+0.182795699 0.642863761
+0.183773216 0.642607513
+0.184750733 0.642350886
+0.185728250 0.642086038
+0.186705767 0.641818123
+0.187683284 0.641549824
+0.188660802 0.641281142
+0.189638319 0.641012074
+0.190615836 0.640742621
+0.191593353 0.640472782
+0.192570870 0.640202555
+0.193548387 0.639931940
+0.194525904 0.639660937
+0.195503421 0.639384233
+0.196480938 0.639102138
+0.197458456 0.638819650
+0.198435973 0.638536767
+0.199413490 0.638253490
+0.200391007 0.637969817
+0.201368524 0.637685747
+0.202346041 0.637401280
+0.203323558 0.637116415
+0.204301075 0.636831150
+0.205278592 0.636542613
+0.206256109 0.636246466
+0.207233627 0.635949918
+0.208211144 0.635652966
+0.209188661 0.635355612
+0.210166178 0.635057853
+0.211143695 0.634759688
+0.212121212 0.634461118
+0.213098729 0.634162142
+0.214076246 0.633862757
+0.215053763 0.633562423
+0.216031281 0.633252376
+0.217008798 0.632941920
+0.217986315 0.632631055
+0.218963832 0.632319779
+0.219941349 0.632008091
+0.220918866 0.631695992
+0.221896383 0.631383479
+0.222873900 0.631070553
+0.223851417 0.630757212
+0.224828935 0.630443455
+0.225806452 0.630121364
+0.226783969 0.629797178
+0.227761486 0.629472576
+0.228739003 0.629147559
+0.229716520 0.628822125
+0.230694037 0.628496272
+0.231671554 0.628170002
+0.232649071 0.627843312
+0.233626588 0.627516202
+0.234604106 0.627188671
+0.235581623 0.626855159
+0.236559140 0.626517443
+0.237536657 0.626179308
+0.238514174 0.625840753
+0.239491691 0.625501777
+0.240469208 0.625162379
+0.241446725 0.624822559
+0.242424242 0.624482316
+0.243401760 0.624141649
+0.244379277 0.623800557
+0.245356794 0.623455725
+0.246334311 0.623104704
+0.247311828 0.622753262
+0.248289345 0.622401397
+0.249266862 0.622049109
+0.250244379 0.621696398
+0.251221896 0.621343261
+0.252199413 0.620989700
+0.253176931 0.620635712
+0.254154448 0.620281297
+0.255131965 0.619925265
+0.256109482 0.619561189
+0.257086999 0.619196691
+0.258064516 0.618831769
+0.259042033 0.618466424
+0.260019550 0.618100655
+0.260997067 0.617734460
+0.261974585 0.617367839
+0.262952102 0.617000791
+0.263929619 0.616633316
+0.264907136 0.616265413
+0.265884653 0.615889366
+0.266862170 0.615512088
+0.267839687 0.615134387
+0.268817204 0.614756264
+0.269794721 0.614377718
+0.270772239 0.613998747
+0.271749756 0.613619351
+0.272727273 0.613239530
+0.273704790 0.612859282
+0.274682307 0.612478608
+0.275659824 0.612091947
+0.276637341 0.611702189
+0.277614858 0.611312012
+0.278592375 0.610921415
+0.279569892 0.610530398
+0.280547410 0.610138959
+0.281524927 0.609747097
+0.282502444 0.609354813
+0.283479961 0.608962106
+0.284457478 0.608568974
+0.285434995 0.608171886
+0.286412512 0.607769974
+0.287390029 0.607367648
+0.288367546 0.606964906
+0.289345064 0.606561748
+0.290322581 0.606158173
+0.291300098 0.605754180
+0.292277615 0.605349770
+0.293255132 0.604944940
+0.294232649 0.604539690
+0.295210166 0.604132380
+0.296187683 0.603718665
+0.297165200 0.603304542
+0.298142717 0.602890009
+0.299120235 0.602475066
+0.300097752 0.602059712
+0.301075269 0.601643947
+0.302052786 0.601227769
+0.303030303 0.600811179
+0.304007820 0.600394176
+0.304985337 0.599976759
+0.305962854 0.599551726
+0.306940371 0.599126182
+0.307917889 0.598700236
+0.308895406 0.598273888
+0.309872923 0.597847137
+0.310850440 0.597419982
+0.311827957 0.596992424
+0.312805474 0.596564460
+0.313782991 0.596136092
+0.314760508 0.595707318
+0.315738025 0.595272860
+0.316715543 0.594836296
+0.317693060 0.594399340
+0.318670577 0.593961991
+0.319648094 0.593524248
+0.320625611 0.593086112
+0.321603128 0.592647581
+0.322580645 0.592208655
+0.323558162 0.591769334
+0.324535679 0.591329617
+0.325513196 0.590886006
+0.326490714 0.590438847
+0.327468231 0.589991307
+0.328445748 0.589543385
+0.329423265 0.589095081
+0.330400782 0.588646394
+0.331378299 0.588197324
+0.332355816 0.587747870
+0.333333333 0.587298033
+0.334310850 0.586847811
+0.335288368 0.586395337
+0.336265885 0.585938031
+0.337243402 0.585480357
+0.338220919 0.585022313
+0.339198436 0.584563900
+0.340175953 0.584105117
+0.341153470 0.583645965
+0.342130987 0.583186441
+0.343108504 0.582726546
+0.344086022 0.582266280
+0.345063539 0.581805253
+0.346041056 0.581338270
+0.347018573 0.580870934
+0.347996090 0.580403243
+0.348973607 0.579935197
+0.349951124 0.579466795
+0.350928641 0.578998038
+0.351906158 0.578528925
+0.352883675 0.578059455
+0.353861193 0.577589628
+0.354838710 0.577119444
+0.355816227 0.576644207
+0.356793744 0.576167703
+0.357771261 0.575690860
+0.358748778 0.575213679
+0.359726295 0.574736158
+0.360703812 0.574258297
+0.361681329 0.573780096
+0.362658847 0.573301554
+0.363636364 0.572822672
+0.364613881 0.572343449
+0.365591398 0.571860698
+0.366568915 0.571375542
+0.367546432 0.570890065
+0.368523949 0.570404267
+0.369501466 0.569918146
+0.370478983 0.569431703
+0.371456500 0.568944938
+0.372434018 0.568457849
+0.373411535 0.567970438
+0.374389052 0.567482703
+0.375366569 0.566992805
+0.376344086 0.566499534
+0.377321603 0.566005960
+0.378299120 0.565512083
+0.379276637 0.565017903
+0.380254154 0.564523420
+0.381231672 0.564028633
+0.382209189 0.563533542
+0.383186706 0.563038147
+0.384164223 0.562542448
+0.385141740 0.562045786
+0.386119257 0.561544954
+0.387096774 0.561043840
+0.388074291 0.560542444
+0.389051808 0.560040764
+0.390029326 0.559538801
+0.391006843 0.559036555
+0.391984360 0.558534026
+0.392961877 0.558031212
+0.393939394 0.557528114
+0.394916911 0.557024732
+0.395894428 0.556517268
+0.396871945 0.556009189
+0.397849462 0.555500848
+0.398826979 0.554992247
+0.399804497 0.554483383
+0.400782014 0.553974258
+0.401759531 0.553464870
+0.402737048 0.552955221
+0.403714565 0.552445308
+0.404692082 0.551935134
+0.405669599 0.551422112
+0.406647116 0.550907660
+0.407624633 0.550392969
+0.408602151 0.549878039
+0.409579668 0.549362870
+0.410557185 0.548847462
+0.411534702 0.548331815
+0.412512219 0.547815928
+0.413489736 0.547299802
+0.414467253 0.546783436
+0.415444770 0.546265287
+0.416422287 0.545745069
+0.417399804 0.545224637
+0.418377322 0.544703989
+0.419354839 0.544183126
+0.420332356 0.543662048
+0.421309873 0.543140754
+0.422287390 0.542619244
+0.423264907 0.542097518
+0.424242424 0.541575577
+0.425219941 0.541052744
+0.426197458 0.540527383
+0.427174976 0.540001832
+0.428152493 0.539476090
+0.429130010 0.538950158
+0.430107527 0.538424035
+0.431085044 0.537897722
+0.432062561 0.537371217
+0.433040078 0.536844521
+0.434017595 0.536317635
+0.434995112 0.535790557
+0.435972630 0.535260701
+0.436950147 0.534730668
+0.437927664 0.534200469
+0.438905181 0.533670106
+0.439882698 0.533139577
+0.440860215 0.532608883
+0.441837732 0.532078024
+0.442815249 0.531546999
+0.443792766 0.531015810
+0.444770283 0.530484454
+0.445747801 0.529951246
+0.446725318 0.529417377
+0.447702835 0.528883370
+0.448680352 0.528349224
+0.449657869 0.527814939
+0.450635386 0.527280516
+0.451612903 0.526745953
+0.452590420 0.526211252
+0.453567937 0.525676412
+0.454545455 0.525141432
+0.455522972 0.524605346
+0.456500489 0.524068300
+0.457478006 0.523531142
+0.458455523 0.522993872
+0.459433040 0.522456490
+0.460410557 0.521918997
+0.461388074 0.521381392
+0.462365591 0.520843675
+0.463343109 0.520305846
+0.464320626 0.519767905
+0.465298143 0.519229421
+0.466275660 0.518689863
+0.467253177 0.518150220
+0.468230694 0.517610493
+0.469208211 0.517070682
+0.470185728 0.516530787
+0.471163245 0.515990807
+0.472140762 0.515450743
+0.473118280 0.514910594
+0.474095797 0.514370361
+0.475073314 0.513829968
+0.476050831 0.513288569
+0.477028348 0.512747115
+0.478005865 0.512205604
+0.478983382 0.511664036
+0.479960899 0.511122412
+0.480938416 0.510580732
+0.481915934 0.510038995
+0.482893451 0.509497202
+0.483870968 0.508955352
+0.484848485 0.508413446
+0.485826002 0.507870980
+0.486803519 0.507328390
+0.487781036 0.506785773
+0.488758553 0.506243127
+0.489736070 0.505700453
+0.490713587 0.505157751
+0.491691105 0.504615020
+0.492668622 0.504072261
+0.493646139 0.503529474
+0.494623656 0.502986658
+0.495601173 0.502443695
+0.496578690 0.501900652
+0.497556207 0.501357608
+0.498533724 0.500814565
+0.499511241 0.500271522
+0.500488759 0.499728478
+0.501466276 0.499185435
+0.502443793 0.498642392
+0.503421310 0.498099348
+0.504398827 0.497556305
+0.505376344 0.497013342
+0.506353861 0.496470526
+0.507331378 0.495927739
+0.508308895 0.495384980
+0.509286413 0.494842249
+0.510263930 0.494299547
+0.511241447 0.493756873
+0.512218964 0.493214227
+0.513196481 0.492671610
+0.514173998 0.492129020
+0.515151515 0.491586554
+0.516129032 0.491044648
+0.517106549 0.490502798
+0.518084066 0.489961005
+0.519061584 0.489419268
+0.520039101 0.488877588
+0.521016618 0.488335964
+0.521994135 0.487794396
+0.522971652 0.487252885
+0.523949169 0.486711431
+0.524926686 0.486170032
+0.525904203 0.485629639
+0.526881720 0.485089406
+0.527859238 0.484549257
+0.528836755 0.484009193
+0.529814272 0.483469213
+0.530791789 0.482929318
+0.531769306 0.482389507
+0.532746823 0.481849780
+0.533724340 0.481310137
+0.534701857 0.480770579
+0.535679374 0.480232095
+0.536656891 0.479694154
+0.537634409 0.479156325
+0.538611926 0.478618608
+0.539589443 0.478081003
+0.540566960 0.477543510
+0.541544477 0.477006128
+0.542521994 0.476468858
+0.543499511 0.475931700
+0.544477028 0.475394654
+0.545454545 0.474858568
+0.546432063 0.474323588
+0.547409580 0.473788748
+0.548387097 0.473254047
+0.549364614 0.472719484
+0.550342131 0.472185061
+0.551319648 0.471650776
+0.552297165 0.471116630
+0.553274682 0.470582623
+0.554252199 0.470048754
+0.555229717 0.469515546
+0.556207234 0.468984190
+0.557184751 0.468453001
+0.558162268 0.467921976
+0.559139785 0.467391117
+0.560117302 0.466860423
+0.561094819 0.466329894
+0.562072336 0.465799531
+0.563049853 0.465269332
+0.564027370 0.464739299
+0.565004888 0.464209443
+0.565982405 0.463682365
+0.566959922 0.463155479
+0.567937439 0.462628783
+0.568914956 0.462102278
+0.569892473 0.461575965
+0.570869990 0.461049842
+0.571847507 0.460523910
+0.572825024 0.459998168
+0.573802542 0.459472617
+0.574780059 0.458947256
+0.575757576 0.458424423
+0.576735093 0.457902482
+0.577712610 0.457380756
+0.578690127 0.456859246
+0.579667644 0.456337952
+0.580645161 0.455816874
+0.581622678 0.455296011
+0.582600196 0.454775363
+0.583577713 0.454254931
+0.584555230 0.453734713
+0.585532747 0.453216564
+0.586510264 0.452700198
+0.587487781 0.452184072
+0.588465298 0.451668185
+0.589442815 0.451152538
+0.590420332 0.450637130
+0.591397849 0.450121961
+0.592375367 0.449607031
+0.593352884 0.449092340
+0.594330401 0.448577888
+0.595307918 0.448064866
+0.596285435 0.447554692
+0.597262952 0.447044779
+0.598240469 0.446535130
+0.599217986 0.446025742
+0.600195503 0.445516617
+0.601173021 0.445007753
+0.602150538 0.444499152
+0.603128055 0.443990811
+0.604105572 0.443482732
+0.605083089 0.442975268
+0.606060606 0.442471886
+0.607038123 0.441968788
+0.608015640 0.441465974
+0.608993157 0.440963445
+0.609970674 0.440461199
+0.610948192 0.439959236
+0.611925709 0.439457556
+0.612903226 0.438956160
+0.613880743 0.438455046
+0.614858260 0.437954214
+0.615835777 0.437457552
+0.616813294 0.436961853
+0.617790811 0.436466458
+0.618768328 0.435971367
+0.619745846 0.435476580
+0.620723363 0.434982097
+0.621700880 0.434487917
+0.622678397 0.433994040
+0.623655914 0.433500466
+0.624633431 0.433007195
+0.625610948 0.432517297
+0.626588465 0.432029562
+0.627565982 0.431542151
+0.628543500 0.431055062
+0.629521017 0.430568297
+0.630498534 0.430081854
+0.631476051 0.429595733
+0.632453568 0.429109935
+0.633431085 0.428624458
+0.634408602 0.428139302
+0.635386119 0.427656551
+0.636363636 0.427177328
+0.637341153 0.426698446
+0.638318671 0.426219904
+0.639296188 0.425741703
+0.640273705 0.425263842
+0.641251222 0.424786321
+0.642228739 0.424309140
+0.643206256 0.423832297
+0.644183773 0.423355793
+0.645161290 0.422880556
+0.646138807 0.422410372
+0.647116325 0.421940545
+0.648093842 0.421471075
+0.649071359 0.421001962
+0.650048876 0.420533205
+0.651026393 0.420064803
+0.652003910 0.419596757
+0.652981427 0.419129066
+0.653958944 0.418661730
+0.654936461 0.418194747
+0.655913978 0.417733720
+0.656891496 0.417273454
+0.657869013 0.416813559
+0.658846530 0.416354035
+0.659824047 0.415894883
+0.660801564 0.415436100
+0.661779081 0.414977687
+0.662756598 0.414519643
+0.663734115 0.414061969
+0.664711632 0.413604663
+0.665689150 0.413152189
+0.666666667 0.412701967
+0.667644184 0.412252130
+0.668621701 0.411802676
+0.669599218 0.411353606
+0.670576735 0.410904919
+0.671554252 0.410456615
+0.672531769 0.410008693
+0.673509286 0.409561153
+0.674486804 0.409113994
+0.675464321 0.408670383
+0.676441838 0.408230666
+0.677419355 0.407791345
+0.678396872 0.407352419
+0.679374389 0.406913888
+0.680351906 0.406475752
+0.681329423 0.406038009
+0.682306940 0.405600660
+0.683284457 0.405163704
+0.684261975 0.404727140
+0.685239492 0.404292682
+0.686217009 0.403863908
+0.687194526 0.403435540
+0.688172043 0.403007576
+0.689149560 0.402580018
+0.690127077 0.402152863
+0.691104594 0.401726112
+0.692082111 0.401299764
+0.693059629 0.400873818
+0.694037146 0.400448274
+0.695014663 0.400023241
+0.695992180 0.399605824
+0.696969697 0.399188821
+0.697947214 0.398772231
+0.698924731 0.398356053
+0.699902248 0.397940288
+0.700879765 0.397524934
+0.701857283 0.397109991
+0.702834800 0.396695458
+0.703812317 0.396281335
+0.704789834 0.395867620
+0.705767351 0.395460310
+0.706744868 0.395055060
+0.707722385 0.394650230
+0.708699902 0.394245820
+0.709677419 0.393841827
+0.710654936 0.393438252
+0.711632454 0.393035094
+0.712609971 0.392632352
+0.713587488 0.392230026
+0.714565005 0.391828114
+0.715542522 0.391431026
+0.716520039 0.391037894
+0.717497556 0.390645187
+0.718475073 0.390252903
+0.719452590 0.389861041
+0.720430108 0.389469602
+0.721407625 0.389078585
+0.722385142 0.388687988
+0.723362659 0.388297811
+0.724340176 0.387908053
+0.725317693 0.387521392
+0.726295210 0.387140718
+0.727272727 0.386760470
+0.728250244 0.386380649
+0.729227761 0.386001253
+0.730205279 0.385622282
+0.731182796 0.385243736
+0.732160313 0.384865613
+0.733137830 0.384487912
+0.734115347 0.384110634
+0.735092864 0.383734587
+0.736070381 0.383366684
+0.737047898 0.382999209
+0.738025415 0.382632161
+0.739002933 0.382265540
+0.739980450 0.381899345
+0.740957967 0.381533576
+0.741935484 0.381168231
+0.742913001 0.380803309
+0.743890518 0.380438811
+0.744868035 0.380074735
+0.745845552 0.379718703
+0.746823069 0.379364288
+0.747800587 0.379010300
+0.748778104 0.378656739
+0.749755621 0.378303602
+0.750733138 0.377950891
+0.751710655 0.377598603
+0.752688172 0.377246738
+0.753665689 0.376895296
+0.754643206 0.376544275
+0.755620723 0.376199443
+0.756598240 0.375858351
+0.757575758 0.375517684
+0.758553275 0.375177441
+0.759530792 0.374837621
+0.760508309 0.374498223
+0.761485826 0.374159247
+0.762463343 0.373820692
+0.763440860 0.373482557
+0.764418377 0.373144841
+0.765395894 0.372811329
+0.766373412 0.372483798
+0.767350929 0.372156688
+0.768328446 0.371829998
+0.769305963 0.371503728
+0.770283480 0.371177875
+0.771260997 0.370852441
+0.772238514 0.370527424
+0.773216031 0.370202822
+0.774193548 0.369878636
+0.775171065 0.369556545
+0.776148583 0.369242788
+0.777126100 0.368929447
+0.778103617 0.368616521
+0.779081134 0.368304008
+0.780058651 0.367991909
+0.781036168 0.367680221
+0.782013685 0.367368945
+0.782991202 0.367058080
+0.783968719 0.366747624
+0.784946237 0.366437577
+0.785923754 0.366137243
+0.786901271 0.365837858
+0.787878788 0.365538882
+0.788856305 0.365240312
+0.789833822 0.364942147
+0.790811339 0.364644388
+0.791788856 0.364347034
+0.792766373 0.364050082
+0.793743891 0.363753534
+0.794721408 0.363457387
+0.795698925 0.363168850
+0.796676442 0.362883585
+0.797653959 0.362598720
+0.798631476 0.362314253
+0.799608993 0.362030183
+0.800586510 0.361746510
+0.801564027 0.361463233
+0.802541544 0.361180350
+0.803519062 0.360897862
+0.804496579 0.360615767
+0.805474096 0.360339063
+0.806451613 0.360068060
+0.807429130 0.359797445
+0.808406647 0.359527218
+0.809384164 0.359257379
+0.810361681 0.358987926
+0.811339198 0.358718858
+0.812316716 0.358450176
+0.813294233 0.358181877
+0.814271750 0.357913962
+0.815249267 0.357649114
+0.816226784 0.357392487
+0.817204301 0.357136239
+0.818181818 0.356880367
+0.819159335 0.356624870
+0.820136852 0.356369749
+0.821114370 0.356115002
+0.822091887 0.355860628
+0.823069404 0.355606627
+0.824046921 0.355352998
+0.825024438 0.355100007
+0.826001955 0.354857853
+0.826979472 0.354616064
+0.827956989 0.354374639
+0.828934506 0.354133576
+0.829912023 0.353892876
+0.830889541 0.353652537
+0.831867058 0.353412559
+0.832844575 0.353172940
+0.833822092 0.352933680
+0.834799609 0.352694779
+0.835777126 0.352464927
+0.836754643 0.352237669
+0.837732160 0.352010761
+0.838709677 0.351784201
+0.839687195 0.351557989
+0.840664712 0.351332125
+0.841642229 0.351106607
+0.842619746 0.350881434
+0.843597263 0.350656607
+0.844574780 0.350432123
+0.845552297 0.350214269
+0.846529814 0.350001593
+0.847507331 0.349789250
+0.848484848 0.349577241
+0.849462366 0.349365564
+0.850439883 0.349154220
+0.851417400 0.348943206
+0.852394917 0.348732523
+0.853372434 0.348522169
+0.854349951 0.348312145
+0.855327468 0.348106237
+0.856304985 0.347908171
+0.857282502 0.347710423
+0.858260020 0.347512992
+0.859237537 0.347315877
+0.860215054 0.347119078
+0.861192571 0.346922593
+0.862170088 0.346726422
+0.863147605 0.346530564
+0.864125122 0.346335018
+0.865102639 0.346140990
+0.866080156 0.345957546
+0.867057674 0.345774402
+0.868035191 0.345591557
+0.869012708 0.345409010
+0.869990225 0.345226762
+0.870967742 0.345044810
+0.871945259 0.344863155
+0.872922776 0.344681795
+0.873900293 0.344500730
+0.874877810 0.344319959
+0.875855327 0.344149671
+0.876832845 0.343981121
+0.877810362 0.343812851
+0.878787879 0.343644861
+0.879765396 0.343477150
+0.880742913 0.343309718
+0.881720430 0.343142563
+0.882697947 0.342975685
+0.883675464 0.342809084
+0.884652981 0.342642758
+0.885630499 0.342484320
+0.886608016 0.342330335
+0.887585533 0.342176611
+0.888563050 0.342023148
+0.889540567 0.341869943
+0.890518084 0.341716998
+0.891495601 0.341564311
+0.892473118 0.341411881
+0.893450635 0.341259709
+0.894428152 0.341107792
+0.895405670 0.340961091
+0.896383187 0.340821627
+0.897360704 0.340682403
+0.898338221 0.340543418
+0.899315738 0.340404672
+0.900293255 0.340266165
+0.901270772 0.340127896
+0.902248289 0.339989864
+0.903225806 0.339852068
+0.904203324 0.339714508
+0.905180841 0.339579421
+0.906158358 0.339454415
+0.907135875 0.339329627
+0.908113392 0.339205058
+0.909090909 0.339080706
+0.910068426 0.338956572
+0.911045943 0.338832654
+0.912023460 0.338708952
+0.913000978 0.338585466
+0.913978495 0.338462194
+0.914956012 0.338339137
+0.915933529 0.338227961
+0.916911046 0.338117532
+0.917888563 0.338007299
+0.918866080 0.337897261
+0.919843597 0.337787419
+0.920821114 0.337677771
+0.921798631 0.337568317
+0.922776149 0.337459057
+0.923753666 0.337349989
+0.924731183 0.337241115
+0.925708700 0.337141380
+0.926686217 0.337045215
+0.927663734 0.336949224
+0.928641251 0.336853406
+0.929618768 0.336757760
+0.930596285 0.336662286
+0.931573803 0.336566984
+0.932551320 0.336471852
+0.933528837 0.336376891
+0.934506354 0.336282100
+0.935483871 0.336193646
+0.936461388 0.336111639
+0.937438905 0.336029782
+0.938416422 0.335948074
+0.939393939 0.335866515
+0.940371457 0.335785105
+0.941348974 0.335703844
+0.942326491 0.335622730
+0.943304008 0.335541763
+0.944281525 0.335460944
+0.945259042 0.335383602
+0.946236559 0.335315631
+0.947214076 0.335247787
+0.948191593 0.335180068
+0.949169110 0.335112475
+0.950146628 0.335045006
+0.951124145 0.334977661
+0.952101662 0.334910441
+0.953079179 0.334843345
+0.954056696 0.334776372
+0.955034213 0.334709966
+0.956011730 0.334655899
+0.956989247 0.334601934
+0.957966764 0.334548070
+0.958944282 0.334494307
+0.959921799 0.334440645
+0.960899316 0.334387083
+0.961876833 0.334333620
+0.962854350 0.334280258
+0.963831867 0.334226995
+0.964809384 0.334173831
+0.965786901 0.334131034
+0.966764418 0.334090804
+0.967741935 0.334050649
+0.968719453 0.334010571
+0.969696970 0.333970568
+0.970674487 0.333930642
+0.971652004 0.333890791
+0.972629521 0.333851014
+0.973607038 0.333811314
+0.974584555 0.333771687
+0.975562072 0.333739521
+0.976539589 0.333712869
+0.977517107 0.333686268
+0.978494624 0.333659718
+0.979472141 0.333633219
+0.980449658 0.333606771
+0.981427175 0.333580374
+0.982404692 0.333554026
+0.983382209 0.333527729
+0.984359726 0.333501482
+0.985337243 0.333479745
+0.986314761 0.333466506
+0.987292278 0.333453293
+0.988269795 0.333440106
+0.989247312 0.333426944
+0.990224829 0.333413807
+0.991202346 0.333400697
+0.992179863 0.333387611
+0.993157380 0.333374550
+0.994134897 0.333361515
+0.995112414 0.333350000
+0.996089932 0.333350000
+0.997067449 0.333350000
+0.998044966 0.333350000
+0.999022483 0.333350000
+1.000000000 0.333350000
diff --git a/examples/mamdani/ObstacleAvoidance.fll b/examples/mamdani/ObstacleAvoidance.fll
new file mode 100644
index 0000000..a47f1b4
--- /dev/null
+++ b/examples/mamdani/ObstacleAvoidance.fll
@@ -0,0 +1,25 @@
+Engine: ObstacleAvoidance
+InputVariable: obstacle
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: mSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 100
+ default: nan
+ lock-previous: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+RuleBlock: mamdani
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: AlgebraicProduct
+ activation: General
+ rule: if obstacle is left then mSteer is right
+ rule: if obstacle is right then mSteer is left \ No newline at end of file
diff --git a/examples/mamdani/ObstacleAvoidance.java b/examples/mamdani/ObstacleAvoidance.java
new file mode 100644
index 0000000..8efef3b
--- /dev/null
+++ b/examples/mamdani/ObstacleAvoidance.java
@@ -0,0 +1,60 @@
+import com.fuzzylite.*;
+import com.fuzzylite.activation.*
+import com.fuzzylite.defuzzifier.*;
+import com.fuzzylite.factory.*;
+import com.fuzzylite.hedge.*;
+import com.fuzzylite.imex.*;
+import com.fuzzylite.norm.*;
+import com.fuzzylite.norm.s.*;
+import com.fuzzylite.norm.t.*;
+import com.fuzzylite.rule.*;
+import com.fuzzylite.term.*;
+import com.fuzzylite.variable.*;
+
+public class ObstacleAvoidance{
+public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
+Engine engine = new Engine();
+engine.setName("ObstacleAvoidance");
+engine.setDescription("");
+
+InputVariable obstacle = new InputVariable();
+obstacle.setName("obstacle");
+obstacle.setDescription("");
+obstacle.setEnabled(true);
+obstacle.setRange(0.000, 1.000);
+obstacle.setLockValueInRange(false);
+obstacle.addTerm(new Ramp("left", 1.000, 0.000));
+obstacle.addTerm(new Ramp("right", 0.000, 1.000));
+engine.addInputVariable(obstacle);
+
+OutputVariable mSteer = new OutputVariable();
+mSteer.setName("mSteer");
+mSteer.setDescription("");
+mSteer.setEnabled(true);
+mSteer.setRange(0.000, 1.000);
+mSteer.setLockValueInRange(false);
+mSteer.setAggregation(new Maximum());
+mSteer.setDefuzzifier(new Centroid(100));
+mSteer.setDefaultValue(Double.NaN);
+mSteer.setLockPreviousValue(false);
+mSteer.addTerm(new Ramp("left", 1.000, 0.000));
+mSteer.addTerm(new Ramp("right", 0.000, 1.000));
+engine.addOutputVariable(mSteer);
+
+RuleBlock mamdani = new RuleBlock();
+mamdani.setName("mamdani");
+mamdani.setDescription("");
+mamdani.setEnabled(true);
+mamdani.setConjunction(null);
+mamdani.setDisjunction(null);
+mamdani.setImplication(new AlgebraicProduct());
+mamdani.setActivation(new General());
+mamdani.addRule(Rule.parse("if obstacle is left then mSteer is right", engine));
+mamdani.addRule(Rule.parse("if obstacle is right then mSteer is left", engine));
+engine.addRuleBlock(mamdani);
+
+
+}
+}
diff --git a/examples/mamdani/ObstacleAvoidance.pdf b/examples/mamdani/ObstacleAvoidance.pdf
new file mode 100644
index 0000000..63e1fe9
--- /dev/null
+++ b/examples/mamdani/ObstacleAvoidance.pdf
Binary files differ
diff --git a/examples/mamdani/SimpleDimmer.R b/examples/mamdani/SimpleDimmer.R
new file mode 100644
index 0000000..77a60f3
--- /dev/null
+++ b/examples/mamdani/SimpleDimmer.R
@@ -0,0 +1,60 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "SimpleDimmer"
+engine.fll = "Engine: SimpleDimmer
+InputVariable: Ambient
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: DARK Triangle 0.000 0.250 0.500
+ term: MEDIUM Triangle 0.250 0.500 0.750
+ term: BRIGHT Triangle 0.500 0.750 1.000
+OutputVariable: Power
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: LOW Triangle 0.000 0.250 0.500
+ term: MEDIUM Triangle 0.250 0.500 0.750
+ term: HIGH Triangle 0.500 0.750 1.000
+RuleBlock:
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: Minimum
+ activation: General
+ rule: if Ambient is DARK then Power is HIGH
+ rule: if Ambient is MEDIUM then Power is MEDIUM
+ rule: if Ambient is BRIGHT then Power is LOW"
+
+engine.fldFile = "SimpleDimmer.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(Ambient, Power)) +
+ geom_line(aes(color=Power), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("Ambient vs Power")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(Ambient, Power)) +
+ geom_line(aes(color=Power), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("Power vs Ambient")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/mamdani/SimpleDimmer.cpp b/examples/mamdani/SimpleDimmer.cpp
index b4c6897..7cd5e73 100644
--- a/examples/mamdani/SimpleDimmer.cpp
+++ b/examples/mamdani/SimpleDimmer.cpp
@@ -1,43 +1,51 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("simple-dimmer");
-
-InputVariable* inputVariable = new InputVariable;
-inputVariable->setEnabled(true);
-inputVariable->setName("Ambient");
-inputVariable->setRange(0.000, 1.000);
-inputVariable->addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
-inputVariable->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-inputVariable->addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
-engine->addInputVariable(inputVariable);
-
-OutputVariable* outputVariable = new OutputVariable;
-outputVariable->setEnabled(true);
-outputVariable->setName("Power");
-outputVariable->setRange(0.000, 1.000);
-outputVariable->fuzzyOutput()->setAccumulation(new Maximum);
-outputVariable->setDefuzzifier(new Centroid(200));
-outputVariable->setDefaultValue(fl::nan);
-outputVariable->setLockPreviousOutputValue(false);
-outputVariable->setLockOutputValueInRange(false);
-outputVariable->addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
-outputVariable->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-outputVariable->addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
-engine->addOutputVariable(outputVariable);
+engine->setName("SimpleDimmer");
+engine->setDescription("");
+
+InputVariable* Ambient = new InputVariable;
+Ambient->setName("Ambient");
+Ambient->setDescription("");
+Ambient->setEnabled(true);
+Ambient->setRange(0.000, 1.000);
+Ambient->setLockValueInRange(false);
+Ambient->addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+Ambient->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Ambient->addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+engine->addInputVariable(Ambient);
+
+OutputVariable* Power = new OutputVariable;
+Power->setName("Power");
+Power->setDescription("");
+Power->setEnabled(true);
+Power->setRange(0.000, 1.000);
+Power->setLockValueInRange(false);
+Power->setAggregation(new Maximum);
+Power->setDefuzzifier(new Centroid(200));
+Power->setDefaultValue(fl::nan);
+Power->setLockPreviousValue(false);
+Power->addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
+Power->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Power->addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
+engine->addOutputVariable(Power);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(fl::null);
ruleBlock->setDisjunction(fl::null);
-ruleBlock->setActivation(new Minimum);
-ruleBlock->addRule(fl::Rule::parse("if Ambient is DARK then Power is HIGH", engine));
-ruleBlock->addRule(fl::Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
-ruleBlock->addRule(fl::Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
+ruleBlock->setImplication(new Minimum);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if Ambient is DARK then Power is HIGH", engine));
+ruleBlock->addRule(Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
+ruleBlock->addRule(Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/mamdani/SimpleDimmer.fcl b/examples/mamdani/SimpleDimmer.fcl
index a9b9552..104990a 100644
--- a/examples/mamdani/SimpleDimmer.fcl
+++ b/examples/mamdani/SimpleDimmer.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK simple-dimmer
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK SimpleDimmer
VAR_INPUT
Ambient: REAL;
diff --git a/examples/mamdani/SimpleDimmer.fis b/examples/mamdani/SimpleDimmer.fis
index 40ac849..3435060 100644
--- a/examples/mamdani/SimpleDimmer.fis
+++ b/examples/mamdani/SimpleDimmer.fis
@@ -1,11 +1,14 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='simple-dimmer'
+Name='SimpleDimmer'
Type='mamdani'
+Version=6.0
NumInputs=1
NumOutputs=1
NumRules=3
-AndMethod=''
-OrMethod=''
+AndMethod='min'
+OrMethod='max'
ImpMethod='min'
AggMethod='max'
DefuzzMethod='centroid'
diff --git a/examples/mamdani/SimpleDimmer.fld b/examples/mamdani/SimpleDimmer.fld
index 4d9a671..bd4dc51 100644
--- a/examples/mamdani/SimpleDimmer.fld
+++ b/examples/mamdani/SimpleDimmer.fld
@@ -1,1026 +1,1025 @@
-#@Engine: simple-dimmer;
-#@InputVariable: Ambient; @OutputVariable: Power;
-0.00000000 nan
-0.00097752 0.75000000
-0.00195503 0.75000000
-0.00293255 0.75000000
-0.00391007 0.75000000
-0.00488759 0.75000000
-0.00586510 0.75000000
-0.00684262 0.75000000
-0.00782014 0.75000000
-0.00879765 0.75000000
-0.00977517 0.75000000
-0.01075269 0.75000000
-0.01173021 0.75000000
-0.01270772 0.75000000
-0.01368524 0.75000000
-0.01466276 0.75000000
-0.01564027 0.75000000
-0.01661779 0.75000000
-0.01759531 0.75000000
-0.01857283 0.75000000
-0.01955034 0.75000000
-0.02052786 0.75000000
-0.02150538 0.75000000
-0.02248289 0.75000000
-0.02346041 0.75000000
-0.02443793 0.75000000
-0.02541544 0.75000000
-0.02639296 0.75000000
-0.02737048 0.75000000
-0.02834800 0.75000000
-0.02932551 0.75000000
-0.03030303 0.75000000
-0.03128055 0.75000000
-0.03225806 0.75000000
-0.03323558 0.75000000
-0.03421310 0.75000000
-0.03519062 0.75000000
-0.03616813 0.75000000
-0.03714565 0.75000000
-0.03812317 0.75000000
-0.03910068 0.75000000
-0.04007820 0.75000000
-0.04105572 0.75000000
-0.04203324 0.75000000
-0.04301075 0.75000000
-0.04398827 0.75000000
-0.04496579 0.75000000
-0.04594330 0.75000000
-0.04692082 0.75000000
-0.04789834 0.75000000
-0.04887586 0.75000000
-0.04985337 0.75000000
-0.05083089 0.75000000
-0.05180841 0.75000000
-0.05278592 0.75000000
-0.05376344 0.75000000
-0.05474096 0.75000000
-0.05571848 0.75000000
-0.05669599 0.75000000
-0.05767351 0.75000000
-0.05865103 0.75000000
-0.05962854 0.75000000
-0.06060606 0.75000000
-0.06158358 0.75000000
-0.06256109 0.75000000
-0.06353861 0.75000000
-0.06451613 0.75000000
-0.06549365 0.75000000
-0.06647116 0.75000000
-0.06744868 0.75000000
-0.06842620 0.75000000
-0.06940371 0.75000000
-0.07038123 0.75000000
-0.07135875 0.75000000
-0.07233627 0.75000000
-0.07331378 0.75000000
-0.07429130 0.75000000
-0.07526882 0.75000000
-0.07624633 0.75000000
-0.07722385 0.75000000
-0.07820137 0.75000000
-0.07917889 0.75000000
-0.08015640 0.75000000
-0.08113392 0.75000000
-0.08211144 0.75000000
-0.08308895 0.75000000
-0.08406647 0.75000000
-0.08504399 0.75000000
-0.08602151 0.75000000
-0.08699902 0.75000000
-0.08797654 0.75000000
-0.08895406 0.75000000
-0.08993157 0.75000000
-0.09090909 0.75000000
-0.09188661 0.75000000
-0.09286413 0.75000000
-0.09384164 0.75000000
-0.09481916 0.75000000
-0.09579668 0.75000000
-0.09677419 0.75000000
-0.09775171 0.75000000
-0.09872923 0.75000000
-0.09970674 0.75000000
-0.10068426 0.75000000
-0.10166178 0.75000000
-0.10263930 0.75000000
-0.10361681 0.75000000
-0.10459433 0.75000000
-0.10557185 0.75000000
-0.10654936 0.75000000
-0.10752688 0.75000000
-0.10850440 0.75000000
-0.10948192 0.75000000
-0.11045943 0.75000000
-0.11143695 0.75000000
-0.11241447 0.75000000
-0.11339198 0.75000000
-0.11436950 0.75000000
-0.11534702 0.75000000
-0.11632454 0.75000000
-0.11730205 0.75000000
-0.11827957 0.75000000
-0.11925709 0.75000000
-0.12023460 0.75000000
-0.12121212 0.75000000
-0.12218964 0.75000000
-0.12316716 0.75000000
-0.12414467 0.75000000
-0.12512219 0.75000000
-0.12609971 0.75000000
-0.12707722 0.75000000
-0.12805474 0.75000000
-0.12903226 0.75000000
-0.13000978 0.75000000
-0.13098729 0.75000000
-0.13196481 0.75000000
-0.13294233 0.75000000
-0.13391984 0.75000000
-0.13489736 0.75000000
-0.13587488 0.75000000
-0.13685239 0.75000000
-0.13782991 0.75000000
-0.13880743 0.75000000
-0.13978495 0.75000000
-0.14076246 0.75000000
-0.14173998 0.75000000
-0.14271750 0.75000000
-0.14369501 0.75000000
-0.14467253 0.75000000
-0.14565005 0.75000000
-0.14662757 0.75000000
-0.14760508 0.75000000
-0.14858260 0.75000000
-0.14956012 0.75000000
-0.15053763 0.75000000
-0.15151515 0.75000000
-0.15249267 0.75000000
-0.15347019 0.75000000
-0.15444770 0.75000000
-0.15542522 0.75000000
-0.15640274 0.75000000
-0.15738025 0.75000000
-0.15835777 0.75000000
-0.15933529 0.75000000
-0.16031281 0.75000000
-0.16129032 0.75000000
-0.16226784 0.75000000
-0.16324536 0.75000000
-0.16422287 0.75000000
-0.16520039 0.75000000
-0.16617791 0.75000000
-0.16715543 0.75000000
-0.16813294 0.75000000
-0.16911046 0.75000000
-0.17008798 0.75000000
-0.17106549 0.75000000
-0.17204301 0.75000000
-0.17302053 0.75000000
-0.17399804 0.75000000
-0.17497556 0.75000000
-0.17595308 0.75000000
-0.17693060 0.75000000
-0.17790811 0.75000000
-0.17888563 0.75000000
-0.17986315 0.75000000
-0.18084066 0.75000000
-0.18181818 0.75000000
-0.18279570 0.75000000
-0.18377322 0.75000000
-0.18475073 0.75000000
-0.18572825 0.75000000
-0.18670577 0.75000000
-0.18768328 0.75000000
-0.18866080 0.75000000
-0.18963832 0.75000000
-0.19061584 0.75000000
-0.19159335 0.75000000
-0.19257087 0.75000000
-0.19354839 0.75000000
-0.19452590 0.75000000
-0.19550342 0.75000000
-0.19648094 0.75000000
-0.19745846 0.75000000
-0.19843597 0.75000000
-0.19941349 0.75000000
-0.20039101 0.75000000
-0.20136852 0.75000000
-0.20234604 0.75000000
-0.20332356 0.75000000
-0.20430108 0.75000000
-0.20527859 0.75000000
-0.20625611 0.75000000
-0.20723363 0.75000000
-0.20821114 0.75000000
-0.20918866 0.75000000
-0.21016618 0.75000000
-0.21114370 0.75000000
-0.21212121 0.75000000
-0.21309873 0.75000000
-0.21407625 0.75000000
-0.21505376 0.75000000
-0.21603128 0.75000000
-0.21700880 0.75000000
-0.21798631 0.75000000
-0.21896383 0.75000000
-0.21994135 0.75000000
-0.22091887 0.75000000
-0.22189638 0.75000000
-0.22287390 0.75000000
-0.22385142 0.75000000
-0.22482893 0.75000000
-0.22580645 0.75000000
-0.22678397 0.75000000
-0.22776149 0.75000000
-0.22873900 0.75000000
-0.22971652 0.75000000
-0.23069404 0.75000000
-0.23167155 0.75000000
-0.23264907 0.75000000
-0.23362659 0.75000000
-0.23460411 0.75000000
-0.23558162 0.75000000
-0.23655914 0.75000000
-0.23753666 0.75000000
-0.23851417 0.75000000
-0.23949169 0.75000000
-0.24046921 0.75000000
-0.24144673 0.75000000
-0.24242424 0.75000000
-0.24340176 0.75000000
-0.24437928 0.75000000
-0.24535679 0.75000000
-0.24633431 0.75000000
-0.24731183 0.75000000
-0.24828935 0.75000000
-0.24926686 0.75000000
-0.25024438 0.74963379
-0.25122190 0.74817607
-0.25219941 0.74672965
-0.25317693 0.74530727
-0.25415445 0.74390115
-0.25513196 0.74250538
-0.25610948 0.74111985
-0.25708700 0.73974444
-0.25806452 0.73838897
-0.25904203 0.73705025
-0.26001955 0.73572080
-0.26099707 0.73440054
-0.26197458 0.73308936
-0.26295210 0.73179453
-0.26392962 0.73051679
-0.26490714 0.72924739
-0.26588465 0.72798623
-0.26686217 0.72673323
-0.26783969 0.72549344
-0.26881720 0.72427097
-0.26979472 0.72305599
-0.27077224 0.72184842
-0.27174976 0.72064820
-0.27272727 0.71945844
-0.27370479 0.71828610
-0.27468231 0.71712050
-0.27565982 0.71596157
-0.27663734 0.71480927
-0.27761486 0.71366501
-0.27859238 0.71253818
-0.27956989 0.71141742
-0.28054741 0.71030267
-0.28152493 0.70919389
-0.28250244 0.70809106
-0.28347996 0.70700557
-0.28445748 0.70592553
-0.28543500 0.70485092
-0.28641251 0.70378169
-0.28739003 0.70271779
-0.28836755 0.70166862
-0.28934506 0.70062558
-0.29032258 0.69958742
-0.29130010 0.69855412
-0.29227761 0.69752564
-0.29325513 0.69650949
-0.29423265 0.69550004
-0.29521017 0.69449498
-0.29618768 0.69349430
-0.29716520 0.69249796
-0.29814272 0.69151186
-0.29912023 0.69053287
-0.30009775 0.68955785
-0.30107527 0.68858676
-0.30205279 0.68761958
-0.30303030 0.68666076
-0.30400782 0.68570938
-0.30498534 0.68476154
-0.30596285 0.68381725
-0.30694037 0.68287647
-0.30791789 0.68194242
-0.30889541 0.68101598
-0.30987292 0.68009273
-0.31085044 0.67917264
-0.31182796 0.67825571
-0.31280547 0.67734408
-0.31378299 0.67644013
-0.31476051 0.67553902
-0.31573803 0.67464075
-0.31671554 0.67374530
-0.31769306 0.67285389
-0.31867058 0.67197014
-0.31964809 0.67108892
-0.32062561 0.67021023
-0.32160313 0.66933404
-0.32258065 0.66846082
-0.32355816 0.66759513
-0.32453568 0.66673167
-0.32551320 0.66587045
-0.32649071 0.66501145
-0.32746823 0.66415466
-0.32844575 0.66330485
-0.32942326 0.66245716
-0.33040078 0.66161144
-0.33137830 0.66076767
-0.33235582 0.65992584
-0.33333333 0.65908967
-0.33431085 0.65825587
-0.33528837 0.65742377
-0.33626588 0.65659337
-0.33724340 0.65576467
-0.33822092 0.65494046
-0.33919844 0.65411875
-0.34017595 0.65329850
-0.34115347 0.65247971
-0.34213099 0.65166237
-0.34310850 0.65084852
-0.34408602 0.65003719
-0.34506354 0.64922708
-0.34604106 0.64841821
-0.34701857 0.64761056
-0.34799609 0.64680554
-0.34897361 0.64600293
-0.34995112 0.64520134
-0.35092864 0.64440076
-0.35190616 0.64360119
-0.35288368 0.64280350
-0.35386119 0.64200804
-0.35483871 0.64121338
-0.35581623 0.64041952
-0.35679374 0.63962646
-0.35777126 0.63883468
-0.35874878 0.63804481
-0.35972630 0.63725555
-0.36070381 0.63646688
-0.36168133 0.63567880
-0.36265885 0.63489151
-0.36363636 0.63410574
-0.36461388 0.63332037
-0.36559140 0.63253539
-0.36656891 0.63175080
-0.36754643 0.63096664
-0.36852395 0.63018348
-0.36950147 0.62940052
-0.37047898 0.62861775
-0.37145650 0.62783518
-0.37243402 0.62705280
-0.37341153 0.62627077
-0.37438905 0.62548876
-0.37536657 0.62470674
-0.37634409 0.62392473
-0.37732160 0.62314272
-0.37829912 0.62236043
-0.37927664 0.62157791
-0.38025415 0.62079519
-0.38123167 0.62001228
-0.38220919 0.61922917
-0.38318671 0.61844529
-0.38416422 0.61766080
-0.38514174 0.61687591
-0.38611926 0.61609064
-0.38709677 0.61530497
-0.38807429 0.61451813
-0.38905181 0.61373020
-0.39002933 0.61294168
-0.39100684 0.61215256
-0.39198436 0.61136285
-0.39296188 0.61057168
-0.39393939 0.60977882
-0.39491691 0.60898516
-0.39589443 0.60819070
-0.39687195 0.60739544
-0.39784946 0.60659855
-0.39882698 0.60579922
-0.39980450 0.60499890
-0.40078201 0.60419756
-0.40175953 0.60339521
-0.40273705 0.60259116
-0.40371457 0.60178382
-0.40469208 0.60097525
-0.40566960 0.60016546
-0.40664712 0.59935443
-0.40762463 0.59854174
-0.40860215 0.59772477
-0.40957967 0.59690634
-0.41055718 0.59608645
-0.41153470 0.59526511
-0.41251222 0.59444225
-0.41348974 0.59361396
-0.41446725 0.59278399
-0.41544477 0.59195232
-0.41642229 0.59111894
-0.41739980 0.59028386
-0.41837732 0.58944297
-0.41935484 0.58859969
-0.42033236 0.58775445
-0.42130987 0.58690726
-0.42228739 0.58605810
-0.42326491 0.58520295
-0.42424242 0.58434451
-0.42521994 0.58348384
-0.42619746 0.58262095
-0.42717498 0.58175582
-0.42815249 0.58088462
-0.42913001 0.58000905
-0.43010753 0.57913099
-0.43108504 0.57825040
-0.43206256 0.57736728
-0.43304008 0.57647812
-0.43401760 0.57558337
-0.43499511 0.57468581
-0.43597263 0.57378542
-0.43695015 0.57288218
-0.43792766 0.57197303
-0.43890518 0.57105688
-0.43988270 0.57013759
-0.44086022 0.56921513
-0.44183773 0.56828949
-0.44281525 0.56735818
-0.44379277 0.56641827
-0.44477028 0.56547486
-0.44574780 0.56452791
-0.44672532 0.56357742
-0.44770283 0.56262161
-0.44868035 0.56165541
-0.44965787 0.56068529
-0.45063539 0.55971125
-0.45161290 0.55873326
-0.45259042 0.55775044
-0.45356794 0.55675519
-0.45454545 0.55575559
-0.45552297 0.55475164
-0.45650049 0.55374329
-0.45747801 0.55273051
-0.45845552 0.55170345
-0.45943304 0.55067135
-0.46041056 0.54963442
-0.46138807 0.54859260
-0.46236559 0.54754587
-0.46334311 0.54648479
-0.46432063 0.54541689
-0.46529814 0.54434363
-0.46627566 0.54326495
-0.46725318 0.54218083
-0.46823069 0.54108237
-0.46920821 0.53997508
-0.47018573 0.53886183
-0.47116325 0.53774257
-0.47214076 0.53661727
-0.47311828 0.53547778
-0.47409580 0.53432712
-0.47507331 0.53316986
-0.47605083 0.53200593
-0.47702835 0.53083528
-0.47800587 0.52965071
-0.47898338 0.52845232
-0.47996090 0.52724659
-0.48093842 0.52603347
-0.48191593 0.52481288
-0.48289345 0.52357875
-0.48387097 0.52232778
-0.48484848 0.52106867
-0.48582600 0.51980133
-0.48680352 0.51852569
-0.48778104 0.51723703
-0.48875855 0.51592811
-0.48973607 0.51461012
-0.49071359 0.51328298
-0.49169110 0.51194659
-0.49266862 0.51059784
-0.49364614 0.50922495
-0.49462366 0.50784195
-0.49560117 0.50644876
-0.49657869 0.50504524
-0.49755621 0.50363020
-0.49853372 0.50218659
-0.49951124 0.50073171
-0.50048876 0.49926829
-0.50146628 0.49781341
-0.50244379 0.49636980
-0.50342131 0.49495476
-0.50439883 0.49355124
-0.50537634 0.49215805
-0.50635386 0.49077505
-0.50733138 0.48940216
-0.50830890 0.48805341
-0.50928641 0.48671702
-0.51026393 0.48538988
-0.51124145 0.48407189
-0.51221896 0.48276297
-0.51319648 0.48147431
-0.51417400 0.48019867
-0.51515152 0.47893133
-0.51612903 0.47767222
-0.51710655 0.47642125
-0.51808407 0.47518712
-0.51906158 0.47396653
-0.52003910 0.47275341
-0.52101662 0.47154768
-0.52199413 0.47034929
-0.52297165 0.46916472
-0.52394917 0.46799407
-0.52492669 0.46683014
-0.52590420 0.46567288
-0.52688172 0.46452222
-0.52785924 0.46338273
-0.52883675 0.46225743
-0.52981427 0.46113817
-0.53079179 0.46002492
-0.53176931 0.45891763
-0.53274682 0.45781917
-0.53372434 0.45673505
-0.53470186 0.45565637
-0.53567937 0.45458311
-0.53665689 0.45351521
-0.53763441 0.45245413
-0.53861193 0.45140740
-0.53958944 0.45036558
-0.54056696 0.44932865
-0.54154448 0.44829655
-0.54252199 0.44726949
-0.54349951 0.44625671
-0.54447703 0.44524836
-0.54545455 0.44424441
-0.54643206 0.44324481
-0.54740958 0.44224956
-0.54838710 0.44126674
-0.54936461 0.44028875
-0.55034213 0.43931471
-0.55131965 0.43834459
-0.55229717 0.43737839
-0.55327468 0.43642258
-0.55425220 0.43547209
-0.55522972 0.43452514
-0.55620723 0.43358173
-0.55718475 0.43264182
-0.55816227 0.43171051
-0.55913978 0.43078487
-0.56011730 0.42986241
-0.56109482 0.42894312
-0.56207234 0.42802697
-0.56304985 0.42711782
-0.56402737 0.42621458
-0.56500489 0.42531419
-0.56598240 0.42441663
-0.56695992 0.42352188
-0.56793744 0.42263272
-0.56891496 0.42174960
-0.56989247 0.42086901
-0.57086999 0.41999095
-0.57184751 0.41911538
-0.57282502 0.41824418
-0.57380254 0.41737905
-0.57478006 0.41651616
-0.57575758 0.41565549
-0.57673509 0.41479705
-0.57771261 0.41394190
-0.57869013 0.41309274
-0.57966764 0.41224555
-0.58064516 0.41140031
-0.58162268 0.41055703
-0.58260020 0.40971614
-0.58357771 0.40888106
-0.58455523 0.40804768
-0.58553275 0.40721601
-0.58651026 0.40638604
-0.58748778 0.40555775
-0.58846530 0.40473489
-0.58944282 0.40391355
-0.59042033 0.40309366
-0.59139785 0.40227523
-0.59237537 0.40145826
-0.59335288 0.40064557
-0.59433040 0.39983454
-0.59530792 0.39902475
-0.59628543 0.39821618
-0.59726295 0.39740884
-0.59824047 0.39660479
-0.59921799 0.39580244
-0.60019550 0.39500110
-0.60117302 0.39420078
-0.60215054 0.39340145
-0.60312805 0.39260456
-0.60410557 0.39180930
-0.60508309 0.39101484
-0.60606061 0.39022118
-0.60703812 0.38942832
-0.60801564 0.38863715
-0.60899316 0.38784744
-0.60997067 0.38705832
-0.61094819 0.38626980
-0.61192571 0.38548187
-0.61290323 0.38469503
-0.61388074 0.38390936
-0.61485826 0.38312409
-0.61583578 0.38233920
-0.61681329 0.38155471
-0.61779081 0.38077083
-0.61876833 0.37998772
-0.61974585 0.37920481
-0.62072336 0.37842209
-0.62170088 0.37763957
-0.62267840 0.37685728
-0.62365591 0.37607527
-0.62463343 0.37529326
-0.62561095 0.37451124
-0.62658847 0.37372923
-0.62756598 0.37294720
-0.62854350 0.37216482
-0.62952102 0.37138225
-0.63049853 0.37059948
-0.63147605 0.36981652
-0.63245357 0.36903336
-0.63343109 0.36824920
-0.63440860 0.36746461
-0.63538612 0.36667963
-0.63636364 0.36589426
-0.63734115 0.36510849
-0.63831867 0.36432120
-0.63929619 0.36353312
-0.64027370 0.36274445
-0.64125122 0.36195519
-0.64222874 0.36116532
-0.64320626 0.36037354
-0.64418377 0.35958048
-0.64516129 0.35878662
-0.64613881 0.35799196
-0.64711632 0.35719650
-0.64809384 0.35639881
-0.64907136 0.35559924
-0.65004888 0.35479866
-0.65102639 0.35399707
-0.65200391 0.35319446
-0.65298143 0.35238944
-0.65395894 0.35158179
-0.65493646 0.35077292
-0.65591398 0.34996281
-0.65689150 0.34915148
-0.65786901 0.34833763
-0.65884653 0.34752029
-0.65982405 0.34670150
-0.66080156 0.34588125
-0.66177908 0.34505954
-0.66275660 0.34423533
-0.66373412 0.34340663
-0.66471163 0.34257623
-0.66568915 0.34174413
-0.66666667 0.34091033
-0.66764418 0.34007416
-0.66862170 0.33923233
-0.66959922 0.33838856
-0.67057674 0.33754284
-0.67155425 0.33669515
-0.67253177 0.33584534
-0.67350929 0.33498855
-0.67448680 0.33412955
-0.67546432 0.33326833
-0.67644184 0.33240487
-0.67741935 0.33153918
-0.67839687 0.33066596
-0.67937439 0.32978977
-0.68035191 0.32891108
-0.68132942 0.32802986
-0.68230694 0.32714611
-0.68328446 0.32625470
-0.68426197 0.32535925
-0.68523949 0.32446098
-0.68621701 0.32355987
-0.68719453 0.32265592
-0.68817204 0.32174429
-0.68914956 0.32082736
-0.69012708 0.31990727
-0.69110459 0.31898402
-0.69208211 0.31805758
-0.69305963 0.31712353
-0.69403715 0.31618275
-0.69501466 0.31523846
-0.69599218 0.31429062
-0.69696970 0.31333924
-0.69794721 0.31238042
-0.69892473 0.31141324
-0.69990225 0.31044215
-0.70087977 0.30946713
-0.70185728 0.30848814
-0.70283480 0.30750204
-0.70381232 0.30650570
-0.70478983 0.30550502
-0.70576735 0.30449996
-0.70674487 0.30349051
-0.70772239 0.30247436
-0.70869990 0.30144588
-0.70967742 0.30041258
-0.71065494 0.29937442
-0.71163245 0.29833138
-0.71260997 0.29728221
-0.71358749 0.29621831
-0.71456500 0.29514908
-0.71554252 0.29407447
-0.71652004 0.29299443
-0.71749756 0.29190894
-0.71847507 0.29080611
-0.71945259 0.28969733
-0.72043011 0.28858258
-0.72140762 0.28746182
-0.72238514 0.28633499
-0.72336266 0.28519073
-0.72434018 0.28403843
-0.72531769 0.28287950
-0.72629521 0.28171390
-0.72727273 0.28054156
-0.72825024 0.27935180
-0.72922776 0.27815158
-0.73020528 0.27694401
-0.73118280 0.27572903
-0.73216031 0.27450656
-0.73313783 0.27326677
-0.73411535 0.27201377
-0.73509286 0.27075261
-0.73607038 0.26948321
-0.73704790 0.26820547
-0.73802542 0.26691064
-0.73900293 0.26559946
-0.73998045 0.26427920
-0.74095797 0.26294975
-0.74193548 0.26161103
-0.74291300 0.26025556
-0.74389052 0.25888015
-0.74486804 0.25749462
-0.74584555 0.25609885
-0.74682307 0.25469273
-0.74780059 0.25327035
-0.74877810 0.25182393
-0.74975562 0.25036621
-0.75073314 0.25000000
-0.75171065 0.25000000
-0.75268817 0.25000000
-0.75366569 0.25000000
-0.75464321 0.25000000
-0.75562072 0.25000000
-0.75659824 0.25000000
-0.75757576 0.25000000
-0.75855327 0.25000000
-0.75953079 0.25000000
-0.76050831 0.25000000
-0.76148583 0.25000000
-0.76246334 0.25000000
-0.76344086 0.25000000
-0.76441838 0.25000000
-0.76539589 0.25000000
-0.76637341 0.25000000
-0.76735093 0.25000000
-0.76832845 0.25000000
-0.76930596 0.25000000
-0.77028348 0.25000000
-0.77126100 0.25000000
-0.77223851 0.25000000
-0.77321603 0.25000000
-0.77419355 0.25000000
-0.77517107 0.25000000
-0.77614858 0.25000000
-0.77712610 0.25000000
-0.77810362 0.25000000
-0.77908113 0.25000000
-0.78005865 0.25000000
-0.78103617 0.25000000
-0.78201369 0.25000000
-0.78299120 0.25000000
-0.78396872 0.25000000
-0.78494624 0.25000000
-0.78592375 0.25000000
-0.78690127 0.25000000
-0.78787879 0.25000000
-0.78885630 0.25000000
-0.78983382 0.25000000
-0.79081134 0.25000000
-0.79178886 0.25000000
-0.79276637 0.25000000
-0.79374389 0.25000000
-0.79472141 0.25000000
-0.79569892 0.25000000
-0.79667644 0.25000000
-0.79765396 0.25000000
-0.79863148 0.25000000
-0.79960899 0.25000000
-0.80058651 0.25000000
-0.80156403 0.25000000
-0.80254154 0.25000000
-0.80351906 0.25000000
-0.80449658 0.25000000
-0.80547410 0.25000000
-0.80645161 0.25000000
-0.80742913 0.25000000
-0.80840665 0.25000000
-0.80938416 0.25000000
-0.81036168 0.25000000
-0.81133920 0.25000000
-0.81231672 0.25000000
-0.81329423 0.25000000
-0.81427175 0.25000000
-0.81524927 0.25000000
-0.81622678 0.25000000
-0.81720430 0.25000000
-0.81818182 0.25000000
-0.81915934 0.25000000
-0.82013685 0.25000000
-0.82111437 0.25000000
-0.82209189 0.25000000
-0.82306940 0.25000000
-0.82404692 0.25000000
-0.82502444 0.25000000
-0.82600196 0.25000000
-0.82697947 0.25000000
-0.82795699 0.25000000
-0.82893451 0.25000000
-0.82991202 0.25000000
-0.83088954 0.25000000
-0.83186706 0.25000000
-0.83284457 0.25000000
-0.83382209 0.25000000
-0.83479961 0.25000000
-0.83577713 0.25000000
-0.83675464 0.25000000
-0.83773216 0.25000000
-0.83870968 0.25000000
-0.83968719 0.25000000
-0.84066471 0.25000000
-0.84164223 0.25000000
-0.84261975 0.25000000
-0.84359726 0.25000000
-0.84457478 0.25000000
-0.84555230 0.25000000
-0.84652981 0.25000000
-0.84750733 0.25000000
-0.84848485 0.25000000
-0.84946237 0.25000000
-0.85043988 0.25000000
-0.85141740 0.25000000
-0.85239492 0.25000000
-0.85337243 0.25000000
-0.85434995 0.25000000
-0.85532747 0.25000000
-0.85630499 0.25000000
-0.85728250 0.25000000
-0.85826002 0.25000000
-0.85923754 0.25000000
-0.86021505 0.25000000
-0.86119257 0.25000000
-0.86217009 0.25000000
-0.86314761 0.25000000
-0.86412512 0.25000000
-0.86510264 0.25000000
-0.86608016 0.25000000
-0.86705767 0.25000000
-0.86803519 0.25000000
-0.86901271 0.25000000
-0.86999022 0.25000000
-0.87096774 0.25000000
-0.87194526 0.25000000
-0.87292278 0.25000000
-0.87390029 0.25000000
-0.87487781 0.25000000
-0.87585533 0.25000000
-0.87683284 0.25000000
-0.87781036 0.25000000
-0.87878788 0.25000000
-0.87976540 0.25000000
-0.88074291 0.25000000
-0.88172043 0.25000000
-0.88269795 0.25000000
-0.88367546 0.25000000
-0.88465298 0.25000000
-0.88563050 0.25000000
-0.88660802 0.25000000
-0.88758553 0.25000000
-0.88856305 0.25000000
-0.88954057 0.25000000
-0.89051808 0.25000000
-0.89149560 0.25000000
-0.89247312 0.25000000
-0.89345064 0.25000000
-0.89442815 0.25000000
-0.89540567 0.25000000
-0.89638319 0.25000000
-0.89736070 0.25000000
-0.89833822 0.25000000
-0.89931574 0.25000000
-0.90029326 0.25000000
-0.90127077 0.25000000
-0.90224829 0.25000000
-0.90322581 0.25000000
-0.90420332 0.25000000
-0.90518084 0.25000000
-0.90615836 0.25000000
-0.90713587 0.25000000
-0.90811339 0.25000000
-0.90909091 0.25000000
-0.91006843 0.25000000
-0.91104594 0.25000000
-0.91202346 0.25000000
-0.91300098 0.25000000
-0.91397849 0.25000000
-0.91495601 0.25000000
-0.91593353 0.25000000
-0.91691105 0.25000000
-0.91788856 0.25000000
-0.91886608 0.25000000
-0.91984360 0.25000000
-0.92082111 0.25000000
-0.92179863 0.25000000
-0.92277615 0.25000000
-0.92375367 0.25000000
-0.92473118 0.25000000
-0.92570870 0.25000000
-0.92668622 0.25000000
-0.92766373 0.25000000
-0.92864125 0.25000000
-0.92961877 0.25000000
-0.93059629 0.25000000
-0.93157380 0.25000000
-0.93255132 0.25000000
-0.93352884 0.25000000
-0.93450635 0.25000000
-0.93548387 0.25000000
-0.93646139 0.25000000
-0.93743891 0.25000000
-0.93841642 0.25000000
-0.93939394 0.25000000
-0.94037146 0.25000000
-0.94134897 0.25000000
-0.94232649 0.25000000
-0.94330401 0.25000000
-0.94428152 0.25000000
-0.94525904 0.25000000
-0.94623656 0.25000000
-0.94721408 0.25000000
-0.94819159 0.25000000
-0.94916911 0.25000000
-0.95014663 0.25000000
-0.95112414 0.25000000
-0.95210166 0.25000000
-0.95307918 0.25000000
-0.95405670 0.25000000
-0.95503421 0.25000000
-0.95601173 0.25000000
-0.95698925 0.25000000
-0.95796676 0.25000000
-0.95894428 0.25000000
-0.95992180 0.25000000
-0.96089932 0.25000000
-0.96187683 0.25000000
-0.96285435 0.25000000
-0.96383187 0.25000000
-0.96480938 0.25000000
-0.96578690 0.25000000
-0.96676442 0.25000000
-0.96774194 0.25000000
-0.96871945 0.25000000
-0.96969697 0.25000000
-0.97067449 0.25000000
-0.97165200 0.25000000
-0.97262952 0.25000000
-0.97360704 0.25000000
-0.97458456 0.25000000
-0.97556207 0.25000000
-0.97653959 0.25000000
-0.97751711 0.25000000
-0.97849462 0.25000000
-0.97947214 0.25000000
-0.98044966 0.25000000
-0.98142717 0.25000000
-0.98240469 0.25000000
-0.98338221 0.25000000
-0.98435973 0.25000000
-0.98533724 0.25000000
-0.98631476 0.25000000
-0.98729228 0.25000000
-0.98826979 0.25000000
-0.98924731 0.25000000
-0.99022483 0.25000000
-0.99120235 0.25000000
-0.99217986 0.25000000
-0.99315738 0.25000000
-0.99413490 0.25000000
-0.99511241 0.25000000
-0.99608993 0.25000000
-0.99706745 0.25000000
-0.99804497 0.25000000
-0.99902248 0.25000000
-1.00000000 nan
+Ambient Power
+0.000000000 nan
+0.000977517 0.750000000
+0.001955034 0.750000000
+0.002932551 0.750000000
+0.003910068 0.750000000
+0.004887586 0.750000000
+0.005865103 0.750000000
+0.006842620 0.750000000
+0.007820137 0.750000000
+0.008797654 0.750000000
+0.009775171 0.750000000
+0.010752688 0.750000000
+0.011730205 0.750000000
+0.012707722 0.750000000
+0.013685239 0.750000000
+0.014662757 0.750000000
+0.015640274 0.750000000
+0.016617791 0.750000000
+0.017595308 0.750000000
+0.018572825 0.750000000
+0.019550342 0.750000000
+0.020527859 0.750000000
+0.021505376 0.750000000
+0.022482893 0.750000000
+0.023460411 0.750000000
+0.024437928 0.750000000
+0.025415445 0.750000000
+0.026392962 0.750000000
+0.027370479 0.750000000
+0.028347996 0.750000000
+0.029325513 0.750000000
+0.030303030 0.750000000
+0.031280547 0.750000000
+0.032258065 0.750000000
+0.033235582 0.750000000
+0.034213099 0.750000000
+0.035190616 0.750000000
+0.036168133 0.750000000
+0.037145650 0.750000000
+0.038123167 0.750000000
+0.039100684 0.750000000
+0.040078201 0.750000000
+0.041055718 0.750000000
+0.042033236 0.750000000
+0.043010753 0.750000000
+0.043988270 0.750000000
+0.044965787 0.750000000
+0.045943304 0.750000000
+0.046920821 0.750000000
+0.047898338 0.750000000
+0.048875855 0.750000000
+0.049853372 0.750000000
+0.050830890 0.750000000
+0.051808407 0.750000000
+0.052785924 0.750000000
+0.053763441 0.750000000
+0.054740958 0.750000000
+0.055718475 0.750000000
+0.056695992 0.750000000
+0.057673509 0.750000000
+0.058651026 0.750000000
+0.059628543 0.750000000
+0.060606061 0.750000000
+0.061583578 0.750000000
+0.062561095 0.750000000
+0.063538612 0.750000000
+0.064516129 0.750000000
+0.065493646 0.750000000
+0.066471163 0.750000000
+0.067448680 0.750000000
+0.068426197 0.750000000
+0.069403715 0.750000000
+0.070381232 0.750000000
+0.071358749 0.750000000
+0.072336266 0.750000000
+0.073313783 0.750000000
+0.074291300 0.750000000
+0.075268817 0.750000000
+0.076246334 0.750000000
+0.077223851 0.750000000
+0.078201369 0.750000000
+0.079178886 0.750000000
+0.080156403 0.750000000
+0.081133920 0.750000000
+0.082111437 0.750000000
+0.083088954 0.750000000
+0.084066471 0.750000000
+0.085043988 0.750000000
+0.086021505 0.750000000
+0.086999022 0.750000000
+0.087976540 0.750000000
+0.088954057 0.750000000
+0.089931574 0.750000000
+0.090909091 0.750000000
+0.091886608 0.750000000
+0.092864125 0.750000000
+0.093841642 0.750000000
+0.094819159 0.750000000
+0.095796676 0.750000000
+0.096774194 0.750000000
+0.097751711 0.750000000
+0.098729228 0.750000000
+0.099706745 0.750000000
+0.100684262 0.750000000
+0.101661779 0.750000000
+0.102639296 0.750000000
+0.103616813 0.750000000
+0.104594330 0.750000000
+0.105571848 0.750000000
+0.106549365 0.750000000
+0.107526882 0.750000000
+0.108504399 0.750000000
+0.109481916 0.750000000
+0.110459433 0.750000000
+0.111436950 0.750000000
+0.112414467 0.750000000
+0.113391984 0.750000000
+0.114369501 0.750000000
+0.115347019 0.750000000
+0.116324536 0.750000000
+0.117302053 0.750000000
+0.118279570 0.750000000
+0.119257087 0.750000000
+0.120234604 0.750000000
+0.121212121 0.750000000
+0.122189638 0.750000000
+0.123167155 0.750000000
+0.124144673 0.750000000
+0.125122190 0.750000000
+0.126099707 0.750000000
+0.127077224 0.750000000
+0.128054741 0.750000000
+0.129032258 0.750000000
+0.130009775 0.750000000
+0.130987292 0.750000000
+0.131964809 0.750000000
+0.132942326 0.750000000
+0.133919844 0.750000000
+0.134897361 0.750000000
+0.135874878 0.750000000
+0.136852395 0.750000000
+0.137829912 0.750000000
+0.138807429 0.750000000
+0.139784946 0.750000000
+0.140762463 0.750000000
+0.141739980 0.750000000
+0.142717498 0.750000000
+0.143695015 0.750000000
+0.144672532 0.750000000
+0.145650049 0.750000000
+0.146627566 0.750000000
+0.147605083 0.750000000
+0.148582600 0.750000000
+0.149560117 0.750000000
+0.150537634 0.750000000
+0.151515152 0.750000000
+0.152492669 0.750000000
+0.153470186 0.750000000
+0.154447703 0.750000000
+0.155425220 0.750000000
+0.156402737 0.750000000
+0.157380254 0.750000000
+0.158357771 0.750000000
+0.159335288 0.750000000
+0.160312805 0.750000000
+0.161290323 0.750000000
+0.162267840 0.750000000
+0.163245357 0.750000000
+0.164222874 0.750000000
+0.165200391 0.750000000
+0.166177908 0.750000000
+0.167155425 0.750000000
+0.168132942 0.750000000
+0.169110459 0.750000000
+0.170087977 0.750000000
+0.171065494 0.750000000
+0.172043011 0.750000000
+0.173020528 0.750000000
+0.173998045 0.750000000
+0.174975562 0.750000000
+0.175953079 0.750000000
+0.176930596 0.750000000
+0.177908113 0.750000000
+0.178885630 0.750000000
+0.179863148 0.750000000
+0.180840665 0.750000000
+0.181818182 0.750000000
+0.182795699 0.750000000
+0.183773216 0.750000000
+0.184750733 0.750000000
+0.185728250 0.750000000
+0.186705767 0.750000000
+0.187683284 0.750000000
+0.188660802 0.750000000
+0.189638319 0.750000000
+0.190615836 0.750000000
+0.191593353 0.750000000
+0.192570870 0.750000000
+0.193548387 0.750000000
+0.194525904 0.750000000
+0.195503421 0.750000000
+0.196480938 0.750000000
+0.197458456 0.750000000
+0.198435973 0.750000000
+0.199413490 0.750000000
+0.200391007 0.750000000
+0.201368524 0.750000000
+0.202346041 0.750000000
+0.203323558 0.750000000
+0.204301075 0.750000000
+0.205278592 0.750000000
+0.206256109 0.750000000
+0.207233627 0.750000000
+0.208211144 0.750000000
+0.209188661 0.750000000
+0.210166178 0.750000000
+0.211143695 0.750000000
+0.212121212 0.750000000
+0.213098729 0.750000000
+0.214076246 0.750000000
+0.215053763 0.750000000
+0.216031281 0.750000000
+0.217008798 0.750000000
+0.217986315 0.750000000
+0.218963832 0.750000000
+0.219941349 0.750000000
+0.220918866 0.750000000
+0.221896383 0.750000000
+0.222873900 0.750000000
+0.223851417 0.750000000
+0.224828935 0.750000000
+0.225806452 0.750000000
+0.226783969 0.750000000
+0.227761486 0.750000000
+0.228739003 0.750000000
+0.229716520 0.750000000
+0.230694037 0.750000000
+0.231671554 0.750000000
+0.232649071 0.750000000
+0.233626588 0.750000000
+0.234604106 0.750000000
+0.235581623 0.750000000
+0.236559140 0.750000000
+0.237536657 0.750000000
+0.238514174 0.750000000
+0.239491691 0.750000000
+0.240469208 0.750000000
+0.241446725 0.750000000
+0.242424242 0.750000000
+0.243401760 0.750000000
+0.244379277 0.750000000
+0.245356794 0.750000000
+0.246334311 0.750000000
+0.247311828 0.750000000
+0.248289345 0.750000000
+0.249266862 0.750000000
+0.250244379 0.749633789
+0.251221896 0.748176070
+0.252199413 0.746729651
+0.253176931 0.745307268
+0.254154448 0.743901152
+0.255131965 0.742505384
+0.256109482 0.741119851
+0.257086999 0.739744439
+0.258064516 0.738388970
+0.259042033 0.737050250
+0.260019550 0.735720805
+0.260997067 0.734400539
+0.261974585 0.733089356
+0.262952102 0.731794526
+0.263929619 0.730516794
+0.264907136 0.729247388
+0.265884653 0.727986227
+0.266862170 0.726733231
+0.267839687 0.725493442
+0.268817204 0.724270974
+0.269794721 0.723055990
+0.270772239 0.721848423
+0.271749756 0.720648204
+0.272727273 0.719458438
+0.273704790 0.718286101
+0.274682307 0.717120499
+0.275659824 0.715961575
+0.276637341 0.714809270
+0.277614858 0.713665012
+0.278592375 0.712538184
+0.279569892 0.711417421
+0.280547410 0.710302674
+0.281524927 0.709193894
+0.282502444 0.708091063
+0.283479961 0.707005566
+0.284457478 0.705925531
+0.285434995 0.704850918
+0.286412512 0.703781686
+0.287390029 0.702717795
+0.288367546 0.701668621
+0.289345064 0.700625580
+0.290322581 0.699587425
+0.291300098 0.698554121
+0.292277615 0.697525635
+0.293255132 0.696509490
+0.294232649 0.695500037
+0.295210166 0.694494984
+0.296187683 0.693494303
+0.297165200 0.692497965
+0.298142717 0.691511860
+0.299120235 0.690532874
+0.300097752 0.689557847
+0.301075269 0.688586755
+0.302052786 0.687619575
+0.303030303 0.686660765
+0.304007820 0.685709376
+0.304985337 0.684761545
+0.305962854 0.683817249
+0.306940371 0.682876470
+0.307917889 0.681942420
+0.308895406 0.681015980
+0.309872923 0.680092726
+0.310850440 0.679172643
+0.311827957 0.678255714
+0.312805474 0.677344077
+0.313782991 0.676440126
+0.314760508 0.675539023
+0.315738025 0.674640752
+0.316715543 0.673745302
+0.317693060 0.672853893
+0.318670577 0.671970143
+0.319648094 0.671088924
+0.320625611 0.670210227
+0.321603128 0.669334041
+0.322580645 0.668460818
+0.323558162 0.667595126
+0.324535679 0.666731672
+0.325513196 0.665870450
+0.326490714 0.665011449
+0.327468231 0.664154662
+0.328445748 0.663304848
+0.329423265 0.662457164
+0.330400782 0.661611439
+0.331378299 0.660767667
+0.332355816 0.659925840
+0.333333333 0.659089669
+0.334310850 0.658255868
+0.335288368 0.657423770
+0.336265885 0.656593371
+0.337243402 0.655764665
+0.338220919 0.654940458
+0.339198436 0.654118746
+0.340175953 0.653298497
+0.341153470 0.652479705
+0.342130987 0.651662368
+0.343108504 0.650848521
+0.344086022 0.650037186
+0.345063539 0.649227083
+0.346041056 0.648418210
+0.347018573 0.647610563
+0.347996090 0.646805538
+0.348973607 0.646002934
+0.349951124 0.645201343
+0.350928641 0.644400763
+0.351906158 0.643601190
+0.352883675 0.642803505
+0.353861193 0.642008044
+0.354838710 0.641213384
+0.355816227 0.640419523
+0.356793744 0.639626459
+0.357771261 0.638834675
+0.358748778 0.638044814
+0.359726295 0.637255548
+0.360703812 0.636466876
+0.361681329 0.635678797
+0.362658847 0.634891512
+0.363636364 0.634105743
+0.364613881 0.633320368
+0.365591398 0.632535386
+0.366568915 0.631750798
+0.367546432 0.630966638
+0.368523949 0.630183479
+0.369501466 0.629400516
+0.370478983 0.628617749
+0.371456500 0.627835178
+0.372434018 0.627052803
+0.373411535 0.626270772
+0.374389052 0.625488759
+0.375366569 0.624706745
+0.376344086 0.623924731
+0.377321603 0.623142717
+0.378299120 0.622360434
+0.379276637 0.621577912
+0.380254154 0.620795194
+0.381231672 0.620012280
+0.382209189 0.619229171
+0.383186706 0.618445288
+0.384164223 0.617660798
+0.385141740 0.616875914
+0.386119257 0.616090638
+0.387096774 0.615304967
+0.388074291 0.614518130
+0.389051808 0.613730200
+0.390029326 0.612941676
+0.391006843 0.612152558
+0.391984360 0.611362846
+0.392961877 0.610571682
+0.393939394 0.609778818
+0.394916911 0.608985156
+0.395894428 0.608190696
+0.396871945 0.607395436
+0.397849462 0.606598545
+0.398826979 0.605799225
+0.399804497 0.604998896
+0.400782014 0.604197558
+0.401759531 0.603395208
+0.402737048 0.602591157
+0.403714565 0.601783817
+0.404692082 0.600975251
+0.405669599 0.600165455
+0.406647116 0.599354429
+0.407624633 0.598541740
+0.408602151 0.597724765
+0.409579668 0.596906338
+0.410557185 0.596086453
+0.411534702 0.595265107
+0.412512219 0.594442248
+0.413489736 0.593613964
+0.414467253 0.592783988
+0.415444770 0.591952316
+0.416422287 0.591118941
+0.417399804 0.590283858
+0.418377322 0.589442972
+0.419354839 0.588599687
+0.420332356 0.587754450
+0.421309873 0.586907257
+0.422287390 0.586058099
+0.423264907 0.585202955
+0.424242424 0.584344508
+0.425219941 0.583483842
+0.426197458 0.582620947
+0.427174976 0.581755815
+0.428152493 0.580884615
+0.429130010 0.580009054
+0.430107527 0.579130986
+0.431085044 0.578250399
+0.432062561 0.577367283
+0.433040078 0.576478121
+0.434017595 0.575583374
+0.434995112 0.574685810
+0.435972630 0.573785416
+0.436950147 0.572882178
+0.437927664 0.571973027
+0.438905181 0.571056884
+0.439882698 0.570137591
+0.440860215 0.569215132
+0.441837732 0.568289490
+0.442815249 0.567358177
+0.443792766 0.566418275
+0.444770283 0.565474860
+0.445747801 0.564527914
+0.446725318 0.563577417
+0.447702835 0.562621612
+0.448680352 0.561655405
+0.449657869 0.560685294
+0.450635386 0.559711253
+0.451612903 0.558733259
+0.452590420 0.557750445
+0.453567937 0.556755188
+0.454545455 0.555755595
+0.455522972 0.554751638
+0.456500489 0.553743287
+0.457478006 0.552730515
+0.458455523 0.551703450
+0.459433040 0.550671354
+0.460410557 0.549634415
+0.461388074 0.548592599
+0.462365591 0.547545872
+0.463343109 0.546484786
+0.464320626 0.545416893
+0.465298143 0.544343629
+0.466275660 0.543264953
+0.467253177 0.542180826
+0.468230694 0.541082374
+0.469208211 0.539975079
+0.470185728 0.538861828
+0.471163245 0.537742573
+0.472140762 0.536617267
+0.473118280 0.535477779
+0.474095797 0.534327120
+0.475073314 0.533169855
+0.476050831 0.532005928
+0.477028348 0.530835281
+0.478005865 0.529650711
+0.478983382 0.528452318
+0.479960899 0.527246594
+0.480938416 0.526033471
+0.481915934 0.524812880
+0.482893451 0.523578752
+0.483870968 0.522327784
+0.484848485 0.521068672
+0.485826002 0.519801335
+0.486803519 0.518525692
+0.487781036 0.517237031
+0.488758553 0.515928105
+0.489736070 0.514610118
+0.490713587 0.513282977
+0.491691105 0.511946585
+0.492668622 0.510597845
+0.493646139 0.509224947
+0.494623656 0.507841954
+0.495601173 0.506448755
+0.496578690 0.505045237
+0.497556207 0.503630203
+0.498533724 0.502186589
+0.499511241 0.500731707
+0.500488759 0.499268293
+0.501466276 0.497813411
+0.502443793 0.496369797
+0.503421310 0.494954763
+0.504398827 0.493551245
+0.505376344 0.492158046
+0.506353861 0.490775053
+0.507331378 0.489402155
+0.508308895 0.488053415
+0.509286413 0.486717023
+0.510263930 0.485389882
+0.511241447 0.484071895
+0.512218964 0.482762969
+0.513196481 0.481474308
+0.514173998 0.480198665
+0.515151515 0.478931328
+0.516129032 0.477672216
+0.517106549 0.476421248
+0.518084066 0.475187120
+0.519061584 0.473966529
+0.520039101 0.472753406
+0.521016618 0.471547682
+0.521994135 0.470349289
+0.522971652 0.469164719
+0.523949169 0.467994072
+0.524926686 0.466830145
+0.525904203 0.465672880
+0.526881720 0.464522221
+0.527859238 0.463382733
+0.528836755 0.462257427
+0.529814272 0.461138172
+0.530791789 0.460024921
+0.531769306 0.458917626
+0.532746823 0.457819174
+0.533724340 0.456735047
+0.534701857 0.455656371
+0.535679374 0.454583107
+0.536656891 0.453515214
+0.537634409 0.452454128
+0.538611926 0.451407401
+0.539589443 0.450365585
+0.540566960 0.449328646
+0.541544477 0.448296550
+0.542521994 0.447269485
+0.543499511 0.446256713
+0.544477028 0.445248362
+0.545454545 0.444244405
+0.546432063 0.443244812
+0.547409580 0.442249555
+0.548387097 0.441266741
+0.549364614 0.440288747
+0.550342131 0.439314706
+0.551319648 0.438344595
+0.552297165 0.437378388
+0.553274682 0.436422583
+0.554252199 0.435472086
+0.555229717 0.434525140
+0.556207234 0.433581725
+0.557184751 0.432641823
+0.558162268 0.431710510
+0.559139785 0.430784868
+0.560117302 0.429862409
+0.561094819 0.428943116
+0.562072336 0.428026973
+0.563049853 0.427117822
+0.564027370 0.426214584
+0.565004888 0.425314190
+0.565982405 0.424416626
+0.566959922 0.423521879
+0.567937439 0.422632717
+0.568914956 0.421749601
+0.569892473 0.420869014
+0.570869990 0.419990946
+0.571847507 0.419115385
+0.572825024 0.418244185
+0.573802542 0.417379053
+0.574780059 0.416516158
+0.575757576 0.415655492
+0.576735093 0.414797045
+0.577712610 0.413941901
+0.578690127 0.413092743
+0.579667644 0.412245550
+0.580645161 0.411400313
+0.581622678 0.410557028
+0.582600196 0.409716142
+0.583577713 0.408881059
+0.584555230 0.408047684
+0.585532747 0.407216012
+0.586510264 0.406386036
+0.587487781 0.405557752
+0.588465298 0.404734893
+0.589442815 0.403913547
+0.590420332 0.403093662
+0.591397849 0.402275235
+0.592375367 0.401458260
+0.593352884 0.400645571
+0.594330401 0.399834545
+0.595307918 0.399024749
+0.596285435 0.398216183
+0.597262952 0.397408843
+0.598240469 0.396604792
+0.599217986 0.395802442
+0.600195503 0.395001104
+0.601173021 0.394200775
+0.602150538 0.393401455
+0.603128055 0.392604564
+0.604105572 0.391809304
+0.605083089 0.391014844
+0.606060606 0.390221182
+0.607038123 0.389428318
+0.608015640 0.388637154
+0.608993157 0.387847442
+0.609970674 0.387058324
+0.610948192 0.386269800
+0.611925709 0.385481870
+0.612903226 0.384695033
+0.613880743 0.383909362
+0.614858260 0.383124086
+0.615835777 0.382339202
+0.616813294 0.381554712
+0.617790811 0.380770829
+0.618768328 0.379987720
+0.619745846 0.379204806
+0.620723363 0.378422088
+0.621700880 0.377639566
+0.622678397 0.376857283
+0.623655914 0.376075269
+0.624633431 0.375293255
+0.625610948 0.374511241
+0.626588465 0.373729228
+0.627565982 0.372947197
+0.628543500 0.372164822
+0.629521017 0.371382251
+0.630498534 0.370599484
+0.631476051 0.369816521
+0.632453568 0.369033362
+0.633431085 0.368249202
+0.634408602 0.367464614
+0.635386119 0.366679632
+0.636363636 0.365894257
+0.637341153 0.365108488
+0.638318671 0.364321203
+0.639296188 0.363533124
+0.640273705 0.362744452
+0.641251222 0.361955186
+0.642228739 0.361165325
+0.643206256 0.360373541
+0.644183773 0.359580477
+0.645161290 0.358786616
+0.646138807 0.357991956
+0.647116325 0.357196495
+0.648093842 0.356398810
+0.649071359 0.355599237
+0.650048876 0.354798657
+0.651026393 0.353997066
+0.652003910 0.353194462
+0.652981427 0.352389437
+0.653958944 0.351581790
+0.654936461 0.350772917
+0.655913978 0.349962814
+0.656891496 0.349151479
+0.657869013 0.348337632
+0.658846530 0.347520295
+0.659824047 0.346701503
+0.660801564 0.345881254
+0.661779081 0.345059542
+0.662756598 0.344235335
+0.663734115 0.343406629
+0.664711632 0.342576230
+0.665689150 0.341744132
+0.666666667 0.340910331
+0.667644184 0.340074160
+0.668621701 0.339232333
+0.669599218 0.338388561
+0.670576735 0.337542836
+0.671554252 0.336695152
+0.672531769 0.335845338
+0.673509286 0.334988551
+0.674486804 0.334129550
+0.675464321 0.333268328
+0.676441838 0.332404874
+0.677419355 0.331539182
+0.678396872 0.330665959
+0.679374389 0.329789773
+0.680351906 0.328911076
+0.681329423 0.328029857
+0.682306940 0.327146107
+0.683284457 0.326254698
+0.684261975 0.325359248
+0.685239492 0.324460977
+0.686217009 0.323559874
+0.687194526 0.322655923
+0.688172043 0.321744286
+0.689149560 0.320827357
+0.690127077 0.319907274
+0.691104594 0.318984020
+0.692082111 0.318057580
+0.693059629 0.317123530
+0.694037146 0.316182751
+0.695014663 0.315238455
+0.695992180 0.314290624
+0.696969697 0.313339235
+0.697947214 0.312380425
+0.698924731 0.311413245
+0.699902248 0.310442153
+0.700879765 0.309467126
+0.701857283 0.308488140
+0.702834800 0.307502035
+0.703812317 0.306505697
+0.704789834 0.305505016
+0.705767351 0.304499963
+0.706744868 0.303490510
+0.707722385 0.302474365
+0.708699902 0.301445879
+0.709677419 0.300412575
+0.710654936 0.299374420
+0.711632454 0.298331379
+0.712609971 0.297282205
+0.713587488 0.296218314
+0.714565005 0.295149082
+0.715542522 0.294074469
+0.716520039 0.292994434
+0.717497556 0.291908937
+0.718475073 0.290806106
+0.719452590 0.289697326
+0.720430108 0.288582579
+0.721407625 0.287461816
+0.722385142 0.286334988
+0.723362659 0.285190730
+0.724340176 0.284038425
+0.725317693 0.282879501
+0.726295210 0.281713899
+0.727272727 0.280541562
+0.728250244 0.279351796
+0.729227761 0.278151577
+0.730205279 0.276944010
+0.731182796 0.275729026
+0.732160313 0.274506558
+0.733137830 0.273266769
+0.734115347 0.272013773
+0.735092864 0.270752612
+0.736070381 0.269483206
+0.737047898 0.268205474
+0.738025415 0.266910644
+0.739002933 0.265599461
+0.739980450 0.264279195
+0.740957967 0.262949750
+0.741935484 0.261611030
+0.742913001 0.260255561
+0.743890518 0.258880149
+0.744868035 0.257494616
+0.745845552 0.256098848
+0.746823069 0.254692732
+0.747800587 0.253270349
+0.748778104 0.251823930
+0.749755621 0.250366211
+0.750733138 0.250000000
+0.751710655 0.250000000
+0.752688172 0.250000000
+0.753665689 0.250000000
+0.754643206 0.250000000
+0.755620723 0.250000000
+0.756598240 0.250000000
+0.757575758 0.250000000
+0.758553275 0.250000000
+0.759530792 0.250000000
+0.760508309 0.250000000
+0.761485826 0.250000000
+0.762463343 0.250000000
+0.763440860 0.250000000
+0.764418377 0.250000000
+0.765395894 0.250000000
+0.766373412 0.250000000
+0.767350929 0.250000000
+0.768328446 0.250000000
+0.769305963 0.250000000
+0.770283480 0.250000000
+0.771260997 0.250000000
+0.772238514 0.250000000
+0.773216031 0.250000000
+0.774193548 0.250000000
+0.775171065 0.250000000
+0.776148583 0.250000000
+0.777126100 0.250000000
+0.778103617 0.250000000
+0.779081134 0.250000000
+0.780058651 0.250000000
+0.781036168 0.250000000
+0.782013685 0.250000000
+0.782991202 0.250000000
+0.783968719 0.250000000
+0.784946237 0.250000000
+0.785923754 0.250000000
+0.786901271 0.250000000
+0.787878788 0.250000000
+0.788856305 0.250000000
+0.789833822 0.250000000
+0.790811339 0.250000000
+0.791788856 0.250000000
+0.792766373 0.250000000
+0.793743891 0.250000000
+0.794721408 0.250000000
+0.795698925 0.250000000
+0.796676442 0.250000000
+0.797653959 0.250000000
+0.798631476 0.250000000
+0.799608993 0.250000000
+0.800586510 0.250000000
+0.801564027 0.250000000
+0.802541544 0.250000000
+0.803519062 0.250000000
+0.804496579 0.250000000
+0.805474096 0.250000000
+0.806451613 0.250000000
+0.807429130 0.250000000
+0.808406647 0.250000000
+0.809384164 0.250000000
+0.810361681 0.250000000
+0.811339198 0.250000000
+0.812316716 0.250000000
+0.813294233 0.250000000
+0.814271750 0.250000000
+0.815249267 0.250000000
+0.816226784 0.250000000
+0.817204301 0.250000000
+0.818181818 0.250000000
+0.819159335 0.250000000
+0.820136852 0.250000000
+0.821114370 0.250000000
+0.822091887 0.250000000
+0.823069404 0.250000000
+0.824046921 0.250000000
+0.825024438 0.250000000
+0.826001955 0.250000000
+0.826979472 0.250000000
+0.827956989 0.250000000
+0.828934506 0.250000000
+0.829912023 0.250000000
+0.830889541 0.250000000
+0.831867058 0.250000000
+0.832844575 0.250000000
+0.833822092 0.250000000
+0.834799609 0.250000000
+0.835777126 0.250000000
+0.836754643 0.250000000
+0.837732160 0.250000000
+0.838709677 0.250000000
+0.839687195 0.250000000
+0.840664712 0.250000000
+0.841642229 0.250000000
+0.842619746 0.250000000
+0.843597263 0.250000000
+0.844574780 0.250000000
+0.845552297 0.250000000
+0.846529814 0.250000000
+0.847507331 0.250000000
+0.848484848 0.250000000
+0.849462366 0.250000000
+0.850439883 0.250000000
+0.851417400 0.250000000
+0.852394917 0.250000000
+0.853372434 0.250000000
+0.854349951 0.250000000
+0.855327468 0.250000000
+0.856304985 0.250000000
+0.857282502 0.250000000
+0.858260020 0.250000000
+0.859237537 0.250000000
+0.860215054 0.250000000
+0.861192571 0.250000000
+0.862170088 0.250000000
+0.863147605 0.250000000
+0.864125122 0.250000000
+0.865102639 0.250000000
+0.866080156 0.250000000
+0.867057674 0.250000000
+0.868035191 0.250000000
+0.869012708 0.250000000
+0.869990225 0.250000000
+0.870967742 0.250000000
+0.871945259 0.250000000
+0.872922776 0.250000000
+0.873900293 0.250000000
+0.874877810 0.250000000
+0.875855327 0.250000000
+0.876832845 0.250000000
+0.877810362 0.250000000
+0.878787879 0.250000000
+0.879765396 0.250000000
+0.880742913 0.250000000
+0.881720430 0.250000000
+0.882697947 0.250000000
+0.883675464 0.250000000
+0.884652981 0.250000000
+0.885630499 0.250000000
+0.886608016 0.250000000
+0.887585533 0.250000000
+0.888563050 0.250000000
+0.889540567 0.250000000
+0.890518084 0.250000000
+0.891495601 0.250000000
+0.892473118 0.250000000
+0.893450635 0.250000000
+0.894428152 0.250000000
+0.895405670 0.250000000
+0.896383187 0.250000000
+0.897360704 0.250000000
+0.898338221 0.250000000
+0.899315738 0.250000000
+0.900293255 0.250000000
+0.901270772 0.250000000
+0.902248289 0.250000000
+0.903225806 0.250000000
+0.904203324 0.250000000
+0.905180841 0.250000000
+0.906158358 0.250000000
+0.907135875 0.250000000
+0.908113392 0.250000000
+0.909090909 0.250000000
+0.910068426 0.250000000
+0.911045943 0.250000000
+0.912023460 0.250000000
+0.913000978 0.250000000
+0.913978495 0.250000000
+0.914956012 0.250000000
+0.915933529 0.250000000
+0.916911046 0.250000000
+0.917888563 0.250000000
+0.918866080 0.250000000
+0.919843597 0.250000000
+0.920821114 0.250000000
+0.921798631 0.250000000
+0.922776149 0.250000000
+0.923753666 0.250000000
+0.924731183 0.250000000
+0.925708700 0.250000000
+0.926686217 0.250000000
+0.927663734 0.250000000
+0.928641251 0.250000000
+0.929618768 0.250000000
+0.930596285 0.250000000
+0.931573803 0.250000000
+0.932551320 0.250000000
+0.933528837 0.250000000
+0.934506354 0.250000000
+0.935483871 0.250000000
+0.936461388 0.250000000
+0.937438905 0.250000000
+0.938416422 0.250000000
+0.939393939 0.250000000
+0.940371457 0.250000000
+0.941348974 0.250000000
+0.942326491 0.250000000
+0.943304008 0.250000000
+0.944281525 0.250000000
+0.945259042 0.250000000
+0.946236559 0.250000000
+0.947214076 0.250000000
+0.948191593 0.250000000
+0.949169110 0.250000000
+0.950146628 0.250000000
+0.951124145 0.250000000
+0.952101662 0.250000000
+0.953079179 0.250000000
+0.954056696 0.250000000
+0.955034213 0.250000000
+0.956011730 0.250000000
+0.956989247 0.250000000
+0.957966764 0.250000000
+0.958944282 0.250000000
+0.959921799 0.250000000
+0.960899316 0.250000000
+0.961876833 0.250000000
+0.962854350 0.250000000
+0.963831867 0.250000000
+0.964809384 0.250000000
+0.965786901 0.250000000
+0.966764418 0.250000000
+0.967741935 0.250000000
+0.968719453 0.250000000
+0.969696970 0.250000000
+0.970674487 0.250000000
+0.971652004 0.250000000
+0.972629521 0.250000000
+0.973607038 0.250000000
+0.974584555 0.250000000
+0.975562072 0.250000000
+0.976539589 0.250000000
+0.977517107 0.250000000
+0.978494624 0.250000000
+0.979472141 0.250000000
+0.980449658 0.250000000
+0.981427175 0.250000000
+0.982404692 0.250000000
+0.983382209 0.250000000
+0.984359726 0.250000000
+0.985337243 0.250000000
+0.986314761 0.250000000
+0.987292278 0.250000000
+0.988269795 0.250000000
+0.989247312 0.250000000
+0.990224829 0.250000000
+0.991202346 0.250000000
+0.992179863 0.250000000
+0.993157380 0.250000000
+0.994134897 0.250000000
+0.995112414 0.250000000
+0.996089932 0.250000000
+0.997067449 0.250000000
+0.998044966 0.250000000
+0.999022483 0.250000000
+1.000000000 nan
diff --git a/examples/mamdani/SimpleDimmer.fll b/examples/mamdani/SimpleDimmer.fll
index 3a4f8f9..896bebf 100644
--- a/examples/mamdani/SimpleDimmer.fll
+++ b/examples/mamdani/SimpleDimmer.fll
@@ -1,18 +1,19 @@
-Engine: simple-dimmer
+Engine: SimpleDimmer
InputVariable: Ambient
enabled: true
range: 0.000 1.000
+ lock-range: false
term: DARK Triangle 0.000 0.250 0.500
term: MEDIUM Triangle 0.250 0.500 0.750
term: BRIGHT Triangle 0.500 0.750 1.000
OutputVariable: Power
enabled: true
range: 0.000 1.000
- accumulation: Maximum
+ lock-range: false
+ aggregation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
- lock-range: false
term: LOW Triangle 0.000 0.250 0.500
term: MEDIUM Triangle 0.250 0.500 0.750
term: HIGH Triangle 0.500 0.750 1.000
@@ -20,7 +21,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if Ambient is DARK then Power is HIGH
rule: if Ambient is MEDIUM then Power is MEDIUM
rule: if Ambient is BRIGHT then Power is LOW \ No newline at end of file
diff --git a/examples/mamdani/SimpleDimmer.java b/examples/mamdani/SimpleDimmer.java
index 1846722..d7b127d 100644
--- a/examples/mamdani/SimpleDimmer.java
+++ b/examples/mamdani/SimpleDimmer.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,38 +13,46 @@ import com.fuzzylite.variable.*;
public class SimpleDimmer{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("simple-dimmer");
+engine.setName("SimpleDimmer");
+engine.setDescription("");
-InputVariable inputVariable = new InputVariable();
-inputVariable.setEnabled(true);
-inputVariable.setName("Ambient");
-inputVariable.setRange(0.000, 1.000);
-inputVariable.addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
-inputVariable.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-inputVariable.addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
-engine.addInputVariable(inputVariable);
+InputVariable Ambient = new InputVariable();
+Ambient.setName("Ambient");
+Ambient.setDescription("");
+Ambient.setEnabled(true);
+Ambient.setRange(0.000, 1.000);
+Ambient.setLockValueInRange(false);
+Ambient.addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+Ambient.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Ambient.addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+engine.addInputVariable(Ambient);
-OutputVariable outputVariable = new OutputVariable();
-outputVariable.setEnabled(true);
-outputVariable.setName("Power");
-outputVariable.setRange(0.000, 1.000);
-outputVariable.fuzzyOutput().setAccumulation(new Maximum());
-outputVariable.setDefuzzifier(new Centroid(200));
-outputVariable.setDefaultValue(Double.NaN);
-outputVariable.setLockPreviousOutputValue(false);
-outputVariable.setLockOutputValueInRange(false);
-outputVariable.addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
-outputVariable.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-outputVariable.addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
-engine.addOutputVariable(outputVariable);
+OutputVariable Power = new OutputVariable();
+Power.setName("Power");
+Power.setDescription("");
+Power.setEnabled(true);
+Power.setRange(0.000, 1.000);
+Power.setLockValueInRange(false);
+Power.setAggregation(new Maximum());
+Power.setDefuzzifier(new Centroid(200));
+Power.setDefaultValue(Double.NaN);
+Power.setLockPreviousValue(false);
+Power.addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
+Power.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Power.addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
+engine.addOutputVariable(Power);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(null);
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(new Minimum());
+ruleBlock.setImplication(new Minimum());
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if Ambient is DARK then Power is HIGH", engine));
ruleBlock.addRule(Rule.parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
ruleBlock.addRule(Rule.parse("if Ambient is BRIGHT then Power is LOW", engine));
diff --git a/examples/mamdani/SimpleDimmer.pdf b/examples/mamdani/SimpleDimmer.pdf
new file mode 100644
index 0000000..82ef82f
--- /dev/null
+++ b/examples/mamdani/SimpleDimmer.pdf
Binary files differ
diff --git a/examples/mamdani/SimpleDimmerChained.R b/examples/mamdani/SimpleDimmerChained.R
new file mode 100644
index 0000000..323aa7d
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerChained.R
@@ -0,0 +1,85 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "SimpleDimmerChained"
+engine.fll = "Engine: SimpleDimmerChained
+InputVariable: Ambient
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: DARK Triangle 0.000 0.250 0.500
+ term: MEDIUM Triangle 0.250 0.500 0.750
+ term: BRIGHT Triangle 0.500 0.750 1.000
+OutputVariable: Power
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: LOW Triangle 0.000 0.250 0.500
+ term: MEDIUM Triangle 0.250 0.500 0.750
+ term: HIGH Triangle 0.500 0.750 1.000
+OutputVariable: InversePower
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 500
+ default: nan
+ lock-previous: false
+ term: LOW Cosine 0.200 0.500
+ term: MEDIUM Cosine 0.500 0.500
+ term: HIGH Cosine 0.800 0.500
+RuleBlock:
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: Minimum
+ activation: General
+ rule: if Ambient is DARK then Power is HIGH
+ rule: if Ambient is MEDIUM then Power is MEDIUM
+ rule: if Ambient is BRIGHT then Power is LOW
+ rule: if Power is LOW then InversePower is HIGH
+ rule: if Power is MEDIUM then InversePower is MEDIUM
+ rule: if Power is HIGH then InversePower is LOW"
+
+engine.fldFile = "SimpleDimmerChained.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(Ambient, Power)) +
+ geom_line(aes(color=Power), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("Ambient vs Power")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(Ambient, Power)) +
+ geom_line(aes(color=Power), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("Power vs Ambient")
+
+engine.plot.i1_o2 = ggplot(engine.df, aes(Ambient, InversePower)) +
+ geom_line(aes(color=InversePower), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("Ambient vs InversePower")
+
+engine.plot.o2_i1 = ggplot(engine.df, aes(Ambient, InversePower)) +
+ geom_line(aes(color=InversePower), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("InversePower vs Ambient")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, engine.plot.i1_o2, engine.plot.o2_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/mamdani/SimpleDimmerChained.cpp b/examples/mamdani/SimpleDimmerChained.cpp
new file mode 100644
index 0000000..bc59c8e
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerChained.cpp
@@ -0,0 +1,70 @@
+#include <fl/Headers.h>
+
+int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
+using namespace fl;
+
+Engine* engine = new Engine;
+engine->setName("SimpleDimmerChained");
+engine->setDescription("");
+
+InputVariable* Ambient = new InputVariable;
+Ambient->setName("Ambient");
+Ambient->setDescription("");
+Ambient->setEnabled(true);
+Ambient->setRange(0.000, 1.000);
+Ambient->setLockValueInRange(false);
+Ambient->addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+Ambient->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Ambient->addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+engine->addInputVariable(Ambient);
+
+OutputVariable* Power = new OutputVariable;
+Power->setName("Power");
+Power->setDescription("");
+Power->setEnabled(true);
+Power->setRange(0.000, 1.000);
+Power->setLockValueInRange(false);
+Power->setAggregation(new Maximum);
+Power->setDefuzzifier(new Centroid(200));
+Power->setDefaultValue(fl::nan);
+Power->setLockPreviousValue(false);
+Power->addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
+Power->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Power->addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
+engine->addOutputVariable(Power);
+
+OutputVariable* InversePower = new OutputVariable;
+InversePower->setName("InversePower");
+InversePower->setDescription("");
+InversePower->setEnabled(true);
+InversePower->setRange(0.000, 1.000);
+InversePower->setLockValueInRange(false);
+InversePower->setAggregation(new Maximum);
+InversePower->setDefuzzifier(new Centroid(500));
+InversePower->setDefaultValue(fl::nan);
+InversePower->setLockPreviousValue(false);
+InversePower->addTerm(new Cosine("LOW", 0.200, 0.500));
+InversePower->addTerm(new Cosine("MEDIUM", 0.500, 0.500));
+InversePower->addTerm(new Cosine("HIGH", 0.800, 0.500));
+engine->addOutputVariable(InversePower);
+
+RuleBlock* ruleBlock = new RuleBlock;
+ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
+ruleBlock->setConjunction(fl::null);
+ruleBlock->setDisjunction(fl::null);
+ruleBlock->setImplication(new Minimum);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if Ambient is DARK then Power is HIGH", engine));
+ruleBlock->addRule(Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
+ruleBlock->addRule(Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
+ruleBlock->addRule(Rule::parse("if Power is LOW then InversePower is HIGH", engine));
+ruleBlock->addRule(Rule::parse("if Power is MEDIUM then InversePower is MEDIUM", engine));
+ruleBlock->addRule(Rule::parse("if Power is HIGH then InversePower is LOW", engine));
+engine->addRuleBlock(ruleBlock);
+
+
+}
diff --git a/examples/mamdani/SimpleDimmerChained.fcl b/examples/mamdani/SimpleDimmerChained.fcl
new file mode 100644
index 0000000..29bb4ea
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerChained.fcl
@@ -0,0 +1,51 @@
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK SimpleDimmerChained
+
+VAR_INPUT
+ Ambient: REAL;
+END_VAR
+
+VAR_OUTPUT
+ Power: REAL;
+ InversePower: REAL;
+END_VAR
+
+FUZZIFY Ambient
+ RANGE := (0.000 .. 1.000);
+ TERM DARK := Triangle 0.000 0.250 0.500;
+ TERM MEDIUM := Triangle 0.250 0.500 0.750;
+ TERM BRIGHT := Triangle 0.500 0.750 1.000;
+END_FUZZIFY
+
+DEFUZZIFY Power
+ RANGE := (0.000 .. 1.000);
+ TERM LOW := Triangle 0.000 0.250 0.500;
+ TERM MEDIUM := Triangle 0.250 0.500 0.750;
+ TERM HIGH := Triangle 0.500 0.750 1.000;
+ METHOD : COG;
+ ACCU : MAX;
+ DEFAULT := nan;
+END_DEFUZZIFY
+
+DEFUZZIFY InversePower
+ RANGE := (0.000 .. 1.000);
+ TERM LOW := Cosine 0.200 0.500;
+ TERM MEDIUM := Cosine 0.500 0.500;
+ TERM HIGH := Cosine 0.800 0.500;
+ METHOD : COG;
+ ACCU : MAX;
+ DEFAULT := nan;
+END_DEFUZZIFY
+
+RULEBLOCK
+ ACT : MIN;
+ RULE 1 : if Ambient is DARK then Power is HIGH
+ RULE 2 : if Ambient is MEDIUM then Power is MEDIUM
+ RULE 3 : if Ambient is BRIGHT then Power is LOW
+ RULE 4 : if Power is LOW then InversePower is HIGH
+ RULE 5 : if Power is MEDIUM then InversePower is MEDIUM
+ RULE 6 : if Power is HIGH then InversePower is LOW
+END_RULEBLOCK
+
+END_FUNCTION_BLOCK
diff --git a/examples/mamdani/SimpleDimmerChained.fis b/examples/mamdani/SimpleDimmerChained.fis
new file mode 100644
index 0000000..c2fc642
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerChained.fis
@@ -0,0 +1,46 @@
+#Code automatically generated with fuzzylite 6.0.
+
+[System]
+Name='SimpleDimmerChained'
+Type='mamdani'
+Version=6.0
+NumInputs=1
+NumOutputs=2
+NumRules=6
+AndMethod='min'
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
+DefuzzMethod='centroid'
+
+[Input1]
+Name='Ambient'
+Range=[0.000 1.000]
+NumMFs=3
+MF1='DARK':'trimf',[0.000 0.250 0.500]
+MF2='MEDIUM':'trimf',[0.250 0.500 0.750]
+MF3='BRIGHT':'trimf',[0.500 0.750 1.000]
+
+[Output1]
+Name='Power'
+Range=[0.000 1.000]
+NumMFs=3
+MF1='LOW':'trimf',[0.000 0.250 0.500]
+MF2='MEDIUM':'trimf',[0.250 0.500 0.750]
+MF3='HIGH':'trimf',[0.500 0.750 1.000]
+
+[Output2]
+Name='InversePower'
+Range=[0.000 1.000]
+NumMFs=3
+MF1='LOW':'cosinemf',[0.200 0.500]
+MF2='MEDIUM':'cosinemf',[0.500 0.500]
+MF3='HIGH':'cosinemf',[0.800 0.500]
+
+[Rules]
+1.000 , 3.000 0.000 (1.000) : 1
+2.000 , 2.000 0.000 (1.000) : 1
+3.000 , 1.000 0.000 (1.000) : 1
+0.000 , 0.000 3.000 (1.000) : 1
+0.000 , 0.000 2.000 (1.000) : 1
+0.000 , 0.000 1.000 (1.000) : 1
diff --git a/examples/mamdani/SimpleDimmerChained.fld b/examples/mamdani/SimpleDimmerChained.fld
new file mode 100644
index 0000000..843c017
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerChained.fld
@@ -0,0 +1,1025 @@
+Ambient Power InversePower
+0.000000000 nan nan
+0.000977517 0.750000000 0.221671502
+0.001955034 0.750000000 0.220306607
+0.002932551 0.750000000 0.219272108
+0.003910068 0.750000000 0.218372593
+0.004887586 0.750000000 0.217595038
+0.005865103 0.750000000 0.216891736
+0.006842620 0.750000000 0.216242049
+0.007820137 0.750000000 0.215635499
+0.008797654 0.750000000 0.215066121
+0.009775171 0.750000000 0.214530188
+0.010752688 0.750000000 0.214025192
+0.011730205 0.750000000 0.213535928
+0.012707722 0.750000000 0.213059653
+0.013685239 0.750000000 0.212609497
+0.014662757 0.750000000 0.212181500
+0.015640274 0.750000000 0.211749797
+0.016617791 0.750000000 0.211342499
+0.017595308 0.750000000 0.210947791
+0.018572825 0.750000000 0.210554977
+0.019550342 0.750000000 0.210185583
+0.020527859 0.750000000 0.209810047
+0.021505376 0.750000000 0.209453273
+0.022482893 0.750000000 0.209099710
+0.023460411 0.750000000 0.208754784
+0.024437928 0.750000000 0.208418460
+0.025415445 0.750000000 0.208108896
+0.026392962 0.750000000 0.207822337
+0.027370479 0.750000000 0.207557090
+0.028347996 0.750000000 0.207310043
+0.029325513 0.750000000 0.207080132
+0.030303030 0.750000000 0.206864987
+0.031280547 0.750000000 0.206663695
+0.032258065 0.750000000 0.206474685
+0.033235582 0.750000000 0.206296887
+0.034213099 0.750000000 0.206129563
+0.035190616 0.750000000 0.205971282
+0.036168133 0.750000000 0.205822154
+0.037145650 0.750000000 0.205680293
+0.038123167 0.750000000 0.205546551
+0.039100684 0.750000000 0.205418994
+0.040078201 0.750000000 0.205298019
+0.041055718 0.750000000 0.205182743
+0.042033236 0.750000000 0.205072718
+0.043010753 0.750000000 0.204968065
+0.043988270 0.750000000 0.204867643
+0.044965787 0.750000000 0.204772102
+0.045943304 0.750000000 0.204680372
+0.046920821 0.750000000 0.204592478
+0.047898338 0.750000000 0.204508389
+0.048875855 0.750000000 0.204427324
+0.049853372 0.750000000 0.204349869
+0.050830890 0.750000000 0.204275190
+0.051808407 0.750000000 0.204203265
+0.052785924 0.750000000 0.204134275
+0.053763441 0.750000000 0.204067513
+0.054740958 0.750000000 0.204003359
+0.055718475 0.750000000 0.203941436
+0.056695992 0.750000000 0.203881398
+0.057673509 0.750000000 0.203823826
+0.058651026 0.750000000 0.203767941
+0.059628543 0.750000000 0.203713842
+0.060606061 0.750000000 0.203661714
+0.061583578 0.750000000 0.203611030
+0.062561095 0.750000000 0.203562034
+0.063538612 0.750000000 0.203514617
+0.064516129 0.750000000 0.203468446
+0.065493646 0.750000000 0.203423862
+0.066471163 0.750000000 0.203380551
+0.067448680 0.750000000 0.203338322
+0.068426197 0.750000000 0.203297578
+0.069403715 0.750000000 0.203257869
+0.070381232 0.750000000 0.203219115
+0.071358749 0.750000000 0.203181723
+0.072336266 0.750000000 0.203145191
+0.073313783 0.750000000 0.203109538
+0.074291300 0.750000000 0.203075066
+0.075268817 0.750000000 0.203041351
+0.076246334 0.750000000 0.203008438
+0.077223851 0.750000000 0.202976564
+0.078201369 0.750000000 0.202945359
+0.079178886 0.750000000 0.202914878
+0.080156403 0.750000000 0.202885326
+0.081133920 0.750000000 0.202856368
+0.082111437 0.750000000 0.202828056
+0.083088954 0.750000000 0.202800588
+0.084066471 0.750000000 0.202773648
+0.085043988 0.750000000 0.202747278
+0.086021505 0.750000000 0.202721688
+0.086999022 0.750000000 0.202696569
+0.087976540 0.750000000 0.202671946
+0.088954057 0.750000000 0.202648053
+0.089931574 0.750000000 0.202624584
+0.090909091 0.750000000 0.202601536
+0.091886608 0.750000000 0.202579184
+0.092864125 0.750000000 0.202557213
+0.093841642 0.750000000 0.202535613
+0.094819159 0.750000000 0.202514642
+0.095796676 0.750000000 0.202494036
+0.096774194 0.750000000 0.202473765
+0.097751711 0.750000000 0.202454042
+0.098729228 0.750000000 0.202434684
+0.099706745 0.750000000 0.202415629
+0.100684262 0.750000000 0.202397043
+0.101661779 0.750000000 0.202378829
+0.102639296 0.750000000 0.202360889
+0.103616813 0.750000000 0.202343345
+0.104594330 0.750000000 0.202326181
+0.105571848 0.750000000 0.202309267
+0.106549365 0.750000000 0.202292677
+0.107526882 0.750000000 0.202276482
+0.108504399 0.750000000 0.202260514
+0.109481916 0.750000000 0.202244803
+0.110459433 0.750000000 0.202229501
+0.111436950 0.750000000 0.202214406
+0.112414467 0.750000000 0.202199515
+0.113391984 0.750000000 0.202185031
+0.114369501 0.750000000 0.202170746
+0.115347019 0.750000000 0.202156646
+0.116324536 0.750000000 0.202142887
+0.117302053 0.750000000 0.202129352
+0.118279570 0.750000000 0.202115988
+0.119257087 0.750000000 0.202102901
+0.120234604 0.750000000 0.202090065
+0.121212121 0.750000000 0.202077384
+0.122189638 0.750000000 0.202064922
+0.123167155 0.750000000 0.202052737
+0.124144673 0.750000000 0.202040694
+0.125122190 0.750000000 0.202028815
+0.126099707 0.750000000 0.202017236
+0.127077224 0.750000000 0.202005788
+0.128054741 0.750000000 0.201994470
+0.129032258 0.750000000 0.201983442
+0.130009775 0.750000000 0.201972551
+0.130987292 0.750000000 0.201961779
+0.131964809 0.750000000 0.201951246
+0.132942326 0.750000000 0.201940877
+0.133919844 0.750000000 0.201930618
+0.134897361 0.750000000 0.201920549
+0.135874878 0.750000000 0.201910669
+0.136852395 0.750000000 0.201900891
+0.137829912 0.750000000 0.201891259
+0.138807429 0.750000000 0.201881839
+0.139784946 0.750000000 0.201872513
+0.140762463 0.750000000 0.201863294
+0.141739980 0.750000000 0.201854307
+0.142717498 0.750000000 0.201845406
+0.143695015 0.750000000 0.201836590
+0.144672532 0.750000000 0.201827998
+0.145650049 0.750000000 0.201819498
+0.146627566 0.750000000 0.201811078
+0.147605083 0.750000000 0.201802845
+0.148582600 0.750000000 0.201794724
+0.149560117 0.750000000 0.201786676
+0.150537634 0.750000000 0.201778785
+0.151515152 0.750000000 0.201771022
+0.152492669 0.750000000 0.201763326
+0.153470186 0.750000000 0.201755760
+0.154447703 0.750000000 0.201748336
+0.155425220 0.750000000 0.201740974
+0.156402737 0.750000000 0.201733719
+0.157380254 0.750000000 0.201726616
+0.158357771 0.750000000 0.201719570
+0.159335288 0.750000000 0.201712612
+0.160312805 0.750000000 0.201705813
+0.161290323 0.750000000 0.201699068
+0.162267840 0.750000000 0.201692394
+0.163245357 0.750000000 0.201685884
+0.164222874 0.750000000 0.201679424
+0.165200391 0.750000000 0.201673024
+0.166177908 0.750000000 0.201666789
+0.167155425 0.750000000 0.201660600
+0.168132942 0.750000000 0.201654463
+0.169110459 0.750000000 0.201648489
+0.170087977 0.750000000 0.201642558
+0.171065494 0.750000000 0.201636676
+0.172043011 0.750000000 0.201630951
+0.173020528 0.750000000 0.201625266
+0.173998045 0.750000000 0.201619630
+0.174975562 0.750000000 0.201614142
+0.175953079 0.750000000 0.201608691
+0.176930596 0.750000000 0.201603293
+0.177908113 0.750000000 0.201598032
+0.178885630 0.750000000 0.201592805
+0.179863148 0.750000000 0.201587638
+0.180840665 0.750000000 0.201582594
+0.181818182 0.750000000 0.201577581
+0.182795699 0.750000000 0.201572640
+0.183773216 0.750000000 0.201567801
+0.184750733 0.750000000 0.201562993
+0.185728250 0.750000000 0.201558272
+0.186705767 0.750000000 0.201553632
+0.187683284 0.750000000 0.201549019
+0.188660802 0.750000000 0.201544513
+0.189638319 0.750000000 0.201540063
+0.190615836 0.750000000 0.201535638
+0.191593353 0.750000000 0.201531342
+0.192570870 0.750000000 0.201527074
+0.193548387 0.750000000 0.201522856
+0.194525904 0.750000000 0.201518740
+0.195503421 0.750000000 0.201514646
+0.196480938 0.750000000 0.201510635
+0.197458456 0.750000000 0.201506688
+0.198435973 0.750000000 0.201502762
+0.199413490 0.750000000 0.201498955
+0.200391007 0.750000000 0.201495170
+0.201368524 0.750000000 0.201491445
+0.202346041 0.750000000 0.201487799
+0.203323558 0.750000000 0.201484172
+0.204301075 0.750000000 0.201480648
+0.205278592 0.750000000 0.201477155
+0.206256109 0.750000000 0.201473716
+0.207233627 0.750000000 0.201470354
+0.208211144 0.750000000 0.201467007
+0.209188661 0.750000000 0.201463769
+0.210166178 0.750000000 0.201460550
+0.211143695 0.750000000 0.201457402
+0.212121212 0.750000000 0.201454307
+0.213098729 0.750000000 0.201451251
+0.214076246 0.750000000 0.201448278
+0.215053763 0.750000000 0.201445318
+0.216031281 0.750000000 0.201442464
+0.217008798 0.750000000 0.201439621
+0.217986315 0.750000000 0.201436866
+0.218963832 0.750000000 0.201434139
+0.219941349 0.750000000 0.201431486
+0.220918866 0.750000000 0.201428872
+0.221896383 0.750000000 0.201426324
+0.222873900 0.750000000 0.201423821
+0.223851417 0.750000000 0.201421381
+0.224828935 0.750000000 0.201418988
+0.225806452 0.750000000 0.201416661
+0.226783969 0.750000000 0.201414375
+0.227761486 0.750000000 0.201412163
+0.228739003 0.750000000 0.201409982
+0.229716520 0.750000000 0.201407891
+0.230694037 0.750000000 0.201405828
+0.231671554 0.750000000 0.201403846
+0.232649071 0.750000000 0.201401913
+0.233626588 0.750000000 0.201400032
+0.234604106 0.750000000 0.201398232
+0.235581623 0.750000000 0.201396477
+0.236559140 0.750000000 0.201394788
+0.237536657 0.750000000 0.201393176
+0.238514174 0.750000000 0.201391621
+0.239491691 0.750000000 0.201390128
+0.240469208 0.750000000 0.201388719
+0.241446725 0.750000000 0.201387385
+0.242424242 0.750000000 0.201386125
+0.243401760 0.750000000 0.201384946
+0.244379277 0.750000000 0.201383854
+0.245356794 0.750000000 0.201382854
+0.246334311 0.750000000 0.201381954
+0.247311828 0.750000000 0.201381173
+0.248289345 0.750000000 0.201380522
+0.249266862 0.750000000 0.201380043
+0.250244379 0.749633789 0.201846207
+0.251221896 0.748176070 0.203676892
+0.252199413 0.746729651 0.205470420
+0.253176931 0.745307268 0.207232921
+0.254154448 0.743901152 0.208969603
+0.255131965 0.742505384 0.210681995
+0.256109482 0.741119851 0.212371422
+0.257086999 0.739744439 0.214039141
+0.258064516 0.738388970 0.215686343
+0.259042033 0.737050250 0.217314161
+0.260019550 0.735720805 0.218923667
+0.260997067 0.734400539 0.220515879
+0.261974585 0.733089356 0.222091759
+0.262952102 0.731794526 0.223649762
+0.263929619 0.730516794 0.225192151
+0.264907136 0.729247388 0.226720383
+0.265884653 0.727986227 0.228232727
+0.266862170 0.726733231 0.229730635
+0.267839687 0.725493442 0.231216292
+0.268817204 0.724270974 0.232685872
+0.269794721 0.723055990 0.234144013
+0.270772239 0.721848423 0.235588818
+0.271749756 0.720648204 0.237021028
+0.272727273 0.719458438 0.238442032
+0.273704790 0.718286101 0.239849792
+0.274682307 0.717120499 0.241247924
+0.275659824 0.715961575 0.242632618
+0.276637341 0.714809270 0.244008759
+0.277614858 0.713665012 0.245371680
+0.278592375 0.712538184 0.246726670
+0.279569892 0.711417421 0.248069026
+0.280547410 0.710302674 0.249403669
+0.281524927 0.709193894 0.250726587
+0.282502444 0.708091063 0.252041647
+0.283479961 0.707005566 0.253346179
+0.284457478 0.705925531 0.254642389
+0.285434995 0.704850918 0.255929518
+0.286412512 0.703781686 0.257207578
+0.287390029 0.702717795 0.258478219
+0.288367546 0.701668621 0.259738800
+0.289345064 0.700625580 0.260993370
+0.290322581 0.699587425 0.262237549
+0.291300098 0.698554121 0.263475527
+0.292277615 0.697525635 0.264705239
+0.293255132 0.696509490 0.265927232
+0.294232649 0.695500037 0.267143201
+0.295210166 0.694494984 0.268349791
+0.296187683 0.693494303 0.269551115
+0.297165200 0.692497965 0.270744440
+0.298142717 0.691511860 0.271931138
+0.299120235 0.690532874 0.273112342
+0.300097752 0.689557847 0.274284946
+0.301075269 0.688586755 0.275452739
+0.302052786 0.687619575 0.276613621
+0.303030303 0.686660765 0.277768031
+0.304007820 0.685709376 0.278917856
+0.304985337 0.684761545 0.280059697
+0.305962854 0.683817249 0.281196818
+0.306940371 0.682876470 0.282328684
+0.307917889 0.681942420 0.283453563
+0.308895406 0.681015980 0.284574256
+0.309872923 0.680092726 0.285688972
+0.310850440 0.679172643 0.286798049
+0.311827957 0.678255714 0.287903138
+0.312805474 0.677344077 0.289001763
+0.313782991 0.676440126 0.290095833
+0.314760508 0.675539023 0.291186105
+0.315738025 0.674640752 0.292269631
+0.316715543 0.673745302 0.293349456
+0.317693060 0.672853893 0.294425247
+0.318670577 0.671970143 0.295495017
+0.319648094 0.671088924 0.296561328
+0.320625611 0.670210227 0.297623455
+0.321603128 0.669334041 0.298680243
+0.322580645 0.668460818 0.299733738
+0.323558162 0.667595126 0.300783030
+0.324535679 0.666731672 0.301827515
+0.325513196 0.665870450 0.302868868
+0.326490714 0.665011449 0.303906100
+0.327468231 0.664154662 0.304938935
+0.328445748 0.663304848 0.305968793
+0.329423265 0.662457164 0.306994695
+0.330400782 0.661611439 0.308016510
+0.331378299 0.660767667 0.309035496
+0.332355816 0.659925840 0.310050754
+0.333333333 0.659089669 0.311062154
+0.334310850 0.658255868 0.312070870
+0.335288368 0.657423770 0.313076130
+0.336265885 0.656593371 0.314077703
+0.337243402 0.655764665 0.315076729
+0.338220919 0.654940458 0.316071981
+0.339198436 0.654118746 0.317062640
+0.340175953 0.653298497 0.318050990
+0.341153470 0.652479705 0.319036167
+0.342130987 0.651662368 0.320016921
+0.343108504 0.650848521 0.320995595
+0.344086022 0.650037186 0.321971698
+0.345063539 0.649227083 0.322943523
+0.346041056 0.648418210 0.323913488
+0.347018573 0.647610563 0.324881463
+0.347996090 0.646805538 0.325845303
+0.348973607 0.646002934 0.326807497
+0.349951124 0.645201343 0.327768050
+0.350928641 0.644400763 0.328725018
+0.351906158 0.643601190 0.329680354
+0.352883675 0.642803505 0.330634256
+0.353861193 0.642008044 0.331585332
+0.354838710 0.641213384 0.332534700
+0.355816227 0.640419523 0.333482835
+0.356793744 0.639626459 0.334428830
+0.357771261 0.638834675 0.335373101
+0.358748778 0.638044814 0.336316337
+0.359726295 0.637255548 0.337258027
+0.360703812 0.636466876 0.338198057
+0.361681329 0.635678797 0.339137245
+0.362658847 0.634891512 0.340075384
+0.363636364 0.634105743 0.341012014
+0.364613881 0.633320368 0.341947992
+0.365591398 0.632535386 0.342883313
+0.366568915 0.631750798 0.343817374
+0.367546432 0.630966638 0.344750971
+0.368523949 0.630183479 0.345684104
+0.369501466 0.629400516 0.346616504
+0.370478983 0.628617749 0.347548540
+0.371456500 0.627835178 0.348480299
+0.372434018 0.627052803 0.349411745
+0.373411535 0.626270772 0.350343037
+0.374389052 0.625488759 0.351274237
+0.375366569 0.624706745 0.352205426
+0.376344086 0.623924731 0.353136787
+0.377321603 0.623142717 0.354068240
+0.378299120 0.622360434 0.354999866
+0.379276637 0.621577912 0.355932108
+0.380254154 0.620795194 0.356864629
+0.381231672 0.620012280 0.357797428
+0.382209189 0.619229171 0.358731329
+0.383186706 0.618445288 0.359665733
+0.384164223 0.617660798 0.360600602
+0.385141740 0.616875914 0.361536789
+0.386119257 0.616090638 0.362473899
+0.387096774 0.615304967 0.363411663
+0.388074291 0.614518130 0.364350853
+0.389051808 0.613730200 0.365291500
+0.390029326 0.612941676 0.366232990
+0.391006843 0.612152558 0.367175921
+0.391984360 0.611362846 0.368120944
+0.392961877 0.610571682 0.369067005
+0.393939394 0.609778818 0.370014435
+0.394916911 0.608985156 0.370964689
+0.395894428 0.608190696 0.371916178
+0.396871945 0.607395436 0.372868906
+0.397849462 0.606598545 0.373825246
+0.398826979 0.605799225 0.374783038
+0.399804497 0.604998896 0.375742272
+0.400782014 0.604197558 0.376705194
+0.401759531 0.603395208 0.377670184
+0.402737048 0.602591157 0.378636823
+0.403714565 0.601783817 0.379607193
+0.404692082 0.600975251 0.380580296
+0.405669599 0.600165455 0.381555265
+0.406647116 0.599354429 0.382533989
+0.407624633 0.598541740 0.383516150
+0.408602151 0.597724765 0.384500397
+0.409579668 0.596906338 0.385488433
+0.410557185 0.596086453 0.386480623
+0.411534702 0.595265107 0.387475131
+0.412512219 0.594442248 0.388473492
+0.413489736 0.593613964 0.389476718
+0.414467253 0.592783988 0.390482499
+0.415444770 0.591952316 0.391491555
+0.416422287 0.591118941 0.392504668
+0.417399804 0.590283858 0.393520477
+0.418377322 0.589442972 0.394539685
+0.419354839 0.588599687 0.395563270
+0.420332356 0.587754450 0.396589695
+0.421309873 0.586907257 0.397619709
+0.422287390 0.586058099 0.398654373
+0.423264907 0.585202955 0.399692025
+0.424242424 0.584344508 0.400733540
+0.425219941 0.583483842 0.401779909
+0.426197458 0.582620947 0.402829422
+0.427174976 0.581755815 0.403883177
+0.428152493 0.580884615 0.404941902
+0.429130010 0.580009054 0.406003935
+0.430107527 0.579130986 0.407070716
+0.431085044 0.578250399 0.408142475
+0.432062561 0.577367283 0.409217712
+0.433040078 0.576478121 0.410298357
+0.434017595 0.575583374 0.411383856
+0.434995112 0.574685810 0.412473008
+0.435972630 0.573785416 0.413568413
+0.436950147 0.572882178 0.414668387
+0.437927664 0.571973027 0.415772198
+0.438905181 0.571056884 0.416883317
+0.439882698 0.570137591 0.417998533
+0.440860215 0.569215132 0.419118581
+0.441837732 0.568289490 0.420245634
+0.442815249 0.567358177 0.421376894
+0.443792766 0.566418275 0.422514343
+0.444770283 0.565474860 0.423658069
+0.445747801 0.564527914 0.424806212
+0.446725318 0.563577417 0.425962211
+0.447702835 0.562621612 0.427123480
+0.448680352 0.561655405 0.428290282
+0.449657869 0.560685294 0.429465166
+0.450635386 0.559711253 0.430644890
+0.451612903 0.558733259 0.431832308
+0.452590420 0.557750445 0.433026364
+0.453567937 0.556755188 0.434226000
+0.454545455 0.555755595 0.435434924
+0.455522972 0.554751638 0.436649146
+0.456500489 0.553743287 0.437871753
+0.457478006 0.552730515 0.439101626
+0.458455523 0.551703450 0.440338101
+0.459433040 0.550671354 0.441584214
+0.460410557 0.549634415 0.442836126
+0.461388074 0.548592599 0.444098260
+0.462365591 0.547545872 0.445367270
+0.463343109 0.546484786 0.446645195
+0.464320626 0.545416893 0.447931951
+0.465298143 0.544343629 0.449226535
+0.466275660 0.543264953 0.450531713
+0.467253177 0.542180826 0.451843888
+0.468230694 0.541082374 0.453168194
+0.469208211 0.539975079 0.454499403
+0.470185728 0.538861828 0.455843131
+0.471163245 0.537742573 0.457194500
+0.472140762 0.536617267 0.458558366
+0.473118280 0.535477779 0.459930679
+0.474095797 0.534327120 0.461315854
+0.475073314 0.533169855 0.462709935
+0.476050831 0.532005928 0.464117671
+0.477028348 0.530835281 0.465534381
+0.478005865 0.529650711 0.466952620
+0.478983382 0.528452318 0.468377996
+0.479960899 0.527246594 0.469806093
+0.480938416 0.526033471 0.471239943
+0.481915934 0.524812880 0.472678374
+0.482893451 0.523578752 0.474120606
+0.483870968 0.522327784 0.475569070
+0.484848485 0.521068672 0.477020289
+0.485826002 0.519801335 0.478476759
+0.486803519 0.518525692 0.479938796
+0.487781036 0.517237031 0.481403707
+0.488758553 0.515928105 0.482873363
+0.489736070 0.514610118 0.484347894
+0.490713587 0.513282977 0.485826893
+0.491691105 0.511946585 0.487309221
+0.492668622 0.510597845 0.488795133
+0.493646139 0.509224947 0.490284775
+0.494623656 0.507841954 0.491777716
+0.495601173 0.506448755 0.493273513
+0.496578690 0.505045237 0.494770784
+0.497556207 0.503630203 0.496268873
+0.498533724 0.502186589 0.497766318
+0.499511241 0.500731707 0.499259366
+0.500488759 0.499268293 0.500740634
+0.501466276 0.497813411 0.502233682
+0.502443793 0.496369797 0.503731127
+0.503421310 0.494954763 0.505229216
+0.504398827 0.493551245 0.506726487
+0.505376344 0.492158046 0.508222284
+0.506353861 0.490775053 0.509715225
+0.507331378 0.489402155 0.511204867
+0.508308895 0.488053415 0.512690779
+0.509286413 0.486717023 0.514173107
+0.510263930 0.485389882 0.515652106
+0.511241447 0.484071895 0.517126637
+0.512218964 0.482762969 0.518596293
+0.513196481 0.481474308 0.520061204
+0.514173998 0.480198665 0.521523241
+0.515151515 0.478931328 0.522979711
+0.516129032 0.477672216 0.524430930
+0.517106549 0.476421248 0.525879394
+0.518084066 0.475187120 0.527321626
+0.519061584 0.473966529 0.528760057
+0.520039101 0.472753406 0.530193907
+0.521016618 0.471547682 0.531622004
+0.521994135 0.470349289 0.533047380
+0.522971652 0.469164719 0.534465619
+0.523949169 0.467994072 0.535882329
+0.524926686 0.466830145 0.537290065
+0.525904203 0.465672880 0.538684146
+0.526881720 0.464522221 0.540069321
+0.527859238 0.463382733 0.541441634
+0.528836755 0.462257427 0.542805500
+0.529814272 0.461138172 0.544156869
+0.530791789 0.460024921 0.545500597
+0.531769306 0.458917626 0.546831806
+0.532746823 0.457819174 0.548156112
+0.533724340 0.456735047 0.549468287
+0.534701857 0.455656371 0.550773465
+0.535679374 0.454583107 0.552068049
+0.536656891 0.453515214 0.553354805
+0.537634409 0.452454128 0.554632730
+0.538611926 0.451407401 0.555901740
+0.539589443 0.450365585 0.557163874
+0.540566960 0.449328646 0.558415786
+0.541544477 0.448296550 0.559661899
+0.542521994 0.447269485 0.560898374
+0.543499511 0.446256713 0.562128247
+0.544477028 0.445248362 0.563350854
+0.545454545 0.444244405 0.564565076
+0.546432063 0.443244812 0.565774000
+0.547409580 0.442249555 0.566973636
+0.548387097 0.441266741 0.568167692
+0.549364614 0.440288747 0.569355110
+0.550342131 0.439314706 0.570534834
+0.551319648 0.438344595 0.571709718
+0.552297165 0.437378388 0.572876520
+0.553274682 0.436422583 0.574037789
+0.554252199 0.435472086 0.575193788
+0.555229717 0.434525140 0.576341931
+0.556207234 0.433581725 0.577485657
+0.557184751 0.432641823 0.578623106
+0.558162268 0.431710510 0.579754366
+0.559139785 0.430784868 0.580881419
+0.560117302 0.429862409 0.582001467
+0.561094819 0.428943116 0.583116683
+0.562072336 0.428026973 0.584227802
+0.563049853 0.427117822 0.585331613
+0.564027370 0.426214584 0.586431587
+0.565004888 0.425314190 0.587526992
+0.565982405 0.424416626 0.588616144
+0.566959922 0.423521879 0.589701643
+0.567937439 0.422632717 0.590782288
+0.568914956 0.421749601 0.591857525
+0.569892473 0.420869014 0.592929284
+0.570869990 0.419990946 0.593996065
+0.571847507 0.419115385 0.595058098
+0.572825024 0.418244185 0.596116823
+0.573802542 0.417379053 0.597170578
+0.574780059 0.416516158 0.598220091
+0.575757576 0.415655492 0.599266460
+0.576735093 0.414797045 0.600307975
+0.577712610 0.413941901 0.601345627
+0.578690127 0.413092743 0.602380291
+0.579667644 0.412245550 0.603410305
+0.580645161 0.411400313 0.604436730
+0.581622678 0.410557028 0.605460315
+0.582600196 0.409716142 0.606479523
+0.583577713 0.408881059 0.607495332
+0.584555230 0.408047684 0.608508445
+0.585532747 0.407216012 0.609517501
+0.586510264 0.406386036 0.610523282
+0.587487781 0.405557752 0.611526508
+0.588465298 0.404734893 0.612524869
+0.589442815 0.403913547 0.613519377
+0.590420332 0.403093662 0.614511567
+0.591397849 0.402275235 0.615499603
+0.592375367 0.401458260 0.616483850
+0.593352884 0.400645571 0.617466011
+0.594330401 0.399834545 0.618444735
+0.595307918 0.399024749 0.619419704
+0.596285435 0.398216183 0.620392807
+0.597262952 0.397408843 0.621363177
+0.598240469 0.396604792 0.622329816
+0.599217986 0.395802442 0.623294806
+0.600195503 0.395001104 0.624257728
+0.601173021 0.394200775 0.625216962
+0.602150538 0.393401455 0.626174754
+0.603128055 0.392604564 0.627131094
+0.604105572 0.391809304 0.628083822
+0.605083089 0.391014844 0.629035311
+0.606060606 0.390221182 0.629985565
+0.607038123 0.389428318 0.630932995
+0.608015640 0.388637154 0.631879056
+0.608993157 0.387847442 0.632824079
+0.609970674 0.387058324 0.633767010
+0.610948192 0.386269800 0.634708500
+0.611925709 0.385481870 0.635649147
+0.612903226 0.384695033 0.636588337
+0.613880743 0.383909362 0.637526101
+0.614858260 0.383124086 0.638463211
+0.615835777 0.382339202 0.639399398
+0.616813294 0.381554712 0.640334267
+0.617790811 0.380770829 0.641268671
+0.618768328 0.379987720 0.642202572
+0.619745846 0.379204806 0.643135371
+0.620723363 0.378422088 0.644067892
+0.621700880 0.377639566 0.645000134
+0.622678397 0.376857283 0.645931760
+0.623655914 0.376075269 0.646863213
+0.624633431 0.375293255 0.647794574
+0.625610948 0.374511241 0.648725763
+0.626588465 0.373729228 0.649656963
+0.627565982 0.372947197 0.650588255
+0.628543500 0.372164822 0.651519701
+0.629521017 0.371382251 0.652451460
+0.630498534 0.370599484 0.653383496
+0.631476051 0.369816521 0.654315896
+0.632453568 0.369033362 0.655249029
+0.633431085 0.368249202 0.656182626
+0.634408602 0.367464614 0.657116687
+0.635386119 0.366679632 0.658052008
+0.636363636 0.365894257 0.658987986
+0.637341153 0.365108488 0.659924616
+0.638318671 0.364321203 0.660862755
+0.639296188 0.363533124 0.661801943
+0.640273705 0.362744452 0.662741973
+0.641251222 0.361955186 0.663683663
+0.642228739 0.361165325 0.664626899
+0.643206256 0.360373541 0.665571170
+0.644183773 0.359580477 0.666517165
+0.645161290 0.358786616 0.667465300
+0.646138807 0.357991956 0.668414668
+0.647116325 0.357196495 0.669365744
+0.648093842 0.356398810 0.670319646
+0.649071359 0.355599237 0.671274982
+0.650048876 0.354798657 0.672231950
+0.651026393 0.353997066 0.673192503
+0.652003910 0.353194462 0.674154697
+0.652981427 0.352389437 0.675118537
+0.653958944 0.351581790 0.676086512
+0.654936461 0.350772917 0.677056477
+0.655913978 0.349962814 0.678028302
+0.656891496 0.349151479 0.679004405
+0.657869013 0.348337632 0.679983079
+0.658846530 0.347520295 0.680963833
+0.659824047 0.346701503 0.681949010
+0.660801564 0.345881254 0.682937360
+0.661779081 0.345059542 0.683928019
+0.662756598 0.344235335 0.684923271
+0.663734115 0.343406629 0.685922297
+0.664711632 0.342576230 0.686923870
+0.665689150 0.341744132 0.687929130
+0.666666667 0.340910331 0.688937846
+0.667644184 0.340074160 0.689949246
+0.668621701 0.339232333 0.690964504
+0.669599218 0.338388561 0.691983490
+0.670576735 0.337542836 0.693005305
+0.671554252 0.336695152 0.694031207
+0.672531769 0.335845338 0.695061065
+0.673509286 0.334988551 0.696093900
+0.674486804 0.334129550 0.697131132
+0.675464321 0.333268328 0.698172485
+0.676441838 0.332404874 0.699216970
+0.677419355 0.331539182 0.700266262
+0.678396872 0.330665959 0.701319757
+0.679374389 0.329789773 0.702376545
+0.680351906 0.328911076 0.703438672
+0.681329423 0.328029857 0.704504983
+0.682306940 0.327146107 0.705574753
+0.683284457 0.326254698 0.706650544
+0.684261975 0.325359248 0.707730369
+0.685239492 0.324460977 0.708813895
+0.686217009 0.323559874 0.709904167
+0.687194526 0.322655923 0.710998237
+0.688172043 0.321744286 0.712096862
+0.689149560 0.320827357 0.713201951
+0.690127077 0.319907274 0.714311028
+0.691104594 0.318984020 0.715425744
+0.692082111 0.318057580 0.716546437
+0.693059629 0.317123530 0.717671316
+0.694037146 0.316182751 0.718803182
+0.695014663 0.315238455 0.719940303
+0.695992180 0.314290624 0.721082144
+0.696969697 0.313339235 0.722231969
+0.697947214 0.312380425 0.723386379
+0.698924731 0.311413245 0.724547261
+0.699902248 0.310442153 0.725715054
+0.700879765 0.309467126 0.726887658
+0.701857283 0.308488140 0.728068862
+0.702834800 0.307502035 0.729255560
+0.703812317 0.306505697 0.730448885
+0.704789834 0.305505016 0.731650209
+0.705767351 0.304499963 0.732856799
+0.706744868 0.303490510 0.734072768
+0.707722385 0.302474365 0.735294761
+0.708699902 0.301445879 0.736524473
+0.709677419 0.300412575 0.737762451
+0.710654936 0.299374420 0.739006630
+0.711632454 0.298331379 0.740261200
+0.712609971 0.297282205 0.741521781
+0.713587488 0.296218314 0.742792422
+0.714565005 0.295149082 0.744070482
+0.715542522 0.294074469 0.745357611
+0.716520039 0.292994434 0.746653821
+0.717497556 0.291908937 0.747958353
+0.718475073 0.290806106 0.749273413
+0.719452590 0.289697326 0.750596331
+0.720430108 0.288582579 0.751930974
+0.721407625 0.287461816 0.753273330
+0.722385142 0.286334988 0.754628320
+0.723362659 0.285190730 0.755991241
+0.724340176 0.284038425 0.757367382
+0.725317693 0.282879501 0.758752076
+0.726295210 0.281713899 0.760150208
+0.727272727 0.280541562 0.761557968
+0.728250244 0.279351796 0.762978972
+0.729227761 0.278151577 0.764411182
+0.730205279 0.276944010 0.765855987
+0.731182796 0.275729026 0.767314128
+0.732160313 0.274506558 0.768783708
+0.733137830 0.273266769 0.770269365
+0.734115347 0.272013773 0.771767273
+0.735092864 0.270752612 0.773279617
+0.736070381 0.269483206 0.774807849
+0.737047898 0.268205474 0.776350238
+0.738025415 0.266910644 0.777908241
+0.739002933 0.265599461 0.779484121
+0.739980450 0.264279195 0.781076333
+0.740957967 0.262949750 0.782685839
+0.741935484 0.261611030 0.784313657
+0.742913001 0.260255561 0.785960859
+0.743890518 0.258880149 0.787628578
+0.744868035 0.257494616 0.789318005
+0.745845552 0.256098848 0.791030397
+0.746823069 0.254692732 0.792767079
+0.747800587 0.253270349 0.794529580
+0.748778104 0.251823930 0.796323108
+0.749755621 0.250366211 0.798153793
+0.750733138 0.250000000 0.798619957
+0.751710655 0.250000000 0.798619478
+0.752688172 0.250000000 0.798618827
+0.753665689 0.250000000 0.798618046
+0.754643206 0.250000000 0.798617146
+0.755620723 0.250000000 0.798616146
+0.756598240 0.250000000 0.798615054
+0.757575758 0.250000000 0.798613875
+0.758553275 0.250000000 0.798612615
+0.759530792 0.250000000 0.798611281
+0.760508309 0.250000000 0.798609872
+0.761485826 0.250000000 0.798608379
+0.762463343 0.250000000 0.798606824
+0.763440860 0.250000000 0.798605212
+0.764418377 0.250000000 0.798603523
+0.765395894 0.250000000 0.798601768
+0.766373412 0.250000000 0.798599968
+0.767350929 0.250000000 0.798598087
+0.768328446 0.250000000 0.798596154
+0.769305963 0.250000000 0.798594172
+0.770283480 0.250000000 0.798592109
+0.771260997 0.250000000 0.798590018
+0.772238514 0.250000000 0.798587837
+0.773216031 0.250000000 0.798585625
+0.774193548 0.250000000 0.798583339
+0.775171065 0.250000000 0.798581012
+0.776148583 0.250000000 0.798578619
+0.777126100 0.250000000 0.798576179
+0.778103617 0.250000000 0.798573676
+0.779081134 0.250000000 0.798571128
+0.780058651 0.250000000 0.798568514
+0.781036168 0.250000000 0.798565861
+0.782013685 0.250000000 0.798563134
+0.782991202 0.250000000 0.798560379
+0.783968719 0.250000000 0.798557536
+0.784946237 0.250000000 0.798554682
+0.785923754 0.250000000 0.798551722
+0.786901271 0.250000000 0.798548749
+0.787878788 0.250000000 0.798545693
+0.788856305 0.250000000 0.798542598
+0.789833822 0.250000000 0.798539450
+0.790811339 0.250000000 0.798536231
+0.791788856 0.250000000 0.798532993
+0.792766373 0.250000000 0.798529646
+0.793743891 0.250000000 0.798526284
+0.794721408 0.250000000 0.798522845
+0.795698925 0.250000000 0.798519352
+0.796676442 0.250000000 0.798515828
+0.797653959 0.250000000 0.798512201
+0.798631476 0.250000000 0.798508555
+0.799608993 0.250000000 0.798504830
+0.800586510 0.250000000 0.798501045
+0.801564027 0.250000000 0.798497238
+0.802541544 0.250000000 0.798493312
+0.803519062 0.250000000 0.798489365
+0.804496579 0.250000000 0.798485354
+0.805474096 0.250000000 0.798481260
+0.806451613 0.250000000 0.798477144
+0.807429130 0.250000000 0.798472926
+0.808406647 0.250000000 0.798468658
+0.809384164 0.250000000 0.798464362
+0.810361681 0.250000000 0.798459937
+0.811339198 0.250000000 0.798455487
+0.812316716 0.250000000 0.798450981
+0.813294233 0.250000000 0.798446368
+0.814271750 0.250000000 0.798441728
+0.815249267 0.250000000 0.798437007
+0.816226784 0.250000000 0.798432199
+0.817204301 0.250000000 0.798427360
+0.818181818 0.250000000 0.798422419
+0.819159335 0.250000000 0.798417406
+0.820136852 0.250000000 0.798412362
+0.821114370 0.250000000 0.798407195
+0.822091887 0.250000000 0.798401968
+0.823069404 0.250000000 0.798396707
+0.824046921 0.250000000 0.798391309
+0.825024438 0.250000000 0.798385858
+0.826001955 0.250000000 0.798380370
+0.826979472 0.250000000 0.798374734
+0.827956989 0.250000000 0.798369049
+0.828934506 0.250000000 0.798363324
+0.829912023 0.250000000 0.798357442
+0.830889541 0.250000000 0.798351511
+0.831867058 0.250000000 0.798345537
+0.832844575 0.250000000 0.798339400
+0.833822092 0.250000000 0.798333211
+0.834799609 0.250000000 0.798326976
+0.835777126 0.250000000 0.798320576
+0.836754643 0.250000000 0.798314116
+0.837732160 0.250000000 0.798307606
+0.838709677 0.250000000 0.798300932
+0.839687195 0.250000000 0.798294187
+0.840664712 0.250000000 0.798287388
+0.841642229 0.250000000 0.798280430
+0.842619746 0.250000000 0.798273384
+0.843597263 0.250000000 0.798266281
+0.844574780 0.250000000 0.798259026
+0.845552297 0.250000000 0.798251664
+0.846529814 0.250000000 0.798244240
+0.847507331 0.250000000 0.798236674
+0.848484848 0.250000000 0.798228978
+0.849462366 0.250000000 0.798221215
+0.850439883 0.250000000 0.798213324
+0.851417400 0.250000000 0.798205276
+0.852394917 0.250000000 0.798197155
+0.853372434 0.250000000 0.798188922
+0.854349951 0.250000000 0.798180502
+0.855327468 0.250000000 0.798172002
+0.856304985 0.250000000 0.798163410
+0.857282502 0.250000000 0.798154594
+0.858260020 0.250000000 0.798145693
+0.859237537 0.250000000 0.798136706
+0.860215054 0.250000000 0.798127487
+0.861192571 0.250000000 0.798118161
+0.862170088 0.250000000 0.798108741
+0.863147605 0.250000000 0.798099109
+0.864125122 0.250000000 0.798089331
+0.865102639 0.250000000 0.798079451
+0.866080156 0.250000000 0.798069382
+0.867057674 0.250000000 0.798059123
+0.868035191 0.250000000 0.798048754
+0.869012708 0.250000000 0.798038221
+0.869990225 0.250000000 0.798027449
+0.870967742 0.250000000 0.798016558
+0.871945259 0.250000000 0.798005530
+0.872922776 0.250000000 0.797994212
+0.873900293 0.250000000 0.797982764
+0.874877810 0.250000000 0.797971185
+0.875855327 0.250000000 0.797959306
+0.876832845 0.250000000 0.797947263
+0.877810362 0.250000000 0.797935078
+0.878787879 0.250000000 0.797922616
+0.879765396 0.250000000 0.797909935
+0.880742913 0.250000000 0.797897099
+0.881720430 0.250000000 0.797884012
+0.882697947 0.250000000 0.797870648
+0.883675464 0.250000000 0.797857113
+0.884652981 0.250000000 0.797843354
+0.885630499 0.250000000 0.797829254
+0.886608016 0.250000000 0.797814969
+0.887585533 0.250000000 0.797800485
+0.888563050 0.250000000 0.797785594
+0.889540567 0.250000000 0.797770499
+0.890518084 0.250000000 0.797755197
+0.891495601 0.250000000 0.797739486
+0.892473118 0.250000000 0.797723518
+0.893450635 0.250000000 0.797707323
+0.894428152 0.250000000 0.797690733
+0.895405670 0.250000000 0.797673819
+0.896383187 0.250000000 0.797656655
+0.897360704 0.250000000 0.797639111
+0.898338221 0.250000000 0.797621171
+0.899315738 0.250000000 0.797602957
+0.900293255 0.250000000 0.797584371
+0.901270772 0.250000000 0.797565316
+0.902248289 0.250000000 0.797545958
+0.903225806 0.250000000 0.797526235
+0.904203324 0.250000000 0.797505964
+0.905180841 0.250000000 0.797485358
+0.906158358 0.250000000 0.797464387
+0.907135875 0.250000000 0.797442787
+0.908113392 0.250000000 0.797420816
+0.909090909 0.250000000 0.797398464
+0.910068426 0.250000000 0.797375416
+0.911045943 0.250000000 0.797351947
+0.912023460 0.250000000 0.797328054
+0.913000978 0.250000000 0.797303431
+0.913978495 0.250000000 0.797278312
+0.914956012 0.250000000 0.797252722
+0.915933529 0.250000000 0.797226352
+0.916911046 0.250000000 0.797199412
+0.917888563 0.250000000 0.797171944
+0.918866080 0.250000000 0.797143632
+0.919843597 0.250000000 0.797114674
+0.920821114 0.250000000 0.797085122
+0.921798631 0.250000000 0.797054641
+0.922776149 0.250000000 0.797023436
+0.923753666 0.250000000 0.796991562
+0.924731183 0.250000000 0.796958649
+0.925708700 0.250000000 0.796924934
+0.926686217 0.250000000 0.796890462
+0.927663734 0.250000000 0.796854809
+0.928641251 0.250000000 0.796818277
+0.929618768 0.250000000 0.796780885
+0.930596285 0.250000000 0.796742131
+0.931573803 0.250000000 0.796702422
+0.932551320 0.250000000 0.796661678
+0.933528837 0.250000000 0.796619449
+0.934506354 0.250000000 0.796576138
+0.935483871 0.250000000 0.796531554
+0.936461388 0.250000000 0.796485383
+0.937438905 0.250000000 0.796437966
+0.938416422 0.250000000 0.796388970
+0.939393939 0.250000000 0.796338286
+0.940371457 0.250000000 0.796286158
+0.941348974 0.250000000 0.796232059
+0.942326491 0.250000000 0.796176174
+0.943304008 0.250000000 0.796118602
+0.944281525 0.250000000 0.796058564
+0.945259042 0.250000000 0.795996641
+0.946236559 0.250000000 0.795932487
+0.947214076 0.250000000 0.795865725
+0.948191593 0.250000000 0.795796735
+0.949169110 0.250000000 0.795724810
+0.950146628 0.250000000 0.795650131
+0.951124145 0.250000000 0.795572676
+0.952101662 0.250000000 0.795491611
+0.953079179 0.250000000 0.795407522
+0.954056696 0.250000000 0.795319628
+0.955034213 0.250000000 0.795227898
+0.956011730 0.250000000 0.795132357
+0.956989247 0.250000000 0.795031935
+0.957966764 0.250000000 0.794927282
+0.958944282 0.250000000 0.794817257
+0.959921799 0.250000000 0.794701981
+0.960899316 0.250000000 0.794581006
+0.961876833 0.250000000 0.794453449
+0.962854350 0.250000000 0.794319707
+0.963831867 0.250000000 0.794177846
+0.964809384 0.250000000 0.794028718
+0.965786901 0.250000000 0.793870437
+0.966764418 0.250000000 0.793703113
+0.967741935 0.250000000 0.793525315
+0.968719453 0.250000000 0.793336305
+0.969696970 0.250000000 0.793135013
+0.970674487 0.250000000 0.792919868
+0.971652004 0.250000000 0.792689957
+0.972629521 0.250000000 0.792442910
+0.973607038 0.250000000 0.792177663
+0.974584555 0.250000000 0.791891104
+0.975562072 0.250000000 0.791581540
+0.976539589 0.250000000 0.791245216
+0.977517107 0.250000000 0.790900290
+0.978494624 0.250000000 0.790546727
+0.979472141 0.250000000 0.790189953
+0.980449658 0.250000000 0.789814417
+0.981427175 0.250000000 0.789445023
+0.982404692 0.250000000 0.789052209
+0.983382209 0.250000000 0.788657501
+0.984359726 0.250000000 0.788250203
+0.985337243 0.250000000 0.787818500
+0.986314761 0.250000000 0.787390503
+0.987292278 0.250000000 0.786940347
+0.988269795 0.250000000 0.786464072
+0.989247312 0.250000000 0.785974808
+0.990224829 0.250000000 0.785469812
+0.991202346 0.250000000 0.784933879
+0.992179863 0.250000000 0.784364501
+0.993157380 0.250000000 0.783757951
+0.994134897 0.250000000 0.783108264
+0.995112414 0.250000000 0.782404962
+0.996089932 0.250000000 0.781627407
+0.997067449 0.250000000 0.780727892
+0.998044966 0.250000000 0.779693393
+0.999022483 0.250000000 0.778328498
+1.000000000 nan nan
diff --git a/examples/mamdani/SimpleDimmerChained.fll b/examples/mamdani/SimpleDimmerChained.fll
index fd6b945..02b35cc 100644
--- a/examples/mamdani/SimpleDimmerChained.fll
+++ b/examples/mamdani/SimpleDimmerChained.fll
@@ -1,29 +1,30 @@
-Engine: simple-dimmer
+Engine: SimpleDimmerChained
InputVariable: Ambient
enabled: true
range: 0.000 1.000
+ lock-range: false
term: DARK Triangle 0.000 0.250 0.500
term: MEDIUM Triangle 0.250 0.500 0.750
term: BRIGHT Triangle 0.500 0.750 1.000
OutputVariable: Power
enabled: true
range: 0.000 1.000
- accumulation: Maximum
+ lock-range: false
+ aggregation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
- lock-range: false
term: LOW Triangle 0.000 0.250 0.500
term: MEDIUM Triangle 0.250 0.500 0.750
term: HIGH Triangle 0.500 0.750 1.000
OutputVariable: InversePower
enabled: true
range: 0.000 1.000
- accumulation: Maximum
+ lock-range: false
+ aggregation: Maximum
defuzzifier: Centroid 500
default: nan
lock-previous: false
- lock-range: false
term: LOW Cosine 0.200 0.500
term: MEDIUM Cosine 0.500 0.500
term: HIGH Cosine 0.800 0.500
@@ -31,7 +32,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if Ambient is DARK then Power is HIGH
rule: if Ambient is MEDIUM then Power is MEDIUM
rule: if Ambient is BRIGHT then Power is LOW
diff --git a/examples/mamdani/SimpleDimmerChained.java b/examples/mamdani/SimpleDimmerChained.java
new file mode 100644
index 0000000..a7c28c6
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerChained.java
@@ -0,0 +1,81 @@
+import com.fuzzylite.*;
+import com.fuzzylite.activation.*
+import com.fuzzylite.defuzzifier.*;
+import com.fuzzylite.factory.*;
+import com.fuzzylite.hedge.*;
+import com.fuzzylite.imex.*;
+import com.fuzzylite.norm.*;
+import com.fuzzylite.norm.s.*;
+import com.fuzzylite.norm.t.*;
+import com.fuzzylite.rule.*;
+import com.fuzzylite.term.*;
+import com.fuzzylite.variable.*;
+
+public class SimpleDimmerChained{
+public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
+Engine engine = new Engine();
+engine.setName("SimpleDimmerChained");
+engine.setDescription("");
+
+InputVariable Ambient = new InputVariable();
+Ambient.setName("Ambient");
+Ambient.setDescription("");
+Ambient.setEnabled(true);
+Ambient.setRange(0.000, 1.000);
+Ambient.setLockValueInRange(false);
+Ambient.addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+Ambient.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Ambient.addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+engine.addInputVariable(Ambient);
+
+OutputVariable Power = new OutputVariable();
+Power.setName("Power");
+Power.setDescription("");
+Power.setEnabled(true);
+Power.setRange(0.000, 1.000);
+Power.setLockValueInRange(false);
+Power.setAggregation(new Maximum());
+Power.setDefuzzifier(new Centroid(200));
+Power.setDefaultValue(Double.NaN);
+Power.setLockPreviousValue(false);
+Power.addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
+Power.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Power.addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
+engine.addOutputVariable(Power);
+
+OutputVariable InversePower = new OutputVariable();
+InversePower.setName("InversePower");
+InversePower.setDescription("");
+InversePower.setEnabled(true);
+InversePower.setRange(0.000, 1.000);
+InversePower.setLockValueInRange(false);
+InversePower.setAggregation(new Maximum());
+InversePower.setDefuzzifier(new Centroid(500));
+InversePower.setDefaultValue(Double.NaN);
+InversePower.setLockPreviousValue(false);
+InversePower.addTerm(new Cosine("LOW", 0.200, 0.500));
+InversePower.addTerm(new Cosine("MEDIUM", 0.500, 0.500));
+InversePower.addTerm(new Cosine("HIGH", 0.800, 0.500));
+engine.addOutputVariable(InversePower);
+
+RuleBlock ruleBlock = new RuleBlock();
+ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
+ruleBlock.setConjunction(null);
+ruleBlock.setDisjunction(null);
+ruleBlock.setImplication(new Minimum());
+ruleBlock.setActivation(new General());
+ruleBlock.addRule(Rule.parse("if Ambient is DARK then Power is HIGH", engine));
+ruleBlock.addRule(Rule.parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
+ruleBlock.addRule(Rule.parse("if Ambient is BRIGHT then Power is LOW", engine));
+ruleBlock.addRule(Rule.parse("if Power is LOW then InversePower is HIGH", engine));
+ruleBlock.addRule(Rule.parse("if Power is MEDIUM then InversePower is MEDIUM", engine));
+ruleBlock.addRule(Rule.parse("if Power is HIGH then InversePower is LOW", engine));
+engine.addRuleBlock(ruleBlock);
+
+
+}
+}
diff --git a/examples/mamdani/SimpleDimmerChained.pdf b/examples/mamdani/SimpleDimmerChained.pdf
new file mode 100644
index 0000000..bc22cfa
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerChained.pdf
Binary files differ
diff --git a/examples/mamdani/SimpleDimmerInverse.R b/examples/mamdani/SimpleDimmerInverse.R
new file mode 100644
index 0000000..358916d
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerInverse.R
@@ -0,0 +1,85 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "SimpleDimmerInverse"
+engine.fll = "Engine: SimpleDimmerInverse
+InputVariable: Ambient
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: DARK Triangle 0.000 0.250 0.500
+ term: MEDIUM Triangle 0.250 0.500 0.750
+ term: BRIGHT Triangle 0.500 0.750 1.000
+OutputVariable: Power
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: LOW Triangle 0.000 0.250 0.500
+ term: MEDIUM Triangle 0.250 0.500 0.750
+ term: HIGH Triangle 0.500 0.750 1.000
+OutputVariable: InversePower
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 500
+ default: nan
+ lock-previous: false
+ term: LOW Cosine 0.200 0.500
+ term: MEDIUM Cosine 0.500 0.500
+ term: HIGH Cosine 0.800 0.500
+RuleBlock:
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: Minimum
+ activation: General
+ rule: if Ambient is DARK then Power is HIGH
+ rule: if Ambient is MEDIUM then Power is MEDIUM
+ rule: if Ambient is BRIGHT then Power is LOW
+ rule: if Power is LOW then InversePower is HIGH
+ rule: if Power is MEDIUM then InversePower is MEDIUM
+ rule: if Power is HIGH then InversePower is LOW"
+
+engine.fldFile = "SimpleDimmerInverse.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(Ambient, Power)) +
+ geom_line(aes(color=Power), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("Ambient vs Power")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(Ambient, Power)) +
+ geom_line(aes(color=Power), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("Power vs Ambient")
+
+engine.plot.i1_o2 = ggplot(engine.df, aes(Ambient, InversePower)) +
+ geom_line(aes(color=InversePower), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("Ambient vs InversePower")
+
+engine.plot.o2_i1 = ggplot(engine.df, aes(Ambient, InversePower)) +
+ geom_line(aes(color=InversePower), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("InversePower vs Ambient")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, engine.plot.i1_o2, engine.plot.o2_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/mamdani/SimpleDimmerInverse.cpp b/examples/mamdani/SimpleDimmerInverse.cpp
index cad1100..1c22275 100644
--- a/examples/mamdani/SimpleDimmerInverse.cpp
+++ b/examples/mamdani/SimpleDimmerInverse.cpp
@@ -1,60 +1,69 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("simple-dimmer");
-
-InputVariable* inputVariable = new InputVariable;
-inputVariable->setEnabled(true);
-inputVariable->setName("Ambient");
-inputVariable->setRange(0.000, 1.000);
-inputVariable->addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
-inputVariable->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-inputVariable->addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
-engine->addInputVariable(inputVariable);
-
-OutputVariable* outputVariable1 = new OutputVariable;
-outputVariable1->setEnabled(true);
-outputVariable1->setName("Power");
-outputVariable1->setRange(0.000, 1.000);
-outputVariable1->fuzzyOutput()->setAccumulation(new Maximum);
-outputVariable1->setDefuzzifier(new Centroid(200));
-outputVariable1->setDefaultValue(fl::nan);
-outputVariable1->setLockPreviousOutputValue(false);
-outputVariable1->setLockOutputValueInRange(false);
-outputVariable1->addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
-outputVariable1->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-outputVariable1->addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
-engine->addOutputVariable(outputVariable1);
-
-OutputVariable* outputVariable2 = new OutputVariable;
-outputVariable2->setEnabled(true);
-outputVariable2->setName("InversePower");
-outputVariable2->setRange(0.000, 1.000);
-outputVariable2->fuzzyOutput()->setAccumulation(new Maximum);
-outputVariable2->setDefuzzifier(new Centroid(500));
-outputVariable2->setDefaultValue(fl::nan);
-outputVariable2->setLockPreviousOutputValue(false);
-outputVariable2->setLockOutputValueInRange(false);
-outputVariable2->addTerm(new Cosine("LOW", 0.200, 0.500));
-outputVariable2->addTerm(new Cosine("MEDIUM", 0.500, 0.500));
-outputVariable2->addTerm(new Cosine("HIGH", 0.800, 0.500));
-engine->addOutputVariable(outputVariable2);
+engine->setName("SimpleDimmerInverse");
+engine->setDescription("");
+
+InputVariable* Ambient = new InputVariable;
+Ambient->setName("Ambient");
+Ambient->setDescription("");
+Ambient->setEnabled(true);
+Ambient->setRange(0.000, 1.000);
+Ambient->setLockValueInRange(false);
+Ambient->addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+Ambient->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Ambient->addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+engine->addInputVariable(Ambient);
+
+OutputVariable* Power = new OutputVariable;
+Power->setName("Power");
+Power->setDescription("");
+Power->setEnabled(true);
+Power->setRange(0.000, 1.000);
+Power->setLockValueInRange(false);
+Power->setAggregation(new Maximum);
+Power->setDefuzzifier(new Centroid(200));
+Power->setDefaultValue(fl::nan);
+Power->setLockPreviousValue(false);
+Power->addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
+Power->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Power->addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
+engine->addOutputVariable(Power);
+
+OutputVariable* InversePower = new OutputVariable;
+InversePower->setName("InversePower");
+InversePower->setDescription("");
+InversePower->setEnabled(true);
+InversePower->setRange(0.000, 1.000);
+InversePower->setLockValueInRange(false);
+InversePower->setAggregation(new Maximum);
+InversePower->setDefuzzifier(new Centroid(500));
+InversePower->setDefaultValue(fl::nan);
+InversePower->setLockPreviousValue(false);
+InversePower->addTerm(new Cosine("LOW", 0.200, 0.500));
+InversePower->addTerm(new Cosine("MEDIUM", 0.500, 0.500));
+InversePower->addTerm(new Cosine("HIGH", 0.800, 0.500));
+engine->addOutputVariable(InversePower);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
-ruleBlock->setConjunction(NULL);
-ruleBlock->setDisjunction(NULL);
-ruleBlock->setActivation(new Minimum);
-ruleBlock->addRule(fl::Rule::parse("if Ambient is DARK then Power is HIGH", engine));
-ruleBlock->addRule(fl::Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
-ruleBlock->addRule(fl::Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
-ruleBlock->addRule(fl::Rule::parse("if Power is LOW then InversePower is HIGH", engine));
-ruleBlock->addRule(fl::Rule::parse("if Power is MEDIUM then InversePower is MEDIUM", engine));
-ruleBlock->addRule(fl::Rule::parse("if Power is HIGH then InversePower is LOW", engine));
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
+ruleBlock->setConjunction(fl::null);
+ruleBlock->setDisjunction(fl::null);
+ruleBlock->setImplication(new Minimum);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if Ambient is DARK then Power is HIGH", engine));
+ruleBlock->addRule(Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
+ruleBlock->addRule(Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
+ruleBlock->addRule(Rule::parse("if Power is LOW then InversePower is HIGH", engine));
+ruleBlock->addRule(Rule::parse("if Power is MEDIUM then InversePower is MEDIUM", engine));
+ruleBlock->addRule(Rule::parse("if Power is HIGH then InversePower is LOW", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/mamdani/SimpleDimmerInverse.fcl b/examples/mamdani/SimpleDimmerInverse.fcl
index 337bc2b..d8043d3 100644
--- a/examples/mamdani/SimpleDimmerInverse.fcl
+++ b/examples/mamdani/SimpleDimmerInverse.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK simple-dimmer
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK SimpleDimmerInverse
VAR_INPUT
Ambient: REAL;
diff --git a/examples/mamdani/SimpleDimmerInverse.fis b/examples/mamdani/SimpleDimmerInverse.fis
new file mode 100644
index 0000000..b044014
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerInverse.fis
@@ -0,0 +1,46 @@
+#Code automatically generated with fuzzylite 6.0.
+
+[System]
+Name='SimpleDimmerInverse'
+Type='mamdani'
+Version=6.0
+NumInputs=1
+NumOutputs=2
+NumRules=6
+AndMethod='min'
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
+DefuzzMethod='centroid'
+
+[Input1]
+Name='Ambient'
+Range=[0.000 1.000]
+NumMFs=3
+MF1='DARK':'trimf',[0.000 0.250 0.500]
+MF2='MEDIUM':'trimf',[0.250 0.500 0.750]
+MF3='BRIGHT':'trimf',[0.500 0.750 1.000]
+
+[Output1]
+Name='Power'
+Range=[0.000 1.000]
+NumMFs=3
+MF1='LOW':'trimf',[0.000 0.250 0.500]
+MF2='MEDIUM':'trimf',[0.250 0.500 0.750]
+MF3='HIGH':'trimf',[0.500 0.750 1.000]
+
+[Output2]
+Name='InversePower'
+Range=[0.000 1.000]
+NumMFs=3
+MF1='LOW':'cosinemf',[0.200 0.500]
+MF2='MEDIUM':'cosinemf',[0.500 0.500]
+MF3='HIGH':'cosinemf',[0.800 0.500]
+
+[Rules]
+1.000 , 3.000 0.000 (1.000) : 1
+2.000 , 2.000 0.000 (1.000) : 1
+3.000 , 1.000 0.000 (1.000) : 1
+0.000 , 0.000 3.000 (1.000) : 1
+0.000 , 0.000 2.000 (1.000) : 1
+0.000 , 0.000 1.000 (1.000) : 1
diff --git a/examples/mamdani/SimpleDimmerInverse.fld b/examples/mamdani/SimpleDimmerInverse.fld
index 45373fa..843c017 100644
--- a/examples/mamdani/SimpleDimmerInverse.fld
+++ b/examples/mamdani/SimpleDimmerInverse.fld
@@ -1,1026 +1,1025 @@
-#@Engine: simple-dimmer;
-#@InputVariable: Ambient; @OutputVariable: Power; @OutputVariable: InversePower;
-0.00000000 nan nan
-0.00097752 0.75000000 0.22167150
-0.00195503 0.75000000 0.22030661
-0.00293255 0.75000000 0.21927211
-0.00391007 0.75000000 0.21837259
-0.00488759 0.75000000 0.21759504
-0.00586510 0.75000000 0.21689174
-0.00684262 0.75000000 0.21624205
-0.00782014 0.75000000 0.21563550
-0.00879765 0.75000000 0.21506612
-0.00977517 0.75000000 0.21453019
-0.01075269 0.75000000 0.21402519
-0.01173021 0.75000000 0.21353593
-0.01270772 0.75000000 0.21305965
-0.01368524 0.75000000 0.21260950
-0.01466276 0.75000000 0.21218150
-0.01564027 0.75000000 0.21174980
-0.01661779 0.75000000 0.21134250
-0.01759531 0.75000000 0.21094779
-0.01857283 0.75000000 0.21055498
-0.01955034 0.75000000 0.21018558
-0.02052786 0.75000000 0.20981005
-0.02150538 0.75000000 0.20945327
-0.02248289 0.75000000 0.20909971
-0.02346041 0.75000000 0.20875478
-0.02443793 0.75000000 0.20841846
-0.02541544 0.75000000 0.20810890
-0.02639296 0.75000000 0.20782234
-0.02737048 0.75000000 0.20755709
-0.02834800 0.75000000 0.20731004
-0.02932551 0.75000000 0.20708013
-0.03030303 0.75000000 0.20686499
-0.03128055 0.75000000 0.20666370
-0.03225806 0.75000000 0.20647468
-0.03323558 0.75000000 0.20629689
-0.03421310 0.75000000 0.20612956
-0.03519062 0.75000000 0.20597128
-0.03616813 0.75000000 0.20582215
-0.03714565 0.75000000 0.20568029
-0.03812317 0.75000000 0.20554655
-0.03910068 0.75000000 0.20541899
-0.04007820 0.75000000 0.20529802
-0.04105572 0.75000000 0.20518274
-0.04203324 0.75000000 0.20507272
-0.04301075 0.75000000 0.20496807
-0.04398827 0.75000000 0.20486764
-0.04496579 0.75000000 0.20477210
-0.04594330 0.75000000 0.20468037
-0.04692082 0.75000000 0.20459248
-0.04789834 0.75000000 0.20450839
-0.04887586 0.75000000 0.20442732
-0.04985337 0.75000000 0.20434987
-0.05083089 0.75000000 0.20427519
-0.05180841 0.75000000 0.20420327
-0.05278592 0.75000000 0.20413428
-0.05376344 0.75000000 0.20406751
-0.05474096 0.75000000 0.20400336
-0.05571848 0.75000000 0.20394144
-0.05669599 0.75000000 0.20388140
-0.05767351 0.75000000 0.20382383
-0.05865103 0.75000000 0.20376794
-0.05962854 0.75000000 0.20371384
-0.06060606 0.75000000 0.20366171
-0.06158358 0.75000000 0.20361103
-0.06256109 0.75000000 0.20356203
-0.06353861 0.75000000 0.20351462
-0.06451613 0.75000000 0.20346845
-0.06549365 0.75000000 0.20342386
-0.06647116 0.75000000 0.20338055
-0.06744868 0.75000000 0.20333832
-0.06842620 0.75000000 0.20329758
-0.06940371 0.75000000 0.20325787
-0.07038123 0.75000000 0.20321911
-0.07135875 0.75000000 0.20318172
-0.07233627 0.75000000 0.20314519
-0.07331378 0.75000000 0.20310954
-0.07429130 0.75000000 0.20307507
-0.07526882 0.75000000 0.20304135
-0.07624633 0.75000000 0.20300844
-0.07722385 0.75000000 0.20297656
-0.07820137 0.75000000 0.20294536
-0.07917889 0.75000000 0.20291488
-0.08015640 0.75000000 0.20288533
-0.08113392 0.75000000 0.20285637
-0.08211144 0.75000000 0.20282806
-0.08308895 0.75000000 0.20280059
-0.08406647 0.75000000 0.20277365
-0.08504399 0.75000000 0.20274728
-0.08602151 0.75000000 0.20272169
-0.08699902 0.75000000 0.20269657
-0.08797654 0.75000000 0.20267195
-0.08895406 0.75000000 0.20264805
-0.08993157 0.75000000 0.20262458
-0.09090909 0.75000000 0.20260154
-0.09188661 0.75000000 0.20257918
-0.09286413 0.75000000 0.20255721
-0.09384164 0.75000000 0.20253561
-0.09481916 0.75000000 0.20251464
-0.09579668 0.75000000 0.20249404
-0.09677419 0.75000000 0.20247377
-0.09775171 0.75000000 0.20245404
-0.09872923 0.75000000 0.20243468
-0.09970674 0.75000000 0.20241563
-0.10068426 0.75000000 0.20239704
-0.10166178 0.75000000 0.20237883
-0.10263930 0.75000000 0.20236089
-0.10361681 0.75000000 0.20234334
-0.10459433 0.75000000 0.20232618
-0.10557185 0.75000000 0.20230927
-0.10654936 0.75000000 0.20229268
-0.10752688 0.75000000 0.20227648
-0.10850440 0.75000000 0.20226051
-0.10948192 0.75000000 0.20224480
-0.11045943 0.75000000 0.20222950
-0.11143695 0.75000000 0.20221441
-0.11241447 0.75000000 0.20219951
-0.11339198 0.75000000 0.20218503
-0.11436950 0.75000000 0.20217075
-0.11534702 0.75000000 0.20215665
-0.11632454 0.75000000 0.20214289
-0.11730205 0.75000000 0.20212935
-0.11827957 0.75000000 0.20211599
-0.11925709 0.75000000 0.20210290
-0.12023460 0.75000000 0.20209006
-0.12121212 0.75000000 0.20207738
-0.12218964 0.75000000 0.20206492
-0.12316716 0.75000000 0.20205274
-0.12414467 0.75000000 0.20204069
-0.12512219 0.75000000 0.20202881
-0.12609971 0.75000000 0.20201724
-0.12707722 0.75000000 0.20200579
-0.12805474 0.75000000 0.20199447
-0.12903226 0.75000000 0.20198344
-0.13000978 0.75000000 0.20197255
-0.13098729 0.75000000 0.20196178
-0.13196481 0.75000000 0.20195125
-0.13294233 0.75000000 0.20194088
-0.13391984 0.75000000 0.20193062
-0.13489736 0.75000000 0.20192055
-0.13587488 0.75000000 0.20191067
-0.13685239 0.75000000 0.20190089
-0.13782991 0.75000000 0.20189126
-0.13880743 0.75000000 0.20188184
-0.13978495 0.75000000 0.20187251
-0.14076246 0.75000000 0.20186329
-0.14173998 0.75000000 0.20185431
-0.14271750 0.75000000 0.20184541
-0.14369501 0.75000000 0.20183659
-0.14467253 0.75000000 0.20182800
-0.14565005 0.75000000 0.20181950
-0.14662757 0.75000000 0.20181108
-0.14760508 0.75000000 0.20180284
-0.14858260 0.75000000 0.20179472
-0.14956012 0.75000000 0.20178668
-0.15053763 0.75000000 0.20177878
-0.15151515 0.75000000 0.20177102
-0.15249267 0.75000000 0.20176333
-0.15347019 0.75000000 0.20175576
-0.15444770 0.75000000 0.20174834
-0.15542522 0.75000000 0.20174097
-0.15640274 0.75000000 0.20173372
-0.15738025 0.75000000 0.20172662
-0.15835777 0.75000000 0.20171957
-0.15933529 0.75000000 0.20171261
-0.16031281 0.75000000 0.20170581
-0.16129032 0.75000000 0.20169907
-0.16226784 0.75000000 0.20169239
-0.16324536 0.75000000 0.20168588
-0.16422287 0.75000000 0.20167942
-0.16520039 0.75000000 0.20167302
-0.16617791 0.75000000 0.20166679
-0.16715543 0.75000000 0.20166060
-0.16813294 0.75000000 0.20165446
-0.16911046 0.75000000 0.20164849
-0.17008798 0.75000000 0.20164256
-0.17106549 0.75000000 0.20163668
-0.17204301 0.75000000 0.20163095
-0.17302053 0.75000000 0.20162527
-0.17399804 0.75000000 0.20161963
-0.17497556 0.75000000 0.20161414
-0.17595308 0.75000000 0.20160869
-0.17693060 0.75000000 0.20160329
-0.17790811 0.75000000 0.20159803
-0.17888563 0.75000000 0.20159280
-0.17986315 0.75000000 0.20158764
-0.18084066 0.75000000 0.20158259
-0.18181818 0.75000000 0.20157758
-0.18279570 0.75000000 0.20157264
-0.18377322 0.75000000 0.20156780
-0.18475073 0.75000000 0.20156299
-0.18572825 0.75000000 0.20155827
-0.18670577 0.75000000 0.20155363
-0.18768328 0.75000000 0.20154902
-0.18866080 0.75000000 0.20154451
-0.18963832 0.75000000 0.20154006
-0.19061584 0.75000000 0.20153564
-0.19159335 0.75000000 0.20153134
-0.19257087 0.75000000 0.20152707
-0.19354839 0.75000000 0.20152286
-0.19452590 0.75000000 0.20151874
-0.19550342 0.75000000 0.20151465
-0.19648094 0.75000000 0.20151063
-0.19745846 0.75000000 0.20150669
-0.19843597 0.75000000 0.20150276
-0.19941349 0.75000000 0.20149895
-0.20039101 0.75000000 0.20149517
-0.20136852 0.75000000 0.20149144
-0.20234604 0.75000000 0.20148780
-0.20332356 0.75000000 0.20148417
-0.20430108 0.75000000 0.20148065
-0.20527859 0.75000000 0.20147715
-0.20625611 0.75000000 0.20147372
-0.20723363 0.75000000 0.20147035
-0.20821114 0.75000000 0.20146701
-0.20918866 0.75000000 0.20146377
-0.21016618 0.75000000 0.20146055
-0.21114370 0.75000000 0.20145740
-0.21212121 0.75000000 0.20145431
-0.21309873 0.75000000 0.20145125
-0.21407625 0.75000000 0.20144828
-0.21505376 0.75000000 0.20144532
-0.21603128 0.75000000 0.20144246
-0.21700880 0.75000000 0.20143962
-0.21798631 0.75000000 0.20143687
-0.21896383 0.75000000 0.20143414
-0.21994135 0.75000000 0.20143149
-0.22091887 0.75000000 0.20142887
-0.22189638 0.75000000 0.20142632
-0.22287390 0.75000000 0.20142382
-0.22385142 0.75000000 0.20142138
-0.22482893 0.75000000 0.20141899
-0.22580645 0.75000000 0.20141666
-0.22678397 0.75000000 0.20141437
-0.22776149 0.75000000 0.20141216
-0.22873900 0.75000000 0.20140998
-0.22971652 0.75000000 0.20140789
-0.23069404 0.75000000 0.20140583
-0.23167155 0.75000000 0.20140385
-0.23264907 0.75000000 0.20140191
-0.23362659 0.75000000 0.20140003
-0.23460411 0.75000000 0.20139823
-0.23558162 0.75000000 0.20139648
-0.23655914 0.75000000 0.20139479
-0.23753666 0.75000000 0.20139318
-0.23851417 0.75000000 0.20139162
-0.23949169 0.75000000 0.20139013
-0.24046921 0.75000000 0.20138872
-0.24144673 0.75000000 0.20138738
-0.24242424 0.75000000 0.20138613
-0.24340176 0.75000000 0.20138495
-0.24437928 0.75000000 0.20138385
-0.24535679 0.75000000 0.20138285
-0.24633431 0.75000000 0.20138195
-0.24731183 0.75000000 0.20138117
-0.24828935 0.75000000 0.20138052
-0.24926686 0.75000000 0.20138004
-0.25024438 0.74963379 0.20184621
-0.25122190 0.74817607 0.20367689
-0.25219941 0.74672965 0.20547042
-0.25317693 0.74530727 0.20723292
-0.25415445 0.74390115 0.20896960
-0.25513196 0.74250538 0.21068200
-0.25610948 0.74111985 0.21237142
-0.25708700 0.73974444 0.21403914
-0.25806452 0.73838897 0.21568634
-0.25904203 0.73705025 0.21731416
-0.26001955 0.73572080 0.21892367
-0.26099707 0.73440054 0.22051588
-0.26197458 0.73308936 0.22209176
-0.26295210 0.73179453 0.22364976
-0.26392962 0.73051679 0.22519215
-0.26490714 0.72924739 0.22672038
-0.26588465 0.72798623 0.22823273
-0.26686217 0.72673323 0.22973063
-0.26783969 0.72549344 0.23121629
-0.26881720 0.72427097 0.23268587
-0.26979472 0.72305599 0.23414401
-0.27077224 0.72184842 0.23558882
-0.27174976 0.72064820 0.23702103
-0.27272727 0.71945844 0.23844203
-0.27370479 0.71828610 0.23984979
-0.27468231 0.71712050 0.24124792
-0.27565982 0.71596157 0.24263262
-0.27663734 0.71480927 0.24400876
-0.27761486 0.71366501 0.24537168
-0.27859238 0.71253818 0.24672667
-0.27956989 0.71141742 0.24806903
-0.28054741 0.71030267 0.24940367
-0.28152493 0.70919389 0.25072659
-0.28250244 0.70809106 0.25204165
-0.28347996 0.70700557 0.25334618
-0.28445748 0.70592553 0.25464239
-0.28543500 0.70485092 0.25592952
-0.28641251 0.70378169 0.25720758
-0.28739003 0.70271779 0.25847822
-0.28836755 0.70166862 0.25973880
-0.28934506 0.70062558 0.26099337
-0.29032258 0.69958742 0.26223755
-0.29130010 0.69855412 0.26347553
-0.29227761 0.69752564 0.26470524
-0.29325513 0.69650949 0.26592723
-0.29423265 0.69550004 0.26714320
-0.29521017 0.69449498 0.26834979
-0.29618768 0.69349430 0.26955111
-0.29716520 0.69249796 0.27074444
-0.29814272 0.69151186 0.27193114
-0.29912023 0.69053287 0.27311234
-0.30009775 0.68955785 0.27428495
-0.30107527 0.68858676 0.27545274
-0.30205279 0.68761958 0.27661362
-0.30303030 0.68666076 0.27776803
-0.30400782 0.68570938 0.27891786
-0.30498534 0.68476154 0.28005970
-0.30596285 0.68381725 0.28119682
-0.30694037 0.68287647 0.28232868
-0.30791789 0.68194242 0.28345356
-0.30889541 0.68101598 0.28457426
-0.30987292 0.68009273 0.28568897
-0.31085044 0.67917264 0.28679805
-0.31182796 0.67825571 0.28790314
-0.31280547 0.67734408 0.28900176
-0.31378299 0.67644013 0.29009583
-0.31476051 0.67553902 0.29118611
-0.31573803 0.67464075 0.29226963
-0.31671554 0.67374530 0.29334946
-0.31769306 0.67285389 0.29442525
-0.31867058 0.67197014 0.29549502
-0.31964809 0.67108892 0.29656133
-0.32062561 0.67021023 0.29762345
-0.32160313 0.66933404 0.29868024
-0.32258065 0.66846082 0.29973374
-0.32355816 0.66759513 0.30078303
-0.32453568 0.66673167 0.30182751
-0.32551320 0.66587045 0.30286887
-0.32649071 0.66501145 0.30390610
-0.32746823 0.66415466 0.30493893
-0.32844575 0.66330485 0.30596879
-0.32942326 0.66245716 0.30699470
-0.33040078 0.66161144 0.30801651
-0.33137830 0.66076767 0.30903550
-0.33235582 0.65992584 0.31005075
-0.33333333 0.65908967 0.31106215
-0.33431085 0.65825587 0.31207087
-0.33528837 0.65742377 0.31307613
-0.33626588 0.65659337 0.31407770
-0.33724340 0.65576467 0.31507673
-0.33822092 0.65494046 0.31607198
-0.33919844 0.65411875 0.31706264
-0.34017595 0.65329850 0.31805099
-0.34115347 0.65247971 0.31903617
-0.34213099 0.65166237 0.32001692
-0.34310850 0.65084852 0.32099560
-0.34408602 0.65003719 0.32197170
-0.34506354 0.64922708 0.32294352
-0.34604106 0.64841821 0.32391349
-0.34701857 0.64761056 0.32488146
-0.34799609 0.64680554 0.32584530
-0.34897361 0.64600293 0.32680750
-0.34995112 0.64520134 0.32776805
-0.35092864 0.64440076 0.32872502
-0.35190616 0.64360119 0.32968035
-0.35288368 0.64280350 0.33063426
-0.35386119 0.64200804 0.33158533
-0.35483871 0.64121338 0.33253470
-0.35581623 0.64041952 0.33348284
-0.35679374 0.63962646 0.33442883
-0.35777126 0.63883468 0.33537310
-0.35874878 0.63804481 0.33631634
-0.35972630 0.63725555 0.33725803
-0.36070381 0.63646688 0.33819806
-0.36168133 0.63567880 0.33913724
-0.36265885 0.63489151 0.34007538
-0.36363636 0.63410574 0.34101201
-0.36461388 0.63332037 0.34194799
-0.36559140 0.63253539 0.34288331
-0.36656891 0.63175080 0.34381737
-0.36754643 0.63096664 0.34475097
-0.36852395 0.63018348 0.34568410
-0.36950147 0.62940052 0.34661650
-0.37047898 0.62861775 0.34754854
-0.37145650 0.62783518 0.34848030
-0.37243402 0.62705280 0.34941175
-0.37341153 0.62627077 0.35034304
-0.37438905 0.62548876 0.35127424
-0.37536657 0.62470674 0.35220543
-0.37634409 0.62392473 0.35313679
-0.37732160 0.62314272 0.35406824
-0.37829912 0.62236043 0.35499987
-0.37927664 0.62157791 0.35593211
-0.38025415 0.62079519 0.35686463
-0.38123167 0.62001228 0.35779743
-0.38220919 0.61922917 0.35873133
-0.38318671 0.61844529 0.35966573
-0.38416422 0.61766080 0.36060060
-0.38514174 0.61687591 0.36153679
-0.38611926 0.61609064 0.36247390
-0.38709677 0.61530497 0.36341166
-0.38807429 0.61451813 0.36435085
-0.38905181 0.61373020 0.36529150
-0.39002933 0.61294168 0.36623299
-0.39100684 0.61215256 0.36717592
-0.39198436 0.61136285 0.36812094
-0.39296188 0.61057168 0.36906701
-0.39393939 0.60977882 0.37001444
-0.39491691 0.60898516 0.37096469
-0.39589443 0.60819070 0.37191618
-0.39687195 0.60739544 0.37286891
-0.39784946 0.60659855 0.37382525
-0.39882698 0.60579922 0.37478304
-0.39980450 0.60499890 0.37574227
-0.40078201 0.60419756 0.37670519
-0.40175953 0.60339521 0.37767018
-0.40273705 0.60259116 0.37863682
-0.40371457 0.60178382 0.37960719
-0.40469208 0.60097525 0.38058030
-0.40566960 0.60016546 0.38155526
-0.40664712 0.59935443 0.38253399
-0.40762463 0.59854174 0.38351615
-0.40860215 0.59772477 0.38450040
-0.40957967 0.59690634 0.38548843
-0.41055718 0.59608645 0.38648062
-0.41153470 0.59526511 0.38747513
-0.41251222 0.59444225 0.38847349
-0.41348974 0.59361396 0.38947672
-0.41446725 0.59278399 0.39048250
-0.41544477 0.59195232 0.39149155
-0.41642229 0.59111894 0.39250467
-0.41739980 0.59028386 0.39352048
-0.41837732 0.58944297 0.39453968
-0.41935484 0.58859969 0.39556327
-0.42033236 0.58775445 0.39658970
-0.42130987 0.58690726 0.39761971
-0.42228739 0.58605810 0.39865437
-0.42326491 0.58520295 0.39969203
-0.42424242 0.58434451 0.40073354
-0.42521994 0.58348384 0.40177991
-0.42619746 0.58262095 0.40282942
-0.42717498 0.58175582 0.40388318
-0.42815249 0.58088462 0.40494190
-0.42913001 0.58000905 0.40600393
-0.43010753 0.57913099 0.40707072
-0.43108504 0.57825040 0.40814248
-0.43206256 0.57736728 0.40921771
-0.43304008 0.57647812 0.41029836
-0.43401760 0.57558337 0.41138386
-0.43499511 0.57468581 0.41247301
-0.43597263 0.57378542 0.41356841
-0.43695015 0.57288218 0.41466839
-0.43792766 0.57197303 0.41577220
-0.43890518 0.57105688 0.41688332
-0.43988270 0.57013759 0.41799853
-0.44086022 0.56921513 0.41911858
-0.44183773 0.56828949 0.42024563
-0.44281525 0.56735818 0.42137689
-0.44379277 0.56641827 0.42251434
-0.44477028 0.56547486 0.42365807
-0.44574780 0.56452791 0.42480621
-0.44672532 0.56357742 0.42596221
-0.44770283 0.56262161 0.42712348
-0.44868035 0.56165541 0.42829028
-0.44965787 0.56068529 0.42946517
-0.45063539 0.55971125 0.43064489
-0.45161290 0.55873326 0.43183231
-0.45259042 0.55775044 0.43302636
-0.45356794 0.55675519 0.43422600
-0.45454545 0.55575559 0.43543492
-0.45552297 0.55475164 0.43664915
-0.45650049 0.55374329 0.43787175
-0.45747801 0.55273051 0.43910163
-0.45845552 0.55170345 0.44033810
-0.45943304 0.55067135 0.44158421
-0.46041056 0.54963442 0.44283613
-0.46138807 0.54859260 0.44409826
-0.46236559 0.54754587 0.44536727
-0.46334311 0.54648479 0.44664519
-0.46432063 0.54541689 0.44793195
-0.46529814 0.54434363 0.44922653
-0.46627566 0.54326495 0.45053171
-0.46725318 0.54218083 0.45184389
-0.46823069 0.54108237 0.45316819
-0.46920821 0.53997508 0.45449940
-0.47018573 0.53886183 0.45584313
-0.47116325 0.53774257 0.45719450
-0.47214076 0.53661727 0.45855837
-0.47311828 0.53547778 0.45993068
-0.47409580 0.53432712 0.46131585
-0.47507331 0.53316986 0.46270993
-0.47605083 0.53200593 0.46411767
-0.47702835 0.53083528 0.46553438
-0.47800587 0.52965071 0.46695262
-0.47898338 0.52845232 0.46837800
-0.47996090 0.52724659 0.46980609
-0.48093842 0.52603347 0.47123994
-0.48191593 0.52481288 0.47267837
-0.48289345 0.52357875 0.47412061
-0.48387097 0.52232778 0.47556907
-0.48484848 0.52106867 0.47702029
-0.48582600 0.51980133 0.47847676
-0.48680352 0.51852569 0.47993880
-0.48778104 0.51723703 0.48140371
-0.48875855 0.51592811 0.48287336
-0.48973607 0.51461012 0.48434789
-0.49071359 0.51328298 0.48582689
-0.49169110 0.51194659 0.48730922
-0.49266862 0.51059784 0.48879513
-0.49364614 0.50922495 0.49028478
-0.49462366 0.50784195 0.49177772
-0.49560117 0.50644876 0.49327351
-0.49657869 0.50504524 0.49477078
-0.49755621 0.50363020 0.49626887
-0.49853372 0.50218659 0.49776632
-0.49951124 0.50073171 0.49925937
-0.50048876 0.49926829 0.50074063
-0.50146628 0.49781341 0.50223368
-0.50244379 0.49636980 0.50373113
-0.50342131 0.49495476 0.50522922
-0.50439883 0.49355124 0.50672649
-0.50537634 0.49215805 0.50822228
-0.50635386 0.49077505 0.50971522
-0.50733138 0.48940216 0.51120487
-0.50830890 0.48805341 0.51269078
-0.50928641 0.48671702 0.51417311
-0.51026393 0.48538988 0.51565211
-0.51124145 0.48407189 0.51712664
-0.51221896 0.48276297 0.51859629
-0.51319648 0.48147431 0.52006120
-0.51417400 0.48019867 0.52152324
-0.51515152 0.47893133 0.52297971
-0.51612903 0.47767222 0.52443093
-0.51710655 0.47642125 0.52587939
-0.51808407 0.47518712 0.52732163
-0.51906158 0.47396653 0.52876006
-0.52003910 0.47275341 0.53019391
-0.52101662 0.47154768 0.53162200
-0.52199413 0.47034929 0.53304738
-0.52297165 0.46916472 0.53446562
-0.52394917 0.46799407 0.53588233
-0.52492669 0.46683014 0.53729007
-0.52590420 0.46567288 0.53868415
-0.52688172 0.46452222 0.54006932
-0.52785924 0.46338273 0.54144163
-0.52883675 0.46225743 0.54280550
-0.52981427 0.46113817 0.54415687
-0.53079179 0.46002492 0.54550060
-0.53176931 0.45891763 0.54683181
-0.53274682 0.45781917 0.54815611
-0.53372434 0.45673505 0.54946829
-0.53470186 0.45565637 0.55077347
-0.53567937 0.45458311 0.55206805
-0.53665689 0.45351521 0.55335481
-0.53763441 0.45245413 0.55463273
-0.53861193 0.45140740 0.55590174
-0.53958944 0.45036558 0.55716387
-0.54056696 0.44932865 0.55841579
-0.54154448 0.44829655 0.55966190
-0.54252199 0.44726949 0.56089837
-0.54349951 0.44625671 0.56212825
-0.54447703 0.44524836 0.56335085
-0.54545455 0.44424441 0.56456508
-0.54643206 0.44324481 0.56577400
-0.54740958 0.44224956 0.56697364
-0.54838710 0.44126674 0.56816769
-0.54936461 0.44028875 0.56935511
-0.55034213 0.43931471 0.57053483
-0.55131965 0.43834459 0.57170972
-0.55229717 0.43737839 0.57287652
-0.55327468 0.43642258 0.57403779
-0.55425220 0.43547209 0.57519379
-0.55522972 0.43452514 0.57634193
-0.55620723 0.43358173 0.57748566
-0.55718475 0.43264182 0.57862311
-0.55816227 0.43171051 0.57975437
-0.55913978 0.43078487 0.58088142
-0.56011730 0.42986241 0.58200147
-0.56109482 0.42894312 0.58311668
-0.56207234 0.42802697 0.58422780
-0.56304985 0.42711782 0.58533161
-0.56402737 0.42621458 0.58643159
-0.56500489 0.42531419 0.58752699
-0.56598240 0.42441663 0.58861614
-0.56695992 0.42352188 0.58970164
-0.56793744 0.42263272 0.59078229
-0.56891496 0.42174960 0.59185752
-0.56989247 0.42086901 0.59292928
-0.57086999 0.41999095 0.59399607
-0.57184751 0.41911538 0.59505810
-0.57282502 0.41824418 0.59611682
-0.57380254 0.41737905 0.59717058
-0.57478006 0.41651616 0.59822009
-0.57575758 0.41565549 0.59926646
-0.57673509 0.41479705 0.60030797
-0.57771261 0.41394190 0.60134563
-0.57869013 0.41309274 0.60238029
-0.57966764 0.41224555 0.60341030
-0.58064516 0.41140031 0.60443673
-0.58162268 0.41055703 0.60546032
-0.58260020 0.40971614 0.60647952
-0.58357771 0.40888106 0.60749533
-0.58455523 0.40804768 0.60850845
-0.58553275 0.40721601 0.60951750
-0.58651026 0.40638604 0.61052328
-0.58748778 0.40555775 0.61152651
-0.58846530 0.40473489 0.61252487
-0.58944282 0.40391355 0.61351938
-0.59042033 0.40309366 0.61451157
-0.59139785 0.40227523 0.61549960
-0.59237537 0.40145826 0.61648385
-0.59335288 0.40064557 0.61746601
-0.59433040 0.39983454 0.61844474
-0.59530792 0.39902475 0.61941970
-0.59628543 0.39821618 0.62039281
-0.59726295 0.39740884 0.62136318
-0.59824047 0.39660479 0.62232982
-0.59921799 0.39580244 0.62329481
-0.60019550 0.39500110 0.62425773
-0.60117302 0.39420078 0.62521696
-0.60215054 0.39340145 0.62617475
-0.60312805 0.39260456 0.62713109
-0.60410557 0.39180930 0.62808382
-0.60508309 0.39101484 0.62903531
-0.60606061 0.39022118 0.62998556
-0.60703812 0.38942832 0.63093299
-0.60801564 0.38863715 0.63187906
-0.60899316 0.38784744 0.63282408
-0.60997067 0.38705832 0.63376701
-0.61094819 0.38626980 0.63470850
-0.61192571 0.38548187 0.63564915
-0.61290323 0.38469503 0.63658834
-0.61388074 0.38390936 0.63752610
-0.61485826 0.38312409 0.63846321
-0.61583578 0.38233920 0.63939940
-0.61681329 0.38155471 0.64033427
-0.61779081 0.38077083 0.64126867
-0.61876833 0.37998772 0.64220257
-0.61974585 0.37920481 0.64313537
-0.62072336 0.37842209 0.64406789
-0.62170088 0.37763957 0.64500013
-0.62267840 0.37685728 0.64593176
-0.62365591 0.37607527 0.64686321
-0.62463343 0.37529326 0.64779457
-0.62561095 0.37451124 0.64872576
-0.62658847 0.37372923 0.64965696
-0.62756598 0.37294720 0.65058825
-0.62854350 0.37216482 0.65151970
-0.62952102 0.37138225 0.65245146
-0.63049853 0.37059948 0.65338350
-0.63147605 0.36981652 0.65431590
-0.63245357 0.36903336 0.65524903
-0.63343109 0.36824920 0.65618263
-0.63440860 0.36746461 0.65711669
-0.63538612 0.36667963 0.65805201
-0.63636364 0.36589426 0.65898799
-0.63734115 0.36510849 0.65992462
-0.63831867 0.36432120 0.66086276
-0.63929619 0.36353312 0.66180194
-0.64027370 0.36274445 0.66274197
-0.64125122 0.36195519 0.66368366
-0.64222874 0.36116532 0.66462690
-0.64320626 0.36037354 0.66557117
-0.64418377 0.35958048 0.66651716
-0.64516129 0.35878662 0.66746530
-0.64613881 0.35799196 0.66841467
-0.64711632 0.35719650 0.66936574
-0.64809384 0.35639881 0.67031965
-0.64907136 0.35559924 0.67127498
-0.65004888 0.35479866 0.67223195
-0.65102639 0.35399707 0.67319250
-0.65200391 0.35319446 0.67415470
-0.65298143 0.35238944 0.67511854
-0.65395894 0.35158179 0.67608651
-0.65493646 0.35077292 0.67705648
-0.65591398 0.34996281 0.67802830
-0.65689150 0.34915148 0.67900440
-0.65786901 0.34833763 0.67998308
-0.65884653 0.34752029 0.68096383
-0.65982405 0.34670150 0.68194901
-0.66080156 0.34588125 0.68293736
-0.66177908 0.34505954 0.68392802
-0.66275660 0.34423533 0.68492327
-0.66373412 0.34340663 0.68592230
-0.66471163 0.34257623 0.68692387
-0.66568915 0.34174413 0.68792913
-0.66666667 0.34091033 0.68893785
-0.66764418 0.34007416 0.68994925
-0.66862170 0.33923233 0.69096450
-0.66959922 0.33838856 0.69198349
-0.67057674 0.33754284 0.69300530
-0.67155425 0.33669515 0.69403121
-0.67253177 0.33584534 0.69506107
-0.67350929 0.33498855 0.69609390
-0.67448680 0.33412955 0.69713113
-0.67546432 0.33326833 0.69817249
-0.67644184 0.33240487 0.69921697
-0.67741935 0.33153918 0.70026626
-0.67839687 0.33066596 0.70131976
-0.67937439 0.32978977 0.70237655
-0.68035191 0.32891108 0.70343867
-0.68132942 0.32802986 0.70450498
-0.68230694 0.32714611 0.70557475
-0.68328446 0.32625470 0.70665054
-0.68426197 0.32535925 0.70773037
-0.68523949 0.32446098 0.70881389
-0.68621701 0.32355987 0.70990417
-0.68719453 0.32265592 0.71099824
-0.68817204 0.32174429 0.71209686
-0.68914956 0.32082736 0.71320195
-0.69012708 0.31990727 0.71431103
-0.69110459 0.31898402 0.71542574
-0.69208211 0.31805758 0.71654644
-0.69305963 0.31712353 0.71767132
-0.69403715 0.31618275 0.71880318
-0.69501466 0.31523846 0.71994030
-0.69599218 0.31429062 0.72108214
-0.69696970 0.31333924 0.72223197
-0.69794721 0.31238042 0.72338638
-0.69892473 0.31141324 0.72454726
-0.69990225 0.31044215 0.72571505
-0.70087977 0.30946713 0.72688766
-0.70185728 0.30848814 0.72806886
-0.70283480 0.30750204 0.72925556
-0.70381232 0.30650570 0.73044889
-0.70478983 0.30550502 0.73165021
-0.70576735 0.30449996 0.73285680
-0.70674487 0.30349051 0.73407277
-0.70772239 0.30247436 0.73529476
-0.70869990 0.30144588 0.73652447
-0.70967742 0.30041258 0.73776245
-0.71065494 0.29937442 0.73900663
-0.71163245 0.29833138 0.74026120
-0.71260997 0.29728221 0.74152178
-0.71358749 0.29621831 0.74279242
-0.71456500 0.29514908 0.74407048
-0.71554252 0.29407447 0.74535761
-0.71652004 0.29299443 0.74665382
-0.71749756 0.29190894 0.74795835
-0.71847507 0.29080611 0.74927341
-0.71945259 0.28969733 0.75059633
-0.72043011 0.28858258 0.75193097
-0.72140762 0.28746182 0.75327333
-0.72238514 0.28633499 0.75462832
-0.72336266 0.28519073 0.75599124
-0.72434018 0.28403843 0.75736738
-0.72531769 0.28287950 0.75875208
-0.72629521 0.28171390 0.76015021
-0.72727273 0.28054156 0.76155797
-0.72825024 0.27935180 0.76297897
-0.72922776 0.27815158 0.76441118
-0.73020528 0.27694401 0.76585599
-0.73118280 0.27572903 0.76731413
-0.73216031 0.27450656 0.76878371
-0.73313783 0.27326677 0.77026937
-0.73411535 0.27201377 0.77176727
-0.73509286 0.27075261 0.77327962
-0.73607038 0.26948321 0.77480785
-0.73704790 0.26820547 0.77635024
-0.73802542 0.26691064 0.77790824
-0.73900293 0.26559946 0.77948412
-0.73998045 0.26427920 0.78107633
-0.74095797 0.26294975 0.78268584
-0.74193548 0.26161103 0.78431366
-0.74291300 0.26025556 0.78596086
-0.74389052 0.25888015 0.78762858
-0.74486804 0.25749462 0.78931800
-0.74584555 0.25609885 0.79103040
-0.74682307 0.25469273 0.79276708
-0.74780059 0.25327035 0.79452958
-0.74877810 0.25182393 0.79632311
-0.74975562 0.25036621 0.79815379
-0.75073314 0.25000000 0.79861996
-0.75171065 0.25000000 0.79861948
-0.75268817 0.25000000 0.79861883
-0.75366569 0.25000000 0.79861805
-0.75464321 0.25000000 0.79861715
-0.75562072 0.25000000 0.79861615
-0.75659824 0.25000000 0.79861505
-0.75757576 0.25000000 0.79861387
-0.75855327 0.25000000 0.79861262
-0.75953079 0.25000000 0.79861128
-0.76050831 0.25000000 0.79860987
-0.76148583 0.25000000 0.79860838
-0.76246334 0.25000000 0.79860682
-0.76344086 0.25000000 0.79860521
-0.76441838 0.25000000 0.79860352
-0.76539589 0.25000000 0.79860177
-0.76637341 0.25000000 0.79859997
-0.76735093 0.25000000 0.79859809
-0.76832845 0.25000000 0.79859615
-0.76930596 0.25000000 0.79859417
-0.77028348 0.25000000 0.79859211
-0.77126100 0.25000000 0.79859002
-0.77223851 0.25000000 0.79858784
-0.77321603 0.25000000 0.79858563
-0.77419355 0.25000000 0.79858334
-0.77517107 0.25000000 0.79858101
-0.77614858 0.25000000 0.79857862
-0.77712610 0.25000000 0.79857618
-0.77810362 0.25000000 0.79857368
-0.77908113 0.25000000 0.79857113
-0.78005865 0.25000000 0.79856851
-0.78103617 0.25000000 0.79856586
-0.78201369 0.25000000 0.79856313
-0.78299120 0.25000000 0.79856038
-0.78396872 0.25000000 0.79855754
-0.78494624 0.25000000 0.79855468
-0.78592375 0.25000000 0.79855172
-0.78690127 0.25000000 0.79854875
-0.78787879 0.25000000 0.79854569
-0.78885630 0.25000000 0.79854260
-0.78983382 0.25000000 0.79853945
-0.79081134 0.25000000 0.79853623
-0.79178886 0.25000000 0.79853299
-0.79276637 0.25000000 0.79852965
-0.79374389 0.25000000 0.79852628
-0.79472141 0.25000000 0.79852285
-0.79569892 0.25000000 0.79851935
-0.79667644 0.25000000 0.79851583
-0.79765396 0.25000000 0.79851220
-0.79863148 0.25000000 0.79850856
-0.79960899 0.25000000 0.79850483
-0.80058651 0.25000000 0.79850105
-0.80156403 0.25000000 0.79849724
-0.80254154 0.25000000 0.79849331
-0.80351906 0.25000000 0.79848937
-0.80449658 0.25000000 0.79848535
-0.80547410 0.25000000 0.79848126
-0.80645161 0.25000000 0.79847714
-0.80742913 0.25000000 0.79847293
-0.80840665 0.25000000 0.79846866
-0.80938416 0.25000000 0.79846436
-0.81036168 0.25000000 0.79845994
-0.81133920 0.25000000 0.79845549
-0.81231672 0.25000000 0.79845098
-0.81329423 0.25000000 0.79844637
-0.81427175 0.25000000 0.79844173
-0.81524927 0.25000000 0.79843701
-0.81622678 0.25000000 0.79843220
-0.81720430 0.25000000 0.79842736
-0.81818182 0.25000000 0.79842242
-0.81915934 0.25000000 0.79841741
-0.82013685 0.25000000 0.79841236
-0.82111437 0.25000000 0.79840720
-0.82209189 0.25000000 0.79840197
-0.82306940 0.25000000 0.79839671
-0.82404692 0.25000000 0.79839131
-0.82502444 0.25000000 0.79838586
-0.82600196 0.25000000 0.79838037
-0.82697947 0.25000000 0.79837473
-0.82795699 0.25000000 0.79836905
-0.82893451 0.25000000 0.79836332
-0.82991202 0.25000000 0.79835744
-0.83088954 0.25000000 0.79835151
-0.83186706 0.25000000 0.79834554
-0.83284457 0.25000000 0.79833940
-0.83382209 0.25000000 0.79833321
-0.83479961 0.25000000 0.79832698
-0.83577713 0.25000000 0.79832058
-0.83675464 0.25000000 0.79831412
-0.83773216 0.25000000 0.79830761
-0.83870968 0.25000000 0.79830093
-0.83968719 0.25000000 0.79829419
-0.84066471 0.25000000 0.79828739
-0.84164223 0.25000000 0.79828043
-0.84261975 0.25000000 0.79827338
-0.84359726 0.25000000 0.79826628
-0.84457478 0.25000000 0.79825903
-0.84555230 0.25000000 0.79825166
-0.84652981 0.25000000 0.79824424
-0.84750733 0.25000000 0.79823667
-0.84848485 0.25000000 0.79822898
-0.84946237 0.25000000 0.79822122
-0.85043988 0.25000000 0.79821332
-0.85141740 0.25000000 0.79820528
-0.85239492 0.25000000 0.79819716
-0.85337243 0.25000000 0.79818892
-0.85434995 0.25000000 0.79818050
-0.85532747 0.25000000 0.79817200
-0.85630499 0.25000000 0.79816341
-0.85728250 0.25000000 0.79815459
-0.85826002 0.25000000 0.79814569
-0.85923754 0.25000000 0.79813671
-0.86021505 0.25000000 0.79812749
-0.86119257 0.25000000 0.79811816
-0.86217009 0.25000000 0.79810874
-0.86314761 0.25000000 0.79809911
-0.86412512 0.25000000 0.79808933
-0.86510264 0.25000000 0.79807945
-0.86608016 0.25000000 0.79806938
-0.86705767 0.25000000 0.79805912
-0.86803519 0.25000000 0.79804875
-0.86901271 0.25000000 0.79803822
-0.86999022 0.25000000 0.79802745
-0.87096774 0.25000000 0.79801656
-0.87194526 0.25000000 0.79800553
-0.87292278 0.25000000 0.79799421
-0.87390029 0.25000000 0.79798276
-0.87487781 0.25000000 0.79797119
-0.87585533 0.25000000 0.79795931
-0.87683284 0.25000000 0.79794726
-0.87781036 0.25000000 0.79793508
-0.87878788 0.25000000 0.79792262
-0.87976540 0.25000000 0.79790994
-0.88074291 0.25000000 0.79789710
-0.88172043 0.25000000 0.79788401
-0.88269795 0.25000000 0.79787065
-0.88367546 0.25000000 0.79785711
-0.88465298 0.25000000 0.79784335
-0.88563050 0.25000000 0.79782925
-0.88660802 0.25000000 0.79781497
-0.88758553 0.25000000 0.79780049
-0.88856305 0.25000000 0.79778559
-0.88954057 0.25000000 0.79777050
-0.89051808 0.25000000 0.79775520
-0.89149560 0.25000000 0.79773949
-0.89247312 0.25000000 0.79772352
-0.89345064 0.25000000 0.79770732
-0.89442815 0.25000000 0.79769073
-0.89540567 0.25000000 0.79767382
-0.89638319 0.25000000 0.79765666
-0.89736070 0.25000000 0.79763911
-0.89833822 0.25000000 0.79762117
-0.89931574 0.25000000 0.79760296
-0.90029326 0.25000000 0.79758437
-0.90127077 0.25000000 0.79756532
-0.90224829 0.25000000 0.79754596
-0.90322581 0.25000000 0.79752623
-0.90420332 0.25000000 0.79750596
-0.90518084 0.25000000 0.79748536
-0.90615836 0.25000000 0.79746439
-0.90713587 0.25000000 0.79744279
-0.90811339 0.25000000 0.79742082
-0.90909091 0.25000000 0.79739846
-0.91006843 0.25000000 0.79737542
-0.91104594 0.25000000 0.79735195
-0.91202346 0.25000000 0.79732805
-0.91300098 0.25000000 0.79730343
-0.91397849 0.25000000 0.79727831
-0.91495601 0.25000000 0.79725272
-0.91593353 0.25000000 0.79722635
-0.91691105 0.25000000 0.79719941
-0.91788856 0.25000000 0.79717194
-0.91886608 0.25000000 0.79714363
-0.91984360 0.25000000 0.79711467
-0.92082111 0.25000000 0.79708512
-0.92179863 0.25000000 0.79705464
-0.92277615 0.25000000 0.79702344
-0.92375367 0.25000000 0.79699156
-0.92473118 0.25000000 0.79695865
-0.92570870 0.25000000 0.79692493
-0.92668622 0.25000000 0.79689046
-0.92766373 0.25000000 0.79685481
-0.92864125 0.25000000 0.79681828
-0.92961877 0.25000000 0.79678089
-0.93059629 0.25000000 0.79674213
-0.93157380 0.25000000 0.79670242
-0.93255132 0.25000000 0.79666168
-0.93352884 0.25000000 0.79661945
-0.93450635 0.25000000 0.79657614
-0.93548387 0.25000000 0.79653155
-0.93646139 0.25000000 0.79648538
-0.93743891 0.25000000 0.79643797
-0.93841642 0.25000000 0.79638897
-0.93939394 0.25000000 0.79633829
-0.94037146 0.25000000 0.79628616
-0.94134897 0.25000000 0.79623206
-0.94232649 0.25000000 0.79617617
-0.94330401 0.25000000 0.79611860
-0.94428152 0.25000000 0.79605856
-0.94525904 0.25000000 0.79599664
-0.94623656 0.25000000 0.79593249
-0.94721408 0.25000000 0.79586572
-0.94819159 0.25000000 0.79579673
-0.94916911 0.25000000 0.79572481
-0.95014663 0.25000000 0.79565013
-0.95112414 0.25000000 0.79557268
-0.95210166 0.25000000 0.79549161
-0.95307918 0.25000000 0.79540752
-0.95405670 0.25000000 0.79531963
-0.95503421 0.25000000 0.79522790
-0.95601173 0.25000000 0.79513236
-0.95698925 0.25000000 0.79503193
-0.95796676 0.25000000 0.79492728
-0.95894428 0.25000000 0.79481726
-0.95992180 0.25000000 0.79470198
-0.96089932 0.25000000 0.79458101
-0.96187683 0.25000000 0.79445345
-0.96285435 0.25000000 0.79431971
-0.96383187 0.25000000 0.79417785
-0.96480938 0.25000000 0.79402872
-0.96578690 0.25000000 0.79387044
-0.96676442 0.25000000 0.79370311
-0.96774194 0.25000000 0.79352532
-0.96871945 0.25000000 0.79333630
-0.96969697 0.25000000 0.79313501
-0.97067449 0.25000000 0.79291987
-0.97165200 0.25000000 0.79268996
-0.97262952 0.25000000 0.79244291
-0.97360704 0.25000000 0.79217766
-0.97458456 0.25000000 0.79189110
-0.97556207 0.25000000 0.79158154
-0.97653959 0.25000000 0.79124522
-0.97751711 0.25000000 0.79090029
-0.97849462 0.25000000 0.79054673
-0.97947214 0.25000000 0.79018995
-0.98044966 0.25000000 0.78981442
-0.98142717 0.25000000 0.78944502
-0.98240469 0.25000000 0.78905221
-0.98338221 0.25000000 0.78865750
-0.98435973 0.25000000 0.78825020
-0.98533724 0.25000000 0.78781850
-0.98631476 0.25000000 0.78739050
-0.98729228 0.25000000 0.78694035
-0.98826979 0.25000000 0.78646407
-0.98924731 0.25000000 0.78597481
-0.99022483 0.25000000 0.78546981
-0.99120235 0.25000000 0.78493388
-0.99217986 0.25000000 0.78436450
-0.99315738 0.25000000 0.78375795
-0.99413490 0.25000000 0.78310826
-0.99511241 0.25000000 0.78240496
-0.99608993 0.25000000 0.78162741
-0.99706745 0.25000000 0.78072789
-0.99804497 0.25000000 0.77969339
-0.99902248 0.25000000 0.77832850
-1.00000000 nan nan
+Ambient Power InversePower
+0.000000000 nan nan
+0.000977517 0.750000000 0.221671502
+0.001955034 0.750000000 0.220306607
+0.002932551 0.750000000 0.219272108
+0.003910068 0.750000000 0.218372593
+0.004887586 0.750000000 0.217595038
+0.005865103 0.750000000 0.216891736
+0.006842620 0.750000000 0.216242049
+0.007820137 0.750000000 0.215635499
+0.008797654 0.750000000 0.215066121
+0.009775171 0.750000000 0.214530188
+0.010752688 0.750000000 0.214025192
+0.011730205 0.750000000 0.213535928
+0.012707722 0.750000000 0.213059653
+0.013685239 0.750000000 0.212609497
+0.014662757 0.750000000 0.212181500
+0.015640274 0.750000000 0.211749797
+0.016617791 0.750000000 0.211342499
+0.017595308 0.750000000 0.210947791
+0.018572825 0.750000000 0.210554977
+0.019550342 0.750000000 0.210185583
+0.020527859 0.750000000 0.209810047
+0.021505376 0.750000000 0.209453273
+0.022482893 0.750000000 0.209099710
+0.023460411 0.750000000 0.208754784
+0.024437928 0.750000000 0.208418460
+0.025415445 0.750000000 0.208108896
+0.026392962 0.750000000 0.207822337
+0.027370479 0.750000000 0.207557090
+0.028347996 0.750000000 0.207310043
+0.029325513 0.750000000 0.207080132
+0.030303030 0.750000000 0.206864987
+0.031280547 0.750000000 0.206663695
+0.032258065 0.750000000 0.206474685
+0.033235582 0.750000000 0.206296887
+0.034213099 0.750000000 0.206129563
+0.035190616 0.750000000 0.205971282
+0.036168133 0.750000000 0.205822154
+0.037145650 0.750000000 0.205680293
+0.038123167 0.750000000 0.205546551
+0.039100684 0.750000000 0.205418994
+0.040078201 0.750000000 0.205298019
+0.041055718 0.750000000 0.205182743
+0.042033236 0.750000000 0.205072718
+0.043010753 0.750000000 0.204968065
+0.043988270 0.750000000 0.204867643
+0.044965787 0.750000000 0.204772102
+0.045943304 0.750000000 0.204680372
+0.046920821 0.750000000 0.204592478
+0.047898338 0.750000000 0.204508389
+0.048875855 0.750000000 0.204427324
+0.049853372 0.750000000 0.204349869
+0.050830890 0.750000000 0.204275190
+0.051808407 0.750000000 0.204203265
+0.052785924 0.750000000 0.204134275
+0.053763441 0.750000000 0.204067513
+0.054740958 0.750000000 0.204003359
+0.055718475 0.750000000 0.203941436
+0.056695992 0.750000000 0.203881398
+0.057673509 0.750000000 0.203823826
+0.058651026 0.750000000 0.203767941
+0.059628543 0.750000000 0.203713842
+0.060606061 0.750000000 0.203661714
+0.061583578 0.750000000 0.203611030
+0.062561095 0.750000000 0.203562034
+0.063538612 0.750000000 0.203514617
+0.064516129 0.750000000 0.203468446
+0.065493646 0.750000000 0.203423862
+0.066471163 0.750000000 0.203380551
+0.067448680 0.750000000 0.203338322
+0.068426197 0.750000000 0.203297578
+0.069403715 0.750000000 0.203257869
+0.070381232 0.750000000 0.203219115
+0.071358749 0.750000000 0.203181723
+0.072336266 0.750000000 0.203145191
+0.073313783 0.750000000 0.203109538
+0.074291300 0.750000000 0.203075066
+0.075268817 0.750000000 0.203041351
+0.076246334 0.750000000 0.203008438
+0.077223851 0.750000000 0.202976564
+0.078201369 0.750000000 0.202945359
+0.079178886 0.750000000 0.202914878
+0.080156403 0.750000000 0.202885326
+0.081133920 0.750000000 0.202856368
+0.082111437 0.750000000 0.202828056
+0.083088954 0.750000000 0.202800588
+0.084066471 0.750000000 0.202773648
+0.085043988 0.750000000 0.202747278
+0.086021505 0.750000000 0.202721688
+0.086999022 0.750000000 0.202696569
+0.087976540 0.750000000 0.202671946
+0.088954057 0.750000000 0.202648053
+0.089931574 0.750000000 0.202624584
+0.090909091 0.750000000 0.202601536
+0.091886608 0.750000000 0.202579184
+0.092864125 0.750000000 0.202557213
+0.093841642 0.750000000 0.202535613
+0.094819159 0.750000000 0.202514642
+0.095796676 0.750000000 0.202494036
+0.096774194 0.750000000 0.202473765
+0.097751711 0.750000000 0.202454042
+0.098729228 0.750000000 0.202434684
+0.099706745 0.750000000 0.202415629
+0.100684262 0.750000000 0.202397043
+0.101661779 0.750000000 0.202378829
+0.102639296 0.750000000 0.202360889
+0.103616813 0.750000000 0.202343345
+0.104594330 0.750000000 0.202326181
+0.105571848 0.750000000 0.202309267
+0.106549365 0.750000000 0.202292677
+0.107526882 0.750000000 0.202276482
+0.108504399 0.750000000 0.202260514
+0.109481916 0.750000000 0.202244803
+0.110459433 0.750000000 0.202229501
+0.111436950 0.750000000 0.202214406
+0.112414467 0.750000000 0.202199515
+0.113391984 0.750000000 0.202185031
+0.114369501 0.750000000 0.202170746
+0.115347019 0.750000000 0.202156646
+0.116324536 0.750000000 0.202142887
+0.117302053 0.750000000 0.202129352
+0.118279570 0.750000000 0.202115988
+0.119257087 0.750000000 0.202102901
+0.120234604 0.750000000 0.202090065
+0.121212121 0.750000000 0.202077384
+0.122189638 0.750000000 0.202064922
+0.123167155 0.750000000 0.202052737
+0.124144673 0.750000000 0.202040694
+0.125122190 0.750000000 0.202028815
+0.126099707 0.750000000 0.202017236
+0.127077224 0.750000000 0.202005788
+0.128054741 0.750000000 0.201994470
+0.129032258 0.750000000 0.201983442
+0.130009775 0.750000000 0.201972551
+0.130987292 0.750000000 0.201961779
+0.131964809 0.750000000 0.201951246
+0.132942326 0.750000000 0.201940877
+0.133919844 0.750000000 0.201930618
+0.134897361 0.750000000 0.201920549
+0.135874878 0.750000000 0.201910669
+0.136852395 0.750000000 0.201900891
+0.137829912 0.750000000 0.201891259
+0.138807429 0.750000000 0.201881839
+0.139784946 0.750000000 0.201872513
+0.140762463 0.750000000 0.201863294
+0.141739980 0.750000000 0.201854307
+0.142717498 0.750000000 0.201845406
+0.143695015 0.750000000 0.201836590
+0.144672532 0.750000000 0.201827998
+0.145650049 0.750000000 0.201819498
+0.146627566 0.750000000 0.201811078
+0.147605083 0.750000000 0.201802845
+0.148582600 0.750000000 0.201794724
+0.149560117 0.750000000 0.201786676
+0.150537634 0.750000000 0.201778785
+0.151515152 0.750000000 0.201771022
+0.152492669 0.750000000 0.201763326
+0.153470186 0.750000000 0.201755760
+0.154447703 0.750000000 0.201748336
+0.155425220 0.750000000 0.201740974
+0.156402737 0.750000000 0.201733719
+0.157380254 0.750000000 0.201726616
+0.158357771 0.750000000 0.201719570
+0.159335288 0.750000000 0.201712612
+0.160312805 0.750000000 0.201705813
+0.161290323 0.750000000 0.201699068
+0.162267840 0.750000000 0.201692394
+0.163245357 0.750000000 0.201685884
+0.164222874 0.750000000 0.201679424
+0.165200391 0.750000000 0.201673024
+0.166177908 0.750000000 0.201666789
+0.167155425 0.750000000 0.201660600
+0.168132942 0.750000000 0.201654463
+0.169110459 0.750000000 0.201648489
+0.170087977 0.750000000 0.201642558
+0.171065494 0.750000000 0.201636676
+0.172043011 0.750000000 0.201630951
+0.173020528 0.750000000 0.201625266
+0.173998045 0.750000000 0.201619630
+0.174975562 0.750000000 0.201614142
+0.175953079 0.750000000 0.201608691
+0.176930596 0.750000000 0.201603293
+0.177908113 0.750000000 0.201598032
+0.178885630 0.750000000 0.201592805
+0.179863148 0.750000000 0.201587638
+0.180840665 0.750000000 0.201582594
+0.181818182 0.750000000 0.201577581
+0.182795699 0.750000000 0.201572640
+0.183773216 0.750000000 0.201567801
+0.184750733 0.750000000 0.201562993
+0.185728250 0.750000000 0.201558272
+0.186705767 0.750000000 0.201553632
+0.187683284 0.750000000 0.201549019
+0.188660802 0.750000000 0.201544513
+0.189638319 0.750000000 0.201540063
+0.190615836 0.750000000 0.201535638
+0.191593353 0.750000000 0.201531342
+0.192570870 0.750000000 0.201527074
+0.193548387 0.750000000 0.201522856
+0.194525904 0.750000000 0.201518740
+0.195503421 0.750000000 0.201514646
+0.196480938 0.750000000 0.201510635
+0.197458456 0.750000000 0.201506688
+0.198435973 0.750000000 0.201502762
+0.199413490 0.750000000 0.201498955
+0.200391007 0.750000000 0.201495170
+0.201368524 0.750000000 0.201491445
+0.202346041 0.750000000 0.201487799
+0.203323558 0.750000000 0.201484172
+0.204301075 0.750000000 0.201480648
+0.205278592 0.750000000 0.201477155
+0.206256109 0.750000000 0.201473716
+0.207233627 0.750000000 0.201470354
+0.208211144 0.750000000 0.201467007
+0.209188661 0.750000000 0.201463769
+0.210166178 0.750000000 0.201460550
+0.211143695 0.750000000 0.201457402
+0.212121212 0.750000000 0.201454307
+0.213098729 0.750000000 0.201451251
+0.214076246 0.750000000 0.201448278
+0.215053763 0.750000000 0.201445318
+0.216031281 0.750000000 0.201442464
+0.217008798 0.750000000 0.201439621
+0.217986315 0.750000000 0.201436866
+0.218963832 0.750000000 0.201434139
+0.219941349 0.750000000 0.201431486
+0.220918866 0.750000000 0.201428872
+0.221896383 0.750000000 0.201426324
+0.222873900 0.750000000 0.201423821
+0.223851417 0.750000000 0.201421381
+0.224828935 0.750000000 0.201418988
+0.225806452 0.750000000 0.201416661
+0.226783969 0.750000000 0.201414375
+0.227761486 0.750000000 0.201412163
+0.228739003 0.750000000 0.201409982
+0.229716520 0.750000000 0.201407891
+0.230694037 0.750000000 0.201405828
+0.231671554 0.750000000 0.201403846
+0.232649071 0.750000000 0.201401913
+0.233626588 0.750000000 0.201400032
+0.234604106 0.750000000 0.201398232
+0.235581623 0.750000000 0.201396477
+0.236559140 0.750000000 0.201394788
+0.237536657 0.750000000 0.201393176
+0.238514174 0.750000000 0.201391621
+0.239491691 0.750000000 0.201390128
+0.240469208 0.750000000 0.201388719
+0.241446725 0.750000000 0.201387385
+0.242424242 0.750000000 0.201386125
+0.243401760 0.750000000 0.201384946
+0.244379277 0.750000000 0.201383854
+0.245356794 0.750000000 0.201382854
+0.246334311 0.750000000 0.201381954
+0.247311828 0.750000000 0.201381173
+0.248289345 0.750000000 0.201380522
+0.249266862 0.750000000 0.201380043
+0.250244379 0.749633789 0.201846207
+0.251221896 0.748176070 0.203676892
+0.252199413 0.746729651 0.205470420
+0.253176931 0.745307268 0.207232921
+0.254154448 0.743901152 0.208969603
+0.255131965 0.742505384 0.210681995
+0.256109482 0.741119851 0.212371422
+0.257086999 0.739744439 0.214039141
+0.258064516 0.738388970 0.215686343
+0.259042033 0.737050250 0.217314161
+0.260019550 0.735720805 0.218923667
+0.260997067 0.734400539 0.220515879
+0.261974585 0.733089356 0.222091759
+0.262952102 0.731794526 0.223649762
+0.263929619 0.730516794 0.225192151
+0.264907136 0.729247388 0.226720383
+0.265884653 0.727986227 0.228232727
+0.266862170 0.726733231 0.229730635
+0.267839687 0.725493442 0.231216292
+0.268817204 0.724270974 0.232685872
+0.269794721 0.723055990 0.234144013
+0.270772239 0.721848423 0.235588818
+0.271749756 0.720648204 0.237021028
+0.272727273 0.719458438 0.238442032
+0.273704790 0.718286101 0.239849792
+0.274682307 0.717120499 0.241247924
+0.275659824 0.715961575 0.242632618
+0.276637341 0.714809270 0.244008759
+0.277614858 0.713665012 0.245371680
+0.278592375 0.712538184 0.246726670
+0.279569892 0.711417421 0.248069026
+0.280547410 0.710302674 0.249403669
+0.281524927 0.709193894 0.250726587
+0.282502444 0.708091063 0.252041647
+0.283479961 0.707005566 0.253346179
+0.284457478 0.705925531 0.254642389
+0.285434995 0.704850918 0.255929518
+0.286412512 0.703781686 0.257207578
+0.287390029 0.702717795 0.258478219
+0.288367546 0.701668621 0.259738800
+0.289345064 0.700625580 0.260993370
+0.290322581 0.699587425 0.262237549
+0.291300098 0.698554121 0.263475527
+0.292277615 0.697525635 0.264705239
+0.293255132 0.696509490 0.265927232
+0.294232649 0.695500037 0.267143201
+0.295210166 0.694494984 0.268349791
+0.296187683 0.693494303 0.269551115
+0.297165200 0.692497965 0.270744440
+0.298142717 0.691511860 0.271931138
+0.299120235 0.690532874 0.273112342
+0.300097752 0.689557847 0.274284946
+0.301075269 0.688586755 0.275452739
+0.302052786 0.687619575 0.276613621
+0.303030303 0.686660765 0.277768031
+0.304007820 0.685709376 0.278917856
+0.304985337 0.684761545 0.280059697
+0.305962854 0.683817249 0.281196818
+0.306940371 0.682876470 0.282328684
+0.307917889 0.681942420 0.283453563
+0.308895406 0.681015980 0.284574256
+0.309872923 0.680092726 0.285688972
+0.310850440 0.679172643 0.286798049
+0.311827957 0.678255714 0.287903138
+0.312805474 0.677344077 0.289001763
+0.313782991 0.676440126 0.290095833
+0.314760508 0.675539023 0.291186105
+0.315738025 0.674640752 0.292269631
+0.316715543 0.673745302 0.293349456
+0.317693060 0.672853893 0.294425247
+0.318670577 0.671970143 0.295495017
+0.319648094 0.671088924 0.296561328
+0.320625611 0.670210227 0.297623455
+0.321603128 0.669334041 0.298680243
+0.322580645 0.668460818 0.299733738
+0.323558162 0.667595126 0.300783030
+0.324535679 0.666731672 0.301827515
+0.325513196 0.665870450 0.302868868
+0.326490714 0.665011449 0.303906100
+0.327468231 0.664154662 0.304938935
+0.328445748 0.663304848 0.305968793
+0.329423265 0.662457164 0.306994695
+0.330400782 0.661611439 0.308016510
+0.331378299 0.660767667 0.309035496
+0.332355816 0.659925840 0.310050754
+0.333333333 0.659089669 0.311062154
+0.334310850 0.658255868 0.312070870
+0.335288368 0.657423770 0.313076130
+0.336265885 0.656593371 0.314077703
+0.337243402 0.655764665 0.315076729
+0.338220919 0.654940458 0.316071981
+0.339198436 0.654118746 0.317062640
+0.340175953 0.653298497 0.318050990
+0.341153470 0.652479705 0.319036167
+0.342130987 0.651662368 0.320016921
+0.343108504 0.650848521 0.320995595
+0.344086022 0.650037186 0.321971698
+0.345063539 0.649227083 0.322943523
+0.346041056 0.648418210 0.323913488
+0.347018573 0.647610563 0.324881463
+0.347996090 0.646805538 0.325845303
+0.348973607 0.646002934 0.326807497
+0.349951124 0.645201343 0.327768050
+0.350928641 0.644400763 0.328725018
+0.351906158 0.643601190 0.329680354
+0.352883675 0.642803505 0.330634256
+0.353861193 0.642008044 0.331585332
+0.354838710 0.641213384 0.332534700
+0.355816227 0.640419523 0.333482835
+0.356793744 0.639626459 0.334428830
+0.357771261 0.638834675 0.335373101
+0.358748778 0.638044814 0.336316337
+0.359726295 0.637255548 0.337258027
+0.360703812 0.636466876 0.338198057
+0.361681329 0.635678797 0.339137245
+0.362658847 0.634891512 0.340075384
+0.363636364 0.634105743 0.341012014
+0.364613881 0.633320368 0.341947992
+0.365591398 0.632535386 0.342883313
+0.366568915 0.631750798 0.343817374
+0.367546432 0.630966638 0.344750971
+0.368523949 0.630183479 0.345684104
+0.369501466 0.629400516 0.346616504
+0.370478983 0.628617749 0.347548540
+0.371456500 0.627835178 0.348480299
+0.372434018 0.627052803 0.349411745
+0.373411535 0.626270772 0.350343037
+0.374389052 0.625488759 0.351274237
+0.375366569 0.624706745 0.352205426
+0.376344086 0.623924731 0.353136787
+0.377321603 0.623142717 0.354068240
+0.378299120 0.622360434 0.354999866
+0.379276637 0.621577912 0.355932108
+0.380254154 0.620795194 0.356864629
+0.381231672 0.620012280 0.357797428
+0.382209189 0.619229171 0.358731329
+0.383186706 0.618445288 0.359665733
+0.384164223 0.617660798 0.360600602
+0.385141740 0.616875914 0.361536789
+0.386119257 0.616090638 0.362473899
+0.387096774 0.615304967 0.363411663
+0.388074291 0.614518130 0.364350853
+0.389051808 0.613730200 0.365291500
+0.390029326 0.612941676 0.366232990
+0.391006843 0.612152558 0.367175921
+0.391984360 0.611362846 0.368120944
+0.392961877 0.610571682 0.369067005
+0.393939394 0.609778818 0.370014435
+0.394916911 0.608985156 0.370964689
+0.395894428 0.608190696 0.371916178
+0.396871945 0.607395436 0.372868906
+0.397849462 0.606598545 0.373825246
+0.398826979 0.605799225 0.374783038
+0.399804497 0.604998896 0.375742272
+0.400782014 0.604197558 0.376705194
+0.401759531 0.603395208 0.377670184
+0.402737048 0.602591157 0.378636823
+0.403714565 0.601783817 0.379607193
+0.404692082 0.600975251 0.380580296
+0.405669599 0.600165455 0.381555265
+0.406647116 0.599354429 0.382533989
+0.407624633 0.598541740 0.383516150
+0.408602151 0.597724765 0.384500397
+0.409579668 0.596906338 0.385488433
+0.410557185 0.596086453 0.386480623
+0.411534702 0.595265107 0.387475131
+0.412512219 0.594442248 0.388473492
+0.413489736 0.593613964 0.389476718
+0.414467253 0.592783988 0.390482499
+0.415444770 0.591952316 0.391491555
+0.416422287 0.591118941 0.392504668
+0.417399804 0.590283858 0.393520477
+0.418377322 0.589442972 0.394539685
+0.419354839 0.588599687 0.395563270
+0.420332356 0.587754450 0.396589695
+0.421309873 0.586907257 0.397619709
+0.422287390 0.586058099 0.398654373
+0.423264907 0.585202955 0.399692025
+0.424242424 0.584344508 0.400733540
+0.425219941 0.583483842 0.401779909
+0.426197458 0.582620947 0.402829422
+0.427174976 0.581755815 0.403883177
+0.428152493 0.580884615 0.404941902
+0.429130010 0.580009054 0.406003935
+0.430107527 0.579130986 0.407070716
+0.431085044 0.578250399 0.408142475
+0.432062561 0.577367283 0.409217712
+0.433040078 0.576478121 0.410298357
+0.434017595 0.575583374 0.411383856
+0.434995112 0.574685810 0.412473008
+0.435972630 0.573785416 0.413568413
+0.436950147 0.572882178 0.414668387
+0.437927664 0.571973027 0.415772198
+0.438905181 0.571056884 0.416883317
+0.439882698 0.570137591 0.417998533
+0.440860215 0.569215132 0.419118581
+0.441837732 0.568289490 0.420245634
+0.442815249 0.567358177 0.421376894
+0.443792766 0.566418275 0.422514343
+0.444770283 0.565474860 0.423658069
+0.445747801 0.564527914 0.424806212
+0.446725318 0.563577417 0.425962211
+0.447702835 0.562621612 0.427123480
+0.448680352 0.561655405 0.428290282
+0.449657869 0.560685294 0.429465166
+0.450635386 0.559711253 0.430644890
+0.451612903 0.558733259 0.431832308
+0.452590420 0.557750445 0.433026364
+0.453567937 0.556755188 0.434226000
+0.454545455 0.555755595 0.435434924
+0.455522972 0.554751638 0.436649146
+0.456500489 0.553743287 0.437871753
+0.457478006 0.552730515 0.439101626
+0.458455523 0.551703450 0.440338101
+0.459433040 0.550671354 0.441584214
+0.460410557 0.549634415 0.442836126
+0.461388074 0.548592599 0.444098260
+0.462365591 0.547545872 0.445367270
+0.463343109 0.546484786 0.446645195
+0.464320626 0.545416893 0.447931951
+0.465298143 0.544343629 0.449226535
+0.466275660 0.543264953 0.450531713
+0.467253177 0.542180826 0.451843888
+0.468230694 0.541082374 0.453168194
+0.469208211 0.539975079 0.454499403
+0.470185728 0.538861828 0.455843131
+0.471163245 0.537742573 0.457194500
+0.472140762 0.536617267 0.458558366
+0.473118280 0.535477779 0.459930679
+0.474095797 0.534327120 0.461315854
+0.475073314 0.533169855 0.462709935
+0.476050831 0.532005928 0.464117671
+0.477028348 0.530835281 0.465534381
+0.478005865 0.529650711 0.466952620
+0.478983382 0.528452318 0.468377996
+0.479960899 0.527246594 0.469806093
+0.480938416 0.526033471 0.471239943
+0.481915934 0.524812880 0.472678374
+0.482893451 0.523578752 0.474120606
+0.483870968 0.522327784 0.475569070
+0.484848485 0.521068672 0.477020289
+0.485826002 0.519801335 0.478476759
+0.486803519 0.518525692 0.479938796
+0.487781036 0.517237031 0.481403707
+0.488758553 0.515928105 0.482873363
+0.489736070 0.514610118 0.484347894
+0.490713587 0.513282977 0.485826893
+0.491691105 0.511946585 0.487309221
+0.492668622 0.510597845 0.488795133
+0.493646139 0.509224947 0.490284775
+0.494623656 0.507841954 0.491777716
+0.495601173 0.506448755 0.493273513
+0.496578690 0.505045237 0.494770784
+0.497556207 0.503630203 0.496268873
+0.498533724 0.502186589 0.497766318
+0.499511241 0.500731707 0.499259366
+0.500488759 0.499268293 0.500740634
+0.501466276 0.497813411 0.502233682
+0.502443793 0.496369797 0.503731127
+0.503421310 0.494954763 0.505229216
+0.504398827 0.493551245 0.506726487
+0.505376344 0.492158046 0.508222284
+0.506353861 0.490775053 0.509715225
+0.507331378 0.489402155 0.511204867
+0.508308895 0.488053415 0.512690779
+0.509286413 0.486717023 0.514173107
+0.510263930 0.485389882 0.515652106
+0.511241447 0.484071895 0.517126637
+0.512218964 0.482762969 0.518596293
+0.513196481 0.481474308 0.520061204
+0.514173998 0.480198665 0.521523241
+0.515151515 0.478931328 0.522979711
+0.516129032 0.477672216 0.524430930
+0.517106549 0.476421248 0.525879394
+0.518084066 0.475187120 0.527321626
+0.519061584 0.473966529 0.528760057
+0.520039101 0.472753406 0.530193907
+0.521016618 0.471547682 0.531622004
+0.521994135 0.470349289 0.533047380
+0.522971652 0.469164719 0.534465619
+0.523949169 0.467994072 0.535882329
+0.524926686 0.466830145 0.537290065
+0.525904203 0.465672880 0.538684146
+0.526881720 0.464522221 0.540069321
+0.527859238 0.463382733 0.541441634
+0.528836755 0.462257427 0.542805500
+0.529814272 0.461138172 0.544156869
+0.530791789 0.460024921 0.545500597
+0.531769306 0.458917626 0.546831806
+0.532746823 0.457819174 0.548156112
+0.533724340 0.456735047 0.549468287
+0.534701857 0.455656371 0.550773465
+0.535679374 0.454583107 0.552068049
+0.536656891 0.453515214 0.553354805
+0.537634409 0.452454128 0.554632730
+0.538611926 0.451407401 0.555901740
+0.539589443 0.450365585 0.557163874
+0.540566960 0.449328646 0.558415786
+0.541544477 0.448296550 0.559661899
+0.542521994 0.447269485 0.560898374
+0.543499511 0.446256713 0.562128247
+0.544477028 0.445248362 0.563350854
+0.545454545 0.444244405 0.564565076
+0.546432063 0.443244812 0.565774000
+0.547409580 0.442249555 0.566973636
+0.548387097 0.441266741 0.568167692
+0.549364614 0.440288747 0.569355110
+0.550342131 0.439314706 0.570534834
+0.551319648 0.438344595 0.571709718
+0.552297165 0.437378388 0.572876520
+0.553274682 0.436422583 0.574037789
+0.554252199 0.435472086 0.575193788
+0.555229717 0.434525140 0.576341931
+0.556207234 0.433581725 0.577485657
+0.557184751 0.432641823 0.578623106
+0.558162268 0.431710510 0.579754366
+0.559139785 0.430784868 0.580881419
+0.560117302 0.429862409 0.582001467
+0.561094819 0.428943116 0.583116683
+0.562072336 0.428026973 0.584227802
+0.563049853 0.427117822 0.585331613
+0.564027370 0.426214584 0.586431587
+0.565004888 0.425314190 0.587526992
+0.565982405 0.424416626 0.588616144
+0.566959922 0.423521879 0.589701643
+0.567937439 0.422632717 0.590782288
+0.568914956 0.421749601 0.591857525
+0.569892473 0.420869014 0.592929284
+0.570869990 0.419990946 0.593996065
+0.571847507 0.419115385 0.595058098
+0.572825024 0.418244185 0.596116823
+0.573802542 0.417379053 0.597170578
+0.574780059 0.416516158 0.598220091
+0.575757576 0.415655492 0.599266460
+0.576735093 0.414797045 0.600307975
+0.577712610 0.413941901 0.601345627
+0.578690127 0.413092743 0.602380291
+0.579667644 0.412245550 0.603410305
+0.580645161 0.411400313 0.604436730
+0.581622678 0.410557028 0.605460315
+0.582600196 0.409716142 0.606479523
+0.583577713 0.408881059 0.607495332
+0.584555230 0.408047684 0.608508445
+0.585532747 0.407216012 0.609517501
+0.586510264 0.406386036 0.610523282
+0.587487781 0.405557752 0.611526508
+0.588465298 0.404734893 0.612524869
+0.589442815 0.403913547 0.613519377
+0.590420332 0.403093662 0.614511567
+0.591397849 0.402275235 0.615499603
+0.592375367 0.401458260 0.616483850
+0.593352884 0.400645571 0.617466011
+0.594330401 0.399834545 0.618444735
+0.595307918 0.399024749 0.619419704
+0.596285435 0.398216183 0.620392807
+0.597262952 0.397408843 0.621363177
+0.598240469 0.396604792 0.622329816
+0.599217986 0.395802442 0.623294806
+0.600195503 0.395001104 0.624257728
+0.601173021 0.394200775 0.625216962
+0.602150538 0.393401455 0.626174754
+0.603128055 0.392604564 0.627131094
+0.604105572 0.391809304 0.628083822
+0.605083089 0.391014844 0.629035311
+0.606060606 0.390221182 0.629985565
+0.607038123 0.389428318 0.630932995
+0.608015640 0.388637154 0.631879056
+0.608993157 0.387847442 0.632824079
+0.609970674 0.387058324 0.633767010
+0.610948192 0.386269800 0.634708500
+0.611925709 0.385481870 0.635649147
+0.612903226 0.384695033 0.636588337
+0.613880743 0.383909362 0.637526101
+0.614858260 0.383124086 0.638463211
+0.615835777 0.382339202 0.639399398
+0.616813294 0.381554712 0.640334267
+0.617790811 0.380770829 0.641268671
+0.618768328 0.379987720 0.642202572
+0.619745846 0.379204806 0.643135371
+0.620723363 0.378422088 0.644067892
+0.621700880 0.377639566 0.645000134
+0.622678397 0.376857283 0.645931760
+0.623655914 0.376075269 0.646863213
+0.624633431 0.375293255 0.647794574
+0.625610948 0.374511241 0.648725763
+0.626588465 0.373729228 0.649656963
+0.627565982 0.372947197 0.650588255
+0.628543500 0.372164822 0.651519701
+0.629521017 0.371382251 0.652451460
+0.630498534 0.370599484 0.653383496
+0.631476051 0.369816521 0.654315896
+0.632453568 0.369033362 0.655249029
+0.633431085 0.368249202 0.656182626
+0.634408602 0.367464614 0.657116687
+0.635386119 0.366679632 0.658052008
+0.636363636 0.365894257 0.658987986
+0.637341153 0.365108488 0.659924616
+0.638318671 0.364321203 0.660862755
+0.639296188 0.363533124 0.661801943
+0.640273705 0.362744452 0.662741973
+0.641251222 0.361955186 0.663683663
+0.642228739 0.361165325 0.664626899
+0.643206256 0.360373541 0.665571170
+0.644183773 0.359580477 0.666517165
+0.645161290 0.358786616 0.667465300
+0.646138807 0.357991956 0.668414668
+0.647116325 0.357196495 0.669365744
+0.648093842 0.356398810 0.670319646
+0.649071359 0.355599237 0.671274982
+0.650048876 0.354798657 0.672231950
+0.651026393 0.353997066 0.673192503
+0.652003910 0.353194462 0.674154697
+0.652981427 0.352389437 0.675118537
+0.653958944 0.351581790 0.676086512
+0.654936461 0.350772917 0.677056477
+0.655913978 0.349962814 0.678028302
+0.656891496 0.349151479 0.679004405
+0.657869013 0.348337632 0.679983079
+0.658846530 0.347520295 0.680963833
+0.659824047 0.346701503 0.681949010
+0.660801564 0.345881254 0.682937360
+0.661779081 0.345059542 0.683928019
+0.662756598 0.344235335 0.684923271
+0.663734115 0.343406629 0.685922297
+0.664711632 0.342576230 0.686923870
+0.665689150 0.341744132 0.687929130
+0.666666667 0.340910331 0.688937846
+0.667644184 0.340074160 0.689949246
+0.668621701 0.339232333 0.690964504
+0.669599218 0.338388561 0.691983490
+0.670576735 0.337542836 0.693005305
+0.671554252 0.336695152 0.694031207
+0.672531769 0.335845338 0.695061065
+0.673509286 0.334988551 0.696093900
+0.674486804 0.334129550 0.697131132
+0.675464321 0.333268328 0.698172485
+0.676441838 0.332404874 0.699216970
+0.677419355 0.331539182 0.700266262
+0.678396872 0.330665959 0.701319757
+0.679374389 0.329789773 0.702376545
+0.680351906 0.328911076 0.703438672
+0.681329423 0.328029857 0.704504983
+0.682306940 0.327146107 0.705574753
+0.683284457 0.326254698 0.706650544
+0.684261975 0.325359248 0.707730369
+0.685239492 0.324460977 0.708813895
+0.686217009 0.323559874 0.709904167
+0.687194526 0.322655923 0.710998237
+0.688172043 0.321744286 0.712096862
+0.689149560 0.320827357 0.713201951
+0.690127077 0.319907274 0.714311028
+0.691104594 0.318984020 0.715425744
+0.692082111 0.318057580 0.716546437
+0.693059629 0.317123530 0.717671316
+0.694037146 0.316182751 0.718803182
+0.695014663 0.315238455 0.719940303
+0.695992180 0.314290624 0.721082144
+0.696969697 0.313339235 0.722231969
+0.697947214 0.312380425 0.723386379
+0.698924731 0.311413245 0.724547261
+0.699902248 0.310442153 0.725715054
+0.700879765 0.309467126 0.726887658
+0.701857283 0.308488140 0.728068862
+0.702834800 0.307502035 0.729255560
+0.703812317 0.306505697 0.730448885
+0.704789834 0.305505016 0.731650209
+0.705767351 0.304499963 0.732856799
+0.706744868 0.303490510 0.734072768
+0.707722385 0.302474365 0.735294761
+0.708699902 0.301445879 0.736524473
+0.709677419 0.300412575 0.737762451
+0.710654936 0.299374420 0.739006630
+0.711632454 0.298331379 0.740261200
+0.712609971 0.297282205 0.741521781
+0.713587488 0.296218314 0.742792422
+0.714565005 0.295149082 0.744070482
+0.715542522 0.294074469 0.745357611
+0.716520039 0.292994434 0.746653821
+0.717497556 0.291908937 0.747958353
+0.718475073 0.290806106 0.749273413
+0.719452590 0.289697326 0.750596331
+0.720430108 0.288582579 0.751930974
+0.721407625 0.287461816 0.753273330
+0.722385142 0.286334988 0.754628320
+0.723362659 0.285190730 0.755991241
+0.724340176 0.284038425 0.757367382
+0.725317693 0.282879501 0.758752076
+0.726295210 0.281713899 0.760150208
+0.727272727 0.280541562 0.761557968
+0.728250244 0.279351796 0.762978972
+0.729227761 0.278151577 0.764411182
+0.730205279 0.276944010 0.765855987
+0.731182796 0.275729026 0.767314128
+0.732160313 0.274506558 0.768783708
+0.733137830 0.273266769 0.770269365
+0.734115347 0.272013773 0.771767273
+0.735092864 0.270752612 0.773279617
+0.736070381 0.269483206 0.774807849
+0.737047898 0.268205474 0.776350238
+0.738025415 0.266910644 0.777908241
+0.739002933 0.265599461 0.779484121
+0.739980450 0.264279195 0.781076333
+0.740957967 0.262949750 0.782685839
+0.741935484 0.261611030 0.784313657
+0.742913001 0.260255561 0.785960859
+0.743890518 0.258880149 0.787628578
+0.744868035 0.257494616 0.789318005
+0.745845552 0.256098848 0.791030397
+0.746823069 0.254692732 0.792767079
+0.747800587 0.253270349 0.794529580
+0.748778104 0.251823930 0.796323108
+0.749755621 0.250366211 0.798153793
+0.750733138 0.250000000 0.798619957
+0.751710655 0.250000000 0.798619478
+0.752688172 0.250000000 0.798618827
+0.753665689 0.250000000 0.798618046
+0.754643206 0.250000000 0.798617146
+0.755620723 0.250000000 0.798616146
+0.756598240 0.250000000 0.798615054
+0.757575758 0.250000000 0.798613875
+0.758553275 0.250000000 0.798612615
+0.759530792 0.250000000 0.798611281
+0.760508309 0.250000000 0.798609872
+0.761485826 0.250000000 0.798608379
+0.762463343 0.250000000 0.798606824
+0.763440860 0.250000000 0.798605212
+0.764418377 0.250000000 0.798603523
+0.765395894 0.250000000 0.798601768
+0.766373412 0.250000000 0.798599968
+0.767350929 0.250000000 0.798598087
+0.768328446 0.250000000 0.798596154
+0.769305963 0.250000000 0.798594172
+0.770283480 0.250000000 0.798592109
+0.771260997 0.250000000 0.798590018
+0.772238514 0.250000000 0.798587837
+0.773216031 0.250000000 0.798585625
+0.774193548 0.250000000 0.798583339
+0.775171065 0.250000000 0.798581012
+0.776148583 0.250000000 0.798578619
+0.777126100 0.250000000 0.798576179
+0.778103617 0.250000000 0.798573676
+0.779081134 0.250000000 0.798571128
+0.780058651 0.250000000 0.798568514
+0.781036168 0.250000000 0.798565861
+0.782013685 0.250000000 0.798563134
+0.782991202 0.250000000 0.798560379
+0.783968719 0.250000000 0.798557536
+0.784946237 0.250000000 0.798554682
+0.785923754 0.250000000 0.798551722
+0.786901271 0.250000000 0.798548749
+0.787878788 0.250000000 0.798545693
+0.788856305 0.250000000 0.798542598
+0.789833822 0.250000000 0.798539450
+0.790811339 0.250000000 0.798536231
+0.791788856 0.250000000 0.798532993
+0.792766373 0.250000000 0.798529646
+0.793743891 0.250000000 0.798526284
+0.794721408 0.250000000 0.798522845
+0.795698925 0.250000000 0.798519352
+0.796676442 0.250000000 0.798515828
+0.797653959 0.250000000 0.798512201
+0.798631476 0.250000000 0.798508555
+0.799608993 0.250000000 0.798504830
+0.800586510 0.250000000 0.798501045
+0.801564027 0.250000000 0.798497238
+0.802541544 0.250000000 0.798493312
+0.803519062 0.250000000 0.798489365
+0.804496579 0.250000000 0.798485354
+0.805474096 0.250000000 0.798481260
+0.806451613 0.250000000 0.798477144
+0.807429130 0.250000000 0.798472926
+0.808406647 0.250000000 0.798468658
+0.809384164 0.250000000 0.798464362
+0.810361681 0.250000000 0.798459937
+0.811339198 0.250000000 0.798455487
+0.812316716 0.250000000 0.798450981
+0.813294233 0.250000000 0.798446368
+0.814271750 0.250000000 0.798441728
+0.815249267 0.250000000 0.798437007
+0.816226784 0.250000000 0.798432199
+0.817204301 0.250000000 0.798427360
+0.818181818 0.250000000 0.798422419
+0.819159335 0.250000000 0.798417406
+0.820136852 0.250000000 0.798412362
+0.821114370 0.250000000 0.798407195
+0.822091887 0.250000000 0.798401968
+0.823069404 0.250000000 0.798396707
+0.824046921 0.250000000 0.798391309
+0.825024438 0.250000000 0.798385858
+0.826001955 0.250000000 0.798380370
+0.826979472 0.250000000 0.798374734
+0.827956989 0.250000000 0.798369049
+0.828934506 0.250000000 0.798363324
+0.829912023 0.250000000 0.798357442
+0.830889541 0.250000000 0.798351511
+0.831867058 0.250000000 0.798345537
+0.832844575 0.250000000 0.798339400
+0.833822092 0.250000000 0.798333211
+0.834799609 0.250000000 0.798326976
+0.835777126 0.250000000 0.798320576
+0.836754643 0.250000000 0.798314116
+0.837732160 0.250000000 0.798307606
+0.838709677 0.250000000 0.798300932
+0.839687195 0.250000000 0.798294187
+0.840664712 0.250000000 0.798287388
+0.841642229 0.250000000 0.798280430
+0.842619746 0.250000000 0.798273384
+0.843597263 0.250000000 0.798266281
+0.844574780 0.250000000 0.798259026
+0.845552297 0.250000000 0.798251664
+0.846529814 0.250000000 0.798244240
+0.847507331 0.250000000 0.798236674
+0.848484848 0.250000000 0.798228978
+0.849462366 0.250000000 0.798221215
+0.850439883 0.250000000 0.798213324
+0.851417400 0.250000000 0.798205276
+0.852394917 0.250000000 0.798197155
+0.853372434 0.250000000 0.798188922
+0.854349951 0.250000000 0.798180502
+0.855327468 0.250000000 0.798172002
+0.856304985 0.250000000 0.798163410
+0.857282502 0.250000000 0.798154594
+0.858260020 0.250000000 0.798145693
+0.859237537 0.250000000 0.798136706
+0.860215054 0.250000000 0.798127487
+0.861192571 0.250000000 0.798118161
+0.862170088 0.250000000 0.798108741
+0.863147605 0.250000000 0.798099109
+0.864125122 0.250000000 0.798089331
+0.865102639 0.250000000 0.798079451
+0.866080156 0.250000000 0.798069382
+0.867057674 0.250000000 0.798059123
+0.868035191 0.250000000 0.798048754
+0.869012708 0.250000000 0.798038221
+0.869990225 0.250000000 0.798027449
+0.870967742 0.250000000 0.798016558
+0.871945259 0.250000000 0.798005530
+0.872922776 0.250000000 0.797994212
+0.873900293 0.250000000 0.797982764
+0.874877810 0.250000000 0.797971185
+0.875855327 0.250000000 0.797959306
+0.876832845 0.250000000 0.797947263
+0.877810362 0.250000000 0.797935078
+0.878787879 0.250000000 0.797922616
+0.879765396 0.250000000 0.797909935
+0.880742913 0.250000000 0.797897099
+0.881720430 0.250000000 0.797884012
+0.882697947 0.250000000 0.797870648
+0.883675464 0.250000000 0.797857113
+0.884652981 0.250000000 0.797843354
+0.885630499 0.250000000 0.797829254
+0.886608016 0.250000000 0.797814969
+0.887585533 0.250000000 0.797800485
+0.888563050 0.250000000 0.797785594
+0.889540567 0.250000000 0.797770499
+0.890518084 0.250000000 0.797755197
+0.891495601 0.250000000 0.797739486
+0.892473118 0.250000000 0.797723518
+0.893450635 0.250000000 0.797707323
+0.894428152 0.250000000 0.797690733
+0.895405670 0.250000000 0.797673819
+0.896383187 0.250000000 0.797656655
+0.897360704 0.250000000 0.797639111
+0.898338221 0.250000000 0.797621171
+0.899315738 0.250000000 0.797602957
+0.900293255 0.250000000 0.797584371
+0.901270772 0.250000000 0.797565316
+0.902248289 0.250000000 0.797545958
+0.903225806 0.250000000 0.797526235
+0.904203324 0.250000000 0.797505964
+0.905180841 0.250000000 0.797485358
+0.906158358 0.250000000 0.797464387
+0.907135875 0.250000000 0.797442787
+0.908113392 0.250000000 0.797420816
+0.909090909 0.250000000 0.797398464
+0.910068426 0.250000000 0.797375416
+0.911045943 0.250000000 0.797351947
+0.912023460 0.250000000 0.797328054
+0.913000978 0.250000000 0.797303431
+0.913978495 0.250000000 0.797278312
+0.914956012 0.250000000 0.797252722
+0.915933529 0.250000000 0.797226352
+0.916911046 0.250000000 0.797199412
+0.917888563 0.250000000 0.797171944
+0.918866080 0.250000000 0.797143632
+0.919843597 0.250000000 0.797114674
+0.920821114 0.250000000 0.797085122
+0.921798631 0.250000000 0.797054641
+0.922776149 0.250000000 0.797023436
+0.923753666 0.250000000 0.796991562
+0.924731183 0.250000000 0.796958649
+0.925708700 0.250000000 0.796924934
+0.926686217 0.250000000 0.796890462
+0.927663734 0.250000000 0.796854809
+0.928641251 0.250000000 0.796818277
+0.929618768 0.250000000 0.796780885
+0.930596285 0.250000000 0.796742131
+0.931573803 0.250000000 0.796702422
+0.932551320 0.250000000 0.796661678
+0.933528837 0.250000000 0.796619449
+0.934506354 0.250000000 0.796576138
+0.935483871 0.250000000 0.796531554
+0.936461388 0.250000000 0.796485383
+0.937438905 0.250000000 0.796437966
+0.938416422 0.250000000 0.796388970
+0.939393939 0.250000000 0.796338286
+0.940371457 0.250000000 0.796286158
+0.941348974 0.250000000 0.796232059
+0.942326491 0.250000000 0.796176174
+0.943304008 0.250000000 0.796118602
+0.944281525 0.250000000 0.796058564
+0.945259042 0.250000000 0.795996641
+0.946236559 0.250000000 0.795932487
+0.947214076 0.250000000 0.795865725
+0.948191593 0.250000000 0.795796735
+0.949169110 0.250000000 0.795724810
+0.950146628 0.250000000 0.795650131
+0.951124145 0.250000000 0.795572676
+0.952101662 0.250000000 0.795491611
+0.953079179 0.250000000 0.795407522
+0.954056696 0.250000000 0.795319628
+0.955034213 0.250000000 0.795227898
+0.956011730 0.250000000 0.795132357
+0.956989247 0.250000000 0.795031935
+0.957966764 0.250000000 0.794927282
+0.958944282 0.250000000 0.794817257
+0.959921799 0.250000000 0.794701981
+0.960899316 0.250000000 0.794581006
+0.961876833 0.250000000 0.794453449
+0.962854350 0.250000000 0.794319707
+0.963831867 0.250000000 0.794177846
+0.964809384 0.250000000 0.794028718
+0.965786901 0.250000000 0.793870437
+0.966764418 0.250000000 0.793703113
+0.967741935 0.250000000 0.793525315
+0.968719453 0.250000000 0.793336305
+0.969696970 0.250000000 0.793135013
+0.970674487 0.250000000 0.792919868
+0.971652004 0.250000000 0.792689957
+0.972629521 0.250000000 0.792442910
+0.973607038 0.250000000 0.792177663
+0.974584555 0.250000000 0.791891104
+0.975562072 0.250000000 0.791581540
+0.976539589 0.250000000 0.791245216
+0.977517107 0.250000000 0.790900290
+0.978494624 0.250000000 0.790546727
+0.979472141 0.250000000 0.790189953
+0.980449658 0.250000000 0.789814417
+0.981427175 0.250000000 0.789445023
+0.982404692 0.250000000 0.789052209
+0.983382209 0.250000000 0.788657501
+0.984359726 0.250000000 0.788250203
+0.985337243 0.250000000 0.787818500
+0.986314761 0.250000000 0.787390503
+0.987292278 0.250000000 0.786940347
+0.988269795 0.250000000 0.786464072
+0.989247312 0.250000000 0.785974808
+0.990224829 0.250000000 0.785469812
+0.991202346 0.250000000 0.784933879
+0.992179863 0.250000000 0.784364501
+0.993157380 0.250000000 0.783757951
+0.994134897 0.250000000 0.783108264
+0.995112414 0.250000000 0.782404962
+0.996089932 0.250000000 0.781627407
+0.997067449 0.250000000 0.780727892
+0.998044966 0.250000000 0.779693393
+0.999022483 0.250000000 0.778328498
+1.000000000 nan nan
diff --git a/examples/mamdani/SimpleDimmerInverse.fll b/examples/mamdani/SimpleDimmerInverse.fll
index fd6b945..4ce7313 100644
--- a/examples/mamdani/SimpleDimmerInverse.fll
+++ b/examples/mamdani/SimpleDimmerInverse.fll
@@ -1,29 +1,30 @@
-Engine: simple-dimmer
+Engine: SimpleDimmerInverse
InputVariable: Ambient
enabled: true
range: 0.000 1.000
+ lock-range: false
term: DARK Triangle 0.000 0.250 0.500
term: MEDIUM Triangle 0.250 0.500 0.750
term: BRIGHT Triangle 0.500 0.750 1.000
OutputVariable: Power
enabled: true
range: 0.000 1.000
- accumulation: Maximum
+ lock-range: false
+ aggregation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
- lock-range: false
term: LOW Triangle 0.000 0.250 0.500
term: MEDIUM Triangle 0.250 0.500 0.750
term: HIGH Triangle 0.500 0.750 1.000
OutputVariable: InversePower
enabled: true
range: 0.000 1.000
- accumulation: Maximum
+ lock-range: false
+ aggregation: Maximum
defuzzifier: Centroid 500
default: nan
lock-previous: false
- lock-range: false
term: LOW Cosine 0.200 0.500
term: MEDIUM Cosine 0.500 0.500
term: HIGH Cosine 0.800 0.500
@@ -31,7 +32,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if Ambient is DARK then Power is HIGH
rule: if Ambient is MEDIUM then Power is MEDIUM
rule: if Ambient is BRIGHT then Power is LOW
diff --git a/examples/mamdani/SimpleDimmerInverse.java b/examples/mamdani/SimpleDimmerInverse.java
index 0bdde89..218f831 100644
--- a/examples/mamdani/SimpleDimmerInverse.java
+++ b/examples/mamdani/SimpleDimmerInverse.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,52 +13,61 @@ import com.fuzzylite.variable.*;
public class SimpleDimmerInverse{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("simple-dimmer");
+engine.setName("SimpleDimmerInverse");
+engine.setDescription("");
-InputVariable inputVariable = new InputVariable();
-inputVariable.setEnabled(true);
-inputVariable.setName("Ambient");
-inputVariable.setRange(0.000, 1.000);
-inputVariable.addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
-inputVariable.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-inputVariable.addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
-engine.addInputVariable(inputVariable);
+InputVariable Ambient = new InputVariable();
+Ambient.setName("Ambient");
+Ambient.setDescription("");
+Ambient.setEnabled(true);
+Ambient.setRange(0.000, 1.000);
+Ambient.setLockValueInRange(false);
+Ambient.addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+Ambient.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Ambient.addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+engine.addInputVariable(Ambient);
-OutputVariable outputVariable1 = new OutputVariable();
-outputVariable1.setEnabled(true);
-outputVariable1.setName("Power");
-outputVariable1.setRange(0.000, 1.000);
-outputVariable1.fuzzyOutput().setAccumulation(new Maximum());
-outputVariable1.setDefuzzifier(new Centroid(200));
-outputVariable1.setDefaultValue(Double.NaN);
-outputVariable1.setLockPreviousOutputValue(false);
-outputVariable1.setLockOutputValueInRange(false);
-outputVariable1.addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
-outputVariable1.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-outputVariable1.addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
-engine.addOutputVariable(outputVariable1);
+OutputVariable Power = new OutputVariable();
+Power.setName("Power");
+Power.setDescription("");
+Power.setEnabled(true);
+Power.setRange(0.000, 1.000);
+Power.setLockValueInRange(false);
+Power.setAggregation(new Maximum());
+Power.setDefuzzifier(new Centroid(200));
+Power.setDefaultValue(Double.NaN);
+Power.setLockPreviousValue(false);
+Power.addTerm(new Triangle("LOW", 0.000, 0.250, 0.500));
+Power.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Power.addTerm(new Triangle("HIGH", 0.500, 0.750, 1.000));
+engine.addOutputVariable(Power);
-OutputVariable outputVariable2 = new OutputVariable();
-outputVariable2.setEnabled(true);
-outputVariable2.setName("InversePower");
-outputVariable2.setRange(0.000, 1.000);
-outputVariable2.fuzzyOutput().setAccumulation(new Maximum());
-outputVariable2.setDefuzzifier(new Centroid(500));
-outputVariable2.setDefaultValue(Double.NaN);
-outputVariable2.setLockPreviousOutputValue(false);
-outputVariable2.setLockOutputValueInRange(false);
-outputVariable2.addTerm(new Cosine("LOW", 0.200, 0.500));
-outputVariable2.addTerm(new Cosine("MEDIUM", 0.500, 0.500));
-outputVariable2.addTerm(new Cosine("HIGH", 0.800, 0.500));
-engine.addOutputVariable(outputVariable2);
+OutputVariable InversePower = new OutputVariable();
+InversePower.setName("InversePower");
+InversePower.setDescription("");
+InversePower.setEnabled(true);
+InversePower.setRange(0.000, 1.000);
+InversePower.setLockValueInRange(false);
+InversePower.setAggregation(new Maximum());
+InversePower.setDefuzzifier(new Centroid(500));
+InversePower.setDefaultValue(Double.NaN);
+InversePower.setLockPreviousValue(false);
+InversePower.addTerm(new Cosine("LOW", 0.200, 0.500));
+InversePower.addTerm(new Cosine("MEDIUM", 0.500, 0.500));
+InversePower.addTerm(new Cosine("HIGH", 0.800, 0.500));
+engine.addOutputVariable(InversePower);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(null);
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(new Minimum());
+ruleBlock.setImplication(new Minimum());
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if Ambient is DARK then Power is HIGH", engine));
ruleBlock.addRule(Rule.parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
ruleBlock.addRule(Rule.parse("if Ambient is BRIGHT then Power is LOW", engine));
diff --git a/examples/mamdani/SimpleDimmerInverse.pdf b/examples/mamdani/SimpleDimmerInverse.pdf
new file mode 100644
index 0000000..0cfb26d
--- /dev/null
+++ b/examples/mamdani/SimpleDimmerInverse.pdf
Binary files differ
diff --git a/examples/mamdani/octave/investment_portfolio.R b/examples/mamdani/octave/investment_portfolio.R
new file mode 100644
index 0000000..c752dab
--- /dev/null
+++ b/examples/mamdani/octave/investment_portfolio.R
@@ -0,0 +1,67 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "investment_portfolio"
+engine.fll = "Engine: investment_portfolio
+InputVariable: Age
+ enabled: true
+ range: 20.000 100.000
+ lock-range: false
+ term: Young ZShape 30.000 90.000
+ term: Old SShape 30.000 90.000
+InputVariable: RiskTolerance
+ enabled: true
+ range: 0.000 10.000
+ lock-range: false
+ term: Low ZShape 2.000 8.000
+ term: High SShape 2.000 8.000
+OutputVariable: PercentageInStocks
+ enabled: true
+ range: 0.000 100.000
+ lock-range: false
+ aggregation: EinsteinSum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: AboutFifteen Gaussian 15.000 10.000
+ term: AboutFifty Gaussian 50.000 10.000
+ term: AboutEightyFive Gaussian 85.000 10.000
+RuleBlock:
+ enabled: true
+ conjunction: EinsteinProduct
+ disjunction: EinsteinSum
+ implication: EinsteinProduct
+ activation: General
+ rule: if Age is Young or RiskTolerance is High then PercentageInStocks is AboutEightyFive
+ rule: if Age is Old or RiskTolerance is Low then PercentageInStocks is AboutFifteen
+ rule: if Age is not extremely Old and RiskTolerance is not extremely Low then PercentageInStocks is AboutFifty with 0.500
+ rule: if Age is not extremely Young and RiskTolerance is not extremely High then PercentageInStocks is AboutFifty with 0.500"
+
+engine.fldFile = "investment_portfolio.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1i2_o1 = ggplot(engine.df, aes(Age, RiskTolerance)) +
+ geom_tile(aes(fill=PercentageInStocks)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Age, y=RiskTolerance, z=PercentageInStocks), color="black") +
+ ggtitle("(Age, RiskTolerance) = PercentageInStocks")
+
+engine.plot.i2i1_o1 = ggplot(engine.df, aes(RiskTolerance, Age)) +
+ geom_tile(aes(fill=PercentageInStocks)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=RiskTolerance, y=Age, z=PercentageInStocks), color="black") +
+ ggtitle("(RiskTolerance, Age) = PercentageInStocks")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1i2_o1, engine.plot.i2i1_o1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/mamdani/octave/investment_portfolio.cpp b/examples/mamdani/octave/investment_portfolio.cpp
index 9ccadc9..2b82b8c 100644
--- a/examples/mamdani/octave/investment_portfolio.cpp
+++ b/examples/mamdani/octave/investment_portfolio.cpp
@@ -1,51 +1,61 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("Investment-Portfolio");
-
-InputVariable* inputVariable1 = new InputVariable;
-inputVariable1->setEnabled(true);
-inputVariable1->setName("Age");
-inputVariable1->setRange(20.000, 100.000);
-inputVariable1->addTerm(new ZShape("Young", 30.000, 90.000));
-inputVariable1->addTerm(new SShape("Old", 30.000, 90.000));
-engine->addInputVariable(inputVariable1);
-
-InputVariable* inputVariable2 = new InputVariable;
-inputVariable2->setEnabled(true);
-inputVariable2->setName("RiskTolerance");
-inputVariable2->setRange(0.000, 10.000);
-inputVariable2->addTerm(new ZShape("Low", 2.000, 8.000));
-inputVariable2->addTerm(new SShape("High", 2.000, 8.000));
-engine->addInputVariable(inputVariable2);
-
-OutputVariable* outputVariable = new OutputVariable;
-outputVariable->setEnabled(true);
-outputVariable->setName("PercentageInStocks");
-outputVariable->setRange(0.000, 100.000);
-outputVariable->fuzzyOutput()->setAccumulation(new EinsteinSum);
-outputVariable->setDefuzzifier(new Centroid(200));
-outputVariable->setDefaultValue(fl::nan);
-outputVariable->setLockPreviousOutputValue(false);
-outputVariable->setLockOutputValueInRange(false);
-outputVariable->addTerm(new Gaussian("AboutFifteen", 15.000, 10.000));
-outputVariable->addTerm(new Gaussian("AboutFifty", 50.000, 10.000));
-outputVariable->addTerm(new Gaussian("AboutEightyFive", 85.000, 10.000));
-engine->addOutputVariable(outputVariable);
+engine->setName("investment_portfolio");
+engine->setDescription("");
+
+InputVariable* Age = new InputVariable;
+Age->setName("Age");
+Age->setDescription("");
+Age->setEnabled(true);
+Age->setRange(20.000, 100.000);
+Age->setLockValueInRange(false);
+Age->addTerm(new ZShape("Young", 30.000, 90.000));
+Age->addTerm(new SShape("Old", 30.000, 90.000));
+engine->addInputVariable(Age);
+
+InputVariable* RiskTolerance = new InputVariable;
+RiskTolerance->setName("RiskTolerance");
+RiskTolerance->setDescription("");
+RiskTolerance->setEnabled(true);
+RiskTolerance->setRange(0.000, 10.000);
+RiskTolerance->setLockValueInRange(false);
+RiskTolerance->addTerm(new ZShape("Low", 2.000, 8.000));
+RiskTolerance->addTerm(new SShape("High", 2.000, 8.000));
+engine->addInputVariable(RiskTolerance);
+
+OutputVariable* PercentageInStocks = new OutputVariable;
+PercentageInStocks->setName("PercentageInStocks");
+PercentageInStocks->setDescription("");
+PercentageInStocks->setEnabled(true);
+PercentageInStocks->setRange(0.000, 100.000);
+PercentageInStocks->setLockValueInRange(false);
+PercentageInStocks->setAggregation(new EinsteinSum);
+PercentageInStocks->setDefuzzifier(new Centroid(200));
+PercentageInStocks->setDefaultValue(fl::nan);
+PercentageInStocks->setLockPreviousValue(false);
+PercentageInStocks->addTerm(new Gaussian("AboutFifteen", 15.000, 10.000));
+PercentageInStocks->addTerm(new Gaussian("AboutFifty", 50.000, 10.000));
+PercentageInStocks->addTerm(new Gaussian("AboutEightyFive", 85.000, 10.000));
+engine->addOutputVariable(PercentageInStocks);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(new EinsteinProduct);
ruleBlock->setDisjunction(new EinsteinSum);
-ruleBlock->setActivation(new EinsteinProduct);
-ruleBlock->addRule(fl::Rule::parse("if Age is Young or RiskTolerance is High then PercentageInStocks is AboutEightyFive", engine));
-ruleBlock->addRule(fl::Rule::parse("if Age is Old or RiskTolerance is Low then PercentageInStocks is AboutFifteen", engine));
-ruleBlock->addRule(fl::Rule::parse("if Age is not extremely Old and RiskTolerance is not extremely Low then PercentageInStocks is AboutFifty with 0.500", engine));
-ruleBlock->addRule(fl::Rule::parse("if Age is not extremely Young and RiskTolerance is not extremely High then PercentageInStocks is AboutFifty with 0.500", engine));
+ruleBlock->setImplication(new EinsteinProduct);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if Age is Young or RiskTolerance is High then PercentageInStocks is AboutEightyFive", engine));
+ruleBlock->addRule(Rule::parse("if Age is Old or RiskTolerance is Low then PercentageInStocks is AboutFifteen", engine));
+ruleBlock->addRule(Rule::parse("if Age is not extremely Old and RiskTolerance is not extremely Low then PercentageInStocks is AboutFifty with 0.500", engine));
+ruleBlock->addRule(Rule::parse("if Age is not extremely Young and RiskTolerance is not extremely High then PercentageInStocks is AboutFifty with 0.500", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/mamdani/octave/investment_portfolio.fcl b/examples/mamdani/octave/investment_portfolio.fcl
index 590ab3b..ec837a7 100644
--- a/examples/mamdani/octave/investment_portfolio.fcl
+++ b/examples/mamdani/octave/investment_portfolio.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK Investment-Portfolio
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK investment_portfolio
VAR_INPUT
Age: REAL;
diff --git a/examples/mamdani/octave/investment_portfolio.fis b/examples/mamdani/octave/investment_portfolio.fis
index 311e728..b512a68 100644
--- a/examples/mamdani/octave/investment_portfolio.fis
+++ b/examples/mamdani/octave/investment_portfolio.fis
@@ -1,6 +1,9 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='Investment-Portfolio'
+Name='investment_portfolio'
Type='mamdani'
+Version=6.0
NumInputs=2
NumOutputs=1
NumRules=4
diff --git a/examples/mamdani/octave/investment_portfolio.fld b/examples/mamdani/octave/investment_portfolio.fld
index 648b0be..4da9cb9 100644
--- a/examples/mamdani/octave/investment_portfolio.fld
+++ b/examples/mamdani/octave/investment_portfolio.fld
@@ -1,1026 +1,1025 @@
-#@Engine: Investment-Portfolio;
-#@InputVariable: Age; @InputVariable: RiskTolerance; @OutputVariable: PercentageInStocks;
-20.00000000 0.00000000 50.00000000
-20.00000000 0.32258065 50.00000000
-20.00000000 0.64516129 50.00000000
-20.00000000 0.96774194 50.00000000
-20.00000000 1.29032258 50.00000000
-20.00000000 1.61290323 50.00000000
-20.00000000 1.93548387 50.00000000
-20.00000000 2.25806452 50.07664849
-20.00000000 2.58064516 50.39007638
-20.00000000 2.90322581 50.95232681
-20.00000000 3.22580645 51.77492832
-20.00000000 3.54838710 52.87098013
-20.00000000 3.87096774 54.25013613
-20.00000000 4.19354839 55.91006054
-20.00000000 4.51612903 57.82311764
-20.00000000 4.83870968 59.91799668
-20.00000000 5.16129032 62.04316294
-20.00000000 5.48387097 64.00662112
-20.00000000 5.80645161 65.82068208
-20.00000000 6.12903226 67.49497664
-20.00000000 6.45161290 69.01370662
-20.00000000 6.77419355 70.34164582
-20.00000000 7.09677419 71.43161596
-20.00000000 7.41935484 72.23344208
-20.00000000 7.74193548 72.70359583
-20.00000000 8.06451613 72.82131403
-20.00000000 8.38709677 72.82131403
-20.00000000 8.70967742 72.82131403
-20.00000000 9.03225806 72.82131403
-20.00000000 9.35483871 72.82131403
-20.00000000 9.67741935 72.82131403
-20.00000000 10.00000000 72.82131403
-22.58064516 0.00000000 50.00000000
-22.58064516 0.32258065 50.00000000
-22.58064516 0.64516129 50.00000000
-22.58064516 0.96774194 50.00000000
-22.58064516 1.29032258 50.00000000
-22.58064516 1.61290323 50.00000000
-22.58064516 1.93548387 50.00000000
-22.58064516 2.25806452 50.07664849
-22.58064516 2.58064516 50.39007638
-22.58064516 2.90322581 50.95232681
-22.58064516 3.22580645 51.77492832
-22.58064516 3.54838710 52.87098013
-22.58064516 3.87096774 54.25013613
-22.58064516 4.19354839 55.91006054
-22.58064516 4.51612903 57.82311764
-22.58064516 4.83870968 59.91799668
-22.58064516 5.16129032 62.04316294
-22.58064516 5.48387097 64.00662112
-22.58064516 5.80645161 65.82068208
-22.58064516 6.12903226 67.49497664
-22.58064516 6.45161290 69.01370662
-22.58064516 6.77419355 70.34164582
-22.58064516 7.09677419 71.43161596
-22.58064516 7.41935484 72.23344208
-22.58064516 7.74193548 72.70359583
-22.58064516 8.06451613 72.82131403
-22.58064516 8.38709677 72.82131403
-22.58064516 8.70967742 72.82131403
-22.58064516 9.03225806 72.82131403
-22.58064516 9.35483871 72.82131403
-22.58064516 9.67741935 72.82131403
-22.58064516 10.00000000 72.82131403
-25.16129032 0.00000000 50.00000000
-25.16129032 0.32258065 50.00000000
-25.16129032 0.64516129 50.00000000
-25.16129032 0.96774194 50.00000000
-25.16129032 1.29032258 50.00000000
-25.16129032 1.61290323 50.00000000
-25.16129032 1.93548387 50.00000000
-25.16129032 2.25806452 50.07664849
-25.16129032 2.58064516 50.39007638
-25.16129032 2.90322581 50.95232681
-25.16129032 3.22580645 51.77492832
-25.16129032 3.54838710 52.87098013
-25.16129032 3.87096774 54.25013613
-25.16129032 4.19354839 55.91006054
-25.16129032 4.51612903 57.82311764
-25.16129032 4.83870968 59.91799668
-25.16129032 5.16129032 62.04316294
-25.16129032 5.48387097 64.00662112
-25.16129032 5.80645161 65.82068208
-25.16129032 6.12903226 67.49497664
-25.16129032 6.45161290 69.01370662
-25.16129032 6.77419355 70.34164582
-25.16129032 7.09677419 71.43161596
-25.16129032 7.41935484 72.23344208
-25.16129032 7.74193548 72.70359583
-25.16129032 8.06451613 72.82131403
-25.16129032 8.38709677 72.82131403
-25.16129032 8.70967742 72.82131403
-25.16129032 9.03225806 72.82131403
-25.16129032 9.35483871 72.82131403
-25.16129032 9.67741935 72.82131403
-25.16129032 10.00000000 72.82131403
-27.74193548 0.00000000 50.00000000
-27.74193548 0.32258065 50.00000000
-27.74193548 0.64516129 50.00000000
-27.74193548 0.96774194 50.00000000
-27.74193548 1.29032258 50.00000000
-27.74193548 1.61290323 50.00000000
-27.74193548 1.93548387 50.00000000
-27.74193548 2.25806452 50.07664849
-27.74193548 2.58064516 50.39007638
-27.74193548 2.90322581 50.95232681
-27.74193548 3.22580645 51.77492832
-27.74193548 3.54838710 52.87098013
-27.74193548 3.87096774 54.25013613
-27.74193548 4.19354839 55.91006054
-27.74193548 4.51612903 57.82311764
-27.74193548 4.83870968 59.91799668
-27.74193548 5.16129032 62.04316294
-27.74193548 5.48387097 64.00662112
-27.74193548 5.80645161 65.82068208
-27.74193548 6.12903226 67.49497664
-27.74193548 6.45161290 69.01370662
-27.74193548 6.77419355 70.34164582
-27.74193548 7.09677419 71.43161596
-27.74193548 7.41935484 72.23344208
-27.74193548 7.74193548 72.70359583
-27.74193548 8.06451613 72.82131403
-27.74193548 8.38709677 72.82131403
-27.74193548 8.70967742 72.82131403
-27.74193548 9.03225806 72.82131403
-27.74193548 9.35483871 72.82131403
-27.74193548 9.67741935 72.82131403
-27.74193548 10.00000000 72.82131403
-30.32258065 0.00000000 49.99880392
-30.32258065 0.32258065 49.99880392
-30.32258065 0.64516129 49.99880392
-30.32258065 0.96774194 49.99880392
-30.32258065 1.29032258 49.99880392
-30.32258065 1.61290323 49.99880392
-30.32258065 1.93548387 49.99880392
-30.32258065 2.25806452 50.07545238
-30.32258065 2.58064516 50.38887965
-30.32258065 2.90322581 50.95112699
-30.32258065 3.22580645 51.77371992
-30.32258065 3.54838710 52.86975395
-30.32258065 3.87096774 54.24887943
-30.32258065 4.19354839 55.90875847
-30.32258065 4.51612903 57.82175684
-30.32258065 4.83870968 59.91657184
-30.32258065 5.16129032 62.04168233
-30.32258065 5.48387097 64.00508502
-30.32258065 5.80645161 65.81908993
-30.32258065 6.12903226 67.49332917
-30.32258065 6.45161290 69.01200609
-30.32258065 6.77419355 70.33989666
-30.32258065 7.09677419 71.42982533
-30.32258065 7.41935484 72.23162005
-30.32258065 7.74193548 72.70175504
-30.32258065 8.06451613 72.81946849
-30.32258065 8.38709677 72.81946849
-30.32258065 8.70967742 72.81946849
-30.32258065 9.03225806 72.81946849
-30.32258065 9.35483871 72.81946849
-30.32258065 9.67741935 72.81946849
-30.32258065 10.00000000 72.81946849
-32.90322581 0.00000000 49.90295798
-32.90322581 0.32258065 49.90295798
-32.90322581 0.64516129 49.90295798
-32.90322581 0.96774194 49.90295798
-32.90322581 1.29032258 49.90295798
-32.90322581 1.61290323 49.90295798
-32.90322581 1.93548387 49.90295798
-32.90322581 2.25806452 49.97960702
-32.90322581 2.58064516 50.29299482
-32.90322581 2.90322581 50.85501365
-32.90322581 3.22580645 51.67694728
-32.90322581 3.54838710 52.77159622
-32.90322581 3.87096774 54.14832785
-32.90322581 4.19354839 55.80464007
-32.90322581 4.51612903 57.71302139
-32.90322581 4.83870968 59.80281425
-32.90322581 5.16129032 61.92356979
-32.90322581 5.48387097 63.88261418
-32.90322581 5.80645161 65.69219320
-32.90322581 6.12903226 67.36205805
-32.90322581 6.45161290 68.87652195
-32.90322581 6.77419355 70.20054895
-32.90322581 7.09677419 71.28718186
-32.90322581 7.41935484 72.08648082
-32.90322581 7.74193548 72.55512448
-32.90322581 8.06451613 72.67246132
-32.90322581 8.38709677 72.67246132
-32.90322581 8.70967742 72.67246132
-32.90322581 9.03225806 72.67246132
-32.90322581 9.35483871 72.67246132
-32.90322581 9.67741935 72.67246132
-32.90322581 10.00000000 72.67246132
-35.48387097 0.00000000 49.65230424
-35.48387097 0.32258065 49.65230424
-35.48387097 0.64516129 49.65230424
-35.48387097 0.96774194 49.65230424
-35.48387097 1.29032258 49.65230424
-35.48387097 1.61290323 49.65230424
-35.48387097 1.93548387 49.65230424
-35.48387097 2.25806452 49.72897859
-35.48387097 2.58064516 50.04236049
-35.48387097 2.90322581 50.60395669
-35.48387097 3.22580645 51.42442479
-35.48387097 3.54838710 52.51580620
-35.48387097 3.87096774 53.88675089
-35.48387097 4.19354839 55.53436093
-35.48387097 4.51612903 57.43147904
-35.48387097 4.83870968 59.50912954
-35.48387097 5.16129032 61.61952428
-35.48387097 5.48387097 63.56796052
-35.48387097 5.80645161 65.36655988
-35.48387097 6.12903226 67.02542761
-35.48387097 6.45161290 68.52927075
-35.48387097 6.77419355 69.84352090
-35.48387097 7.09677419 70.92180186
-35.48387097 7.41935484 71.71475942
-35.48387097 7.74193548 72.17961322
-35.48387097 8.06451613 72.29599292
-35.48387097 8.38709677 72.29599292
-35.48387097 8.70967742 72.29599292
-35.48387097 9.03225806 72.29599292
-35.48387097 9.35483871 72.29599292
-35.48387097 9.67741935 72.29599292
-35.48387097 10.00000000 72.29599292
-38.06451613 0.00000000 49.24309895
-38.06451613 0.32258065 49.24309895
-38.06451613 0.64516129 49.24309895
-38.06451613 0.96774194 49.24309895
-38.06451613 1.29032258 49.24309895
-38.06451613 1.61290323 49.24309895
-38.06451613 1.93548387 49.24309895
-38.06451613 2.25806452 49.31988482
-38.06451613 2.58064516 49.63354393
-38.06451613 2.90322581 50.19496500
-38.06451613 3.22580645 51.01379991
-38.06451613 3.54838710 52.10088544
-38.06451613 3.87096774 53.46376445
-38.06451613 4.19354839 55.09898884
-38.06451613 4.51612903 56.98007353
-38.06451613 4.83870968 59.04077124
-38.06451613 5.16129032 61.13722688
-38.06451613 5.48387097 63.07064236
-38.06451613 5.80645161 64.85305357
-38.06451613 6.12903226 66.49534778
-38.06451613 6.45161290 67.98296760
-38.06451613 6.77419355 69.28218358
-38.06451613 7.09677419 70.34756047
-38.06451613 7.41935484 71.13072959
-38.06451613 7.74193548 71.58971545
-38.06451613 8.06451613 71.70461300
-38.06451613 8.38709677 71.70461300
-38.06451613 8.70967742 71.70461300
-38.06451613 9.03225806 71.70461300
-38.06451613 9.35483871 71.70461300
-38.06451613 9.67741935 71.70461300
-38.06451613 10.00000000 71.70461300
-40.64516129 0.00000000 48.66974302
-40.64516129 0.32258065 48.66974302
-40.64516129 0.64516129 48.66974302
-40.64516129 0.96774194 48.66974302
-40.64516129 1.29032258 48.66974302
-40.64516129 1.61290323 48.66974302
-40.64516129 1.93548387 48.66974302
-40.64516129 2.25806452 48.74681972
-40.64516129 2.58064516 49.06141626
-40.64516129 2.90322581 49.62357390
-40.64516129 3.22580645 50.44156177
-40.64516129 3.54838710 51.52458831
-40.64516129 3.87096774 52.87875978
-40.64516129 4.19354839 54.50003124
-40.64516129 4.51612903 56.36302984
-40.64516129 4.83870968 58.40529847
-40.64516129 5.16129032 60.48775451
-40.64516129 5.48387097 62.40444567
-40.64516129 5.80645161 64.16746517
-40.64516129 6.12903226 65.78913336
-40.64516129 6.45161290 67.25614371
-40.64516129 6.77419355 68.53604701
-40.64516129 7.09677419 69.58475383
-40.64516129 7.41935484 70.35521241
-40.64516129 7.74193548 70.80658497
-40.64516129 8.06451613 70.91955552
-40.64516129 8.38709677 70.91955552
-40.64516129 8.70967742 70.91955552
-40.64516129 9.03225806 70.91955552
-40.64516129 9.35483871 70.91955552
-40.64516129 9.67741935 70.91955552
-40.64516129 10.00000000 70.91955552
-43.22580645 0.00000000 47.92553362
-43.22580645 0.32258065 47.92553362
-43.22580645 0.64516129 47.92553362
-43.22580645 0.96774194 47.92553362
-43.22580645 1.29032258 47.92553362
-43.22580645 1.61290323 47.92553362
-43.22580645 1.93548387 47.92553362
-43.22580645 2.25806452 48.00319612
-43.22580645 2.58064516 48.31985647
-43.22580645 2.90322581 48.88447571
-43.22580645 3.22580645 49.70355442
-43.22580645 3.54838710 50.78426142
-43.22580645 3.87096774 52.13099528
-43.22580645 4.19354839 53.73918510
-43.22580645 4.51612903 55.58515207
-43.22580645 4.83870968 57.61132963
-43.22580645 5.16129032 59.68382184
-43.22580645 5.48387097 61.58536931
-43.22580645 5.80645161 63.32828142
-43.22580645 6.12903226 64.92718203
-43.22580645 6.45161290 66.37069947
-43.22580645 6.77419355 67.62820397
-43.22580645 7.09677419 68.65739074
-43.22580645 7.41935484 69.41289095
-43.22580645 7.74193548 69.85526918
-43.22580645 8.06451613 69.96596156
-43.22580645 8.38709677 69.96596156
-43.22580645 8.70967742 69.96596156
-43.22580645 9.03225806 69.96596156
-43.22580645 9.35483871 69.96596156
-43.22580645 9.67741935 69.96596156
-43.22580645 10.00000000 69.96596156
-45.80645161 0.00000000 47.00393487
-45.80645161 0.32258065 47.00393487
-45.80645161 0.64516129 47.00393487
-45.80645161 0.96774194 47.00393487
-45.80645161 1.29032258 47.00393487
-45.80645161 1.61290323 47.00393487
-45.80645161 1.93548387 47.00393487
-45.80645161 2.25806452 47.08260248
-45.80645161 2.58064516 47.40295027
-45.80645161 2.90322581 47.97260761
-45.80645161 3.22580645 48.79588816
-45.80645161 3.54838710 49.87749533
-45.80645161 3.87096774 51.21988342
-45.80645161 4.19354839 52.81813027
-45.80645161 4.51612903 54.65098576
-45.80645161 4.83870968 56.66698079
-45.80645161 5.16129032 58.73758982
-45.80645161 5.48387097 60.62911442
-45.80645161 5.80645161 62.35401414
-45.80645161 6.12903226 63.93019461
-45.80645161 6.45161290 65.34904000
-45.80645161 6.77419355 66.58237935
-45.80645161 7.09677419 67.59018730
-45.80645161 7.41935484 68.32916295
-45.80645161 7.74193548 68.76155861
-45.80645161 8.06451613 68.86971710
-45.80645161 8.38709677 68.86971710
-45.80645161 8.70967742 68.86971710
-45.80645161 9.03225806 68.86971710
-45.80645161 9.35483871 68.86971710
-45.80645161 9.67741935 68.86971710
-45.80645161 10.00000000 68.86971710
-48.38709677 0.00000000 45.90059861
-48.38709677 0.32258065 45.90059861
-48.38709677 0.64516129 45.90059861
-48.38709677 0.96774194 45.90059861
-48.38709677 1.29032258 45.90059861
-48.38709677 1.61290323 45.90059861
-48.38709677 1.93548387 45.90059861
-48.38709677 2.25806452 45.98080335
-48.38709677 2.58064516 46.30690509
-48.38709677 2.90322581 46.88490696
-48.38709677 3.22580645 47.71644736
-48.38709677 3.54838710 48.80327906
-48.38709677 3.87096774 50.14566326
-48.38709677 4.19354839 51.73856779
-48.38709677 4.51612903 53.56406480
-48.38709677 4.83870968 55.57822661
-48.38709677 5.16129032 57.65828336
-48.38709677 5.48387097 59.54837018
-48.38709677 5.80645161 61.26036274
-48.38709677 6.12903226 62.81628542
-48.38709677 6.45161290 64.21114285
-48.38709677 6.77419355 65.41994481
-48.38709677 7.09677419 66.40551444
-48.38709677 7.41935484 67.12705985
-48.38709677 7.74193548 67.54884508
-48.38709677 8.06451613 67.65430104
-48.38709677 8.38709677 67.65430104
-48.38709677 8.70967742 67.65430104
-48.38709677 9.03225806 67.65430104
-48.38709677 9.35483871 67.65430104
-48.38709677 9.67741935 67.65430104
-48.38709677 10.00000000 67.65430104
-50.96774194 0.00000000 44.61641577
-50.96774194 0.32258065 44.61641577
-50.96774194 0.64516129 44.61641577
-50.96774194 0.96774194 44.61641577
-50.96774194 1.29032258 44.61641577
-50.96774194 1.61290323 44.61641577
-50.96774194 1.93548387 44.61641577
-50.96774194 2.25806452 44.69876030
-50.96774194 2.58064516 45.03294688
-50.96774194 2.90322581 45.62298535
-50.96774194 3.22580645 46.46723847
-50.96774194 3.54838710 47.56391012
-50.96774194 3.87096774 48.91074345
-50.96774194 4.19354839 50.50284021
-50.96774194 4.51612903 52.32663397
-50.96774194 4.83870968 54.34758826
-50.96774194 5.16129032 56.44995468
-50.96774194 5.48387097 58.35016147
-50.96774194 5.80645161 60.05744033
-50.96774194 6.12903226 61.59819880
-50.96774194 6.45161290 62.97178502
-50.96774194 6.77419355 64.15714114
-50.96774194 7.09677419 65.12059667
-50.96774194 7.41935484 65.82440942
-50.96774194 7.74193548 66.23526465
-50.96774194 8.06451613 66.33792129
-50.96774194 8.38709677 66.33792129
-50.96774194 8.70967742 66.33792129
-50.96774194 9.03225806 66.33792129
-50.96774194 9.35483871 66.33792129
-50.96774194 9.67741935 66.33792129
-50.96774194 10.00000000 66.33792129
-53.54838710 0.00000000 43.16186397
-53.54838710 0.32258065 43.16186397
-53.54838710 0.64516129 43.16186397
-53.54838710 0.96774194 43.16186397
-53.54838710 1.29032258 43.16186397
-53.54838710 1.61290323 43.16186397
-53.54838710 1.93548387 43.16186397
-53.54838710 2.25806452 43.24693567
-53.54838710 2.58064516 43.59144915
-53.54838710 2.90322581 44.19696211
-53.54838710 3.22580645 45.05782673
-53.54838710 3.54838710 46.16794938
-53.54838710 3.87096774 47.52208653
-53.54838710 4.19354839 49.11561738
-53.54838710 4.51612903 50.94043496
-53.54838710 4.83870968 52.97375509
-53.54838710 5.16129032 55.10984868
-53.54838710 5.48387097 57.03353782
-53.54838710 5.80645161 58.74723142
-53.54838710 6.12903226 60.28074724
-53.54838710 6.45161290 61.63802885
-53.54838710 6.77419355 62.80260996
-53.54838710 7.09677419 63.74506644
-53.54838710 7.41935484 64.43139325
-53.54838710 7.74193548 64.83124074
-53.54838710 8.06451613 64.93106623
-53.54838710 8.38709677 64.93106623
-53.54838710 8.70967742 64.93106623
-53.54838710 9.03225806 64.93106623
-53.54838710 9.35483871 64.93106623
-53.54838710 9.67741935 64.93106623
-53.54838710 10.00000000 64.93106623
-56.12903226 0.00000000 41.56275742
-56.12903226 0.32258065 41.56275742
-56.12903226 0.64516129 41.56275742
-56.12903226 0.96774194 41.56275742
-56.12903226 1.29032258 41.56275742
-56.12903226 1.61290323 41.56275742
-56.12903226 1.93548387 41.56275742
-56.12903226 2.25806452 41.65098310
-56.12903226 2.58064516 42.00739488
-56.12903226 2.90322581 42.63056788
-56.12903226 3.22580645 43.51001484
-56.12903226 3.54838710 44.63446668
-56.12903226 3.87096774 45.99502950
-56.12903226 4.19354839 47.58723244
-56.12903226 4.51612903 49.40932005
-56.12903226 4.83870968 51.45296580
-56.12903226 5.16129032 53.62799552
-56.12903226 5.48387097 55.58793124
-56.12903226 5.80645161 57.32139748
-56.12903226 6.12903226 58.85847793
-56.12903226 6.45161290 60.20693213
-56.12903226 6.77419355 61.35519439
-56.12903226 7.09677419 62.27884289
-56.12903226 7.41935484 62.94847543
-56.12903226 7.74193548 63.33747330
-56.12903226 8.06451613 63.43446352
-56.12903226 8.38709677 63.43446352
-56.12903226 8.70967742 63.43446352
-56.12903226 9.03225806 63.43446352
-56.12903226 9.35483871 63.43446352
-56.12903226 9.67741935 63.43446352
-56.12903226 10.00000000 63.43446352
-58.70967742 0.00000000 39.86708229
-58.70967742 0.32258065 39.86708229
-58.70967742 0.64516129 39.86708229
-58.70967742 0.96774194 39.86708229
-58.70967742 1.29032258 39.86708229
-58.70967742 1.61290323 39.86708229
-58.70967742 1.93548387 39.86708229
-58.70967742 2.25806452 39.95851324
-58.70967742 2.58064516 40.32688461
-58.70967742 2.90322581 40.96728935
-58.70967742 3.22580645 41.86364269
-58.70967742 3.54838710 42.99862876
-58.70967742 3.87096774 44.35883597
-58.70967742 4.19354839 45.93926995
-58.70967742 4.51612903 47.74461410
-58.70967742 4.83870968 49.78326881
-58.70967742 5.16129032 51.98897073
-58.70967742 5.48387097 53.99267848
-58.70967742 5.80645161 55.75955980
-58.70967742 6.12903226 57.31349232
-58.70967742 6.45161290 58.66332782
-58.70967742 6.77419355 59.80184437
-58.70967742 7.09677419 60.71018916
-58.70967742 7.41935484 61.36458028
-58.70967742 7.74193548 61.74313870
-58.70967742 8.06451613 61.83734579
-58.70967742 8.38709677 61.83734579
-58.70967742 8.70967742 61.83734579
-58.70967742 9.03225806 61.83734579
-58.70967742 9.35483871 61.83734579
-58.70967742 9.67741935 61.83734579
-58.70967742 10.00000000 61.83734579
-61.29032258 0.00000000 38.16265421
-61.29032258 0.32258065 38.16265421
-61.29032258 0.64516129 38.16265421
-61.29032258 0.96774194 38.16265421
-61.29032258 1.29032258 38.16265421
-61.29032258 1.61290323 38.16265421
-61.29032258 1.93548387 38.16265421
-61.29032258 2.25806452 38.25686130
-61.29032258 2.58064516 38.63541972
-61.29032258 2.90322581 39.28981084
-61.29032258 3.22580645 40.19815563
-61.29032258 3.54838710 41.33667218
-61.29032258 3.87096774 42.68650768
-61.29032258 4.19354839 44.24044020
-61.29032258 4.51612903 46.00732152
-61.29032258 4.83870968 48.01102927
-61.29032258 5.16129032 50.21673119
-61.29032258 5.48387097 52.25538590
-61.29032258 5.80645161 54.06073005
-61.29032258 6.12903226 55.64116403
-61.29032258 6.45161290 57.00137124
-61.29032258 6.77419355 58.13635731
-61.29032258 7.09677419 59.03271065
-61.29032258 7.41935484 59.67311539
-61.29032258 7.74193548 60.04148676
-61.29032258 8.06451613 60.13291771
-61.29032258 8.38709677 60.13291771
-61.29032258 8.70967742 60.13291771
-61.29032258 9.03225806 60.13291771
-61.29032258 9.35483871 60.13291771
-61.29032258 9.67741935 60.13291771
-61.29032258 10.00000000 60.13291771
-63.87096774 0.00000000 36.56553648
-63.87096774 0.32258065 36.56553648
-63.87096774 0.64516129 36.56553648
-63.87096774 0.96774194 36.56553648
-63.87096774 1.29032258 36.56553648
-63.87096774 1.61290323 36.56553648
-63.87096774 1.93548387 36.56553648
-63.87096774 2.25806452 36.66252670
-63.87096774 2.58064516 37.05152457
-63.87096774 2.90322581 37.72115711
-63.87096774 3.22580645 38.64480561
-63.87096774 3.54838710 39.79306787
-63.87096774 3.87096774 41.14152207
-63.87096774 4.19354839 42.67860252
-63.87096774 4.51612903 44.41206876
-63.87096774 4.83870968 46.37200448
-63.87096774 5.16129032 48.54703420
-63.87096774 5.48387097 50.59067995
-63.87096774 5.80645161 52.41276756
-63.87096774 6.12903226 54.00497050
-63.87096774 6.45161290 55.36553332
-63.87096774 6.77419355 56.48998516
-63.87096774 7.09677419 57.36943212
-63.87096774 7.41935484 57.99260512
-63.87096774 7.74193548 58.34901690
-63.87096774 8.06451613 58.43724258
-63.87096774 8.38709677 58.43724258
-63.87096774 8.70967742 58.43724258
-63.87096774 9.03225806 58.43724258
-63.87096774 9.35483871 58.43724258
-63.87096774 9.67741935 58.43724258
-63.87096774 10.00000000 58.43724258
-66.45161290 0.00000000 35.06893377
-66.45161290 0.32258065 35.06893377
-66.45161290 0.64516129 35.06893377
-66.45161290 0.96774194 35.06893377
-66.45161290 1.29032258 35.06893377
-66.45161290 1.61290323 35.06893377
-66.45161290 1.93548387 35.06893377
-66.45161290 2.25806452 35.16875926
-66.45161290 2.58064516 35.56860675
-66.45161290 2.90322581 36.25493356
-66.45161290 3.22580645 37.19739004
-66.45161290 3.54838710 38.36197115
-66.45161290 3.87096774 39.71925276
-66.45161290 4.19354839 41.25276858
-66.45161290 4.51612903 42.96646218
-66.45161290 4.83870968 44.89015132
-66.45161290 5.16129032 47.02624491
-66.45161290 5.48387097 49.05956504
-66.45161290 5.80645161 50.88438262
-66.45161290 6.12903226 52.47791347
-66.45161290 6.45161290 53.83205062
-66.45161290 6.77419355 54.94217327
-66.45161290 7.09677419 55.80303789
-66.45161290 7.41935484 56.40855085
-66.45161290 7.74193548 56.75306433
-66.45161290 8.06451613 56.83813603
-66.45161290 8.38709677 56.83813603
-66.45161290 8.70967742 56.83813603
-66.45161290 9.03225806 56.83813603
-66.45161290 9.35483871 56.83813603
-66.45161290 9.67741935 56.83813603
-66.45161290 10.00000000 56.83813603
-69.03225806 0.00000000 33.66207871
-69.03225806 0.32258065 33.66207871
-69.03225806 0.64516129 33.66207871
-69.03225806 0.96774194 33.66207871
-69.03225806 1.29032258 33.66207871
-69.03225806 1.61290323 33.66207871
-69.03225806 1.93548387 33.66207871
-69.03225806 2.25806452 33.76473535
-69.03225806 2.58064516 34.17559058
-69.03225806 2.90322581 34.87940333
-69.03225806 3.22580645 35.84285886
-69.03225806 3.54838710 37.02821498
-69.03225806 3.87096774 38.40180120
-69.03225806 4.19354839 39.94255967
-69.03225806 4.51612903 41.64983853
-69.03225806 4.83870968 43.55004532
-69.03225806 5.16129032 45.65241174
-69.03225806 5.48387097 47.67336603
-69.03225806 5.80645161 49.49715979
-69.03225806 6.12903226 51.08925655
-69.03225806 6.45161290 52.43608988
-69.03225806 6.77419355 53.53276153
-69.03225806 7.09677419 54.37701465
-69.03225806 7.41935484 54.96705312
-69.03225806 7.74193548 55.30123970
-69.03225806 8.06451613 55.38358423
-69.03225806 8.38709677 55.38358423
-69.03225806 8.70967742 55.38358423
-69.03225806 9.03225806 55.38358423
-69.03225806 9.35483871 55.38358423
-69.03225806 9.67741935 55.38358423
-69.03225806 10.00000000 55.38358423
-71.61290323 0.00000000 32.34569896
-71.61290323 0.32258065 32.34569896
-71.61290323 0.64516129 32.34569896
-71.61290323 0.96774194 32.34569896
-71.61290323 1.29032258 32.34569896
-71.61290323 1.61290323 32.34569896
-71.61290323 1.93548387 32.34569896
-71.61290323 2.25806452 32.45115492
-71.61290323 2.58064516 32.87294015
-71.61290323 2.90322581 33.59448556
-71.61290323 3.22580645 34.58005519
-71.61290323 3.54838710 35.78885715
-71.61290323 3.87096774 37.18371458
-71.61290323 4.19354839 38.73963726
-71.61290323 4.51612903 40.45162982
-71.61290323 4.83870968 42.34171664
-71.61290323 5.16129032 44.42177339
-71.61290323 5.48387097 46.43593520
-71.61290323 5.80645161 48.26143221
-71.61290323 6.12903226 49.85433674
-71.61290323 6.45161290 51.19672094
-71.61290323 6.77419355 52.28355264
-71.61290323 7.09677419 53.11509304
-71.61290323 7.41935484 53.69309491
-71.61290323 7.74193548 54.01919665
-71.61290323 8.06451613 54.09940139
-71.61290323 8.38709677 54.09940139
-71.61290323 8.70967742 54.09940139
-71.61290323 9.03225806 54.09940139
-71.61290323 9.35483871 54.09940139
-71.61290323 9.67741935 54.09940139
-71.61290323 10.00000000 54.09940139
-74.19354839 0.00000000 31.13028290
-74.19354839 0.32258065 31.13028290
-74.19354839 0.64516129 31.13028290
-74.19354839 0.96774194 31.13028290
-74.19354839 1.29032258 31.13028290
-74.19354839 1.61290323 31.13028290
-74.19354839 1.93548387 31.13028290
-74.19354839 2.25806452 31.23844139
-74.19354839 2.58064516 31.67083705
-74.19354839 2.90322581 32.40981270
-74.19354839 3.22580645 33.41762065
-74.19354839 3.54838710 34.65096000
-74.19354839 3.87096774 36.06980539
-74.19354839 4.19354839 37.64598586
-74.19354839 4.51612903 39.37088558
-74.19354839 4.83870968 41.26241018
-74.19354839 5.16129032 43.33301921
-74.19354839 5.48387097 45.34901424
-74.19354839 5.80645161 47.18186973
-74.19354839 6.12903226 48.78011658
-74.19354839 6.45161290 50.12250467
-74.19354839 6.77419355 51.20411184
-74.19354839 7.09677419 52.02739239
-74.19354839 7.41935484 52.59704973
-74.19354839 7.74193548 52.91739752
-74.19354839 8.06451613 52.99606513
-74.19354839 8.38709677 52.99606513
-74.19354839 8.70967742 52.99606513
-74.19354839 9.03225806 52.99606513
-74.19354839 9.35483871 52.99606513
-74.19354839 9.67741935 52.99606513
-74.19354839 10.00000000 52.99606513
-76.77419355 0.00000000 30.03403844
-76.77419355 0.32258065 30.03403844
-76.77419355 0.64516129 30.03403844
-76.77419355 0.96774194 30.03403844
-76.77419355 1.29032258 30.03403844
-76.77419355 1.61290323 30.03403844
-76.77419355 1.93548387 30.03403844
-76.77419355 2.25806452 30.14473082
-76.77419355 2.58064516 30.58710905
-76.77419355 2.90322581 31.34260926
-76.77419355 3.22580645 32.37179603
-76.77419355 3.54838710 33.62930053
-76.77419355 3.87096774 35.07281797
-76.77419355 4.19354839 36.67171858
-76.77419355 4.51612903 38.41463069
-76.77419355 4.83870968 40.31617816
-76.77419355 5.16129032 42.38867037
-76.77419355 5.48387097 44.41484793
-76.77419355 5.80645161 46.26081490
-76.77419355 6.12903226 47.86900472
-76.77419355 6.45161290 49.21573858
-76.77419355 6.77419355 50.29644558
-76.77419355 7.09677419 51.11552429
-76.77419355 7.41935484 51.68014353
-76.77419355 7.74193548 51.99680388
-76.77419355 8.06451613 52.07446638
-76.77419355 8.38709677 52.07446638
-76.77419355 8.70967742 52.07446638
-76.77419355 9.03225806 52.07446638
-76.77419355 9.35483871 52.07446638
-76.77419355 9.67741935 52.07446638
-76.77419355 10.00000000 52.07446638
-79.35483871 0.00000000 29.08044448
-79.35483871 0.32258065 29.08044448
-79.35483871 0.64516129 29.08044448
-79.35483871 0.96774194 29.08044448
-79.35483871 1.29032258 29.08044448
-79.35483871 1.61290323 29.08044448
-79.35483871 1.93548387 29.08044448
-79.35483871 2.25806452 29.19341503
-79.35483871 2.58064516 29.64478759
-79.35483871 2.90322581 30.41524617
-79.35483871 3.22580645 31.46395299
-79.35483871 3.54838710 32.74385629
-79.35483871 3.87096774 34.21086664
-79.35483871 4.19354839 35.83253483
-79.35483871 4.51612903 37.59555433
-79.35483871 4.83870968 39.51224549
-79.35483871 5.16129032 41.59470153
-79.35483871 5.48387097 43.63697016
-79.35483871 5.80645161 45.49996876
-79.35483871 6.12903226 47.12124022
-79.35483871 6.45161290 48.47541169
-79.35483871 6.77419355 49.55843823
-79.35483871 7.09677419 50.37642610
-79.35483871 7.41935484 50.93858374
-79.35483871 7.74193548 51.25318028
-79.35483871 8.06451613 51.33025698
-79.35483871 8.38709677 51.33025698
-79.35483871 8.70967742 51.33025698
-79.35483871 9.03225806 51.33025698
-79.35483871 9.35483871 51.33025698
-79.35483871 9.67741935 51.33025698
-79.35483871 10.00000000 51.33025698
-81.93548387 0.00000000 28.29538700
-81.93548387 0.32258065 28.29538700
-81.93548387 0.64516129 28.29538700
-81.93548387 0.96774194 28.29538700
-81.93548387 1.29032258 28.29538700
-81.93548387 1.61290323 28.29538700
-81.93548387 1.93548387 28.29538700
-81.93548387 2.25806452 28.41028455
-81.93548387 2.58064516 28.86927041
-81.93548387 2.90322581 29.65243953
-81.93548387 3.22580645 30.71781642
-81.93548387 3.54838710 32.01703240
-81.93548387 3.87096774 33.50465222
-81.93548387 4.19354839 35.14694643
-81.93548387 4.51612903 36.92935764
-81.93548387 4.83870968 38.86277312
-81.93548387 5.16129032 40.95922876
-81.93548387 5.48387097 43.01992647
-81.93548387 5.80645161 44.90101116
-81.93548387 6.12903226 46.53623555
-81.93548387 6.45161290 47.89911456
-81.93548387 6.77419355 48.98620009
-81.93548387 7.09677419 49.80503500
-81.93548387 7.41935484 50.36645607
-81.93548387 7.74193548 50.68011518
-81.93548387 8.06451613 50.75690105
-81.93548387 8.38709677 50.75690105
-81.93548387 8.70967742 50.75690105
-81.93548387 9.03225806 50.75690105
-81.93548387 9.35483871 50.75690105
-81.93548387 9.67741935 50.75690105
-81.93548387 10.00000000 50.75690105
-84.51612903 0.00000000 27.70400708
-84.51612903 0.32258065 27.70400708
-84.51612903 0.64516129 27.70400708
-84.51612903 0.96774194 27.70400708
-84.51612903 1.29032258 27.70400708
-84.51612903 1.61290323 27.70400708
-84.51612903 1.93548387 27.70400708
-84.51612903 2.25806452 27.82038678
-84.51612903 2.58064516 28.28524058
-84.51612903 2.90322581 29.07819814
-84.51612903 3.22580645 30.15647910
-84.51612903 3.54838710 31.47072925
-84.51612903 3.87096774 32.97457239
-84.51612903 4.19354839 34.63344012
-84.51612903 4.51612903 36.43203948
-84.51612903 4.83870968 38.38047572
-84.51612903 5.16129032 40.49087046
-84.51612903 5.48387097 42.56852096
-84.51612903 5.80645161 44.46563907
-84.51612903 6.12903226 46.11324911
-84.51612903 6.45161290 47.48419380
-84.51612903 6.77419355 48.57557521
-84.51612903 7.09677419 49.39604331
-84.51612903 7.41935484 49.95763951
-84.51612903 7.74193548 50.27102141
-84.51612903 8.06451613 50.34769576
-84.51612903 8.38709677 50.34769576
-84.51612903 8.70967742 50.34769576
-84.51612903 9.03225806 50.34769576
-84.51612903 9.35483871 50.34769576
-84.51612903 9.67741935 50.34769576
-84.51612903 10.00000000 50.34769576
-87.09677419 0.00000000 27.32753868
-87.09677419 0.32258065 27.32753868
-87.09677419 0.64516129 27.32753868
-87.09677419 0.96774194 27.32753868
-87.09677419 1.29032258 27.32753868
-87.09677419 1.61290323 27.32753868
-87.09677419 1.93548387 27.32753868
-87.09677419 2.25806452 27.44487552
-87.09677419 2.58064516 27.91351918
-87.09677419 2.90322581 28.71281814
-87.09677419 3.22580645 29.79945105
-87.09677419 3.54838710 31.12347805
-87.09677419 3.87096774 32.63794195
-87.09677419 4.19354839 34.30780680
-87.09677419 4.51612903 36.11738582
-87.09677419 4.83870968 38.07643021
-87.09677419 5.16129032 40.19718575
-87.09677419 5.48387097 42.28697861
-87.09677419 5.80645161 44.19535993
-87.09677419 6.12903226 45.85167215
-87.09677419 6.45161290 47.22840378
-87.09677419 6.77419355 48.32305272
-87.09677419 7.09677419 49.14498635
-87.09677419 7.41935484 49.70700518
-87.09677419 7.74193548 50.02039298
-87.09677419 8.06451613 50.09704202
-87.09677419 8.38709677 50.09704202
-87.09677419 8.70967742 50.09704202
-87.09677419 9.03225806 50.09704202
-87.09677419 9.35483871 50.09704202
-87.09677419 9.67741935 50.09704202
-87.09677419 10.00000000 50.09704202
-89.67741935 0.00000000 27.18053151
-89.67741935 0.32258065 27.18053151
-89.67741935 0.64516129 27.18053151
-89.67741935 0.96774194 27.18053151
-89.67741935 1.29032258 27.18053151
-89.67741935 1.61290323 27.18053151
-89.67741935 1.93548387 27.18053151
-89.67741935 2.25806452 27.29824496
-89.67741935 2.58064516 27.76837995
-89.67741935 2.90322581 28.57017467
-89.67741935 3.22580645 29.66010334
-89.67741935 3.54838710 30.98799391
-89.67741935 3.87096774 32.50667083
-89.67741935 4.19354839 34.18091007
-89.67741935 4.51612903 35.99491498
-89.67741935 4.83870968 37.95831767
-89.67741935 5.16129032 40.08342816
-89.67741935 5.48387097 42.17824316
-89.67741935 5.80645161 44.09124153
-89.67741935 6.12903226 45.75112057
-89.67741935 6.45161290 47.13024605
-89.67741935 6.77419355 48.22628008
-89.67741935 7.09677419 49.04887301
-89.67741935 7.41935484 49.61112035
-89.67741935 7.74193548 49.92454762
-89.67741935 8.06451613 50.00119608
-89.67741935 8.38709677 50.00119608
-89.67741935 8.70967742 50.00119608
-89.67741935 9.03225806 50.00119608
-89.67741935 9.35483871 50.00119608
-89.67741935 9.67741935 50.00119608
-89.67741935 10.00000000 50.00119608
-92.25806452 0.00000000 27.17868597
-92.25806452 0.32258065 27.17868597
-92.25806452 0.64516129 27.17868597
-92.25806452 0.96774194 27.17868597
-92.25806452 1.29032258 27.17868597
-92.25806452 1.61290323 27.17868597
-92.25806452 1.93548387 27.17868597
-92.25806452 2.25806452 27.29640417
-92.25806452 2.58064516 27.76655792
-92.25806452 2.90322581 28.56838404
-92.25806452 3.22580645 29.65835418
-92.25806452 3.54838710 30.98629338
-92.25806452 3.87096774 32.50502336
-92.25806452 4.19354839 34.17931792
-92.25806452 4.51612903 35.99337888
-92.25806452 4.83870968 37.95683706
-92.25806452 5.16129032 40.08200332
-92.25806452 5.48387097 42.17688236
-92.25806452 5.80645161 44.08993946
-92.25806452 6.12903226 45.74986387
-92.25806452 6.45161290 47.12901987
-92.25806452 6.77419355 48.22507168
-92.25806452 7.09677419 49.04767319
-92.25806452 7.41935484 49.60992362
-92.25806452 7.74193548 49.92335151
-92.25806452 8.06451613 50.00000000
-92.25806452 8.38709677 50.00000000
-92.25806452 8.70967742 50.00000000
-92.25806452 9.03225806 50.00000000
-92.25806452 9.35483871 50.00000000
-92.25806452 9.67741935 50.00000000
-92.25806452 10.00000000 50.00000000
-94.83870968 0.00000000 27.17868597
-94.83870968 0.32258065 27.17868597
-94.83870968 0.64516129 27.17868597
-94.83870968 0.96774194 27.17868597
-94.83870968 1.29032258 27.17868597
-94.83870968 1.61290323 27.17868597
-94.83870968 1.93548387 27.17868597
-94.83870968 2.25806452 27.29640417
-94.83870968 2.58064516 27.76655792
-94.83870968 2.90322581 28.56838404
-94.83870968 3.22580645 29.65835418
-94.83870968 3.54838710 30.98629338
-94.83870968 3.87096774 32.50502336
-94.83870968 4.19354839 34.17931792
-94.83870968 4.51612903 35.99337888
-94.83870968 4.83870968 37.95683706
-94.83870968 5.16129032 40.08200332
-94.83870968 5.48387097 42.17688236
-94.83870968 5.80645161 44.08993946
-94.83870968 6.12903226 45.74986387
-94.83870968 6.45161290 47.12901987
-94.83870968 6.77419355 48.22507168
-94.83870968 7.09677419 49.04767319
-94.83870968 7.41935484 49.60992362
-94.83870968 7.74193548 49.92335151
-94.83870968 8.06451613 50.00000000
-94.83870968 8.38709677 50.00000000
-94.83870968 8.70967742 50.00000000
-94.83870968 9.03225806 50.00000000
-94.83870968 9.35483871 50.00000000
-94.83870968 9.67741935 50.00000000
-94.83870968 10.00000000 50.00000000
-97.41935484 0.00000000 27.17868597
-97.41935484 0.32258065 27.17868597
-97.41935484 0.64516129 27.17868597
-97.41935484 0.96774194 27.17868597
-97.41935484 1.29032258 27.17868597
-97.41935484 1.61290323 27.17868597
-97.41935484 1.93548387 27.17868597
-97.41935484 2.25806452 27.29640417
-97.41935484 2.58064516 27.76655792
-97.41935484 2.90322581 28.56838404
-97.41935484 3.22580645 29.65835418
-97.41935484 3.54838710 30.98629338
-97.41935484 3.87096774 32.50502336
-97.41935484 4.19354839 34.17931792
-97.41935484 4.51612903 35.99337888
-97.41935484 4.83870968 37.95683706
-97.41935484 5.16129032 40.08200332
-97.41935484 5.48387097 42.17688236
-97.41935484 5.80645161 44.08993946
-97.41935484 6.12903226 45.74986387
-97.41935484 6.45161290 47.12901987
-97.41935484 6.77419355 48.22507168
-97.41935484 7.09677419 49.04767319
-97.41935484 7.41935484 49.60992362
-97.41935484 7.74193548 49.92335151
-97.41935484 8.06451613 50.00000000
-97.41935484 8.38709677 50.00000000
-97.41935484 8.70967742 50.00000000
-97.41935484 9.03225806 50.00000000
-97.41935484 9.35483871 50.00000000
-97.41935484 9.67741935 50.00000000
-97.41935484 10.00000000 50.00000000
-100.00000000 0.00000000 27.17868597
-100.00000000 0.32258065 27.17868597
-100.00000000 0.64516129 27.17868597
-100.00000000 0.96774194 27.17868597
-100.00000000 1.29032258 27.17868597
-100.00000000 1.61290323 27.17868597
-100.00000000 1.93548387 27.17868597
-100.00000000 2.25806452 27.29640417
-100.00000000 2.58064516 27.76655792
-100.00000000 2.90322581 28.56838404
-100.00000000 3.22580645 29.65835418
-100.00000000 3.54838710 30.98629338
-100.00000000 3.87096774 32.50502336
-100.00000000 4.19354839 34.17931792
-100.00000000 4.51612903 35.99337888
-100.00000000 4.83870968 37.95683706
-100.00000000 5.16129032 40.08200332
-100.00000000 5.48387097 42.17688236
-100.00000000 5.80645161 44.08993946
-100.00000000 6.12903226 45.74986387
-100.00000000 6.45161290 47.12901987
-100.00000000 6.77419355 48.22507168
-100.00000000 7.09677419 49.04767319
-100.00000000 7.41935484 49.60992362
-100.00000000 7.74193548 49.92335151
-100.00000000 8.06451613 50.00000000
-100.00000000 8.38709677 50.00000000
-100.00000000 8.70967742 50.00000000
-100.00000000 9.03225806 50.00000000
-100.00000000 9.35483871 50.00000000
-100.00000000 9.67741935 50.00000000
-100.00000000 10.00000000 50.00000000
+Age RiskTolerance PercentageInStocks
+20.000000000 0.000000000 50.000000000
+20.000000000 0.322580645 50.000000000
+20.000000000 0.645161290 50.000000000
+20.000000000 0.967741935 50.000000000
+20.000000000 1.290322581 50.000000000
+20.000000000 1.612903226 50.000000000
+20.000000000 1.935483871 50.000000000
+20.000000000 2.258064516 50.076648486
+20.000000000 2.580645161 50.390076379
+20.000000000 2.903225806 50.952326813
+20.000000000 3.225806452 51.774928323
+20.000000000 3.548387097 52.870980129
+20.000000000 3.870967742 54.250136129
+20.000000000 4.193548387 55.910060541
+20.000000000 4.516129032 57.823117640
+20.000000000 4.838709677 59.917996684
+20.000000000 5.161290323 62.043162940
+20.000000000 5.483870968 64.006621117
+20.000000000 5.806451613 65.820682078
+20.000000000 6.129032258 67.494976640
+20.000000000 6.451612903 69.013706618
+20.000000000 6.774193548 70.341645817
+20.000000000 7.096774194 71.431615962
+20.000000000 7.419354839 72.233442079
+20.000000000 7.741935484 72.703595829
+20.000000000 8.064516129 72.821314025
+20.000000000 8.387096774 72.821314025
+20.000000000 8.709677419 72.821314025
+20.000000000 9.032258065 72.821314025
+20.000000000 9.354838710 72.821314025
+20.000000000 9.677419355 72.821314025
+20.000000000 10.000000000 72.821314025
+22.580645161 0.000000000 50.000000000
+22.580645161 0.322580645 50.000000000
+22.580645161 0.645161290 50.000000000
+22.580645161 0.967741935 50.000000000
+22.580645161 1.290322581 50.000000000
+22.580645161 1.612903226 50.000000000
+22.580645161 1.935483871 50.000000000
+22.580645161 2.258064516 50.076648486
+22.580645161 2.580645161 50.390076379
+22.580645161 2.903225806 50.952326813
+22.580645161 3.225806452 51.774928323
+22.580645161 3.548387097 52.870980129
+22.580645161 3.870967742 54.250136129
+22.580645161 4.193548387 55.910060541
+22.580645161 4.516129032 57.823117640
+22.580645161 4.838709677 59.917996684
+22.580645161 5.161290323 62.043162940
+22.580645161 5.483870968 64.006621117
+22.580645161 5.806451613 65.820682078
+22.580645161 6.129032258 67.494976640
+22.580645161 6.451612903 69.013706618
+22.580645161 6.774193548 70.341645817
+22.580645161 7.096774194 71.431615962
+22.580645161 7.419354839 72.233442079
+22.580645161 7.741935484 72.703595829
+22.580645161 8.064516129 72.821314025
+22.580645161 8.387096774 72.821314025
+22.580645161 8.709677419 72.821314025
+22.580645161 9.032258065 72.821314025
+22.580645161 9.354838710 72.821314025
+22.580645161 9.677419355 72.821314025
+22.580645161 10.000000000 72.821314025
+25.161290323 0.000000000 50.000000000
+25.161290323 0.322580645 50.000000000
+25.161290323 0.645161290 50.000000000
+25.161290323 0.967741935 50.000000000
+25.161290323 1.290322581 50.000000000
+25.161290323 1.612903226 50.000000000
+25.161290323 1.935483871 50.000000000
+25.161290323 2.258064516 50.076648486
+25.161290323 2.580645161 50.390076379
+25.161290323 2.903225806 50.952326813
+25.161290323 3.225806452 51.774928323
+25.161290323 3.548387097 52.870980129
+25.161290323 3.870967742 54.250136129
+25.161290323 4.193548387 55.910060541
+25.161290323 4.516129032 57.823117640
+25.161290323 4.838709677 59.917996684
+25.161290323 5.161290323 62.043162940
+25.161290323 5.483870968 64.006621117
+25.161290323 5.806451613 65.820682078
+25.161290323 6.129032258 67.494976640
+25.161290323 6.451612903 69.013706618
+25.161290323 6.774193548 70.341645817
+25.161290323 7.096774194 71.431615962
+25.161290323 7.419354839 72.233442079
+25.161290323 7.741935484 72.703595829
+25.161290323 8.064516129 72.821314025
+25.161290323 8.387096774 72.821314025
+25.161290323 8.709677419 72.821314025
+25.161290323 9.032258065 72.821314025
+25.161290323 9.354838710 72.821314025
+25.161290323 9.677419355 72.821314025
+25.161290323 10.000000000 72.821314025
+27.741935484 0.000000000 50.000000000
+27.741935484 0.322580645 50.000000000
+27.741935484 0.645161290 50.000000000
+27.741935484 0.967741935 50.000000000
+27.741935484 1.290322581 50.000000000
+27.741935484 1.612903226 50.000000000
+27.741935484 1.935483871 50.000000000
+27.741935484 2.258064516 50.076648486
+27.741935484 2.580645161 50.390076379
+27.741935484 2.903225806 50.952326813
+27.741935484 3.225806452 51.774928323
+27.741935484 3.548387097 52.870980129
+27.741935484 3.870967742 54.250136129
+27.741935484 4.193548387 55.910060541
+27.741935484 4.516129032 57.823117640
+27.741935484 4.838709677 59.917996684
+27.741935484 5.161290323 62.043162940
+27.741935484 5.483870968 64.006621117
+27.741935484 5.806451613 65.820682078
+27.741935484 6.129032258 67.494976640
+27.741935484 6.451612903 69.013706618
+27.741935484 6.774193548 70.341645817
+27.741935484 7.096774194 71.431615962
+27.741935484 7.419354839 72.233442079
+27.741935484 7.741935484 72.703595829
+27.741935484 8.064516129 72.821314025
+27.741935484 8.387096774 72.821314025
+27.741935484 8.709677419 72.821314025
+27.741935484 9.032258065 72.821314025
+27.741935484 9.354838710 72.821314025
+27.741935484 9.677419355 72.821314025
+27.741935484 10.000000000 72.821314025
+30.322580645 0.000000000 49.998803919
+30.322580645 0.322580645 49.998803919
+30.322580645 0.645161290 49.998803919
+30.322580645 0.967741935 49.998803919
+30.322580645 1.290322581 49.998803919
+30.322580645 1.612903226 49.998803919
+30.322580645 1.935483871 49.998803919
+30.322580645 2.258064516 50.075452379
+30.322580645 2.580645161 50.388879647
+30.322580645 2.903225806 50.951126990
+30.322580645 3.225806452 51.773719919
+30.322580645 3.548387097 52.869753955
+30.322580645 3.870967742 54.248879432
+30.322580645 4.193548387 55.908758472
+30.322580645 4.516129032 57.821756837
+30.322580645 4.838709677 59.916571839
+30.322580645 5.161290323 62.041682326
+30.322580645 5.483870968 64.005085024
+30.322580645 5.806451613 65.819089933
+30.322580645 6.129032258 67.493329173
+30.322580645 6.451612903 69.012006089
+30.322580645 6.774193548 70.339896659
+30.322580645 7.096774194 71.429825333
+30.322580645 7.419354839 72.231620048
+30.322580645 7.741935484 72.701755036
+30.322580645 8.064516129 72.819468494
+30.322580645 8.387096774 72.819468494
+30.322580645 8.709677419 72.819468494
+30.322580645 9.032258065 72.819468494
+30.322580645 9.354838710 72.819468494
+30.322580645 9.677419355 72.819468494
+30.322580645 10.000000000 72.819468494
+32.903225806 0.000000000 49.902957979
+32.903225806 0.322580645 49.902957979
+32.903225806 0.645161290 49.902957979
+32.903225806 0.967741935 49.902957979
+32.903225806 1.290322581 49.902957979
+32.903225806 1.612903226 49.902957979
+32.903225806 1.935483871 49.902957979
+32.903225806 2.258064516 49.979607017
+32.903225806 2.580645161 50.292994821
+32.903225806 2.903225806 50.855013655
+32.903225806 3.225806452 51.676947279
+32.903225806 3.548387097 52.771596216
+32.903225806 3.870967742 54.148327846
+32.903225806 4.193548387 55.804640065
+32.903225806 4.516129032 57.713021387
+32.903225806 4.838709677 59.802814253
+32.903225806 5.161290323 61.923569792
+32.903225806 5.483870968 63.882614176
+32.903225806 5.806451613 65.692193202
+32.903225806 6.129032258 67.362058048
+32.903225806 6.451612903 68.876521949
+32.903225806 6.774193548 70.200548955
+32.903225806 7.096774194 71.287181858
+32.903225806 7.419354839 72.086480819
+32.903225806 7.741935484 72.555124481
+32.903225806 8.064516129 72.672461319
+32.903225806 8.387096774 72.672461319
+32.903225806 8.709677419 72.672461319
+32.903225806 9.032258065 72.672461319
+32.903225806 9.354838710 72.672461319
+32.903225806 9.677419355 72.672461319
+32.903225806 10.000000000 72.672461319
+35.483870968 0.000000000 49.652304243
+35.483870968 0.322580645 49.652304243
+35.483870968 0.645161290 49.652304243
+35.483870968 0.967741935 49.652304243
+35.483870968 1.290322581 49.652304243
+35.483870968 1.612903226 49.652304243
+35.483870968 1.935483871 49.652304243
+35.483870968 2.258064516 49.728978589
+35.483870968 2.580645161 50.042360495
+35.483870968 2.903225806 50.603956690
+35.483870968 3.225806452 51.424424786
+35.483870968 3.548387097 52.515806201
+35.483870968 3.870967742 53.886750889
+35.483870968 4.193548387 55.534360928
+35.483870968 4.516129032 57.431479038
+35.483870968 4.838709677 59.509129544
+35.483870968 5.161290323 61.619524277
+35.483870968 5.483870968 63.567960518
+35.483870968 5.806451613 65.366559879
+35.483870968 6.129032258 67.025427611
+35.483870968 6.451612903 68.529270750
+35.483870968 6.774193548 69.843520900
+35.483870968 7.096774194 70.921801863
+35.483870968 7.419354839 71.714759421
+35.483870968 7.741935484 72.179613221
+35.483870968 8.064516129 72.295992918
+35.483870968 8.387096774 72.295992918
+35.483870968 8.709677419 72.295992918
+35.483870968 9.032258065 72.295992918
+35.483870968 9.354838710 72.295992918
+35.483870968 9.677419355 72.295992918
+35.483870968 10.000000000 72.295992918
+38.064516129 0.000000000 49.243098952
+38.064516129 0.322580645 49.243098952
+38.064516129 0.645161290 49.243098952
+38.064516129 0.967741935 49.243098952
+38.064516129 1.290322581 49.243098952
+38.064516129 1.612903226 49.243098952
+38.064516129 1.935483871 49.243098952
+38.064516129 2.258064516 49.319884816
+38.064516129 2.580645161 49.633543934
+38.064516129 2.903225806 50.194964997
+38.064516129 3.225806452 51.013799907
+38.064516129 3.548387097 52.100885441
+38.064516129 3.870967742 53.463764454
+38.064516129 4.193548387 55.098988836
+38.064516129 4.516129032 56.980073530
+38.064516129 4.838709677 59.040771242
+38.064516129 5.161290323 61.137226881
+38.064516129 5.483870968 63.070642355
+38.064516129 5.806451613 64.853053568
+38.064516129 6.129032258 66.495347777
+38.064516129 6.451612903 67.982967596
+38.064516129 6.774193548 69.282183577
+38.064516129 7.096774194 70.347560475
+38.064516129 7.419354839 71.130729588
+38.064516129 7.741935484 71.589715449
+38.064516129 8.064516129 71.704613000
+38.064516129 8.387096774 71.704613000
+38.064516129 8.709677419 71.704613000
+38.064516129 9.032258065 71.704613000
+38.064516129 9.354838710 71.704613000
+38.064516129 9.677419355 71.704613000
+38.064516129 10.000000000 71.704613000
+40.645161290 0.000000000 48.669743020
+40.645161290 0.322580645 48.669743020
+40.645161290 0.645161290 48.669743020
+40.645161290 0.967741935 48.669743020
+40.645161290 1.290322581 48.669743020
+40.645161290 1.612903226 48.669743020
+40.645161290 1.935483871 48.669743020
+40.645161290 2.258064516 48.746819724
+40.645161290 2.580645161 49.061416258
+40.645161290 2.903225806 49.623573900
+40.645161290 3.225806452 50.441561774
+40.645161290 3.548387097 51.524588313
+40.645161290 3.870967742 52.878759776
+40.645161290 4.193548387 54.500031239
+40.645161290 4.516129032 56.363029835
+40.645161290 4.838709677 58.405298469
+40.645161290 5.161290323 60.487754513
+40.645161290 5.483870968 62.404445671
+40.645161290 5.806451613 64.167465175
+40.645161290 6.129032258 65.789133360
+40.645161290 6.451612903 67.256143706
+40.645161290 6.774193548 68.536047010
+40.645161290 7.096774194 69.584753827
+40.645161290 7.419354839 70.355212405
+40.645161290 7.741935484 70.806584970
+40.645161290 8.064516129 70.919555525
+40.645161290 8.387096774 70.919555525
+40.645161290 8.709677419 70.919555525
+40.645161290 9.032258065 70.919555525
+40.645161290 9.354838710 70.919555525
+40.645161290 9.677419355 70.919555525
+40.645161290 10.000000000 70.919555525
+43.225806452 0.000000000 47.925533624
+43.225806452 0.322580645 47.925533624
+43.225806452 0.645161290 47.925533624
+43.225806452 0.967741935 47.925533624
+43.225806452 1.290322581 47.925533624
+43.225806452 1.612903226 47.925533624
+43.225806452 1.935483871 47.925533624
+43.225806452 2.258064516 48.003196119
+43.225806452 2.580645161 48.319856471
+43.225806452 2.903225806 48.884475705
+43.225806452 3.225806452 49.703554418
+43.225806452 3.548387097 50.784261421
+43.225806452 3.870967742 52.130995284
+43.225806452 4.193548387 53.739185104
+43.225806452 4.516129032 55.585152066
+43.225806452 4.838709677 57.611329633
+43.225806452 5.161290323 59.683821844
+43.225806452 5.483870968 61.585369310
+43.225806452 5.806451613 63.328281417
+43.225806452 6.129032258 64.927182028
+43.225806452 6.451612903 66.370699474
+43.225806452 6.774193548 67.628203974
+43.225806452 7.096774194 68.657390741
+43.225806452 7.419354839 69.412890949
+43.225806452 7.741935484 69.855269182
+43.225806452 8.064516129 69.965961562
+43.225806452 8.387096774 69.965961562
+43.225806452 8.709677419 69.965961562
+43.225806452 9.032258065 69.965961562
+43.225806452 9.354838710 69.965961562
+43.225806452 9.677419355 69.965961562
+43.225806452 10.000000000 69.965961562
+45.806451613 0.000000000 47.003934865
+45.806451613 0.322580645 47.003934865
+45.806451613 0.645161290 47.003934865
+45.806451613 0.967741935 47.003934865
+45.806451613 1.290322581 47.003934865
+45.806451613 1.612903226 47.003934865
+45.806451613 1.935483871 47.003934865
+45.806451613 2.258064516 47.082602480
+45.806451613 2.580645161 47.402950274
+45.806451613 2.903225806 47.972607613
+45.806451613 3.225806452 48.795888161
+45.806451613 3.548387097 49.877495327
+45.806451613 3.870967742 51.219883421
+45.806451613 4.193548387 52.818130271
+45.806451613 4.516129032 54.650985755
+45.806451613 4.838709677 56.666980792
+45.806451613 5.161290323 58.737589822
+45.806451613 5.483870968 60.629114424
+45.806451613 5.806451613 62.354014142
+45.806451613 6.129032258 63.930194608
+45.806451613 6.451612903 65.349040002
+45.806451613 6.774193548 66.582379353
+45.806451613 7.096774194 67.590187304
+45.806451613 7.419354839 68.329162947
+45.806451613 7.741935484 68.761558609
+45.806451613 8.064516129 68.869717097
+45.806451613 8.387096774 68.869717097
+45.806451613 8.709677419 68.869717097
+45.806451613 9.032258065 68.869717097
+45.806451613 9.354838710 68.869717097
+45.806451613 9.677419355 68.869717097
+45.806451613 10.000000000 68.869717097
+48.387096774 0.000000000 45.900598613
+48.387096774 0.322580645 45.900598613
+48.387096774 0.645161290 45.900598613
+48.387096774 0.967741935 45.900598613
+48.387096774 1.290322581 45.900598613
+48.387096774 1.612903226 45.900598613
+48.387096774 1.935483871 45.900598613
+48.387096774 2.258064516 45.980803355
+48.387096774 2.580645161 46.306905089
+48.387096774 2.903225806 46.884906961
+48.387096774 3.225806452 47.716447362
+48.387096774 3.548387097 48.803279055
+48.387096774 3.870967742 50.145663256
+48.387096774 4.193548387 51.738567788
+48.387096774 4.516129032 53.564064802
+48.387096774 4.838709677 55.578226605
+48.387096774 5.161290323 57.658283364
+48.387096774 5.483870968 59.548370180
+48.387096774 5.806451613 61.260362735
+48.387096774 6.129032258 62.816285423
+48.387096774 6.451612903 64.211142848
+48.387096774 6.774193548 65.419944811
+48.387096774 7.096774194 66.405514442
+48.387096774 7.419354839 67.127059853
+48.387096774 7.741935484 67.548845082
+48.387096774 8.064516129 67.654301037
+48.387096774 8.387096774 67.654301037
+48.387096774 8.709677419 67.654301037
+48.387096774 9.032258065 67.654301037
+48.387096774 9.354838710 67.654301037
+48.387096774 9.677419355 67.654301037
+48.387096774 10.000000000 67.654301037
+50.967741935 0.000000000 44.616415770
+50.967741935 0.322580645 44.616415770
+50.967741935 0.645161290 44.616415770
+50.967741935 0.967741935 44.616415770
+50.967741935 1.290322581 44.616415770
+50.967741935 1.612903226 44.616415770
+50.967741935 1.935483871 44.616415770
+50.967741935 2.258064516 44.698760304
+50.967741935 2.580645161 45.032946883
+50.967741935 2.903225806 45.622985345
+50.967741935 3.225806452 46.467238467
+50.967741935 3.548387097 47.563910116
+50.967741935 3.870967742 48.910743445
+50.967741935 4.193548387 50.502840212
+50.967741935 4.516129032 52.326633965
+50.967741935 4.838709677 54.347588260
+50.967741935 5.161290323 56.449954685
+50.967741935 5.483870968 58.350161475
+50.967741935 5.806451613 60.057440330
+50.967741935 6.129032258 61.598198804
+50.967741935 6.451612903 62.971785017
+50.967741935 6.774193548 64.157141145
+50.967741935 7.096774194 65.120596669
+50.967741935 7.419354839 65.824409419
+50.967741935 7.741935484 66.235264649
+50.967741935 8.064516129 66.337921286
+50.967741935 8.387096774 66.337921286
+50.967741935 8.709677419 66.337921286
+50.967741935 9.032258065 66.337921286
+50.967741935 9.354838710 66.337921286
+50.967741935 9.677419355 66.337921286
+50.967741935 10.000000000 66.337921286
+53.548387097 0.000000000 43.161863967
+53.548387097 0.322580645 43.161863967
+53.548387097 0.645161290 43.161863967
+53.548387097 0.967741935 43.161863967
+53.548387097 1.290322581 43.161863967
+53.548387097 1.612903226 43.161863967
+53.548387097 1.935483871 43.161863967
+53.548387097 2.258064516 43.246935669
+53.548387097 2.580645161 43.591449152
+53.548387097 2.903225806 44.196962107
+53.548387097 3.225806452 45.057826729
+53.548387097 3.548387097 46.167949378
+53.548387097 3.870967742 47.522086534
+53.548387097 4.193548387 49.115617384
+53.548387097 4.516129032 50.940434962
+53.548387097 4.838709677 52.973755088
+53.548387097 5.161290323 55.109848682
+53.548387097 5.483870968 57.033537819
+53.548387097 5.806451613 58.747231415
+53.548387097 6.129032258 60.280747236
+53.548387097 6.451612903 61.638028848
+53.548387097 6.774193548 62.802609961
+53.548387097 7.096774194 63.745066439
+53.548387097 7.419354839 64.431393253
+53.548387097 7.741935484 64.831240735
+53.548387097 8.064516129 64.931066230
+53.548387097 8.387096774 64.931066230
+53.548387097 8.709677419 64.931066230
+53.548387097 9.032258065 64.931066230
+53.548387097 9.354838710 64.931066230
+53.548387097 9.677419355 64.931066230
+53.548387097 10.000000000 64.931066230
+56.129032258 0.000000000 41.562757424
+56.129032258 0.322580645 41.562757424
+56.129032258 0.645161290 41.562757424
+56.129032258 0.967741935 41.562757424
+56.129032258 1.290322581 41.562757424
+56.129032258 1.612903226 41.562757424
+56.129032258 1.935483871 41.562757424
+56.129032258 2.258064516 41.650983104
+56.129032258 2.580645161 42.007394877
+56.129032258 2.903225806 42.630567878
+56.129032258 3.225806452 43.510014838
+56.129032258 3.548387097 44.634466681
+56.129032258 3.870967742 45.995029495
+56.129032258 4.193548387 47.587232438
+56.129032258 4.516129032 49.409320054
+56.129032258 4.838709677 51.452965804
+56.129032258 5.161290323 53.627995525
+56.129032258 5.483870968 55.587931245
+56.129032258 5.806451613 57.321397482
+56.129032258 6.129032258 58.858477926
+56.129032258 6.451612903 60.206932126
+56.129032258 6.774193548 61.355194390
+56.129032258 7.096774194 62.278842892
+56.129032258 7.419354839 62.948475434
+56.129032258 7.741935484 63.337473295
+56.129032258 8.064516129 63.434463522
+56.129032258 8.387096774 63.434463522
+56.129032258 8.709677419 63.434463522
+56.129032258 9.032258065 63.434463522
+56.129032258 9.354838710 63.434463522
+56.129032258 9.677419355 63.434463522
+56.129032258 10.000000000 63.434463522
+58.709677419 0.000000000 39.867082291
+58.709677419 0.322580645 39.867082291
+58.709677419 0.645161290 39.867082291
+58.709677419 0.967741935 39.867082291
+58.709677419 1.290322581 39.867082291
+58.709677419 1.612903226 39.867082291
+58.709677419 1.935483871 39.867082291
+58.709677419 2.258064516 39.958513244
+58.709677419 2.580645161 40.326884614
+58.709677419 2.903225806 40.967289350
+58.709677419 3.225806452 41.863642692
+58.709677419 3.548387097 42.998628756
+58.709677419 3.870967742 44.358835965
+58.709677419 4.193548387 45.939269950
+58.709677419 4.516129032 47.744614100
+58.709677419 4.838709677 49.783268810
+58.709677419 5.161290323 51.988970730
+58.709677419 5.483870968 53.992678480
+58.709677419 5.806451613 55.759559804
+58.709677419 6.129032258 57.313492323
+58.709677419 6.451612903 58.663327822
+58.709677419 6.774193548 59.801844372
+58.709677419 7.096774194 60.710189164
+58.709677419 7.419354839 61.364580282
+58.709677419 7.741935484 61.743138699
+58.709677419 8.064516129 61.837345788
+58.709677419 8.387096774 61.837345788
+58.709677419 8.709677419 61.837345788
+58.709677419 9.032258065 61.837345788
+58.709677419 9.354838710 61.837345788
+58.709677419 9.677419355 61.837345788
+58.709677419 10.000000000 61.837345788
+61.290322581 0.000000000 38.162654212
+61.290322581 0.322580645 38.162654212
+61.290322581 0.645161290 38.162654212
+61.290322581 0.967741935 38.162654212
+61.290322581 1.290322581 38.162654212
+61.290322581 1.612903226 38.162654212
+61.290322581 1.935483871 38.162654212
+61.290322581 2.258064516 38.256861301
+61.290322581 2.580645161 38.635419718
+61.290322581 2.903225806 39.289810836
+61.290322581 3.225806452 40.198155628
+61.290322581 3.548387097 41.336672178
+61.290322581 3.870967742 42.686507677
+61.290322581 4.193548387 44.240440196
+61.290322581 4.516129032 46.007321520
+61.290322581 4.838709677 48.011029270
+61.290322581 5.161290323 50.216731190
+61.290322581 5.483870968 52.255385900
+61.290322581 5.806451613 54.060730050
+61.290322581 6.129032258 55.641164035
+61.290322581 6.451612903 57.001371244
+61.290322581 6.774193548 58.136357308
+61.290322581 7.096774194 59.032710650
+61.290322581 7.419354839 59.673115386
+61.290322581 7.741935484 60.041486756
+61.290322581 8.064516129 60.132917709
+61.290322581 8.387096774 60.132917709
+61.290322581 8.709677419 60.132917709
+61.290322581 9.032258065 60.132917709
+61.290322581 9.354838710 60.132917709
+61.290322581 9.677419355 60.132917709
+61.290322581 10.000000000 60.132917709
+63.870967742 0.000000000 36.565536478
+63.870967742 0.322580645 36.565536478
+63.870967742 0.645161290 36.565536478
+63.870967742 0.967741935 36.565536478
+63.870967742 1.290322581 36.565536478
+63.870967742 1.612903226 36.565536478
+63.870967742 1.935483871 36.565536478
+63.870967742 2.258064516 36.662526705
+63.870967742 2.580645161 37.051524566
+63.870967742 2.903225806 37.721157108
+63.870967742 3.225806452 38.644805610
+63.870967742 3.548387097 39.793067874
+63.870967742 3.870967742 41.141522074
+63.870967742 4.193548387 42.678602518
+63.870967742 4.516129032 44.412068755
+63.870967742 4.838709677 46.372004475
+63.870967742 5.161290323 48.547034196
+63.870967742 5.483870968 50.590679946
+63.870967742 5.806451613 52.412767562
+63.870967742 6.129032258 54.004970505
+63.870967742 6.451612903 55.365533319
+63.870967742 6.774193548 56.489985162
+63.870967742 7.096774194 57.369432122
+63.870967742 7.419354839 57.992605123
+63.870967742 7.741935484 58.349016896
+63.870967742 8.064516129 58.437242576
+63.870967742 8.387096774 58.437242576
+63.870967742 8.709677419 58.437242576
+63.870967742 9.032258065 58.437242576
+63.870967742 9.354838710 58.437242576
+63.870967742 9.677419355 58.437242576
+63.870967742 10.000000000 58.437242576
+66.451612903 0.000000000 35.068933770
+66.451612903 0.322580645 35.068933770
+66.451612903 0.645161290 35.068933770
+66.451612903 0.967741935 35.068933770
+66.451612903 1.290322581 35.068933770
+66.451612903 1.612903226 35.068933770
+66.451612903 1.935483871 35.068933770
+66.451612903 2.258064516 35.168759265
+66.451612903 2.580645161 35.568606747
+66.451612903 2.903225806 36.254933561
+66.451612903 3.225806452 37.197390039
+66.451612903 3.548387097 38.361971152
+66.451612903 3.870967742 39.719252764
+66.451612903 4.193548387 41.252768585
+66.451612903 4.516129032 42.966462181
+66.451612903 4.838709677 44.890151318
+66.451612903 5.161290323 47.026244912
+66.451612903 5.483870968 49.059565038
+66.451612903 5.806451613 50.884382616
+66.451612903 6.129032258 52.477913466
+66.451612903 6.451612903 53.832050622
+66.451612903 6.774193548 54.942173271
+66.451612903 7.096774194 55.803037893
+66.451612903 7.419354839 56.408550848
+66.451612903 7.741935484 56.753064331
+66.451612903 8.064516129 56.838136033
+66.451612903 8.387096774 56.838136033
+66.451612903 8.709677419 56.838136033
+66.451612903 9.032258065 56.838136033
+66.451612903 9.354838710 56.838136033
+66.451612903 9.677419355 56.838136033
+66.451612903 10.000000000 56.838136033
+69.032258065 0.000000000 33.662078714
+69.032258065 0.322580645 33.662078714
+69.032258065 0.645161290 33.662078714
+69.032258065 0.967741935 33.662078714
+69.032258065 1.290322581 33.662078714
+69.032258065 1.612903226 33.662078714
+69.032258065 1.935483871 33.662078714
+69.032258065 2.258064516 33.764735351
+69.032258065 2.580645161 34.175590581
+69.032258065 2.903225806 34.879403331
+69.032258065 3.225806452 35.842858855
+69.032258065 3.548387097 37.028214983
+69.032258065 3.870967742 38.401801196
+69.032258065 4.193548387 39.942559670
+69.032258065 4.516129032 41.649838525
+69.032258065 4.838709677 43.550045315
+69.032258065 5.161290323 45.652411740
+69.032258065 5.483870968 47.673366035
+69.032258065 5.806451613 49.497159788
+69.032258065 6.129032258 51.089256555
+69.032258065 6.451612903 52.436089884
+69.032258065 6.774193548 53.532761533
+69.032258065 7.096774194 54.377014655
+69.032258065 7.419354839 54.967053117
+69.032258065 7.741935484 55.301239696
+69.032258065 8.064516129 55.383584230
+69.032258065 8.387096774 55.383584230
+69.032258065 8.709677419 55.383584230
+69.032258065 9.032258065 55.383584230
+69.032258065 9.354838710 55.383584230
+69.032258065 9.677419355 55.383584230
+69.032258065 10.000000000 55.383584230
+71.612903226 0.000000000 32.345698963
+71.612903226 0.322580645 32.345698963
+71.612903226 0.645161290 32.345698963
+71.612903226 0.967741935 32.345698963
+71.612903226 1.290322581 32.345698963
+71.612903226 1.612903226 32.345698963
+71.612903226 1.935483871 32.345698963
+71.612903226 2.258064516 32.451154918
+71.612903226 2.580645161 32.872940147
+71.612903226 2.903225806 33.594485558
+71.612903226 3.225806452 34.580055189
+71.612903226 3.548387097 35.788857152
+71.612903226 3.870967742 37.183714577
+71.612903226 4.193548387 38.739637265
+71.612903226 4.516129032 40.451629820
+71.612903226 4.838709677 42.341716636
+71.612903226 5.161290323 44.421773395
+71.612903226 5.483870968 46.435935198
+71.612903226 5.806451613 48.261432212
+71.612903226 6.129032258 49.854336744
+71.612903226 6.451612903 51.196720945
+71.612903226 6.774193548 52.283552638
+71.612903226 7.096774194 53.115093039
+71.612903226 7.419354839 53.693094911
+71.612903226 7.741935484 54.019196645
+71.612903226 8.064516129 54.099401387
+71.612903226 8.387096774 54.099401387
+71.612903226 8.709677419 54.099401387
+71.612903226 9.032258065 54.099401387
+71.612903226 9.354838710 54.099401387
+71.612903226 9.677419355 54.099401387
+71.612903226 10.000000000 54.099401387
+74.193548387 0.000000000 31.130282903
+74.193548387 0.322580645 31.130282903
+74.193548387 0.645161290 31.130282903
+74.193548387 0.967741935 31.130282903
+74.193548387 1.290322581 31.130282903
+74.193548387 1.612903226 31.130282903
+74.193548387 1.935483871 31.130282903
+74.193548387 2.258064516 31.238441391
+74.193548387 2.580645161 31.670837053
+74.193548387 2.903225806 32.409812696
+74.193548387 3.225806452 33.417620647
+74.193548387 3.548387097 34.650959998
+74.193548387 3.870967742 36.069805392
+74.193548387 4.193548387 37.645985858
+74.193548387 4.516129032 39.370885576
+74.193548387 4.838709677 41.262410178
+74.193548387 5.161290323 43.333019208
+74.193548387 5.483870968 45.349014245
+74.193548387 5.806451613 47.181869729
+74.193548387 6.129032258 48.780116579
+74.193548387 6.451612903 50.122504673
+74.193548387 6.774193548 51.204111839
+74.193548387 7.096774194 52.027392387
+74.193548387 7.419354839 52.597049726
+74.193548387 7.741935484 52.917397520
+74.193548387 8.064516129 52.996065135
+74.193548387 8.387096774 52.996065135
+74.193548387 8.709677419 52.996065135
+74.193548387 9.032258065 52.996065135
+74.193548387 9.354838710 52.996065135
+74.193548387 9.677419355 52.996065135
+74.193548387 10.000000000 52.996065135
+76.774193548 0.000000000 30.034038438
+76.774193548 0.322580645 30.034038438
+76.774193548 0.645161290 30.034038438
+76.774193548 0.967741935 30.034038438
+76.774193548 1.290322581 30.034038438
+76.774193548 1.612903226 30.034038438
+76.774193548 1.935483871 30.034038438
+76.774193548 2.258064516 30.144730818
+76.774193548 2.580645161 30.587109051
+76.774193548 2.903225806 31.342609259
+76.774193548 3.225806452 32.371796026
+76.774193548 3.548387097 33.629300526
+76.774193548 3.870967742 35.072817972
+76.774193548 4.193548387 36.671718583
+76.774193548 4.516129032 38.414630690
+76.774193548 4.838709677 40.316178156
+76.774193548 5.161290323 42.388670367
+76.774193548 5.483870968 44.414847934
+76.774193548 5.806451613 46.260814896
+76.774193548 6.129032258 47.869004716
+76.774193548 6.451612903 49.215738579
+76.774193548 6.774193548 50.296445582
+76.774193548 7.096774194 51.115524295
+76.774193548 7.419354839 51.680143529
+76.774193548 7.741935484 51.996803881
+76.774193548 8.064516129 52.074466376
+76.774193548 8.387096774 52.074466376
+76.774193548 8.709677419 52.074466376
+76.774193548 9.032258065 52.074466376
+76.774193548 9.354838710 52.074466376
+76.774193548 9.677419355 52.074466376
+76.774193548 10.000000000 52.074466376
+79.354838710 0.000000000 29.080444475
+79.354838710 0.322580645 29.080444475
+79.354838710 0.645161290 29.080444475
+79.354838710 0.967741935 29.080444475
+79.354838710 1.290322581 29.080444475
+79.354838710 1.612903226 29.080444475
+79.354838710 1.935483871 29.080444475
+79.354838710 2.258064516 29.193415030
+79.354838710 2.580645161 29.644787595
+79.354838710 2.903225806 30.415246173
+79.354838710 3.225806452 31.463952990
+79.354838710 3.548387097 32.743856294
+79.354838710 3.870967742 34.210866640
+79.354838710 4.193548387 35.832534825
+79.354838710 4.516129032 37.595554329
+79.354838710 4.838709677 39.512245487
+79.354838710 5.161290323 41.594701531
+79.354838710 5.483870968 43.636970165
+79.354838710 5.806451613 45.499968761
+79.354838710 6.129032258 47.121240224
+79.354838710 6.451612903 48.475411687
+79.354838710 6.774193548 49.558438226
+79.354838710 7.096774194 50.376426100
+79.354838710 7.419354839 50.938583742
+79.354838710 7.741935484 51.253180276
+79.354838710 8.064516129 51.330256980
+79.354838710 8.387096774 51.330256980
+79.354838710 8.709677419 51.330256980
+79.354838710 9.032258065 51.330256980
+79.354838710 9.354838710 51.330256980
+79.354838710 9.677419355 51.330256980
+79.354838710 10.000000000 51.330256980
+81.935483871 0.000000000 28.295387000
+81.935483871 0.322580645 28.295387000
+81.935483871 0.645161290 28.295387000
+81.935483871 0.967741935 28.295387000
+81.935483871 1.290322581 28.295387000
+81.935483871 1.612903226 28.295387000
+81.935483871 1.935483871 28.295387000
+81.935483871 2.258064516 28.410284551
+81.935483871 2.580645161 28.869270412
+81.935483871 2.903225806 29.652439525
+81.935483871 3.225806452 30.717816423
+81.935483871 3.548387097 32.017032404
+81.935483871 3.870967742 33.504652223
+81.935483871 4.193548387 35.146946432
+81.935483871 4.516129032 36.929357645
+81.935483871 4.838709677 38.862773119
+81.935483871 5.161290323 40.959228758
+81.935483871 5.483870968 43.019926470
+81.935483871 5.806451613 44.901011164
+81.935483871 6.129032258 46.536235546
+81.935483871 6.451612903 47.899114559
+81.935483871 6.774193548 48.986200093
+81.935483871 7.096774194 49.805035003
+81.935483871 7.419354839 50.366456066
+81.935483871 7.741935484 50.680115184
+81.935483871 8.064516129 50.756901048
+81.935483871 8.387096774 50.756901048
+81.935483871 8.709677419 50.756901048
+81.935483871 9.032258065 50.756901048
+81.935483871 9.354838710 50.756901048
+81.935483871 9.677419355 50.756901048
+81.935483871 10.000000000 50.756901048
+84.516129032 0.000000000 27.704007082
+84.516129032 0.322580645 27.704007082
+84.516129032 0.645161290 27.704007082
+84.516129032 0.967741935 27.704007082
+84.516129032 1.290322581 27.704007082
+84.516129032 1.612903226 27.704007082
+84.516129032 1.935483871 27.704007082
+84.516129032 2.258064516 27.820386779
+84.516129032 2.580645161 28.285240579
+84.516129032 2.903225806 29.078198137
+84.516129032 3.225806452 30.156479100
+84.516129032 3.548387097 31.470729250
+84.516129032 3.870967742 32.974572389
+84.516129032 4.193548387 34.633440121
+84.516129032 4.516129032 36.432039482
+84.516129032 4.838709677 38.380475723
+84.516129032 5.161290323 40.490870456
+84.516129032 5.483870968 42.568520962
+84.516129032 5.806451613 44.465639072
+84.516129032 6.129032258 46.113249111
+84.516129032 6.451612903 47.484193799
+84.516129032 6.774193548 48.575575214
+84.516129032 7.096774194 49.396043310
+84.516129032 7.419354839 49.957639505
+84.516129032 7.741935484 50.271021411
+84.516129032 8.064516129 50.347695757
+84.516129032 8.387096774 50.347695757
+84.516129032 8.709677419 50.347695757
+84.516129032 9.032258065 50.347695757
+84.516129032 9.354838710 50.347695757
+84.516129032 9.677419355 50.347695757
+84.516129032 10.000000000 50.347695757
+87.096774194 0.000000000 27.327538681
+87.096774194 0.322580645 27.327538681
+87.096774194 0.645161290 27.327538681
+87.096774194 0.967741935 27.327538681
+87.096774194 1.290322581 27.327538681
+87.096774194 1.612903226 27.327538681
+87.096774194 1.935483871 27.327538681
+87.096774194 2.258064516 27.444875519
+87.096774194 2.580645161 27.913519181
+87.096774194 2.903225806 28.712818142
+87.096774194 3.225806452 29.799451045
+87.096774194 3.548387097 31.123478051
+87.096774194 3.870967742 32.637941952
+87.096774194 4.193548387 34.307806798
+87.096774194 4.516129032 36.117385824
+87.096774194 4.838709677 38.076430208
+87.096774194 5.161290323 40.197185747
+87.096774194 5.483870968 42.286978613
+87.096774194 5.806451613 44.195359935
+87.096774194 6.129032258 45.851672154
+87.096774194 6.451612903 47.228403784
+87.096774194 6.774193548 48.323052721
+87.096774194 7.096774194 49.144986345
+87.096774194 7.419354839 49.707005179
+87.096774194 7.741935484 50.020392983
+87.096774194 8.064516129 50.097042021
+87.096774194 8.387096774 50.097042021
+87.096774194 8.709677419 50.097042021
+87.096774194 9.032258065 50.097042021
+87.096774194 9.354838710 50.097042021
+87.096774194 9.677419355 50.097042021
+87.096774194 10.000000000 50.097042021
+89.677419355 0.000000000 27.180531506
+89.677419355 0.322580645 27.180531506
+89.677419355 0.645161290 27.180531506
+89.677419355 0.967741935 27.180531506
+89.677419355 1.290322581 27.180531506
+89.677419355 1.612903226 27.180531506
+89.677419355 1.935483871 27.180531506
+89.677419355 2.258064516 27.298244964
+89.677419355 2.580645161 27.768379952
+89.677419355 2.903225806 28.570174667
+89.677419355 3.225806452 29.660103341
+89.677419355 3.548387097 30.987993911
+89.677419355 3.870967742 32.506670827
+89.677419355 4.193548387 34.180910067
+89.677419355 4.516129032 35.994914976
+89.677419355 4.838709677 37.958317674
+89.677419355 5.161290323 40.083428161
+89.677419355 5.483870968 42.178243163
+89.677419355 5.806451613 44.091241528
+89.677419355 6.129032258 45.751120568
+89.677419355 6.451612903 47.130246045
+89.677419355 6.774193548 48.226280081
+89.677419355 7.096774194 49.048873010
+89.677419355 7.419354839 49.611120353
+89.677419355 7.741935484 49.924547621
+89.677419355 8.064516129 50.001196081
+89.677419355 8.387096774 50.001196081
+89.677419355 8.709677419 50.001196081
+89.677419355 9.032258065 50.001196081
+89.677419355 9.354838710 50.001196081
+89.677419355 9.677419355 50.001196081
+89.677419355 10.000000000 50.001196081
+92.258064516 0.000000000 27.178685975
+92.258064516 0.322580645 27.178685975
+92.258064516 0.645161290 27.178685975
+92.258064516 0.967741935 27.178685975
+92.258064516 1.290322581 27.178685975
+92.258064516 1.612903226 27.178685975
+92.258064516 1.935483871 27.178685975
+92.258064516 2.258064516 27.296404171
+92.258064516 2.580645161 27.766557921
+92.258064516 2.903225806 28.568384038
+92.258064516 3.225806452 29.658354183
+92.258064516 3.548387097 30.986293382
+92.258064516 3.870967742 32.505023360
+92.258064516 4.193548387 34.179317922
+92.258064516 4.516129032 35.993378883
+92.258064516 4.838709677 37.956837060
+92.258064516 5.161290323 40.082003316
+92.258064516 5.483870968 42.176882360
+92.258064516 5.806451613 44.089939459
+92.258064516 6.129032258 45.749863871
+92.258064516 6.451612903 47.129019871
+92.258064516 6.774193548 48.225071677
+92.258064516 7.096774194 49.047673187
+92.258064516 7.419354839 49.609923621
+92.258064516 7.741935484 49.923351514
+92.258064516 8.064516129 50.000000000
+92.258064516 8.387096774 50.000000000
+92.258064516 8.709677419 50.000000000
+92.258064516 9.032258065 50.000000000
+92.258064516 9.354838710 50.000000000
+92.258064516 9.677419355 50.000000000
+92.258064516 10.000000000 50.000000000
+94.838709677 0.000000000 27.178685975
+94.838709677 0.322580645 27.178685975
+94.838709677 0.645161290 27.178685975
+94.838709677 0.967741935 27.178685975
+94.838709677 1.290322581 27.178685975
+94.838709677 1.612903226 27.178685975
+94.838709677 1.935483871 27.178685975
+94.838709677 2.258064516 27.296404171
+94.838709677 2.580645161 27.766557921
+94.838709677 2.903225806 28.568384038
+94.838709677 3.225806452 29.658354183
+94.838709677 3.548387097 30.986293382
+94.838709677 3.870967742 32.505023360
+94.838709677 4.193548387 34.179317922
+94.838709677 4.516129032 35.993378883
+94.838709677 4.838709677 37.956837060
+94.838709677 5.161290323 40.082003316
+94.838709677 5.483870968 42.176882360
+94.838709677 5.806451613 44.089939459
+94.838709677 6.129032258 45.749863871
+94.838709677 6.451612903 47.129019871
+94.838709677 6.774193548 48.225071677
+94.838709677 7.096774194 49.047673187
+94.838709677 7.419354839 49.609923621
+94.838709677 7.741935484 49.923351514
+94.838709677 8.064516129 50.000000000
+94.838709677 8.387096774 50.000000000
+94.838709677 8.709677419 50.000000000
+94.838709677 9.032258065 50.000000000
+94.838709677 9.354838710 50.000000000
+94.838709677 9.677419355 50.000000000
+94.838709677 10.000000000 50.000000000
+97.419354839 0.000000000 27.178685975
+97.419354839 0.322580645 27.178685975
+97.419354839 0.645161290 27.178685975
+97.419354839 0.967741935 27.178685975
+97.419354839 1.290322581 27.178685975
+97.419354839 1.612903226 27.178685975
+97.419354839 1.935483871 27.178685975
+97.419354839 2.258064516 27.296404171
+97.419354839 2.580645161 27.766557921
+97.419354839 2.903225806 28.568384038
+97.419354839 3.225806452 29.658354183
+97.419354839 3.548387097 30.986293382
+97.419354839 3.870967742 32.505023360
+97.419354839 4.193548387 34.179317922
+97.419354839 4.516129032 35.993378883
+97.419354839 4.838709677 37.956837060
+97.419354839 5.161290323 40.082003316
+97.419354839 5.483870968 42.176882360
+97.419354839 5.806451613 44.089939459
+97.419354839 6.129032258 45.749863871
+97.419354839 6.451612903 47.129019871
+97.419354839 6.774193548 48.225071677
+97.419354839 7.096774194 49.047673187
+97.419354839 7.419354839 49.609923621
+97.419354839 7.741935484 49.923351514
+97.419354839 8.064516129 50.000000000
+97.419354839 8.387096774 50.000000000
+97.419354839 8.709677419 50.000000000
+97.419354839 9.032258065 50.000000000
+97.419354839 9.354838710 50.000000000
+97.419354839 9.677419355 50.000000000
+97.419354839 10.000000000 50.000000000
+100.000000000 0.000000000 27.178685975
+100.000000000 0.322580645 27.178685975
+100.000000000 0.645161290 27.178685975
+100.000000000 0.967741935 27.178685975
+100.000000000 1.290322581 27.178685975
+100.000000000 1.612903226 27.178685975
+100.000000000 1.935483871 27.178685975
+100.000000000 2.258064516 27.296404171
+100.000000000 2.580645161 27.766557921
+100.000000000 2.903225806 28.568384038
+100.000000000 3.225806452 29.658354183
+100.000000000 3.548387097 30.986293382
+100.000000000 3.870967742 32.505023360
+100.000000000 4.193548387 34.179317922
+100.000000000 4.516129032 35.993378883
+100.000000000 4.838709677 37.956837060
+100.000000000 5.161290323 40.082003316
+100.000000000 5.483870968 42.176882360
+100.000000000 5.806451613 44.089939459
+100.000000000 6.129032258 45.749863871
+100.000000000 6.451612903 47.129019871
+100.000000000 6.774193548 48.225071677
+100.000000000 7.096774194 49.047673187
+100.000000000 7.419354839 49.609923621
+100.000000000 7.741935484 49.923351514
+100.000000000 8.064516129 50.000000000
+100.000000000 8.387096774 50.000000000
+100.000000000 8.709677419 50.000000000
+100.000000000 9.032258065 50.000000000
+100.000000000 9.354838710 50.000000000
+100.000000000 9.677419355 50.000000000
+100.000000000 10.000000000 50.000000000
diff --git a/examples/mamdani/octave/investment_portfolio.fll b/examples/mamdani/octave/investment_portfolio.fll
index 4bb14e1..628fdef 100644
--- a/examples/mamdani/octave/investment_portfolio.fll
+++ b/examples/mamdani/octave/investment_portfolio.fll
@@ -1,22 +1,24 @@
-Engine: Investment-Portfolio
+Engine: investment_portfolio
InputVariable: Age
enabled: true
range: 20.000 100.000
+ lock-range: false
term: Young ZShape 30.000 90.000
term: Old SShape 30.000 90.000
InputVariable: RiskTolerance
enabled: true
range: 0.000 10.000
+ lock-range: false
term: Low ZShape 2.000 8.000
term: High SShape 2.000 8.000
OutputVariable: PercentageInStocks
enabled: true
range: 0.000 100.000
- accumulation: EinsteinSum
+ lock-range: false
+ aggregation: EinsteinSum
defuzzifier: Centroid 200
default: nan
lock-previous: false
- lock-range: false
term: AboutFifteen Gaussian 15.000 10.000
term: AboutFifty Gaussian 50.000 10.000
term: AboutEightyFive Gaussian 85.000 10.000
@@ -24,7 +26,8 @@ RuleBlock:
enabled: true
conjunction: EinsteinProduct
disjunction: EinsteinSum
- activation: EinsteinProduct
+ implication: EinsteinProduct
+ activation: General
rule: if Age is Young or RiskTolerance is High then PercentageInStocks is AboutEightyFive
rule: if Age is Old or RiskTolerance is Low then PercentageInStocks is AboutFifteen
rule: if Age is not extremely Old and RiskTolerance is not extremely Low then PercentageInStocks is AboutFifty with 0.500
diff --git a/examples/mamdani/octave/investment_portfolio.java b/examples/mamdani/octave/investment_portfolio.java
index 09084f1..9dff687 100644
--- a/examples/mamdani/octave/investment_portfolio.java
+++ b/examples/mamdani/octave/investment_portfolio.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,45 +13,55 @@ import com.fuzzylite.variable.*;
public class investment_portfolio{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("Investment-Portfolio");
-
-InputVariable inputVariable1 = new InputVariable();
-inputVariable1.setEnabled(true);
-inputVariable1.setName("Age");
-inputVariable1.setRange(20.000, 100.000);
-inputVariable1.addTerm(new ZShape("Young", 30.000, 90.000));
-inputVariable1.addTerm(new SShape("Old", 30.000, 90.000));
-engine.addInputVariable(inputVariable1);
-
-InputVariable inputVariable2 = new InputVariable();
-inputVariable2.setEnabled(true);
-inputVariable2.setName("RiskTolerance");
-inputVariable2.setRange(0.000, 10.000);
-inputVariable2.addTerm(new ZShape("Low", 2.000, 8.000));
-inputVariable2.addTerm(new SShape("High", 2.000, 8.000));
-engine.addInputVariable(inputVariable2);
-
-OutputVariable outputVariable = new OutputVariable();
-outputVariable.setEnabled(true);
-outputVariable.setName("PercentageInStocks");
-outputVariable.setRange(0.000, 100.000);
-outputVariable.fuzzyOutput().setAccumulation(new EinsteinSum());
-outputVariable.setDefuzzifier(new Centroid(200));
-outputVariable.setDefaultValue(Double.NaN);
-outputVariable.setLockPreviousOutputValue(false);
-outputVariable.setLockOutputValueInRange(false);
-outputVariable.addTerm(new Gaussian("AboutFifteen", 15.000, 10.000));
-outputVariable.addTerm(new Gaussian("AboutFifty", 50.000, 10.000));
-outputVariable.addTerm(new Gaussian("AboutEightyFive", 85.000, 10.000));
-engine.addOutputVariable(outputVariable);
+engine.setName("investment_portfolio");
+engine.setDescription("");
+
+InputVariable Age = new InputVariable();
+Age.setName("Age");
+Age.setDescription("");
+Age.setEnabled(true);
+Age.setRange(20.000, 100.000);
+Age.setLockValueInRange(false);
+Age.addTerm(new ZShape("Young", 30.000, 90.000));
+Age.addTerm(new SShape("Old", 30.000, 90.000));
+engine.addInputVariable(Age);
+
+InputVariable RiskTolerance = new InputVariable();
+RiskTolerance.setName("RiskTolerance");
+RiskTolerance.setDescription("");
+RiskTolerance.setEnabled(true);
+RiskTolerance.setRange(0.000, 10.000);
+RiskTolerance.setLockValueInRange(false);
+RiskTolerance.addTerm(new ZShape("Low", 2.000, 8.000));
+RiskTolerance.addTerm(new SShape("High", 2.000, 8.000));
+engine.addInputVariable(RiskTolerance);
+
+OutputVariable PercentageInStocks = new OutputVariable();
+PercentageInStocks.setName("PercentageInStocks");
+PercentageInStocks.setDescription("");
+PercentageInStocks.setEnabled(true);
+PercentageInStocks.setRange(0.000, 100.000);
+PercentageInStocks.setLockValueInRange(false);
+PercentageInStocks.setAggregation(new EinsteinSum());
+PercentageInStocks.setDefuzzifier(new Centroid(200));
+PercentageInStocks.setDefaultValue(Double.NaN);
+PercentageInStocks.setLockPreviousValue(false);
+PercentageInStocks.addTerm(new Gaussian("AboutFifteen", 15.000, 10.000));
+PercentageInStocks.addTerm(new Gaussian("AboutFifty", 50.000, 10.000));
+PercentageInStocks.addTerm(new Gaussian("AboutEightyFive", 85.000, 10.000));
+engine.addOutputVariable(PercentageInStocks);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(new EinsteinProduct());
ruleBlock.setDisjunction(new EinsteinSum());
-ruleBlock.setActivation(new EinsteinProduct());
+ruleBlock.setImplication(new EinsteinProduct());
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if Age is Young or RiskTolerance is High then PercentageInStocks is AboutEightyFive", engine));
ruleBlock.addRule(Rule.parse("if Age is Old or RiskTolerance is Low then PercentageInStocks is AboutFifteen", engine));
ruleBlock.addRule(Rule.parse("if Age is not extremely Old and RiskTolerance is not extremely Low then PercentageInStocks is AboutFifty with 0.500", engine));
diff --git a/examples/mamdani/octave/investment_portfolio.pdf b/examples/mamdani/octave/investment_portfolio.pdf
new file mode 100644
index 0000000..c9c897e
--- /dev/null
+++ b/examples/mamdani/octave/investment_portfolio.pdf
Binary files differ
diff --git a/examples/mamdani/octave/mamdani_tip_calculator.R b/examples/mamdani/octave/mamdani_tip_calculator.R
new file mode 100644
index 0000000..81eabe2
--- /dev/null
+++ b/examples/mamdani/octave/mamdani_tip_calculator.R
@@ -0,0 +1,90 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "mamdani_tip_calculator"
+engine.fll = "Engine: mamdani_tip_calculator
+InputVariable: FoodQuality
+ enabled: true
+ range: 1.000 10.000
+ lock-range: false
+ term: Bad Trapezoid 0.000 1.000 3.000 7.000
+ term: Good Trapezoid 3.000 7.000 10.000 11.000
+InputVariable: Service
+ enabled: true
+ range: 1.000 10.000
+ lock-range: false
+ term: Bad Trapezoid 0.000 1.000 3.000 7.000
+ term: Good Trapezoid 3.000 7.000 10.000 11.000
+OutputVariable: Tip
+ enabled: true
+ range: 0.000 30.000
+ lock-range: false
+ aggregation: AlgebraicSum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: AboutTenPercent Gaussian 10.000 2.000
+ term: AboutFifteenPercent Gaussian 15.000 2.000
+ term: AboutTwentyPercent Gaussian 20.000 2.000
+OutputVariable: CheckPlusTip
+ enabled: true
+ range: 1.000 1.300
+ lock-range: false
+ aggregation: AlgebraicSum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: PlusAboutTenPercent Gaussian 1.100 0.020
+ term: PlusAboutFifteenPercent Gaussian 1.150 0.020
+ term: PlusAboutTwentyPercent Gaussian 1.200 0.020
+RuleBlock:
+ enabled: true
+ conjunction: AlgebraicProduct
+ disjunction: Maximum
+ implication: Minimum
+ activation: General
+ rule: if FoodQuality is Bad and Service is Bad then Tip is AboutTenPercent and CheckPlusTip is PlusAboutTenPercent
+ rule: if FoodQuality is Bad and Service is Good then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent
+ rule: if FoodQuality is Good and Service is Bad then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent
+ rule: if FoodQuality is Good and Service is Good then Tip is AboutTwentyPercent and CheckPlusTip is PlusAboutTwentyPercent"
+
+engine.fldFile = "mamdani_tip_calculator.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1i2_o1 = ggplot(engine.df, aes(FoodQuality, Service)) +
+ geom_tile(aes(fill=Tip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=FoodQuality, y=Service, z=Tip), color="black") +
+ ggtitle("(FoodQuality, Service) = Tip")
+
+engine.plot.i2i1_o1 = ggplot(engine.df, aes(Service, FoodQuality)) +
+ geom_tile(aes(fill=Tip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Service, y=FoodQuality, z=Tip), color="black") +
+ ggtitle("(Service, FoodQuality) = Tip")
+
+engine.plot.i1i2_o2 = ggplot(engine.df, aes(FoodQuality, Service)) +
+ geom_tile(aes(fill=CheckPlusTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=FoodQuality, y=Service, z=CheckPlusTip), color="black") +
+ ggtitle("(FoodQuality, Service) = CheckPlusTip")
+
+engine.plot.i2i1_o2 = ggplot(engine.df, aes(Service, FoodQuality)) +
+ geom_tile(aes(fill=CheckPlusTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Service, y=FoodQuality, z=CheckPlusTip), color="black") +
+ ggtitle("(Service, FoodQuality) = CheckPlusTip")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1i2_o1, engine.plot.i2i1_o1, engine.plot.i1i2_o2, engine.plot.i2i1_o2, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/mamdani/octave/mamdani_tip_calculator.cpp b/examples/mamdani/octave/mamdani_tip_calculator.cpp
index cd57bf7..86d6464 100644
--- a/examples/mamdani/octave/mamdani_tip_calculator.cpp
+++ b/examples/mamdani/octave/mamdani_tip_calculator.cpp
@@ -1,65 +1,76 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("Mamdani-Tip-Calculator");
+engine->setName("mamdani_tip_calculator");
+engine->setDescription("");
-InputVariable* inputVariable1 = new InputVariable;
-inputVariable1->setEnabled(true);
-inputVariable1->setName("FoodQuality");
-inputVariable1->setRange(1.000, 10.000);
-inputVariable1->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable1->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine->addInputVariable(inputVariable1);
+InputVariable* FoodQuality = new InputVariable;
+FoodQuality->setName("FoodQuality");
+FoodQuality->setDescription("");
+FoodQuality->setEnabled(true);
+FoodQuality->setRange(1.000, 10.000);
+FoodQuality->setLockValueInRange(false);
+FoodQuality->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+FoodQuality->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine->addInputVariable(FoodQuality);
-InputVariable* inputVariable2 = new InputVariable;
-inputVariable2->setEnabled(true);
-inputVariable2->setName("Service");
-inputVariable2->setRange(1.000, 10.000);
-inputVariable2->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable2->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine->addInputVariable(inputVariable2);
+InputVariable* Service = new InputVariable;
+Service->setName("Service");
+Service->setDescription("");
+Service->setEnabled(true);
+Service->setRange(1.000, 10.000);
+Service->setLockValueInRange(false);
+Service->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+Service->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine->addInputVariable(Service);
-OutputVariable* outputVariable1 = new OutputVariable;
-outputVariable1->setEnabled(true);
-outputVariable1->setName("Tip");
-outputVariable1->setRange(0.000, 30.000);
-outputVariable1->fuzzyOutput()->setAccumulation(new AlgebraicSum);
-outputVariable1->setDefuzzifier(new Centroid(200));
-outputVariable1->setDefaultValue(fl::nan);
-outputVariable1->setLockPreviousOutputValue(false);
-outputVariable1->setLockOutputValueInRange(false);
-outputVariable1->addTerm(new Gaussian("AboutTenPercent", 10.000, 2.000));
-outputVariable1->addTerm(new Gaussian("AboutFifteenPercent", 15.000, 2.000));
-outputVariable1->addTerm(new Gaussian("AboutTwentyPercent", 20.000, 2.000));
-engine->addOutputVariable(outputVariable1);
+OutputVariable* Tip = new OutputVariable;
+Tip->setName("Tip");
+Tip->setDescription("");
+Tip->setEnabled(true);
+Tip->setRange(0.000, 30.000);
+Tip->setLockValueInRange(false);
+Tip->setAggregation(new AlgebraicSum);
+Tip->setDefuzzifier(new Centroid(200));
+Tip->setDefaultValue(fl::nan);
+Tip->setLockPreviousValue(false);
+Tip->addTerm(new Gaussian("AboutTenPercent", 10.000, 2.000));
+Tip->addTerm(new Gaussian("AboutFifteenPercent", 15.000, 2.000));
+Tip->addTerm(new Gaussian("AboutTwentyPercent", 20.000, 2.000));
+engine->addOutputVariable(Tip);
-OutputVariable* outputVariable2 = new OutputVariable;
-outputVariable2->setEnabled(true);
-outputVariable2->setName("CheckPlusTip");
-outputVariable2->setRange(1.000, 1.300);
-outputVariable2->fuzzyOutput()->setAccumulation(new AlgebraicSum);
-outputVariable2->setDefuzzifier(new Centroid(200));
-outputVariable2->setDefaultValue(fl::nan);
-outputVariable2->setLockPreviousOutputValue(false);
-outputVariable2->setLockOutputValueInRange(false);
-outputVariable2->addTerm(new Gaussian("PlusAboutTenPercent", 1.100, 0.020));
-outputVariable2->addTerm(new Gaussian("PlusAboutFifteenPercent", 1.150, 0.020));
-outputVariable2->addTerm(new Gaussian("PlusAboutTwentyPercent", 1.200, 0.020));
-engine->addOutputVariable(outputVariable2);
+OutputVariable* CheckPlusTip = new OutputVariable;
+CheckPlusTip->setName("CheckPlusTip");
+CheckPlusTip->setDescription("");
+CheckPlusTip->setEnabled(true);
+CheckPlusTip->setRange(1.000, 1.300);
+CheckPlusTip->setLockValueInRange(false);
+CheckPlusTip->setAggregation(new AlgebraicSum);
+CheckPlusTip->setDefuzzifier(new Centroid(200));
+CheckPlusTip->setDefaultValue(fl::nan);
+CheckPlusTip->setLockPreviousValue(false);
+CheckPlusTip->addTerm(new Gaussian("PlusAboutTenPercent", 1.100, 0.020));
+CheckPlusTip->addTerm(new Gaussian("PlusAboutFifteenPercent", 1.150, 0.020));
+CheckPlusTip->addTerm(new Gaussian("PlusAboutTwentyPercent", 1.200, 0.020));
+engine->addOutputVariable(CheckPlusTip);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(new AlgebraicProduct);
ruleBlock->setDisjunction(new Maximum);
-ruleBlock->setActivation(new Minimum);
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Bad and Service is Bad then Tip is AboutTenPercent and CheckPlusTip is PlusAboutTenPercent", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Bad and Service is Good then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Good and Service is Bad then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Good and Service is Good then Tip is AboutTwentyPercent and CheckPlusTip is PlusAboutTwentyPercent", engine));
+ruleBlock->setImplication(new Minimum);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if FoodQuality is Bad and Service is Bad then Tip is AboutTenPercent and CheckPlusTip is PlusAboutTenPercent", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Bad and Service is Good then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Good and Service is Bad then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Good and Service is Good then Tip is AboutTwentyPercent and CheckPlusTip is PlusAboutTwentyPercent", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/mamdani/octave/mamdani_tip_calculator.fcl b/examples/mamdani/octave/mamdani_tip_calculator.fcl
index 3ea903a..0265bc2 100644
--- a/examples/mamdani/octave/mamdani_tip_calculator.fcl
+++ b/examples/mamdani/octave/mamdani_tip_calculator.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK Mamdani-Tip-Calculator
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK mamdani_tip_calculator
VAR_INPUT
FoodQuality: REAL;
diff --git a/examples/mamdani/octave/mamdani_tip_calculator.fis b/examples/mamdani/octave/mamdani_tip_calculator.fis
index 42cf1df..13cd802 100644
--- a/examples/mamdani/octave/mamdani_tip_calculator.fis
+++ b/examples/mamdani/octave/mamdani_tip_calculator.fis
@@ -1,13 +1,16 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='Mamdani-Tip-Calculator'
+Name='mamdani_tip_calculator'
Type='mamdani'
+Version=6.0
NumInputs=2
NumOutputs=2
NumRules=4
AndMethod='prod'
OrMethod='max'
ImpMethod='min'
-AggMethod='sum'
+AggMethod='probor'
DefuzzMethod='centroid'
[Input1]
diff --git a/examples/mamdani/octave/mamdani_tip_calculator.fld b/examples/mamdani/octave/mamdani_tip_calculator.fld
index 9d54109..9d87eab 100644
--- a/examples/mamdani/octave/mamdani_tip_calculator.fld
+++ b/examples/mamdani/octave/mamdani_tip_calculator.fld
@@ -1,1026 +1,1025 @@
-#@Engine: Mamdani-Tip-Calculator;
-#@InputVariable: FoodQuality; @InputVariable: Service; @OutputVariable: Tip; @OutputVariable: CheckPlusTip;
-1.00000000 1.00000000 10.00000296 1.10000003
-1.00000000 1.29032258 10.00000296 1.10000003
-1.00000000 1.58064516 10.00000296 1.10000003
-1.00000000 1.87096774 10.00000296 1.10000003
-1.00000000 2.16129032 10.00000296 1.10000003
-1.00000000 2.45161290 10.00000296 1.10000003
-1.00000000 2.74193548 10.00000296 1.10000003
-1.00000000 3.03225806 10.10361204 1.10103612
-1.00000000 3.32258065 10.70846739 1.10708467
-1.00000000 3.61290323 11.13394556 1.11133946
-1.00000000 3.90322581 11.47924881 1.11479249
-1.00000000 4.19354839 11.77837052 1.11778371
-1.00000000 4.48387097 12.05010492 1.12050105
-1.00000000 4.77419355 12.30576276 1.12305763
-1.00000000 5.06451613 12.55517544 1.12555175
-1.00000000 5.35483871 12.80665986 1.12806660
-1.00000000 5.64516129 13.06809323 1.13068093
-1.00000000 5.93548387 13.35056196 1.13350562
-1.00000000 6.22580645 13.66657067 1.13666571
-1.00000000 6.51612903 14.04212491 1.14042125
-1.00000000 6.80645161 14.52492871 1.14524929
-1.00000000 7.09677419 15.00000000 1.15000000
-1.00000000 7.38709677 15.00000000 1.15000000
-1.00000000 7.67741935 15.00000000 1.15000000
-1.00000000 7.96774194 15.00000000 1.15000000
-1.00000000 8.25806452 15.00000000 1.15000000
-1.00000000 8.54838710 15.00000000 1.15000000
-1.00000000 8.83870968 15.00000000 1.15000000
-1.00000000 9.12903226 15.00000000 1.15000000
-1.00000000 9.41935484 15.00000000 1.15000000
-1.00000000 9.70967742 15.00000000 1.15000000
-1.00000000 10.00000000 15.00000000 1.15000000
-1.29032258 1.00000000 10.00000296 1.10000003
-1.29032258 1.29032258 10.00000296 1.10000003
-1.29032258 1.58064516 10.00000296 1.10000003
-1.29032258 1.87096774 10.00000296 1.10000003
-1.29032258 2.16129032 10.00000296 1.10000003
-1.29032258 2.45161290 10.00000296 1.10000003
-1.29032258 2.74193548 10.00000296 1.10000003
-1.29032258 3.03225806 10.10361204 1.10103612
-1.29032258 3.32258065 10.70846739 1.10708467
-1.29032258 3.61290323 11.13394556 1.11133946
-1.29032258 3.90322581 11.47924881 1.11479249
-1.29032258 4.19354839 11.77837052 1.11778371
-1.29032258 4.48387097 12.05010492 1.12050105
-1.29032258 4.77419355 12.30576276 1.12305763
-1.29032258 5.06451613 12.55517544 1.12555175
-1.29032258 5.35483871 12.80665986 1.12806660
-1.29032258 5.64516129 13.06809323 1.13068093
-1.29032258 5.93548387 13.35056196 1.13350562
-1.29032258 6.22580645 13.66657067 1.13666571
-1.29032258 6.51612903 14.04212491 1.14042125
-1.29032258 6.80645161 14.52492871 1.14524929
-1.29032258 7.09677419 15.00000000 1.15000000
-1.29032258 7.38709677 15.00000000 1.15000000
-1.29032258 7.67741935 15.00000000 1.15000000
-1.29032258 7.96774194 15.00000000 1.15000000
-1.29032258 8.25806452 15.00000000 1.15000000
-1.29032258 8.54838710 15.00000000 1.15000000
-1.29032258 8.83870968 15.00000000 1.15000000
-1.29032258 9.12903226 15.00000000 1.15000000
-1.29032258 9.41935484 15.00000000 1.15000000
-1.29032258 9.70967742 15.00000000 1.15000000
-1.29032258 10.00000000 15.00000000 1.15000000
-1.58064516 1.00000000 10.00000296 1.10000003
-1.58064516 1.29032258 10.00000296 1.10000003
-1.58064516 1.58064516 10.00000296 1.10000003
-1.58064516 1.87096774 10.00000296 1.10000003
-1.58064516 2.16129032 10.00000296 1.10000003
-1.58064516 2.45161290 10.00000296 1.10000003
-1.58064516 2.74193548 10.00000296 1.10000003
-1.58064516 3.03225806 10.10361204 1.10103612
-1.58064516 3.32258065 10.70846739 1.10708467
-1.58064516 3.61290323 11.13394556 1.11133946
-1.58064516 3.90322581 11.47924881 1.11479249
-1.58064516 4.19354839 11.77837052 1.11778371
-1.58064516 4.48387097 12.05010492 1.12050105
-1.58064516 4.77419355 12.30576276 1.12305763
-1.58064516 5.06451613 12.55517544 1.12555175
-1.58064516 5.35483871 12.80665986 1.12806660
-1.58064516 5.64516129 13.06809323 1.13068093
-1.58064516 5.93548387 13.35056196 1.13350562
-1.58064516 6.22580645 13.66657067 1.13666571
-1.58064516 6.51612903 14.04212491 1.14042125
-1.58064516 6.80645161 14.52492871 1.14524929
-1.58064516 7.09677419 15.00000000 1.15000000
-1.58064516 7.38709677 15.00000000 1.15000000
-1.58064516 7.67741935 15.00000000 1.15000000
-1.58064516 7.96774194 15.00000000 1.15000000
-1.58064516 8.25806452 15.00000000 1.15000000
-1.58064516 8.54838710 15.00000000 1.15000000
-1.58064516 8.83870968 15.00000000 1.15000000
-1.58064516 9.12903226 15.00000000 1.15000000
-1.58064516 9.41935484 15.00000000 1.15000000
-1.58064516 9.70967742 15.00000000 1.15000000
-1.58064516 10.00000000 15.00000000 1.15000000
-1.87096774 1.00000000 10.00000296 1.10000003
-1.87096774 1.29032258 10.00000296 1.10000003
-1.87096774 1.58064516 10.00000296 1.10000003
-1.87096774 1.87096774 10.00000296 1.10000003
-1.87096774 2.16129032 10.00000296 1.10000003
-1.87096774 2.45161290 10.00000296 1.10000003
-1.87096774 2.74193548 10.00000296 1.10000003
-1.87096774 3.03225806 10.10361204 1.10103612
-1.87096774 3.32258065 10.70846739 1.10708467
-1.87096774 3.61290323 11.13394556 1.11133946
-1.87096774 3.90322581 11.47924881 1.11479249
-1.87096774 4.19354839 11.77837052 1.11778371
-1.87096774 4.48387097 12.05010492 1.12050105
-1.87096774 4.77419355 12.30576276 1.12305763
-1.87096774 5.06451613 12.55517544 1.12555175
-1.87096774 5.35483871 12.80665986 1.12806660
-1.87096774 5.64516129 13.06809323 1.13068093
-1.87096774 5.93548387 13.35056196 1.13350562
-1.87096774 6.22580645 13.66657067 1.13666571
-1.87096774 6.51612903 14.04212491 1.14042125
-1.87096774 6.80645161 14.52492871 1.14524929
-1.87096774 7.09677419 15.00000000 1.15000000
-1.87096774 7.38709677 15.00000000 1.15000000
-1.87096774 7.67741935 15.00000000 1.15000000
-1.87096774 7.96774194 15.00000000 1.15000000
-1.87096774 8.25806452 15.00000000 1.15000000
-1.87096774 8.54838710 15.00000000 1.15000000
-1.87096774 8.83870968 15.00000000 1.15000000
-1.87096774 9.12903226 15.00000000 1.15000000
-1.87096774 9.41935484 15.00000000 1.15000000
-1.87096774 9.70967742 15.00000000 1.15000000
-1.87096774 10.00000000 15.00000000 1.15000000
-2.16129032 1.00000000 10.00000296 1.10000003
-2.16129032 1.29032258 10.00000296 1.10000003
-2.16129032 1.58064516 10.00000296 1.10000003
-2.16129032 1.87096774 10.00000296 1.10000003
-2.16129032 2.16129032 10.00000296 1.10000003
-2.16129032 2.45161290 10.00000296 1.10000003
-2.16129032 2.74193548 10.00000296 1.10000003
-2.16129032 3.03225806 10.10361204 1.10103612
-2.16129032 3.32258065 10.70846739 1.10708467
-2.16129032 3.61290323 11.13394556 1.11133946
-2.16129032 3.90322581 11.47924881 1.11479249
-2.16129032 4.19354839 11.77837052 1.11778371
-2.16129032 4.48387097 12.05010492 1.12050105
-2.16129032 4.77419355 12.30576276 1.12305763
-2.16129032 5.06451613 12.55517544 1.12555175
-2.16129032 5.35483871 12.80665986 1.12806660
-2.16129032 5.64516129 13.06809323 1.13068093
-2.16129032 5.93548387 13.35056196 1.13350562
-2.16129032 6.22580645 13.66657067 1.13666571
-2.16129032 6.51612903 14.04212491 1.14042125
-2.16129032 6.80645161 14.52492871 1.14524929
-2.16129032 7.09677419 15.00000000 1.15000000
-2.16129032 7.38709677 15.00000000 1.15000000
-2.16129032 7.67741935 15.00000000 1.15000000
-2.16129032 7.96774194 15.00000000 1.15000000
-2.16129032 8.25806452 15.00000000 1.15000000
-2.16129032 8.54838710 15.00000000 1.15000000
-2.16129032 8.83870968 15.00000000 1.15000000
-2.16129032 9.12903226 15.00000000 1.15000000
-2.16129032 9.41935484 15.00000000 1.15000000
-2.16129032 9.70967742 15.00000000 1.15000000
-2.16129032 10.00000000 15.00000000 1.15000000
-2.45161290 1.00000000 10.00000296 1.10000003
-2.45161290 1.29032258 10.00000296 1.10000003
-2.45161290 1.58064516 10.00000296 1.10000003
-2.45161290 1.87096774 10.00000296 1.10000003
-2.45161290 2.16129032 10.00000296 1.10000003
-2.45161290 2.45161290 10.00000296 1.10000003
-2.45161290 2.74193548 10.00000296 1.10000003
-2.45161290 3.03225806 10.10361204 1.10103612
-2.45161290 3.32258065 10.70846739 1.10708467
-2.45161290 3.61290323 11.13394556 1.11133946
-2.45161290 3.90322581 11.47924881 1.11479249
-2.45161290 4.19354839 11.77837052 1.11778371
-2.45161290 4.48387097 12.05010492 1.12050105
-2.45161290 4.77419355 12.30576276 1.12305763
-2.45161290 5.06451613 12.55517544 1.12555175
-2.45161290 5.35483871 12.80665986 1.12806660
-2.45161290 5.64516129 13.06809323 1.13068093
-2.45161290 5.93548387 13.35056196 1.13350562
-2.45161290 6.22580645 13.66657067 1.13666571
-2.45161290 6.51612903 14.04212491 1.14042125
-2.45161290 6.80645161 14.52492871 1.14524929
-2.45161290 7.09677419 15.00000000 1.15000000
-2.45161290 7.38709677 15.00000000 1.15000000
-2.45161290 7.67741935 15.00000000 1.15000000
-2.45161290 7.96774194 15.00000000 1.15000000
-2.45161290 8.25806452 15.00000000 1.15000000
-2.45161290 8.54838710 15.00000000 1.15000000
-2.45161290 8.83870968 15.00000000 1.15000000
-2.45161290 9.12903226 15.00000000 1.15000000
-2.45161290 9.41935484 15.00000000 1.15000000
-2.45161290 9.70967742 15.00000000 1.15000000
-2.45161290 10.00000000 15.00000000 1.15000000
-2.74193548 1.00000000 10.00000296 1.10000003
-2.74193548 1.29032258 10.00000296 1.10000003
-2.74193548 1.58064516 10.00000296 1.10000003
-2.74193548 1.87096774 10.00000296 1.10000003
-2.74193548 2.16129032 10.00000296 1.10000003
-2.74193548 2.45161290 10.00000296 1.10000003
-2.74193548 2.74193548 10.00000296 1.10000003
-2.74193548 3.03225806 10.10361204 1.10103612
-2.74193548 3.32258065 10.70846739 1.10708467
-2.74193548 3.61290323 11.13394556 1.11133946
-2.74193548 3.90322581 11.47924881 1.11479249
-2.74193548 4.19354839 11.77837052 1.11778371
-2.74193548 4.48387097 12.05010492 1.12050105
-2.74193548 4.77419355 12.30576276 1.12305763
-2.74193548 5.06451613 12.55517544 1.12555175
-2.74193548 5.35483871 12.80665986 1.12806660
-2.74193548 5.64516129 13.06809323 1.13068093
-2.74193548 5.93548387 13.35056196 1.13350562
-2.74193548 6.22580645 13.66657067 1.13666571
-2.74193548 6.51612903 14.04212491 1.14042125
-2.74193548 6.80645161 14.52492871 1.14524929
-2.74193548 7.09677419 15.00000000 1.15000000
-2.74193548 7.38709677 15.00000000 1.15000000
-2.74193548 7.67741935 15.00000000 1.15000000
-2.74193548 7.96774194 15.00000000 1.15000000
-2.74193548 8.25806452 15.00000000 1.15000000
-2.74193548 8.54838710 15.00000000 1.15000000
-2.74193548 8.83870968 15.00000000 1.15000000
-2.74193548 9.12903226 15.00000000 1.15000000
-2.74193548 9.41935484 15.00000000 1.15000000
-2.74193548 9.70967742 15.00000000 1.15000000
-2.74193548 10.00000000 15.00000000 1.15000000
-3.03225806 1.00000000 10.10361204 1.10103612
-3.03225806 1.29032258 10.10361204 1.10103612
-3.03225806 1.58064516 10.10361204 1.10103612
-3.03225806 1.87096774 10.10361204 1.10103612
-3.03225806 2.16129032 10.10361204 1.10103612
-3.03225806 2.45161290 10.10361204 1.10103612
-3.03225806 2.74193548 10.10361204 1.10103612
-3.03225806 3.03225806 10.20435811 1.10204358
-3.03225806 3.32258065 10.79601822 1.10796018
-3.03225806 3.61290323 11.21535874 1.11215359
-3.03225806 3.90322581 11.55784646 1.11557846
-3.03225806 4.19354839 11.85579036 1.11855790
-3.03225806 4.48387097 12.12724043 1.12127240
-3.03225806 4.77419355 12.38405258 1.12384053
-3.03225806 5.06451613 12.63499742 1.12634997
-3.03225806 5.35483871 12.88858563 1.12888586
-3.03225806 5.64516129 13.15323067 1.13153231
-3.03225806 5.93548387 13.43888099 1.13438881
-3.03225806 6.22580645 13.75926546 1.13759265
-3.03225806 6.51612903 14.13934485 1.14139345
-3.03225806 6.80645161 14.62674650 1.14626746
-3.03225806 7.09677419 15.10357489 1.15103575
-3.03225806 7.38709677 15.10357489 1.15103575
-3.03225806 7.67741935 15.10357489 1.15103575
-3.03225806 7.96774194 15.10357489 1.15103575
-3.03225806 8.25806452 15.10357489 1.15103575
-3.03225806 8.54838710 15.10357489 1.15103575
-3.03225806 8.83870968 15.10357489 1.15103575
-3.03225806 9.12903226 15.10357489 1.15103575
-3.03225806 9.41935484 15.10357489 1.15103575
-3.03225806 9.70967742 15.10357489 1.15103575
-3.03225806 10.00000000 15.10357489 1.15103575
-3.32258065 1.00000000 10.70846739 1.10708467
-3.32258065 1.29032258 10.70846739 1.10708467
-3.32258065 1.58064516 10.70846739 1.10708467
-3.32258065 1.87096774 10.70846739 1.10708467
-3.32258065 2.16129032 10.70846739 1.10708467
-3.32258065 2.45161290 10.70846739 1.10708467
-3.32258065 2.74193548 10.70846739 1.10708467
-3.32258065 3.03225806 10.79601822 1.10796018
-3.32258065 3.32258065 11.32266175 1.11322662
-3.32258065 3.61290323 11.71291316 1.11712913
-3.32258065 3.90322581 12.04341522 1.12043415
-3.32258065 4.19354839 12.33970940 1.12339709
-3.32258065 4.48387097 12.61573315 1.12615733
-3.32258065 4.77419355 12.88122387 1.12881224
-3.32258065 5.06451613 13.14483502 1.13144835
-3.32258065 5.35483871 13.41408247 1.13414082
-3.32258065 5.64516129 13.69613892 1.13696139
-3.32258065 5.93548387 14.00077769 1.14000778
-3.32258065 6.22580645 14.34225854 1.14342259
-3.32258065 6.51612903 14.73996425 1.14739964
-3.32258065 6.80645161 15.23916402 1.15239164
-3.32258065 7.09677419 15.70844950 1.15708449
-3.32258065 7.38709677 15.70844950 1.15708449
-3.32258065 7.67741935 15.70844950 1.15708449
-3.32258065 7.96774194 15.70844950 1.15708449
-3.32258065 8.25806452 15.70844950 1.15708449
-3.32258065 8.54838710 15.70844950 1.15708449
-3.32258065 8.83870968 15.70844950 1.15708449
-3.32258065 9.12903226 15.70844950 1.15708449
-3.32258065 9.41935484 15.70844950 1.15708449
-3.32258065 9.70967742 15.70844950 1.15708449
-3.32258065 10.00000000 15.70844950 1.15708449
-3.61290323 1.00000000 11.13394556 1.11133946
-3.61290323 1.29032258 11.13394556 1.11133946
-3.61290323 1.58064516 11.13394556 1.11133946
-3.61290323 1.87096774 11.13394556 1.11133946
-3.61290323 2.16129032 11.13394556 1.11133946
-3.61290323 2.45161290 11.13394556 1.11133946
-3.61290323 2.74193548 11.13394556 1.11133946
-3.61290323 3.03225806 11.21535874 1.11215359
-3.61290323 3.32258065 11.71291316 1.11712913
-3.61290323 3.61290323 12.09048689 1.12090487
-3.61290323 3.90322581 12.41795109 1.12417951
-3.61290323 4.19354839 12.71702039 1.12717020
-3.61290323 4.48387097 12.99911163 1.12999112
-3.61290323 4.77419355 13.27378061 1.13273781
-3.61290323 5.06451613 13.54771797 1.13547718
-3.61290323 5.35483871 13.82751223 1.13827512
-3.61290323 5.64516129 14.12018766 1.14120188
-3.61290323 5.93548387 14.43537168 1.14435372
-3.61290323 6.22580645 14.78491413 1.14784914
-3.61290323 6.51612903 15.18700487 1.15187005
-3.61290323 6.80645161 15.68154801 1.15681548
-3.61290323 7.09677419 16.13382374 1.16133824
-3.61290323 7.38709677 16.13382374 1.16133824
-3.61290323 7.67741935 16.13382374 1.16133824
-3.61290323 7.96774194 16.13382374 1.16133824
-3.61290323 8.25806452 16.13382374 1.16133824
-3.61290323 8.54838710 16.13382374 1.16133824
-3.61290323 8.83870968 16.13382374 1.16133824
-3.61290323 9.12903226 16.13382374 1.16133824
-3.61290323 9.41935484 16.13382374 1.16133824
-3.61290323 9.70967742 16.13382374 1.16133824
-3.61290323 10.00000000 16.13382374 1.16133824
-3.90322581 1.00000000 11.47924881 1.11479249
-3.90322581 1.29032258 11.47924881 1.11479249
-3.90322581 1.58064516 11.47924881 1.11479249
-3.90322581 1.87096774 11.47924881 1.11479249
-3.90322581 2.16129032 11.47924881 1.11479249
-3.90322581 2.45161290 11.47924881 1.11479249
-3.90322581 2.74193548 11.47924881 1.11479249
-3.90322581 3.03225806 11.55784646 1.11557846
-3.90322581 3.32258065 12.04341522 1.12043415
-3.90322581 3.61290323 12.41795109 1.12417951
-3.90322581 3.90322581 12.74629906 1.12746299
-3.90322581 4.19354839 13.04969635 1.13049696
-3.90322581 4.48387097 13.33797049 1.13337970
-3.90322581 4.77419355 13.62015959 1.13620160
-3.90322581 5.06451613 13.90194660 1.13901947
-3.90322581 5.35483871 14.18888316 1.14188883
-3.90322581 5.64516129 14.48954068 1.14489541
-3.90322581 5.93548387 14.80982202 1.14809822
-3.90322581 6.22580645 15.16074884 1.15160749
-3.90322581 6.51612903 15.56087142 1.15560871
-3.90322581 6.80645161 16.04390018 1.16043900
-3.90322581 7.09677419 16.47922769 1.16479228
-3.90322581 7.38709677 16.47922769 1.16479228
-3.90322581 7.67741935 16.47922769 1.16479228
-3.90322581 7.96774194 16.47922769 1.16479228
-3.90322581 8.25806452 16.47922769 1.16479228
-3.90322581 8.54838710 16.47922769 1.16479228
-3.90322581 8.83870968 16.47922769 1.16479228
-3.90322581 9.12903226 16.47922769 1.16479228
-3.90322581 9.41935484 16.47922769 1.16479228
-3.90322581 9.70967742 16.47922769 1.16479228
-3.90322581 10.00000000 16.47922769 1.16479228
-4.19354839 1.00000000 11.77837052 1.11778371
-4.19354839 1.29032258 11.77837052 1.11778371
-4.19354839 1.58064516 11.77837052 1.11778371
-4.19354839 1.87096774 11.77837052 1.11778371
-4.19354839 2.16129032 11.77837052 1.11778371
-4.19354839 2.45161290 11.77837052 1.11778371
-4.19354839 2.74193548 11.77837052 1.11778371
-4.19354839 3.03225806 11.85579036 1.11855790
-4.19354839 3.32258065 12.33970940 1.12339709
-4.19354839 3.61290323 12.71702039 1.12717020
-4.19354839 3.90322581 13.04969635 1.13049696
-4.19354839 4.19354839 13.35789542 1.13357895
-4.19354839 4.48387097 13.65214664 1.13652147
-4.19354839 4.77419355 13.94035790 1.13940358
-4.19354839 5.06451613 14.22819712 1.14228197
-4.19354839 5.35483871 14.52045260 1.14520453
-4.19354839 5.64516129 14.82442596 1.14824426
-4.19354839 5.93548387 15.14611095 1.15146111
-4.19354839 6.22580645 15.49584016 1.15495840
-4.19354839 6.51612903 15.88989883 1.15889899
-4.19354839 6.80645161 16.36071096 1.16360711
-4.19354839 7.09677419 16.77845274 1.16778453
-4.19354839 7.38709677 16.77845274 1.16778453
-4.19354839 7.67741935 16.77845274 1.16778453
-4.19354839 7.96774194 16.77845274 1.16778453
-4.19354839 8.25806452 16.77845274 1.16778453
-4.19354839 8.54838710 16.77845274 1.16778453
-4.19354839 8.83870968 16.77845274 1.16778453
-4.19354839 9.12903226 16.77845274 1.16778453
-4.19354839 9.41935484 16.77845274 1.16778453
-4.19354839 9.70967742 16.77845274 1.16778453
-4.19354839 10.00000000 16.77845274 1.16778453
-4.48387097 1.00000000 12.05010492 1.12050105
-4.48387097 1.29032258 12.05010492 1.12050105
-4.48387097 1.58064516 12.05010492 1.12050105
-4.48387097 1.87096774 12.05010492 1.12050105
-4.48387097 2.16129032 12.05010492 1.12050105
-4.48387097 2.45161290 12.05010492 1.12050105
-4.48387097 2.74193548 12.05010492 1.12050105
-4.48387097 3.03225806 12.12724043 1.12127240
-4.48387097 3.32258065 12.61573315 1.12615733
-4.48387097 3.61290323 12.99911163 1.12999112
-4.48387097 3.90322581 13.33797049 1.13337970
-4.48387097 4.19354839 13.65214664 1.13652147
-4.48387097 4.48387097 13.95167976 1.13951680
-4.48387097 4.77419355 14.24536545 1.14245365
-4.48387097 5.06451613 14.53742599 1.14537426
-4.48387097 5.35483871 14.83253803 1.14832538
-4.48387097 5.64516129 15.13703643 1.15137036
-4.48387097 5.93548387 15.45709896 1.15457099
-4.48387097 6.22580645 15.80333467 1.15803335
-4.48387097 6.51612903 16.18964589 1.16189646
-4.48387097 6.80645161 16.64650295 1.16646503
-4.48387097 7.09677419 17.05002382 1.17050024
-4.48387097 7.38709677 17.05002382 1.17050024
-4.48387097 7.67741935 17.05002382 1.17050024
-4.48387097 7.96774194 17.05002382 1.17050024
-4.48387097 8.25806452 17.05002382 1.17050024
-4.48387097 8.54838710 17.05002382 1.17050024
-4.48387097 8.83870968 17.05002382 1.17050024
-4.48387097 9.12903226 17.05002382 1.17050024
-4.48387097 9.41935484 17.05002382 1.17050024
-4.48387097 9.70967742 17.05002382 1.17050024
-4.48387097 10.00000000 17.05002382 1.17050024
-4.77419355 1.00000000 12.30576276 1.12305763
-4.77419355 1.29032258 12.30576276 1.12305763
-4.77419355 1.58064516 12.30576276 1.12305763
-4.77419355 1.87096774 12.30576276 1.12305763
-4.77419355 2.16129032 12.30576276 1.12305763
-4.77419355 2.45161290 12.30576276 1.12305763
-4.77419355 2.74193548 12.30576276 1.12305763
-4.77419355 3.03225806 12.38405258 1.12384053
-4.77419355 3.32258065 12.88122387 1.12881224
-4.77419355 3.61290323 13.27378061 1.13273781
-4.77419355 3.90322581 13.62015959 1.13620160
-4.77419355 4.19354839 13.94035790 1.13940358
-4.77419355 4.48387097 14.24536545 1.14245365
-4.77419355 4.77419355 14.54225355 1.14542254
-4.77419355 5.06451613 14.83618630 1.14836186
-4.77419355 5.35483871 15.13221695 1.15132217
-4.77419355 5.64516129 15.43597664 1.15435977
-4.77419355 5.93548387 15.75365034 1.15753650
-4.77419355 6.22580645 16.09439857 1.16094399
-4.77419355 6.51612903 16.47201646 1.16472016
-4.77419355 6.80645161 16.91532876 1.16915329
-4.77419355 7.09677419 17.30571907 1.17305719
-4.77419355 7.38709677 17.30571907 1.17305719
-4.77419355 7.67741935 17.30571907 1.17305719
-4.77419355 7.96774194 17.30571907 1.17305719
-4.77419355 8.25806452 17.30571907 1.17305719
-4.77419355 8.54838710 17.30571907 1.17305719
-4.77419355 8.83870968 17.30571907 1.17305719
-4.77419355 9.12903226 17.30571907 1.17305719
-4.77419355 9.41935484 17.30571907 1.17305719
-4.77419355 9.70967742 17.30571907 1.17305719
-4.77419355 10.00000000 17.30571907 1.17305719
-5.06451613 1.00000000 12.55517544 1.12555175
-5.06451613 1.29032258 12.55517544 1.12555175
-5.06451613 1.58064516 12.55517544 1.12555175
-5.06451613 1.87096774 12.55517544 1.12555175
-5.06451613 2.16129032 12.55517544 1.12555175
-5.06451613 2.45161290 12.55517544 1.12555175
-5.06451613 2.74193548 12.55517544 1.12555175
-5.06451613 3.03225806 12.63499742 1.12634997
-5.06451613 3.32258065 13.14483502 1.13144835
-5.06451613 3.61290323 13.54771797 1.13547718
-5.06451613 3.90322581 13.90194660 1.13901947
-5.06451613 4.19354839 14.22819712 1.14228197
-5.06451613 4.48387097 14.53742599 1.14537426
-5.06451613 4.77419355 14.83618630 1.14836186
-5.06451613 5.06451613 15.13082220 1.15130822
-5.06451613 5.35483871 15.42613481 1.15426135
-5.06451613 5.64516129 15.72760843 1.15727608
-5.06451613 5.93548387 16.04091807 1.16040918
-5.06451613 6.22580645 16.37497163 1.16374972
-5.06451613 6.51612903 16.74347970 1.16743480
-5.06451613 6.80645161 17.17503189 1.17175032
-5.06451613 7.09677419 17.55554644 1.17555546
-5.06451613 7.38709677 17.55554644 1.17555546
-5.06451613 7.67741935 17.55554644 1.17555546
-5.06451613 7.96774194 17.55554644 1.17555546
-5.06451613 8.25806452 17.55554644 1.17555546
-5.06451613 8.54838710 17.55554644 1.17555546
-5.06451613 8.83870968 17.55554644 1.17555546
-5.06451613 9.12903226 17.55554644 1.17555546
-5.06451613 9.41935484 17.55554644 1.17555546
-5.06451613 9.70967742 17.55554644 1.17555546
-5.06451613 10.00000000 17.55554644 1.17555546
-5.35483871 1.00000000 12.80665986 1.12806660
-5.35483871 1.29032258 12.80665986 1.12806660
-5.35483871 1.58064516 12.80665986 1.12806660
-5.35483871 1.87096774 12.80665986 1.12806660
-5.35483871 2.16129032 12.80665986 1.12806660
-5.35483871 2.45161290 12.80665986 1.12806660
-5.35483871 2.74193548 12.80665986 1.12806660
-5.35483871 3.03225806 12.88858563 1.12888586
-5.35483871 3.32258065 13.41408247 1.13414082
-5.35483871 3.61290323 13.82751223 1.13827512
-5.35483871 3.90322581 14.18888316 1.14188883
-5.35483871 4.19354839 14.52045260 1.14520453
-5.35483871 4.48387097 14.83253803 1.14832538
-5.35483871 4.77419355 15.13221695 1.15132217
-5.35483871 5.06451613 15.42613481 1.15426135
-5.35483871 5.35483871 15.71936190 1.15719362
-5.35483871 5.64516129 16.01779116 1.16017791
-5.35483871 5.93548387 16.32590382 1.16325904
-5.35483871 6.22580645 16.65335849 1.16653358
-5.35483871 6.51612903 17.01334871 1.17013349
-5.35483871 6.80645161 17.43409709 1.17434097
-5.35483871 7.09677419 17.80639865 1.17806399
-5.35483871 7.38709677 17.80639865 1.17806399
-5.35483871 7.67741935 17.80639865 1.17806399
-5.35483871 7.96774194 17.80639865 1.17806399
-5.35483871 8.25806452 17.80639865 1.17806399
-5.35483871 8.54838710 17.80639865 1.17806399
-5.35483871 8.83870968 17.80639865 1.17806399
-5.35483871 9.12903226 17.80639865 1.17806399
-5.35483871 9.41935484 17.80639865 1.17806399
-5.35483871 9.70967742 17.80639865 1.17806399
-5.35483871 10.00000000 17.80639865 1.17806399
-5.64516129 1.00000000 13.06809323 1.13068093
-5.64516129 1.29032258 13.06809323 1.13068093
-5.64516129 1.58064516 13.06809323 1.13068093
-5.64516129 1.87096774 13.06809323 1.13068093
-5.64516129 2.16129032 13.06809323 1.13068093
-5.64516129 2.45161290 13.06809323 1.13068093
-5.64516129 2.74193548 13.06809323 1.13068093
-5.64516129 3.03225806 13.15323067 1.13153231
-5.64516129 3.32258065 13.69613892 1.13696139
-5.64516129 3.61290323 14.12018766 1.14120188
-5.64516129 3.90322581 14.48954068 1.14489541
-5.64516129 4.19354839 14.82442596 1.14824426
-5.64516129 4.48387097 15.13703643 1.15137036
-5.64516129 4.77419355 15.43597664 1.15435977
-5.64516129 5.06451613 15.72760843 1.15727608
-5.64516129 5.35483871 16.01779116 1.16017791
-5.64516129 5.64516129 16.31159861 1.16311599
-5.64516129 5.93548387 16.61373257 1.16613733
-5.64516129 6.22580645 16.93399499 1.16933995
-5.64516129 6.51612903 17.28681907 1.17286819
-5.64516129 6.80645161 17.70002087 1.17700021
-5.64516129 7.09677419 18.06809818 1.18068098
-5.64516129 7.38709677 18.06809818 1.18068098
-5.64516129 7.67741935 18.06809818 1.18068098
-5.64516129 7.96774194 18.06809818 1.18068098
-5.64516129 8.25806452 18.06809818 1.18068098
-5.64516129 8.54838710 18.06809818 1.18068098
-5.64516129 8.83870968 18.06809818 1.18068098
-5.64516129 9.12903226 18.06809818 1.18068098
-5.64516129 9.41935484 18.06809818 1.18068098
-5.64516129 9.70967742 18.06809818 1.18068098
-5.64516129 10.00000000 18.06809818 1.18068098
-5.93548387 1.00000000 13.35056196 1.13350562
-5.93548387 1.29032258 13.35056196 1.13350562
-5.93548387 1.58064516 13.35056196 1.13350562
-5.93548387 1.87096774 13.35056196 1.13350562
-5.93548387 2.16129032 13.35056196 1.13350562
-5.93548387 2.45161290 13.35056196 1.13350562
-5.93548387 2.74193548 13.35056196 1.13350562
-5.93548387 3.03225806 13.43888099 1.13438881
-5.93548387 3.32258065 14.00077769 1.14000778
-5.93548387 3.61290323 14.43537168 1.14435372
-5.93548387 3.90322581 14.80982202 1.14809822
-5.93548387 4.19354839 15.14611095 1.15146111
-5.93548387 4.48387097 15.45709896 1.15457099
-5.93548387 4.77419355 15.75365034 1.15753650
-5.93548387 5.06451613 16.04091807 1.16040918
-5.93548387 5.35483871 16.32590382 1.16325904
-5.93548387 5.64516129 16.61373257 1.16613733
-5.93548387 5.93548387 16.91101948 1.16911019
-5.93548387 6.22580645 17.22556302 1.17225563
-5.93548387 6.51612903 17.57263541 1.17572635
-5.93548387 6.80645161 17.98210647 1.17982106
-5.93548387 7.09677419 18.34996260 1.18349963
-5.93548387 7.38709677 18.34996260 1.18349963
-5.93548387 7.67741935 18.34996260 1.18349963
-5.93548387 7.96774194 18.34996260 1.18349963
-5.93548387 8.25806452 18.34996260 1.18349963
-5.93548387 8.54838710 18.34996260 1.18349963
-5.93548387 8.83870968 18.34996260 1.18349963
-5.93548387 9.12903226 18.34996260 1.18349963
-5.93548387 9.41935484 18.34996260 1.18349963
-5.93548387 9.70967742 18.34996260 1.18349963
-5.93548387 10.00000000 18.34996260 1.18349963
-6.22580645 1.00000000 13.66657067 1.13666571
-6.22580645 1.29032258 13.66657067 1.13666571
-6.22580645 1.58064516 13.66657067 1.13666571
-6.22580645 1.87096774 13.66657067 1.13666571
-6.22580645 2.16129032 13.66657067 1.13666571
-6.22580645 2.45161290 13.66657067 1.13666571
-6.22580645 2.74193548 13.66657067 1.13666571
-6.22580645 3.03225806 13.75926546 1.13759265
-6.22580645 3.32258065 14.34225854 1.14342259
-6.22580645 3.61290323 14.78491413 1.14784914
-6.22580645 3.90322581 15.16074884 1.15160749
-6.22580645 4.19354839 15.49584016 1.15495840
-6.22580645 4.48387097 15.80333467 1.15803335
-6.22580645 4.77419355 16.09439857 1.16094399
-6.22580645 5.06451613 16.37497163 1.16374972
-6.22580645 5.35483871 16.65335849 1.16653358
-6.22580645 5.64516129 16.93399499 1.16933995
-6.22580645 5.93548387 17.22556302 1.17225563
-6.22580645 6.22580645 17.53669460 1.17536695
-6.22580645 6.51612903 17.88214034 1.17882140
-6.22580645 6.80645161 18.29211153 1.18292112
-6.22580645 7.09677419 18.66701771 1.18667018
-6.22580645 7.38709677 18.66701771 1.18667018
-6.22580645 7.67741935 18.66701771 1.18667018
-6.22580645 7.96774194 18.66701771 1.18667018
-6.22580645 8.25806452 18.66701771 1.18667018
-6.22580645 8.54838710 18.66701771 1.18667018
-6.22580645 8.83870968 18.66701771 1.18667018
-6.22580645 9.12903226 18.66701771 1.18667018
-6.22580645 9.41935484 18.66701771 1.18667018
-6.22580645 9.70967742 18.66701771 1.18667018
-6.22580645 10.00000000 18.66701771 1.18667018
-6.51612903 1.00000000 14.04212491 1.14042125
-6.51612903 1.29032258 14.04212491 1.14042125
-6.51612903 1.58064516 14.04212491 1.14042125
-6.51612903 1.87096774 14.04212491 1.14042125
-6.51612903 2.16129032 14.04212491 1.14042125
-6.51612903 2.45161290 14.04212491 1.14042125
-6.51612903 2.74193548 14.04212491 1.14042125
-6.51612903 3.03225806 14.13934485 1.14139345
-6.51612903 3.32258065 14.73996425 1.14739964
-6.51612903 3.61290323 15.18700487 1.15187005
-6.51612903 3.90322581 15.56087142 1.15560871
-6.51612903 4.19354839 15.88989883 1.15889899
-6.51612903 4.48387097 16.18964589 1.16189646
-6.51612903 4.77419355 16.47201646 1.16472016
-6.51612903 5.06451613 16.74347970 1.16743480
-6.51612903 5.35483871 17.01334871 1.17013349
-6.51612903 5.64516129 17.28681907 1.17286819
-6.51612903 5.93548387 17.57263541 1.17572635
-6.51612903 6.22580645 17.88214034 1.17882140
-6.51612903 6.51612903 18.22999587 1.18229996
-6.51612903 6.80645161 18.65108897 1.18651089
-6.51612903 7.09677419 19.04189908 1.19041899
-6.51612903 7.38709677 19.04189908 1.19041899
-6.51612903 7.67741935 19.04189908 1.19041899
-6.51612903 7.96774194 19.04189908 1.19041899
-6.51612903 8.25806452 19.04189908 1.19041899
-6.51612903 8.54838710 19.04189908 1.19041899
-6.51612903 8.83870968 19.04189908 1.19041899
-6.51612903 9.12903226 19.04189908 1.19041899
-6.51612903 9.41935484 19.04189908 1.19041899
-6.51612903 9.70967742 19.04189908 1.19041899
-6.51612903 10.00000000 19.04189908 1.19041899
-6.80645161 1.00000000 14.52492871 1.14524929
-6.80645161 1.29032258 14.52492871 1.14524929
-6.80645161 1.58064516 14.52492871 1.14524929
-6.80645161 1.87096774 14.52492871 1.14524929
-6.80645161 2.16129032 14.52492871 1.14524929
-6.80645161 2.45161290 14.52492871 1.14524929
-6.80645161 2.74193548 14.52492871 1.14524929
-6.80645161 3.03225806 14.62674650 1.14626746
-6.80645161 3.32258065 15.23916402 1.15239164
-6.80645161 3.61290323 15.68154801 1.15681548
-6.80645161 3.90322581 16.04390018 1.16043900
-6.80645161 4.19354839 16.36071096 1.16360711
-6.80645161 4.48387097 16.64650295 1.16646503
-6.80645161 4.77419355 16.91532876 1.16915329
-6.80645161 5.06451613 17.17503189 1.17175032
-6.80645161 5.35483871 17.43409709 1.17434097
-6.80645161 5.64516129 17.70002087 1.17700021
-6.80645161 5.93548387 17.98210647 1.17982106
-6.80645161 6.22580645 18.29211153 1.18292112
-6.80645161 6.51612903 18.65108897 1.18651089
-6.80645161 6.80645161 19.09888025 1.19098880
-6.80645161 7.09677419 19.52496415 1.19524964
-6.80645161 7.38709677 19.52496415 1.19524964
-6.80645161 7.67741935 19.52496415 1.19524964
-6.80645161 7.96774194 19.52496415 1.19524964
-6.80645161 8.25806452 19.52496415 1.19524964
-6.80645161 8.54838710 19.52496415 1.19524964
-6.80645161 8.83870968 19.52496415 1.19524964
-6.80645161 9.12903226 19.52496415 1.19524964
-6.80645161 9.41935484 19.52496415 1.19524964
-6.80645161 9.70967742 19.52496415 1.19524964
-6.80645161 10.00000000 19.52496415 1.19524964
-7.09677419 1.00000000 15.00000000 1.15000000
-7.09677419 1.29032258 15.00000000 1.15000000
-7.09677419 1.58064516 15.00000000 1.15000000
-7.09677419 1.87096774 15.00000000 1.15000000
-7.09677419 2.16129032 15.00000000 1.15000000
-7.09677419 2.45161290 15.00000000 1.15000000
-7.09677419 2.74193548 15.00000000 1.15000000
-7.09677419 3.03225806 15.10357489 1.15103575
-7.09677419 3.32258065 15.70844950 1.15708449
-7.09677419 3.61290323 16.13382374 1.16133824
-7.09677419 3.90322581 16.47922769 1.16479228
-7.09677419 4.19354839 16.77845274 1.16778453
-7.09677419 4.48387097 17.05002382 1.17050024
-7.09677419 4.77419355 17.30571907 1.17305719
-7.09677419 5.06451613 17.55554644 1.17555546
-7.09677419 5.35483871 17.80639865 1.17806399
-7.09677419 5.64516129 18.06809818 1.18068098
-7.09677419 5.93548387 18.34996260 1.18349963
-7.09677419 6.22580645 18.66701771 1.18667018
-7.09677419 6.51612903 19.04189908 1.19041899
-7.09677419 6.80645161 19.52496415 1.19524964
-7.09677419 7.09677419 19.99999704 1.19999997
-7.09677419 7.38709677 19.99999704 1.19999997
-7.09677419 7.67741935 19.99999704 1.19999997
-7.09677419 7.96774194 19.99999704 1.19999997
-7.09677419 8.25806452 19.99999704 1.19999997
-7.09677419 8.54838710 19.99999704 1.19999997
-7.09677419 8.83870968 19.99999704 1.19999997
-7.09677419 9.12903226 19.99999704 1.19999997
-7.09677419 9.41935484 19.99999704 1.19999997
-7.09677419 9.70967742 19.99999704 1.19999997
-7.09677419 10.00000000 19.99999704 1.19999997
-7.38709677 1.00000000 15.00000000 1.15000000
-7.38709677 1.29032258 15.00000000 1.15000000
-7.38709677 1.58064516 15.00000000 1.15000000
-7.38709677 1.87096774 15.00000000 1.15000000
-7.38709677 2.16129032 15.00000000 1.15000000
-7.38709677 2.45161290 15.00000000 1.15000000
-7.38709677 2.74193548 15.00000000 1.15000000
-7.38709677 3.03225806 15.10357489 1.15103575
-7.38709677 3.32258065 15.70844950 1.15708449
-7.38709677 3.61290323 16.13382374 1.16133824
-7.38709677 3.90322581 16.47922769 1.16479228
-7.38709677 4.19354839 16.77845274 1.16778453
-7.38709677 4.48387097 17.05002382 1.17050024
-7.38709677 4.77419355 17.30571907 1.17305719
-7.38709677 5.06451613 17.55554644 1.17555546
-7.38709677 5.35483871 17.80639865 1.17806399
-7.38709677 5.64516129 18.06809818 1.18068098
-7.38709677 5.93548387 18.34996260 1.18349963
-7.38709677 6.22580645 18.66701771 1.18667018
-7.38709677 6.51612903 19.04189908 1.19041899
-7.38709677 6.80645161 19.52496415 1.19524964
-7.38709677 7.09677419 19.99999704 1.19999997
-7.38709677 7.38709677 19.99999704 1.19999997
-7.38709677 7.67741935 19.99999704 1.19999997
-7.38709677 7.96774194 19.99999704 1.19999997
-7.38709677 8.25806452 19.99999704 1.19999997
-7.38709677 8.54838710 19.99999704 1.19999997
-7.38709677 8.83870968 19.99999704 1.19999997
-7.38709677 9.12903226 19.99999704 1.19999997
-7.38709677 9.41935484 19.99999704 1.19999997
-7.38709677 9.70967742 19.99999704 1.19999997
-7.38709677 10.00000000 19.99999704 1.19999997
-7.67741935 1.00000000 15.00000000 1.15000000
-7.67741935 1.29032258 15.00000000 1.15000000
-7.67741935 1.58064516 15.00000000 1.15000000
-7.67741935 1.87096774 15.00000000 1.15000000
-7.67741935 2.16129032 15.00000000 1.15000000
-7.67741935 2.45161290 15.00000000 1.15000000
-7.67741935 2.74193548 15.00000000 1.15000000
-7.67741935 3.03225806 15.10357489 1.15103575
-7.67741935 3.32258065 15.70844950 1.15708449
-7.67741935 3.61290323 16.13382374 1.16133824
-7.67741935 3.90322581 16.47922769 1.16479228
-7.67741935 4.19354839 16.77845274 1.16778453
-7.67741935 4.48387097 17.05002382 1.17050024
-7.67741935 4.77419355 17.30571907 1.17305719
-7.67741935 5.06451613 17.55554644 1.17555546
-7.67741935 5.35483871 17.80639865 1.17806399
-7.67741935 5.64516129 18.06809818 1.18068098
-7.67741935 5.93548387 18.34996260 1.18349963
-7.67741935 6.22580645 18.66701771 1.18667018
-7.67741935 6.51612903 19.04189908 1.19041899
-7.67741935 6.80645161 19.52496415 1.19524964
-7.67741935 7.09677419 19.99999704 1.19999997
-7.67741935 7.38709677 19.99999704 1.19999997
-7.67741935 7.67741935 19.99999704 1.19999997
-7.67741935 7.96774194 19.99999704 1.19999997
-7.67741935 8.25806452 19.99999704 1.19999997
-7.67741935 8.54838710 19.99999704 1.19999997
-7.67741935 8.83870968 19.99999704 1.19999997
-7.67741935 9.12903226 19.99999704 1.19999997
-7.67741935 9.41935484 19.99999704 1.19999997
-7.67741935 9.70967742 19.99999704 1.19999997
-7.67741935 10.00000000 19.99999704 1.19999997
-7.96774194 1.00000000 15.00000000 1.15000000
-7.96774194 1.29032258 15.00000000 1.15000000
-7.96774194 1.58064516 15.00000000 1.15000000
-7.96774194 1.87096774 15.00000000 1.15000000
-7.96774194 2.16129032 15.00000000 1.15000000
-7.96774194 2.45161290 15.00000000 1.15000000
-7.96774194 2.74193548 15.00000000 1.15000000
-7.96774194 3.03225806 15.10357489 1.15103575
-7.96774194 3.32258065 15.70844950 1.15708449
-7.96774194 3.61290323 16.13382374 1.16133824
-7.96774194 3.90322581 16.47922769 1.16479228
-7.96774194 4.19354839 16.77845274 1.16778453
-7.96774194 4.48387097 17.05002382 1.17050024
-7.96774194 4.77419355 17.30571907 1.17305719
-7.96774194 5.06451613 17.55554644 1.17555546
-7.96774194 5.35483871 17.80639865 1.17806399
-7.96774194 5.64516129 18.06809818 1.18068098
-7.96774194 5.93548387 18.34996260 1.18349963
-7.96774194 6.22580645 18.66701771 1.18667018
-7.96774194 6.51612903 19.04189908 1.19041899
-7.96774194 6.80645161 19.52496415 1.19524964
-7.96774194 7.09677419 19.99999704 1.19999997
-7.96774194 7.38709677 19.99999704 1.19999997
-7.96774194 7.67741935 19.99999704 1.19999997
-7.96774194 7.96774194 19.99999704 1.19999997
-7.96774194 8.25806452 19.99999704 1.19999997
-7.96774194 8.54838710 19.99999704 1.19999997
-7.96774194 8.83870968 19.99999704 1.19999997
-7.96774194 9.12903226 19.99999704 1.19999997
-7.96774194 9.41935484 19.99999704 1.19999997
-7.96774194 9.70967742 19.99999704 1.19999997
-7.96774194 10.00000000 19.99999704 1.19999997
-8.25806452 1.00000000 15.00000000 1.15000000
-8.25806452 1.29032258 15.00000000 1.15000000
-8.25806452 1.58064516 15.00000000 1.15000000
-8.25806452 1.87096774 15.00000000 1.15000000
-8.25806452 2.16129032 15.00000000 1.15000000
-8.25806452 2.45161290 15.00000000 1.15000000
-8.25806452 2.74193548 15.00000000 1.15000000
-8.25806452 3.03225806 15.10357489 1.15103575
-8.25806452 3.32258065 15.70844950 1.15708449
-8.25806452 3.61290323 16.13382374 1.16133824
-8.25806452 3.90322581 16.47922769 1.16479228
-8.25806452 4.19354839 16.77845274 1.16778453
-8.25806452 4.48387097 17.05002382 1.17050024
-8.25806452 4.77419355 17.30571907 1.17305719
-8.25806452 5.06451613 17.55554644 1.17555546
-8.25806452 5.35483871 17.80639865 1.17806399
-8.25806452 5.64516129 18.06809818 1.18068098
-8.25806452 5.93548387 18.34996260 1.18349963
-8.25806452 6.22580645 18.66701771 1.18667018
-8.25806452 6.51612903 19.04189908 1.19041899
-8.25806452 6.80645161 19.52496415 1.19524964
-8.25806452 7.09677419 19.99999704 1.19999997
-8.25806452 7.38709677 19.99999704 1.19999997
-8.25806452 7.67741935 19.99999704 1.19999997
-8.25806452 7.96774194 19.99999704 1.19999997
-8.25806452 8.25806452 19.99999704 1.19999997
-8.25806452 8.54838710 19.99999704 1.19999997
-8.25806452 8.83870968 19.99999704 1.19999997
-8.25806452 9.12903226 19.99999704 1.19999997
-8.25806452 9.41935484 19.99999704 1.19999997
-8.25806452 9.70967742 19.99999704 1.19999997
-8.25806452 10.00000000 19.99999704 1.19999997
-8.54838710 1.00000000 15.00000000 1.15000000
-8.54838710 1.29032258 15.00000000 1.15000000
-8.54838710 1.58064516 15.00000000 1.15000000
-8.54838710 1.87096774 15.00000000 1.15000000
-8.54838710 2.16129032 15.00000000 1.15000000
-8.54838710 2.45161290 15.00000000 1.15000000
-8.54838710 2.74193548 15.00000000 1.15000000
-8.54838710 3.03225806 15.10357489 1.15103575
-8.54838710 3.32258065 15.70844950 1.15708449
-8.54838710 3.61290323 16.13382374 1.16133824
-8.54838710 3.90322581 16.47922769 1.16479228
-8.54838710 4.19354839 16.77845274 1.16778453
-8.54838710 4.48387097 17.05002382 1.17050024
-8.54838710 4.77419355 17.30571907 1.17305719
-8.54838710 5.06451613 17.55554644 1.17555546
-8.54838710 5.35483871 17.80639865 1.17806399
-8.54838710 5.64516129 18.06809818 1.18068098
-8.54838710 5.93548387 18.34996260 1.18349963
-8.54838710 6.22580645 18.66701771 1.18667018
-8.54838710 6.51612903 19.04189908 1.19041899
-8.54838710 6.80645161 19.52496415 1.19524964
-8.54838710 7.09677419 19.99999704 1.19999997
-8.54838710 7.38709677 19.99999704 1.19999997
-8.54838710 7.67741935 19.99999704 1.19999997
-8.54838710 7.96774194 19.99999704 1.19999997
-8.54838710 8.25806452 19.99999704 1.19999997
-8.54838710 8.54838710 19.99999704 1.19999997
-8.54838710 8.83870968 19.99999704 1.19999997
-8.54838710 9.12903226 19.99999704 1.19999997
-8.54838710 9.41935484 19.99999704 1.19999997
-8.54838710 9.70967742 19.99999704 1.19999997
-8.54838710 10.00000000 19.99999704 1.19999997
-8.83870968 1.00000000 15.00000000 1.15000000
-8.83870968 1.29032258 15.00000000 1.15000000
-8.83870968 1.58064516 15.00000000 1.15000000
-8.83870968 1.87096774 15.00000000 1.15000000
-8.83870968 2.16129032 15.00000000 1.15000000
-8.83870968 2.45161290 15.00000000 1.15000000
-8.83870968 2.74193548 15.00000000 1.15000000
-8.83870968 3.03225806 15.10357489 1.15103575
-8.83870968 3.32258065 15.70844950 1.15708449
-8.83870968 3.61290323 16.13382374 1.16133824
-8.83870968 3.90322581 16.47922769 1.16479228
-8.83870968 4.19354839 16.77845274 1.16778453
-8.83870968 4.48387097 17.05002382 1.17050024
-8.83870968 4.77419355 17.30571907 1.17305719
-8.83870968 5.06451613 17.55554644 1.17555546
-8.83870968 5.35483871 17.80639865 1.17806399
-8.83870968 5.64516129 18.06809818 1.18068098
-8.83870968 5.93548387 18.34996260 1.18349963
-8.83870968 6.22580645 18.66701771 1.18667018
-8.83870968 6.51612903 19.04189908 1.19041899
-8.83870968 6.80645161 19.52496415 1.19524964
-8.83870968 7.09677419 19.99999704 1.19999997
-8.83870968 7.38709677 19.99999704 1.19999997
-8.83870968 7.67741935 19.99999704 1.19999997
-8.83870968 7.96774194 19.99999704 1.19999997
-8.83870968 8.25806452 19.99999704 1.19999997
-8.83870968 8.54838710 19.99999704 1.19999997
-8.83870968 8.83870968 19.99999704 1.19999997
-8.83870968 9.12903226 19.99999704 1.19999997
-8.83870968 9.41935484 19.99999704 1.19999997
-8.83870968 9.70967742 19.99999704 1.19999997
-8.83870968 10.00000000 19.99999704 1.19999997
-9.12903226 1.00000000 15.00000000 1.15000000
-9.12903226 1.29032258 15.00000000 1.15000000
-9.12903226 1.58064516 15.00000000 1.15000000
-9.12903226 1.87096774 15.00000000 1.15000000
-9.12903226 2.16129032 15.00000000 1.15000000
-9.12903226 2.45161290 15.00000000 1.15000000
-9.12903226 2.74193548 15.00000000 1.15000000
-9.12903226 3.03225806 15.10357489 1.15103575
-9.12903226 3.32258065 15.70844950 1.15708449
-9.12903226 3.61290323 16.13382374 1.16133824
-9.12903226 3.90322581 16.47922769 1.16479228
-9.12903226 4.19354839 16.77845274 1.16778453
-9.12903226 4.48387097 17.05002382 1.17050024
-9.12903226 4.77419355 17.30571907 1.17305719
-9.12903226 5.06451613 17.55554644 1.17555546
-9.12903226 5.35483871 17.80639865 1.17806399
-9.12903226 5.64516129 18.06809818 1.18068098
-9.12903226 5.93548387 18.34996260 1.18349963
-9.12903226 6.22580645 18.66701771 1.18667018
-9.12903226 6.51612903 19.04189908 1.19041899
-9.12903226 6.80645161 19.52496415 1.19524964
-9.12903226 7.09677419 19.99999704 1.19999997
-9.12903226 7.38709677 19.99999704 1.19999997
-9.12903226 7.67741935 19.99999704 1.19999997
-9.12903226 7.96774194 19.99999704 1.19999997
-9.12903226 8.25806452 19.99999704 1.19999997
-9.12903226 8.54838710 19.99999704 1.19999997
-9.12903226 8.83870968 19.99999704 1.19999997
-9.12903226 9.12903226 19.99999704 1.19999997
-9.12903226 9.41935484 19.99999704 1.19999997
-9.12903226 9.70967742 19.99999704 1.19999997
-9.12903226 10.00000000 19.99999704 1.19999997
-9.41935484 1.00000000 15.00000000 1.15000000
-9.41935484 1.29032258 15.00000000 1.15000000
-9.41935484 1.58064516 15.00000000 1.15000000
-9.41935484 1.87096774 15.00000000 1.15000000
-9.41935484 2.16129032 15.00000000 1.15000000
-9.41935484 2.45161290 15.00000000 1.15000000
-9.41935484 2.74193548 15.00000000 1.15000000
-9.41935484 3.03225806 15.10357489 1.15103575
-9.41935484 3.32258065 15.70844950 1.15708449
-9.41935484 3.61290323 16.13382374 1.16133824
-9.41935484 3.90322581 16.47922769 1.16479228
-9.41935484 4.19354839 16.77845274 1.16778453
-9.41935484 4.48387097 17.05002382 1.17050024
-9.41935484 4.77419355 17.30571907 1.17305719
-9.41935484 5.06451613 17.55554644 1.17555546
-9.41935484 5.35483871 17.80639865 1.17806399
-9.41935484 5.64516129 18.06809818 1.18068098
-9.41935484 5.93548387 18.34996260 1.18349963
-9.41935484 6.22580645 18.66701771 1.18667018
-9.41935484 6.51612903 19.04189908 1.19041899
-9.41935484 6.80645161 19.52496415 1.19524964
-9.41935484 7.09677419 19.99999704 1.19999997
-9.41935484 7.38709677 19.99999704 1.19999997
-9.41935484 7.67741935 19.99999704 1.19999997
-9.41935484 7.96774194 19.99999704 1.19999997
-9.41935484 8.25806452 19.99999704 1.19999997
-9.41935484 8.54838710 19.99999704 1.19999997
-9.41935484 8.83870968 19.99999704 1.19999997
-9.41935484 9.12903226 19.99999704 1.19999997
-9.41935484 9.41935484 19.99999704 1.19999997
-9.41935484 9.70967742 19.99999704 1.19999997
-9.41935484 10.00000000 19.99999704 1.19999997
-9.70967742 1.00000000 15.00000000 1.15000000
-9.70967742 1.29032258 15.00000000 1.15000000
-9.70967742 1.58064516 15.00000000 1.15000000
-9.70967742 1.87096774 15.00000000 1.15000000
-9.70967742 2.16129032 15.00000000 1.15000000
-9.70967742 2.45161290 15.00000000 1.15000000
-9.70967742 2.74193548 15.00000000 1.15000000
-9.70967742 3.03225806 15.10357489 1.15103575
-9.70967742 3.32258065 15.70844950 1.15708449
-9.70967742 3.61290323 16.13382374 1.16133824
-9.70967742 3.90322581 16.47922769 1.16479228
-9.70967742 4.19354839 16.77845274 1.16778453
-9.70967742 4.48387097 17.05002382 1.17050024
-9.70967742 4.77419355 17.30571907 1.17305719
-9.70967742 5.06451613 17.55554644 1.17555546
-9.70967742 5.35483871 17.80639865 1.17806399
-9.70967742 5.64516129 18.06809818 1.18068098
-9.70967742 5.93548387 18.34996260 1.18349963
-9.70967742 6.22580645 18.66701771 1.18667018
-9.70967742 6.51612903 19.04189908 1.19041899
-9.70967742 6.80645161 19.52496415 1.19524964
-9.70967742 7.09677419 19.99999704 1.19999997
-9.70967742 7.38709677 19.99999704 1.19999997
-9.70967742 7.67741935 19.99999704 1.19999997
-9.70967742 7.96774194 19.99999704 1.19999997
-9.70967742 8.25806452 19.99999704 1.19999997
-9.70967742 8.54838710 19.99999704 1.19999997
-9.70967742 8.83870968 19.99999704 1.19999997
-9.70967742 9.12903226 19.99999704 1.19999997
-9.70967742 9.41935484 19.99999704 1.19999997
-9.70967742 9.70967742 19.99999704 1.19999997
-9.70967742 10.00000000 19.99999704 1.19999997
-10.00000000 1.00000000 15.00000000 1.15000000
-10.00000000 1.29032258 15.00000000 1.15000000
-10.00000000 1.58064516 15.00000000 1.15000000
-10.00000000 1.87096774 15.00000000 1.15000000
-10.00000000 2.16129032 15.00000000 1.15000000
-10.00000000 2.45161290 15.00000000 1.15000000
-10.00000000 2.74193548 15.00000000 1.15000000
-10.00000000 3.03225806 15.10357489 1.15103575
-10.00000000 3.32258065 15.70844950 1.15708449
-10.00000000 3.61290323 16.13382374 1.16133824
-10.00000000 3.90322581 16.47922769 1.16479228
-10.00000000 4.19354839 16.77845274 1.16778453
-10.00000000 4.48387097 17.05002382 1.17050024
-10.00000000 4.77419355 17.30571907 1.17305719
-10.00000000 5.06451613 17.55554644 1.17555546
-10.00000000 5.35483871 17.80639865 1.17806399
-10.00000000 5.64516129 18.06809818 1.18068098
-10.00000000 5.93548387 18.34996260 1.18349963
-10.00000000 6.22580645 18.66701771 1.18667018
-10.00000000 6.51612903 19.04189908 1.19041899
-10.00000000 6.80645161 19.52496415 1.19524964
-10.00000000 7.09677419 19.99999704 1.19999997
-10.00000000 7.38709677 19.99999704 1.19999997
-10.00000000 7.67741935 19.99999704 1.19999997
-10.00000000 7.96774194 19.99999704 1.19999997
-10.00000000 8.25806452 19.99999704 1.19999997
-10.00000000 8.54838710 19.99999704 1.19999997
-10.00000000 8.83870968 19.99999704 1.19999997
-10.00000000 9.12903226 19.99999704 1.19999997
-10.00000000 9.41935484 19.99999704 1.19999997
-10.00000000 9.70967742 19.99999704 1.19999997
-10.00000000 10.00000000 19.99999704 1.19999997
+FoodQuality Service Tip CheckPlusTip
+1.000000000 1.000000000 10.000002957 1.100000030
+1.000000000 1.290322581 10.000002957 1.100000030
+1.000000000 1.580645161 10.000002957 1.100000030
+1.000000000 1.870967742 10.000002957 1.100000030
+1.000000000 2.161290323 10.000002957 1.100000030
+1.000000000 2.451612903 10.000002957 1.100000030
+1.000000000 2.741935484 10.000002957 1.100000030
+1.000000000 3.032258065 10.103612040 1.101036120
+1.000000000 3.322580645 10.708467388 1.107084674
+1.000000000 3.612903226 11.133945555 1.111339456
+1.000000000 3.903225806 11.479248807 1.114792488
+1.000000000 4.193548387 11.778370516 1.117783705
+1.000000000 4.483870968 12.050104922 1.120501049
+1.000000000 4.774193548 12.305762763 1.123057628
+1.000000000 5.064516129 12.555175445 1.125551754
+1.000000000 5.354838710 12.806659860 1.128066599
+1.000000000 5.645161290 13.068093230 1.130680932
+1.000000000 5.935483871 13.350561957 1.133505620
+1.000000000 6.225806452 13.666570669 1.136665707
+1.000000000 6.516129032 14.042124914 1.140421249
+1.000000000 6.806451613 14.524928709 1.145249287
+1.000000000 7.096774194 15.000000000 1.150000000
+1.000000000 7.387096774 15.000000000 1.150000000
+1.000000000 7.677419355 15.000000000 1.150000000
+1.000000000 7.967741935 15.000000000 1.150000000
+1.000000000 8.258064516 15.000000000 1.150000000
+1.000000000 8.548387097 15.000000000 1.150000000
+1.000000000 8.838709677 15.000000000 1.150000000
+1.000000000 9.129032258 15.000000000 1.150000000
+1.000000000 9.419354839 15.000000000 1.150000000
+1.000000000 9.709677419 15.000000000 1.150000000
+1.000000000 10.000000000 15.000000000 1.150000000
+1.290322581 1.000000000 10.000002957 1.100000030
+1.290322581 1.290322581 10.000002957 1.100000030
+1.290322581 1.580645161 10.000002957 1.100000030
+1.290322581 1.870967742 10.000002957 1.100000030
+1.290322581 2.161290323 10.000002957 1.100000030
+1.290322581 2.451612903 10.000002957 1.100000030
+1.290322581 2.741935484 10.000002957 1.100000030
+1.290322581 3.032258065 10.103612040 1.101036120
+1.290322581 3.322580645 10.708467388 1.107084674
+1.290322581 3.612903226 11.133945555 1.111339456
+1.290322581 3.903225806 11.479248807 1.114792488
+1.290322581 4.193548387 11.778370516 1.117783705
+1.290322581 4.483870968 12.050104922 1.120501049
+1.290322581 4.774193548 12.305762763 1.123057628
+1.290322581 5.064516129 12.555175445 1.125551754
+1.290322581 5.354838710 12.806659860 1.128066599
+1.290322581 5.645161290 13.068093230 1.130680932
+1.290322581 5.935483871 13.350561957 1.133505620
+1.290322581 6.225806452 13.666570669 1.136665707
+1.290322581 6.516129032 14.042124914 1.140421249
+1.290322581 6.806451613 14.524928709 1.145249287
+1.290322581 7.096774194 15.000000000 1.150000000
+1.290322581 7.387096774 15.000000000 1.150000000
+1.290322581 7.677419355 15.000000000 1.150000000
+1.290322581 7.967741935 15.000000000 1.150000000
+1.290322581 8.258064516 15.000000000 1.150000000
+1.290322581 8.548387097 15.000000000 1.150000000
+1.290322581 8.838709677 15.000000000 1.150000000
+1.290322581 9.129032258 15.000000000 1.150000000
+1.290322581 9.419354839 15.000000000 1.150000000
+1.290322581 9.709677419 15.000000000 1.150000000
+1.290322581 10.000000000 15.000000000 1.150000000
+1.580645161 1.000000000 10.000002957 1.100000030
+1.580645161 1.290322581 10.000002957 1.100000030
+1.580645161 1.580645161 10.000002957 1.100000030
+1.580645161 1.870967742 10.000002957 1.100000030
+1.580645161 2.161290323 10.000002957 1.100000030
+1.580645161 2.451612903 10.000002957 1.100000030
+1.580645161 2.741935484 10.000002957 1.100000030
+1.580645161 3.032258065 10.103612040 1.101036120
+1.580645161 3.322580645 10.708467388 1.107084674
+1.580645161 3.612903226 11.133945555 1.111339456
+1.580645161 3.903225806 11.479248807 1.114792488
+1.580645161 4.193548387 11.778370516 1.117783705
+1.580645161 4.483870968 12.050104922 1.120501049
+1.580645161 4.774193548 12.305762763 1.123057628
+1.580645161 5.064516129 12.555175445 1.125551754
+1.580645161 5.354838710 12.806659860 1.128066599
+1.580645161 5.645161290 13.068093230 1.130680932
+1.580645161 5.935483871 13.350561957 1.133505620
+1.580645161 6.225806452 13.666570669 1.136665707
+1.580645161 6.516129032 14.042124914 1.140421249
+1.580645161 6.806451613 14.524928709 1.145249287
+1.580645161 7.096774194 15.000000000 1.150000000
+1.580645161 7.387096774 15.000000000 1.150000000
+1.580645161 7.677419355 15.000000000 1.150000000
+1.580645161 7.967741935 15.000000000 1.150000000
+1.580645161 8.258064516 15.000000000 1.150000000
+1.580645161 8.548387097 15.000000000 1.150000000
+1.580645161 8.838709677 15.000000000 1.150000000
+1.580645161 9.129032258 15.000000000 1.150000000
+1.580645161 9.419354839 15.000000000 1.150000000
+1.580645161 9.709677419 15.000000000 1.150000000
+1.580645161 10.000000000 15.000000000 1.150000000
+1.870967742 1.000000000 10.000002957 1.100000030
+1.870967742 1.290322581 10.000002957 1.100000030
+1.870967742 1.580645161 10.000002957 1.100000030
+1.870967742 1.870967742 10.000002957 1.100000030
+1.870967742 2.161290323 10.000002957 1.100000030
+1.870967742 2.451612903 10.000002957 1.100000030
+1.870967742 2.741935484 10.000002957 1.100000030
+1.870967742 3.032258065 10.103612040 1.101036120
+1.870967742 3.322580645 10.708467388 1.107084674
+1.870967742 3.612903226 11.133945555 1.111339456
+1.870967742 3.903225806 11.479248807 1.114792488
+1.870967742 4.193548387 11.778370516 1.117783705
+1.870967742 4.483870968 12.050104922 1.120501049
+1.870967742 4.774193548 12.305762763 1.123057628
+1.870967742 5.064516129 12.555175445 1.125551754
+1.870967742 5.354838710 12.806659860 1.128066599
+1.870967742 5.645161290 13.068093230 1.130680932
+1.870967742 5.935483871 13.350561957 1.133505620
+1.870967742 6.225806452 13.666570669 1.136665707
+1.870967742 6.516129032 14.042124914 1.140421249
+1.870967742 6.806451613 14.524928709 1.145249287
+1.870967742 7.096774194 15.000000000 1.150000000
+1.870967742 7.387096774 15.000000000 1.150000000
+1.870967742 7.677419355 15.000000000 1.150000000
+1.870967742 7.967741935 15.000000000 1.150000000
+1.870967742 8.258064516 15.000000000 1.150000000
+1.870967742 8.548387097 15.000000000 1.150000000
+1.870967742 8.838709677 15.000000000 1.150000000
+1.870967742 9.129032258 15.000000000 1.150000000
+1.870967742 9.419354839 15.000000000 1.150000000
+1.870967742 9.709677419 15.000000000 1.150000000
+1.870967742 10.000000000 15.000000000 1.150000000
+2.161290323 1.000000000 10.000002957 1.100000030
+2.161290323 1.290322581 10.000002957 1.100000030
+2.161290323 1.580645161 10.000002957 1.100000030
+2.161290323 1.870967742 10.000002957 1.100000030
+2.161290323 2.161290323 10.000002957 1.100000030
+2.161290323 2.451612903 10.000002957 1.100000030
+2.161290323 2.741935484 10.000002957 1.100000030
+2.161290323 3.032258065 10.103612040 1.101036120
+2.161290323 3.322580645 10.708467388 1.107084674
+2.161290323 3.612903226 11.133945555 1.111339456
+2.161290323 3.903225806 11.479248807 1.114792488
+2.161290323 4.193548387 11.778370516 1.117783705
+2.161290323 4.483870968 12.050104922 1.120501049
+2.161290323 4.774193548 12.305762763 1.123057628
+2.161290323 5.064516129 12.555175445 1.125551754
+2.161290323 5.354838710 12.806659860 1.128066599
+2.161290323 5.645161290 13.068093230 1.130680932
+2.161290323 5.935483871 13.350561957 1.133505620
+2.161290323 6.225806452 13.666570669 1.136665707
+2.161290323 6.516129032 14.042124914 1.140421249
+2.161290323 6.806451613 14.524928709 1.145249287
+2.161290323 7.096774194 15.000000000 1.150000000
+2.161290323 7.387096774 15.000000000 1.150000000
+2.161290323 7.677419355 15.000000000 1.150000000
+2.161290323 7.967741935 15.000000000 1.150000000
+2.161290323 8.258064516 15.000000000 1.150000000
+2.161290323 8.548387097 15.000000000 1.150000000
+2.161290323 8.838709677 15.000000000 1.150000000
+2.161290323 9.129032258 15.000000000 1.150000000
+2.161290323 9.419354839 15.000000000 1.150000000
+2.161290323 9.709677419 15.000000000 1.150000000
+2.161290323 10.000000000 15.000000000 1.150000000
+2.451612903 1.000000000 10.000002957 1.100000030
+2.451612903 1.290322581 10.000002957 1.100000030
+2.451612903 1.580645161 10.000002957 1.100000030
+2.451612903 1.870967742 10.000002957 1.100000030
+2.451612903 2.161290323 10.000002957 1.100000030
+2.451612903 2.451612903 10.000002957 1.100000030
+2.451612903 2.741935484 10.000002957 1.100000030
+2.451612903 3.032258065 10.103612040 1.101036120
+2.451612903 3.322580645 10.708467388 1.107084674
+2.451612903 3.612903226 11.133945555 1.111339456
+2.451612903 3.903225806 11.479248807 1.114792488
+2.451612903 4.193548387 11.778370516 1.117783705
+2.451612903 4.483870968 12.050104922 1.120501049
+2.451612903 4.774193548 12.305762763 1.123057628
+2.451612903 5.064516129 12.555175445 1.125551754
+2.451612903 5.354838710 12.806659860 1.128066599
+2.451612903 5.645161290 13.068093230 1.130680932
+2.451612903 5.935483871 13.350561957 1.133505620
+2.451612903 6.225806452 13.666570669 1.136665707
+2.451612903 6.516129032 14.042124914 1.140421249
+2.451612903 6.806451613 14.524928709 1.145249287
+2.451612903 7.096774194 15.000000000 1.150000000
+2.451612903 7.387096774 15.000000000 1.150000000
+2.451612903 7.677419355 15.000000000 1.150000000
+2.451612903 7.967741935 15.000000000 1.150000000
+2.451612903 8.258064516 15.000000000 1.150000000
+2.451612903 8.548387097 15.000000000 1.150000000
+2.451612903 8.838709677 15.000000000 1.150000000
+2.451612903 9.129032258 15.000000000 1.150000000
+2.451612903 9.419354839 15.000000000 1.150000000
+2.451612903 9.709677419 15.000000000 1.150000000
+2.451612903 10.000000000 15.000000000 1.150000000
+2.741935484 1.000000000 10.000002957 1.100000030
+2.741935484 1.290322581 10.000002957 1.100000030
+2.741935484 1.580645161 10.000002957 1.100000030
+2.741935484 1.870967742 10.000002957 1.100000030
+2.741935484 2.161290323 10.000002957 1.100000030
+2.741935484 2.451612903 10.000002957 1.100000030
+2.741935484 2.741935484 10.000002957 1.100000030
+2.741935484 3.032258065 10.103612040 1.101036120
+2.741935484 3.322580645 10.708467388 1.107084674
+2.741935484 3.612903226 11.133945555 1.111339456
+2.741935484 3.903225806 11.479248807 1.114792488
+2.741935484 4.193548387 11.778370516 1.117783705
+2.741935484 4.483870968 12.050104922 1.120501049
+2.741935484 4.774193548 12.305762763 1.123057628
+2.741935484 5.064516129 12.555175445 1.125551754
+2.741935484 5.354838710 12.806659860 1.128066599
+2.741935484 5.645161290 13.068093230 1.130680932
+2.741935484 5.935483871 13.350561957 1.133505620
+2.741935484 6.225806452 13.666570669 1.136665707
+2.741935484 6.516129032 14.042124914 1.140421249
+2.741935484 6.806451613 14.524928709 1.145249287
+2.741935484 7.096774194 15.000000000 1.150000000
+2.741935484 7.387096774 15.000000000 1.150000000
+2.741935484 7.677419355 15.000000000 1.150000000
+2.741935484 7.967741935 15.000000000 1.150000000
+2.741935484 8.258064516 15.000000000 1.150000000
+2.741935484 8.548387097 15.000000000 1.150000000
+2.741935484 8.838709677 15.000000000 1.150000000
+2.741935484 9.129032258 15.000000000 1.150000000
+2.741935484 9.419354839 15.000000000 1.150000000
+2.741935484 9.709677419 15.000000000 1.150000000
+2.741935484 10.000000000 15.000000000 1.150000000
+3.032258065 1.000000000 10.103612040 1.101036120
+3.032258065 1.290322581 10.103612040 1.101036120
+3.032258065 1.580645161 10.103612040 1.101036120
+3.032258065 1.870967742 10.103612040 1.101036120
+3.032258065 2.161290323 10.103612040 1.101036120
+3.032258065 2.451612903 10.103612040 1.101036120
+3.032258065 2.741935484 10.103612040 1.101036120
+3.032258065 3.032258065 10.204358113 1.102043581
+3.032258065 3.322580645 10.796018218 1.107960182
+3.032258065 3.612903226 11.215358735 1.112153587
+3.032258065 3.903225806 11.557846462 1.115578465
+3.032258065 4.193548387 11.855790361 1.118557904
+3.032258065 4.483870968 12.127240434 1.121272404
+3.032258065 4.774193548 12.384052580 1.123840526
+3.032258065 5.064516129 12.634997421 1.126349974
+3.032258065 5.354838710 12.888585631 1.128885856
+3.032258065 5.645161290 13.153230669 1.131532307
+3.032258065 5.935483871 13.438880990 1.134388810
+3.032258065 6.225806452 13.759265462 1.137592655
+3.032258065 6.516129032 14.139344845 1.141393448
+3.032258065 6.806451613 14.626746497 1.146267465
+3.032258065 7.096774194 15.103574890 1.151035749
+3.032258065 7.387096774 15.103574890 1.151035749
+3.032258065 7.677419355 15.103574890 1.151035749
+3.032258065 7.967741935 15.103574890 1.151035749
+3.032258065 8.258064516 15.103574890 1.151035749
+3.032258065 8.548387097 15.103574890 1.151035749
+3.032258065 8.838709677 15.103574890 1.151035749
+3.032258065 9.129032258 15.103574890 1.151035749
+3.032258065 9.419354839 15.103574890 1.151035749
+3.032258065 9.709677419 15.103574890 1.151035749
+3.032258065 10.000000000 15.103574890 1.151035749
+3.322580645 1.000000000 10.708467388 1.107084674
+3.322580645 1.290322581 10.708467388 1.107084674
+3.322580645 1.580645161 10.708467388 1.107084674
+3.322580645 1.870967742 10.708467388 1.107084674
+3.322580645 2.161290323 10.708467388 1.107084674
+3.322580645 2.451612903 10.708467388 1.107084674
+3.322580645 2.741935484 10.708467388 1.107084674
+3.322580645 3.032258065 10.796018218 1.107960182
+3.322580645 3.322580645 11.322661747 1.113226617
+3.322580645 3.612903226 11.712913158 1.117129132
+3.322580645 3.903225806 12.043415217 1.120434152
+3.322580645 4.193548387 12.339709404 1.123397094
+3.322580645 4.483870968 12.615733153 1.126157332
+3.322580645 4.774193548 12.881223868 1.128812239
+3.322580645 5.064516129 13.144835022 1.131448350
+3.322580645 5.354838710 13.414082467 1.134140825
+3.322580645 5.645161290 13.696138923 1.136961389
+3.322580645 5.935483871 14.000777693 1.140007777
+3.322580645 6.225806452 14.342258539 1.143422585
+3.322580645 6.516129032 14.739964250 1.147399642
+3.322580645 6.806451613 15.239164015 1.152391640
+3.322580645 7.096774194 15.708449495 1.157084495
+3.322580645 7.387096774 15.708449495 1.157084495
+3.322580645 7.677419355 15.708449495 1.157084495
+3.322580645 7.967741935 15.708449495 1.157084495
+3.322580645 8.258064516 15.708449495 1.157084495
+3.322580645 8.548387097 15.708449495 1.157084495
+3.322580645 8.838709677 15.708449495 1.157084495
+3.322580645 9.129032258 15.708449495 1.157084495
+3.322580645 9.419354839 15.708449495 1.157084495
+3.322580645 9.709677419 15.708449495 1.157084495
+3.322580645 10.000000000 15.708449495 1.157084495
+3.612903226 1.000000000 11.133945555 1.111339456
+3.612903226 1.290322581 11.133945555 1.111339456
+3.612903226 1.580645161 11.133945555 1.111339456
+3.612903226 1.870967742 11.133945555 1.111339456
+3.612903226 2.161290323 11.133945555 1.111339456
+3.612903226 2.451612903 11.133945555 1.111339456
+3.612903226 2.741935484 11.133945555 1.111339456
+3.612903226 3.032258065 11.215358735 1.112153587
+3.612903226 3.322580645 11.712913158 1.117129132
+3.612903226 3.612903226 12.090486886 1.120904869
+3.612903226 3.903225806 12.417951094 1.124179511
+3.612903226 4.193548387 12.717020386 1.127170204
+3.612903226 4.483870968 12.999111631 1.129991116
+3.612903226 4.774193548 13.273780609 1.132737806
+3.612903226 5.064516129 13.547717972 1.135477180
+3.612903226 5.354838710 13.827512227 1.138275122
+3.612903226 5.645161290 14.120187657 1.141201877
+3.612903226 5.935483871 14.435371678 1.144353717
+3.612903226 6.225806452 14.784914127 1.147849141
+3.612903226 6.516129032 15.187004870 1.151870049
+3.612903226 6.806451613 15.681548005 1.156815480
+3.612903226 7.096774194 16.133823742 1.161338237
+3.612903226 7.387096774 16.133823742 1.161338237
+3.612903226 7.677419355 16.133823742 1.161338237
+3.612903226 7.967741935 16.133823742 1.161338237
+3.612903226 8.258064516 16.133823742 1.161338237
+3.612903226 8.548387097 16.133823742 1.161338237
+3.612903226 8.838709677 16.133823742 1.161338237
+3.612903226 9.129032258 16.133823742 1.161338237
+3.612903226 9.419354839 16.133823742 1.161338237
+3.612903226 9.709677419 16.133823742 1.161338237
+3.612903226 10.000000000 16.133823742 1.161338237
+3.903225806 1.000000000 11.479248807 1.114792488
+3.903225806 1.290322581 11.479248807 1.114792488
+3.903225806 1.580645161 11.479248807 1.114792488
+3.903225806 1.870967742 11.479248807 1.114792488
+3.903225806 2.161290323 11.479248807 1.114792488
+3.903225806 2.451612903 11.479248807 1.114792488
+3.903225806 2.741935484 11.479248807 1.114792488
+3.903225806 3.032258065 11.557846462 1.115578465
+3.903225806 3.322580645 12.043415217 1.120434152
+3.903225806 3.612903226 12.417951094 1.124179511
+3.903225806 3.903225806 12.746299057 1.127462991
+3.903225806 4.193548387 13.049696353 1.130496964
+3.903225806 4.483870968 13.337970486 1.133379705
+3.903225806 4.774193548 13.620159587 1.136201596
+3.903225806 5.064516129 13.901946604 1.139019466
+3.903225806 5.354838710 14.188883155 1.141888832
+3.903225806 5.645161290 14.489540684 1.144895407
+3.903225806 5.935483871 14.809822020 1.148098220
+3.903225806 6.225806452 15.160748839 1.151607488
+3.903225806 6.516129032 15.560871420 1.155608714
+3.903225806 6.806451613 16.043900181 1.160439002
+3.903225806 7.096774194 16.479227686 1.164792277
+3.903225806 7.387096774 16.479227686 1.164792277
+3.903225806 7.677419355 16.479227686 1.164792277
+3.903225806 7.967741935 16.479227686 1.164792277
+3.903225806 8.258064516 16.479227686 1.164792277
+3.903225806 8.548387097 16.479227686 1.164792277
+3.903225806 8.838709677 16.479227686 1.164792277
+3.903225806 9.129032258 16.479227686 1.164792277
+3.903225806 9.419354839 16.479227686 1.164792277
+3.903225806 9.709677419 16.479227686 1.164792277
+3.903225806 10.000000000 16.479227686 1.164792277
+4.193548387 1.000000000 11.778370516 1.117783705
+4.193548387 1.290322581 11.778370516 1.117783705
+4.193548387 1.580645161 11.778370516 1.117783705
+4.193548387 1.870967742 11.778370516 1.117783705
+4.193548387 2.161290323 11.778370516 1.117783705
+4.193548387 2.451612903 11.778370516 1.117783705
+4.193548387 2.741935484 11.778370516 1.117783705
+4.193548387 3.032258065 11.855790361 1.118557904
+4.193548387 3.322580645 12.339709404 1.123397094
+4.193548387 3.612903226 12.717020386 1.127170204
+4.193548387 3.903225806 13.049696353 1.130496964
+4.193548387 4.193548387 13.357895418 1.133578954
+4.193548387 4.483870968 13.652146644 1.136521466
+4.193548387 4.774193548 13.940357897 1.139403579
+4.193548387 5.064516129 14.228197117 1.142281971
+4.193548387 5.354838710 14.520452601 1.145204526
+4.193548387 5.645161290 14.824425958 1.148244260
+4.193548387 5.935483871 15.146110946 1.151461109
+4.193548387 6.225806452 15.495840162 1.154958402
+4.193548387 6.516129032 15.889898831 1.158898988
+4.193548387 6.806451613 16.360710958 1.163607110
+4.193548387 7.096774194 16.778452741 1.167784527
+4.193548387 7.387096774 16.778452741 1.167784527
+4.193548387 7.677419355 16.778452741 1.167784527
+4.193548387 7.967741935 16.778452741 1.167784527
+4.193548387 8.258064516 16.778452741 1.167784527
+4.193548387 8.548387097 16.778452741 1.167784527
+4.193548387 8.838709677 16.778452741 1.167784527
+4.193548387 9.129032258 16.778452741 1.167784527
+4.193548387 9.419354839 16.778452741 1.167784527
+4.193548387 9.709677419 16.778452741 1.167784527
+4.193548387 10.000000000 16.778452741 1.167784527
+4.483870968 1.000000000 12.050104922 1.120501049
+4.483870968 1.290322581 12.050104922 1.120501049
+4.483870968 1.580645161 12.050104922 1.120501049
+4.483870968 1.870967742 12.050104922 1.120501049
+4.483870968 2.161290323 12.050104922 1.120501049
+4.483870968 2.451612903 12.050104922 1.120501049
+4.483870968 2.741935484 12.050104922 1.120501049
+4.483870968 3.032258065 12.127240434 1.121272404
+4.483870968 3.322580645 12.615733153 1.126157332
+4.483870968 3.612903226 12.999111631 1.129991116
+4.483870968 3.903225806 13.337970486 1.133379705
+4.483870968 4.193548387 13.652146644 1.136521466
+4.483870968 4.483870968 13.951679758 1.139516798
+4.483870968 4.774193548 14.245365454 1.142453655
+4.483870968 5.064516129 14.537425993 1.145374260
+4.483870968 5.354838710 14.832538034 1.148325380
+4.483870968 5.645161290 15.137036426 1.151370364
+4.483870968 5.935483871 15.457098960 1.154570990
+4.483870968 6.225806452 15.803334671 1.158033347
+4.483870968 6.516129032 16.189645887 1.161896459
+4.483870968 6.806451613 16.646502949 1.166465029
+4.483870968 7.096774194 17.050023823 1.170500238
+4.483870968 7.387096774 17.050023823 1.170500238
+4.483870968 7.677419355 17.050023823 1.170500238
+4.483870968 7.967741935 17.050023823 1.170500238
+4.483870968 8.258064516 17.050023823 1.170500238
+4.483870968 8.548387097 17.050023823 1.170500238
+4.483870968 8.838709677 17.050023823 1.170500238
+4.483870968 9.129032258 17.050023823 1.170500238
+4.483870968 9.419354839 17.050023823 1.170500238
+4.483870968 9.709677419 17.050023823 1.170500238
+4.483870968 10.000000000 17.050023823 1.170500238
+4.774193548 1.000000000 12.305762763 1.123057628
+4.774193548 1.290322581 12.305762763 1.123057628
+4.774193548 1.580645161 12.305762763 1.123057628
+4.774193548 1.870967742 12.305762763 1.123057628
+4.774193548 2.161290323 12.305762763 1.123057628
+4.774193548 2.451612903 12.305762763 1.123057628
+4.774193548 2.741935484 12.305762763 1.123057628
+4.774193548 3.032258065 12.384052580 1.123840526
+4.774193548 3.322580645 12.881223868 1.128812239
+4.774193548 3.612903226 13.273780609 1.132737806
+4.774193548 3.903225806 13.620159587 1.136201596
+4.774193548 4.193548387 13.940357897 1.139403579
+4.774193548 4.483870968 14.245365454 1.142453655
+4.774193548 4.774193548 14.542253555 1.145422536
+4.774193548 5.064516129 14.836186297 1.148361863
+4.774193548 5.354838710 15.132216948 1.151322169
+4.774193548 5.645161290 15.435976637 1.154359766
+4.774193548 5.935483871 15.753650335 1.157536503
+4.774193548 6.225806452 16.094398574 1.160943986
+4.774193548 6.516129032 16.472016458 1.164720165
+4.774193548 6.806451613 16.915328759 1.169153288
+4.774193548 7.096774194 17.305719073 1.173057191
+4.774193548 7.387096774 17.305719073 1.173057191
+4.774193548 7.677419355 17.305719073 1.173057191
+4.774193548 7.967741935 17.305719073 1.173057191
+4.774193548 8.258064516 17.305719073 1.173057191
+4.774193548 8.548387097 17.305719073 1.173057191
+4.774193548 8.838709677 17.305719073 1.173057191
+4.774193548 9.129032258 17.305719073 1.173057191
+4.774193548 9.419354839 17.305719073 1.173057191
+4.774193548 9.709677419 17.305719073 1.173057191
+4.774193548 10.000000000 17.305719073 1.173057191
+5.064516129 1.000000000 12.555175445 1.125551754
+5.064516129 1.290322581 12.555175445 1.125551754
+5.064516129 1.580645161 12.555175445 1.125551754
+5.064516129 1.870967742 12.555175445 1.125551754
+5.064516129 2.161290323 12.555175445 1.125551754
+5.064516129 2.451612903 12.555175445 1.125551754
+5.064516129 2.741935484 12.555175445 1.125551754
+5.064516129 3.032258065 12.634997421 1.126349974
+5.064516129 3.322580645 13.144835022 1.131448350
+5.064516129 3.612903226 13.547717972 1.135477180
+5.064516129 3.903225806 13.901946604 1.139019466
+5.064516129 4.193548387 14.228197117 1.142281971
+5.064516129 4.483870968 14.537425993 1.145374260
+5.064516129 4.774193548 14.836186297 1.148361863
+5.064516129 5.064516129 15.130822202 1.151308222
+5.064516129 5.354838710 15.426134812 1.154261348
+5.064516129 5.645161290 15.727608429 1.157276084
+5.064516129 5.935483871 16.040918075 1.160409181
+5.064516129 6.225806452 16.374971626 1.163749716
+5.064516129 6.516129032 16.743479696 1.167434797
+5.064516129 6.806451613 17.175031887 1.171750319
+5.064516129 7.096774194 17.555546435 1.175555464
+5.064516129 7.387096774 17.555546435 1.175555464
+5.064516129 7.677419355 17.555546435 1.175555464
+5.064516129 7.967741935 17.555546435 1.175555464
+5.064516129 8.258064516 17.555546435 1.175555464
+5.064516129 8.548387097 17.555546435 1.175555464
+5.064516129 8.838709677 17.555546435 1.175555464
+5.064516129 9.129032258 17.555546435 1.175555464
+5.064516129 9.419354839 17.555546435 1.175555464
+5.064516129 9.709677419 17.555546435 1.175555464
+5.064516129 10.000000000 17.555546435 1.175555464
+5.354838710 1.000000000 12.806659860 1.128066599
+5.354838710 1.290322581 12.806659860 1.128066599
+5.354838710 1.580645161 12.806659860 1.128066599
+5.354838710 1.870967742 12.806659860 1.128066599
+5.354838710 2.161290323 12.806659860 1.128066599
+5.354838710 2.451612903 12.806659860 1.128066599
+5.354838710 2.741935484 12.806659860 1.128066599
+5.354838710 3.032258065 12.888585631 1.128885856
+5.354838710 3.322580645 13.414082467 1.134140825
+5.354838710 3.612903226 13.827512227 1.138275122
+5.354838710 3.903225806 14.188883155 1.141888832
+5.354838710 4.193548387 14.520452601 1.145204526
+5.354838710 4.483870968 14.832538034 1.148325380
+5.354838710 4.774193548 15.132216948 1.151322169
+5.354838710 5.064516129 15.426134812 1.154261348
+5.354838710 5.354838710 15.719361905 1.157193619
+5.354838710 5.645161290 16.017791161 1.160177912
+5.354838710 5.935483871 16.325903819 1.163259038
+5.354838710 6.225806452 16.653358486 1.166533585
+5.354838710 6.516129032 17.013348713 1.170133487
+5.354838710 6.806451613 17.434097089 1.174340971
+5.354838710 7.096774194 17.806398651 1.178063987
+5.354838710 7.387096774 17.806398651 1.178063987
+5.354838710 7.677419355 17.806398651 1.178063987
+5.354838710 7.967741935 17.806398651 1.178063987
+5.354838710 8.258064516 17.806398651 1.178063987
+5.354838710 8.548387097 17.806398651 1.178063987
+5.354838710 8.838709677 17.806398651 1.178063987
+5.354838710 9.129032258 17.806398651 1.178063987
+5.354838710 9.419354839 17.806398651 1.178063987
+5.354838710 9.709677419 17.806398651 1.178063987
+5.354838710 10.000000000 17.806398651 1.178063987
+5.645161290 1.000000000 13.068093230 1.130680932
+5.645161290 1.290322581 13.068093230 1.130680932
+5.645161290 1.580645161 13.068093230 1.130680932
+5.645161290 1.870967742 13.068093230 1.130680932
+5.645161290 2.161290323 13.068093230 1.130680932
+5.645161290 2.451612903 13.068093230 1.130680932
+5.645161290 2.741935484 13.068093230 1.130680932
+5.645161290 3.032258065 13.153230669 1.131532307
+5.645161290 3.322580645 13.696138923 1.136961389
+5.645161290 3.612903226 14.120187657 1.141201877
+5.645161290 3.903225806 14.489540684 1.144895407
+5.645161290 4.193548387 14.824425958 1.148244260
+5.645161290 4.483870968 15.137036426 1.151370364
+5.645161290 4.774193548 15.435976637 1.154359766
+5.645161290 5.064516129 15.727608429 1.157276084
+5.645161290 5.354838710 16.017791161 1.160177912
+5.645161290 5.645161290 16.311598605 1.163115986
+5.645161290 5.935483871 16.613732570 1.166137326
+5.645161290 6.225806452 16.933994986 1.169339950
+5.645161290 6.516129032 17.286819066 1.172868191
+5.645161290 6.806451613 17.700020869 1.177000209
+5.645161290 7.096774194 18.068098179 1.180680982
+5.645161290 7.387096774 18.068098179 1.180680982
+5.645161290 7.677419355 18.068098179 1.180680982
+5.645161290 7.967741935 18.068098179 1.180680982
+5.645161290 8.258064516 18.068098179 1.180680982
+5.645161290 8.548387097 18.068098179 1.180680982
+5.645161290 8.838709677 18.068098179 1.180680982
+5.645161290 9.129032258 18.068098179 1.180680982
+5.645161290 9.419354839 18.068098179 1.180680982
+5.645161290 9.709677419 18.068098179 1.180680982
+5.645161290 10.000000000 18.068098179 1.180680982
+5.935483871 1.000000000 13.350561957 1.133505620
+5.935483871 1.290322581 13.350561957 1.133505620
+5.935483871 1.580645161 13.350561957 1.133505620
+5.935483871 1.870967742 13.350561957 1.133505620
+5.935483871 2.161290323 13.350561957 1.133505620
+5.935483871 2.451612903 13.350561957 1.133505620
+5.935483871 2.741935484 13.350561957 1.133505620
+5.935483871 3.032258065 13.438880990 1.134388810
+5.935483871 3.322580645 14.000777693 1.140007777
+5.935483871 3.612903226 14.435371678 1.144353717
+5.935483871 3.903225806 14.809822020 1.148098220
+5.935483871 4.193548387 15.146110946 1.151461109
+5.935483871 4.483870968 15.457098960 1.154570990
+5.935483871 4.774193548 15.753650335 1.157536503
+5.935483871 5.064516129 16.040918075 1.160409181
+5.935483871 5.354838710 16.325903819 1.163259038
+5.935483871 5.645161290 16.613732570 1.166137326
+5.935483871 5.935483871 16.911019483 1.169110195
+5.935483871 6.225806452 17.225563024 1.172255630
+5.935483871 6.516129032 17.572635415 1.175726354
+5.935483871 6.806451613 17.982106473 1.179821065
+5.935483871 7.096774194 18.349962605 1.183499626
+5.935483871 7.387096774 18.349962605 1.183499626
+5.935483871 7.677419355 18.349962605 1.183499626
+5.935483871 7.967741935 18.349962605 1.183499626
+5.935483871 8.258064516 18.349962605 1.183499626
+5.935483871 8.548387097 18.349962605 1.183499626
+5.935483871 8.838709677 18.349962605 1.183499626
+5.935483871 9.129032258 18.349962605 1.183499626
+5.935483871 9.419354839 18.349962605 1.183499626
+5.935483871 9.709677419 18.349962605 1.183499626
+5.935483871 10.000000000 18.349962605 1.183499626
+6.225806452 1.000000000 13.666570669 1.136665707
+6.225806452 1.290322581 13.666570669 1.136665707
+6.225806452 1.580645161 13.666570669 1.136665707
+6.225806452 1.870967742 13.666570669 1.136665707
+6.225806452 2.161290323 13.666570669 1.136665707
+6.225806452 2.451612903 13.666570669 1.136665707
+6.225806452 2.741935484 13.666570669 1.136665707
+6.225806452 3.032258065 13.759265462 1.137592655
+6.225806452 3.322580645 14.342258539 1.143422585
+6.225806452 3.612903226 14.784914127 1.147849141
+6.225806452 3.903225806 15.160748839 1.151607488
+6.225806452 4.193548387 15.495840162 1.154958402
+6.225806452 4.483870968 15.803334671 1.158033347
+6.225806452 4.774193548 16.094398574 1.160943986
+6.225806452 5.064516129 16.374971626 1.163749716
+6.225806452 5.354838710 16.653358486 1.166533585
+6.225806452 5.645161290 16.933994986 1.169339950
+6.225806452 5.935483871 17.225563024 1.172255630
+6.225806452 6.225806452 17.536694601 1.175366946
+6.225806452 6.516129032 17.882140340 1.178821403
+6.225806452 6.806451613 18.292111531 1.182921115
+6.225806452 7.096774194 18.667017714 1.186670177
+6.225806452 7.387096774 18.667017714 1.186670177
+6.225806452 7.677419355 18.667017714 1.186670177
+6.225806452 7.967741935 18.667017714 1.186670177
+6.225806452 8.258064516 18.667017714 1.186670177
+6.225806452 8.548387097 18.667017714 1.186670177
+6.225806452 8.838709677 18.667017714 1.186670177
+6.225806452 9.129032258 18.667017714 1.186670177
+6.225806452 9.419354839 18.667017714 1.186670177
+6.225806452 9.709677419 18.667017714 1.186670177
+6.225806452 10.000000000 18.667017714 1.186670177
+6.516129032 1.000000000 14.042124914 1.140421249
+6.516129032 1.290322581 14.042124914 1.140421249
+6.516129032 1.580645161 14.042124914 1.140421249
+6.516129032 1.870967742 14.042124914 1.140421249
+6.516129032 2.161290323 14.042124914 1.140421249
+6.516129032 2.451612903 14.042124914 1.140421249
+6.516129032 2.741935484 14.042124914 1.140421249
+6.516129032 3.032258065 14.139344845 1.141393448
+6.516129032 3.322580645 14.739964250 1.147399642
+6.516129032 3.612903226 15.187004870 1.151870049
+6.516129032 3.903225806 15.560871420 1.155608714
+6.516129032 4.193548387 15.889898831 1.158898988
+6.516129032 4.483870968 16.189645887 1.161896459
+6.516129032 4.774193548 16.472016458 1.164720165
+6.516129032 5.064516129 16.743479696 1.167434797
+6.516129032 5.354838710 17.013348713 1.170133487
+6.516129032 5.645161290 17.286819066 1.172868191
+6.516129032 5.935483871 17.572635415 1.175726354
+6.516129032 6.225806452 17.882140340 1.178821403
+6.516129032 6.516129032 18.229995875 1.182299959
+6.516129032 6.806451613 18.651088969 1.186510890
+6.516129032 7.096774194 19.041899081 1.190418991
+6.516129032 7.387096774 19.041899081 1.190418991
+6.516129032 7.677419355 19.041899081 1.190418991
+6.516129032 7.967741935 19.041899081 1.190418991
+6.516129032 8.258064516 19.041899081 1.190418991
+6.516129032 8.548387097 19.041899081 1.190418991
+6.516129032 8.838709677 19.041899081 1.190418991
+6.516129032 9.129032258 19.041899081 1.190418991
+6.516129032 9.419354839 19.041899081 1.190418991
+6.516129032 9.709677419 19.041899081 1.190418991
+6.516129032 10.000000000 19.041899081 1.190418991
+6.806451613 1.000000000 14.524928709 1.145249287
+6.806451613 1.290322581 14.524928709 1.145249287
+6.806451613 1.580645161 14.524928709 1.145249287
+6.806451613 1.870967742 14.524928709 1.145249287
+6.806451613 2.161290323 14.524928709 1.145249287
+6.806451613 2.451612903 14.524928709 1.145249287
+6.806451613 2.741935484 14.524928709 1.145249287
+6.806451613 3.032258065 14.626746497 1.146267465
+6.806451613 3.322580645 15.239164015 1.152391640
+6.806451613 3.612903226 15.681548005 1.156815480
+6.806451613 3.903225806 16.043900181 1.160439002
+6.806451613 4.193548387 16.360710958 1.163607110
+6.806451613 4.483870968 16.646502949 1.166465029
+6.806451613 4.774193548 16.915328759 1.169153288
+6.806451613 5.064516129 17.175031887 1.171750319
+6.806451613 5.354838710 17.434097089 1.174340971
+6.806451613 5.645161290 17.700020869 1.177000209
+6.806451613 5.935483871 17.982106473 1.179821065
+6.806451613 6.225806452 18.292111531 1.182921115
+6.806451613 6.516129032 18.651088969 1.186510890
+6.806451613 6.806451613 19.098880252 1.190988803
+6.806451613 7.096774194 19.524964154 1.195249642
+6.806451613 7.387096774 19.524964154 1.195249642
+6.806451613 7.677419355 19.524964154 1.195249642
+6.806451613 7.967741935 19.524964154 1.195249642
+6.806451613 8.258064516 19.524964154 1.195249642
+6.806451613 8.548387097 19.524964154 1.195249642
+6.806451613 8.838709677 19.524964154 1.195249642
+6.806451613 9.129032258 19.524964154 1.195249642
+6.806451613 9.419354839 19.524964154 1.195249642
+6.806451613 9.709677419 19.524964154 1.195249642
+6.806451613 10.000000000 19.524964154 1.195249642
+7.096774194 1.000000000 15.000000000 1.150000000
+7.096774194 1.290322581 15.000000000 1.150000000
+7.096774194 1.580645161 15.000000000 1.150000000
+7.096774194 1.870967742 15.000000000 1.150000000
+7.096774194 2.161290323 15.000000000 1.150000000
+7.096774194 2.451612903 15.000000000 1.150000000
+7.096774194 2.741935484 15.000000000 1.150000000
+7.096774194 3.032258065 15.103574890 1.151035749
+7.096774194 3.322580645 15.708449495 1.157084495
+7.096774194 3.612903226 16.133823742 1.161338237
+7.096774194 3.903225806 16.479227686 1.164792277
+7.096774194 4.193548387 16.778452741 1.167784527
+7.096774194 4.483870968 17.050023823 1.170500238
+7.096774194 4.774193548 17.305719073 1.173057191
+7.096774194 5.064516129 17.555546435 1.175555464
+7.096774194 5.354838710 17.806398651 1.178063987
+7.096774194 5.645161290 18.068098179 1.180680982
+7.096774194 5.935483871 18.349962605 1.183499626
+7.096774194 6.225806452 18.667017714 1.186670177
+7.096774194 6.516129032 19.041899081 1.190418991
+7.096774194 6.806451613 19.524964154 1.195249642
+7.096774194 7.096774194 19.999997043 1.199999970
+7.096774194 7.387096774 19.999997043 1.199999970
+7.096774194 7.677419355 19.999997043 1.199999970
+7.096774194 7.967741935 19.999997043 1.199999970
+7.096774194 8.258064516 19.999997043 1.199999970
+7.096774194 8.548387097 19.999997043 1.199999970
+7.096774194 8.838709677 19.999997043 1.199999970
+7.096774194 9.129032258 19.999997043 1.199999970
+7.096774194 9.419354839 19.999997043 1.199999970
+7.096774194 9.709677419 19.999997043 1.199999970
+7.096774194 10.000000000 19.999997043 1.199999970
+7.387096774 1.000000000 15.000000000 1.150000000
+7.387096774 1.290322581 15.000000000 1.150000000
+7.387096774 1.580645161 15.000000000 1.150000000
+7.387096774 1.870967742 15.000000000 1.150000000
+7.387096774 2.161290323 15.000000000 1.150000000
+7.387096774 2.451612903 15.000000000 1.150000000
+7.387096774 2.741935484 15.000000000 1.150000000
+7.387096774 3.032258065 15.103574890 1.151035749
+7.387096774 3.322580645 15.708449495 1.157084495
+7.387096774 3.612903226 16.133823742 1.161338237
+7.387096774 3.903225806 16.479227686 1.164792277
+7.387096774 4.193548387 16.778452741 1.167784527
+7.387096774 4.483870968 17.050023823 1.170500238
+7.387096774 4.774193548 17.305719073 1.173057191
+7.387096774 5.064516129 17.555546435 1.175555464
+7.387096774 5.354838710 17.806398651 1.178063987
+7.387096774 5.645161290 18.068098179 1.180680982
+7.387096774 5.935483871 18.349962605 1.183499626
+7.387096774 6.225806452 18.667017714 1.186670177
+7.387096774 6.516129032 19.041899081 1.190418991
+7.387096774 6.806451613 19.524964154 1.195249642
+7.387096774 7.096774194 19.999997043 1.199999970
+7.387096774 7.387096774 19.999997043 1.199999970
+7.387096774 7.677419355 19.999997043 1.199999970
+7.387096774 7.967741935 19.999997043 1.199999970
+7.387096774 8.258064516 19.999997043 1.199999970
+7.387096774 8.548387097 19.999997043 1.199999970
+7.387096774 8.838709677 19.999997043 1.199999970
+7.387096774 9.129032258 19.999997043 1.199999970
+7.387096774 9.419354839 19.999997043 1.199999970
+7.387096774 9.709677419 19.999997043 1.199999970
+7.387096774 10.000000000 19.999997043 1.199999970
+7.677419355 1.000000000 15.000000000 1.150000000
+7.677419355 1.290322581 15.000000000 1.150000000
+7.677419355 1.580645161 15.000000000 1.150000000
+7.677419355 1.870967742 15.000000000 1.150000000
+7.677419355 2.161290323 15.000000000 1.150000000
+7.677419355 2.451612903 15.000000000 1.150000000
+7.677419355 2.741935484 15.000000000 1.150000000
+7.677419355 3.032258065 15.103574890 1.151035749
+7.677419355 3.322580645 15.708449495 1.157084495
+7.677419355 3.612903226 16.133823742 1.161338237
+7.677419355 3.903225806 16.479227686 1.164792277
+7.677419355 4.193548387 16.778452741 1.167784527
+7.677419355 4.483870968 17.050023823 1.170500238
+7.677419355 4.774193548 17.305719073 1.173057191
+7.677419355 5.064516129 17.555546435 1.175555464
+7.677419355 5.354838710 17.806398651 1.178063987
+7.677419355 5.645161290 18.068098179 1.180680982
+7.677419355 5.935483871 18.349962605 1.183499626
+7.677419355 6.225806452 18.667017714 1.186670177
+7.677419355 6.516129032 19.041899081 1.190418991
+7.677419355 6.806451613 19.524964154 1.195249642
+7.677419355 7.096774194 19.999997043 1.199999970
+7.677419355 7.387096774 19.999997043 1.199999970
+7.677419355 7.677419355 19.999997043 1.199999970
+7.677419355 7.967741935 19.999997043 1.199999970
+7.677419355 8.258064516 19.999997043 1.199999970
+7.677419355 8.548387097 19.999997043 1.199999970
+7.677419355 8.838709677 19.999997043 1.199999970
+7.677419355 9.129032258 19.999997043 1.199999970
+7.677419355 9.419354839 19.999997043 1.199999970
+7.677419355 9.709677419 19.999997043 1.199999970
+7.677419355 10.000000000 19.999997043 1.199999970
+7.967741935 1.000000000 15.000000000 1.150000000
+7.967741935 1.290322581 15.000000000 1.150000000
+7.967741935 1.580645161 15.000000000 1.150000000
+7.967741935 1.870967742 15.000000000 1.150000000
+7.967741935 2.161290323 15.000000000 1.150000000
+7.967741935 2.451612903 15.000000000 1.150000000
+7.967741935 2.741935484 15.000000000 1.150000000
+7.967741935 3.032258065 15.103574890 1.151035749
+7.967741935 3.322580645 15.708449495 1.157084495
+7.967741935 3.612903226 16.133823742 1.161338237
+7.967741935 3.903225806 16.479227686 1.164792277
+7.967741935 4.193548387 16.778452741 1.167784527
+7.967741935 4.483870968 17.050023823 1.170500238
+7.967741935 4.774193548 17.305719073 1.173057191
+7.967741935 5.064516129 17.555546435 1.175555464
+7.967741935 5.354838710 17.806398651 1.178063987
+7.967741935 5.645161290 18.068098179 1.180680982
+7.967741935 5.935483871 18.349962605 1.183499626
+7.967741935 6.225806452 18.667017714 1.186670177
+7.967741935 6.516129032 19.041899081 1.190418991
+7.967741935 6.806451613 19.524964154 1.195249642
+7.967741935 7.096774194 19.999997043 1.199999970
+7.967741935 7.387096774 19.999997043 1.199999970
+7.967741935 7.677419355 19.999997043 1.199999970
+7.967741935 7.967741935 19.999997043 1.199999970
+7.967741935 8.258064516 19.999997043 1.199999970
+7.967741935 8.548387097 19.999997043 1.199999970
+7.967741935 8.838709677 19.999997043 1.199999970
+7.967741935 9.129032258 19.999997043 1.199999970
+7.967741935 9.419354839 19.999997043 1.199999970
+7.967741935 9.709677419 19.999997043 1.199999970
+7.967741935 10.000000000 19.999997043 1.199999970
+8.258064516 1.000000000 15.000000000 1.150000000
+8.258064516 1.290322581 15.000000000 1.150000000
+8.258064516 1.580645161 15.000000000 1.150000000
+8.258064516 1.870967742 15.000000000 1.150000000
+8.258064516 2.161290323 15.000000000 1.150000000
+8.258064516 2.451612903 15.000000000 1.150000000
+8.258064516 2.741935484 15.000000000 1.150000000
+8.258064516 3.032258065 15.103574890 1.151035749
+8.258064516 3.322580645 15.708449495 1.157084495
+8.258064516 3.612903226 16.133823742 1.161338237
+8.258064516 3.903225806 16.479227686 1.164792277
+8.258064516 4.193548387 16.778452741 1.167784527
+8.258064516 4.483870968 17.050023823 1.170500238
+8.258064516 4.774193548 17.305719073 1.173057191
+8.258064516 5.064516129 17.555546435 1.175555464
+8.258064516 5.354838710 17.806398651 1.178063987
+8.258064516 5.645161290 18.068098179 1.180680982
+8.258064516 5.935483871 18.349962605 1.183499626
+8.258064516 6.225806452 18.667017714 1.186670177
+8.258064516 6.516129032 19.041899081 1.190418991
+8.258064516 6.806451613 19.524964154 1.195249642
+8.258064516 7.096774194 19.999997043 1.199999970
+8.258064516 7.387096774 19.999997043 1.199999970
+8.258064516 7.677419355 19.999997043 1.199999970
+8.258064516 7.967741935 19.999997043 1.199999970
+8.258064516 8.258064516 19.999997043 1.199999970
+8.258064516 8.548387097 19.999997043 1.199999970
+8.258064516 8.838709677 19.999997043 1.199999970
+8.258064516 9.129032258 19.999997043 1.199999970
+8.258064516 9.419354839 19.999997043 1.199999970
+8.258064516 9.709677419 19.999997043 1.199999970
+8.258064516 10.000000000 19.999997043 1.199999970
+8.548387097 1.000000000 15.000000000 1.150000000
+8.548387097 1.290322581 15.000000000 1.150000000
+8.548387097 1.580645161 15.000000000 1.150000000
+8.548387097 1.870967742 15.000000000 1.150000000
+8.548387097 2.161290323 15.000000000 1.150000000
+8.548387097 2.451612903 15.000000000 1.150000000
+8.548387097 2.741935484 15.000000000 1.150000000
+8.548387097 3.032258065 15.103574890 1.151035749
+8.548387097 3.322580645 15.708449495 1.157084495
+8.548387097 3.612903226 16.133823742 1.161338237
+8.548387097 3.903225806 16.479227686 1.164792277
+8.548387097 4.193548387 16.778452741 1.167784527
+8.548387097 4.483870968 17.050023823 1.170500238
+8.548387097 4.774193548 17.305719073 1.173057191
+8.548387097 5.064516129 17.555546435 1.175555464
+8.548387097 5.354838710 17.806398651 1.178063987
+8.548387097 5.645161290 18.068098179 1.180680982
+8.548387097 5.935483871 18.349962605 1.183499626
+8.548387097 6.225806452 18.667017714 1.186670177
+8.548387097 6.516129032 19.041899081 1.190418991
+8.548387097 6.806451613 19.524964154 1.195249642
+8.548387097 7.096774194 19.999997043 1.199999970
+8.548387097 7.387096774 19.999997043 1.199999970
+8.548387097 7.677419355 19.999997043 1.199999970
+8.548387097 7.967741935 19.999997043 1.199999970
+8.548387097 8.258064516 19.999997043 1.199999970
+8.548387097 8.548387097 19.999997043 1.199999970
+8.548387097 8.838709677 19.999997043 1.199999970
+8.548387097 9.129032258 19.999997043 1.199999970
+8.548387097 9.419354839 19.999997043 1.199999970
+8.548387097 9.709677419 19.999997043 1.199999970
+8.548387097 10.000000000 19.999997043 1.199999970
+8.838709677 1.000000000 15.000000000 1.150000000
+8.838709677 1.290322581 15.000000000 1.150000000
+8.838709677 1.580645161 15.000000000 1.150000000
+8.838709677 1.870967742 15.000000000 1.150000000
+8.838709677 2.161290323 15.000000000 1.150000000
+8.838709677 2.451612903 15.000000000 1.150000000
+8.838709677 2.741935484 15.000000000 1.150000000
+8.838709677 3.032258065 15.103574890 1.151035749
+8.838709677 3.322580645 15.708449495 1.157084495
+8.838709677 3.612903226 16.133823742 1.161338237
+8.838709677 3.903225806 16.479227686 1.164792277
+8.838709677 4.193548387 16.778452741 1.167784527
+8.838709677 4.483870968 17.050023823 1.170500238
+8.838709677 4.774193548 17.305719073 1.173057191
+8.838709677 5.064516129 17.555546435 1.175555464
+8.838709677 5.354838710 17.806398651 1.178063987
+8.838709677 5.645161290 18.068098179 1.180680982
+8.838709677 5.935483871 18.349962605 1.183499626
+8.838709677 6.225806452 18.667017714 1.186670177
+8.838709677 6.516129032 19.041899081 1.190418991
+8.838709677 6.806451613 19.524964154 1.195249642
+8.838709677 7.096774194 19.999997043 1.199999970
+8.838709677 7.387096774 19.999997043 1.199999970
+8.838709677 7.677419355 19.999997043 1.199999970
+8.838709677 7.967741935 19.999997043 1.199999970
+8.838709677 8.258064516 19.999997043 1.199999970
+8.838709677 8.548387097 19.999997043 1.199999970
+8.838709677 8.838709677 19.999997043 1.199999970
+8.838709677 9.129032258 19.999997043 1.199999970
+8.838709677 9.419354839 19.999997043 1.199999970
+8.838709677 9.709677419 19.999997043 1.199999970
+8.838709677 10.000000000 19.999997043 1.199999970
+9.129032258 1.000000000 15.000000000 1.150000000
+9.129032258 1.290322581 15.000000000 1.150000000
+9.129032258 1.580645161 15.000000000 1.150000000
+9.129032258 1.870967742 15.000000000 1.150000000
+9.129032258 2.161290323 15.000000000 1.150000000
+9.129032258 2.451612903 15.000000000 1.150000000
+9.129032258 2.741935484 15.000000000 1.150000000
+9.129032258 3.032258065 15.103574890 1.151035749
+9.129032258 3.322580645 15.708449495 1.157084495
+9.129032258 3.612903226 16.133823742 1.161338237
+9.129032258 3.903225806 16.479227686 1.164792277
+9.129032258 4.193548387 16.778452741 1.167784527
+9.129032258 4.483870968 17.050023823 1.170500238
+9.129032258 4.774193548 17.305719073 1.173057191
+9.129032258 5.064516129 17.555546435 1.175555464
+9.129032258 5.354838710 17.806398651 1.178063987
+9.129032258 5.645161290 18.068098179 1.180680982
+9.129032258 5.935483871 18.349962605 1.183499626
+9.129032258 6.225806452 18.667017714 1.186670177
+9.129032258 6.516129032 19.041899081 1.190418991
+9.129032258 6.806451613 19.524964154 1.195249642
+9.129032258 7.096774194 19.999997043 1.199999970
+9.129032258 7.387096774 19.999997043 1.199999970
+9.129032258 7.677419355 19.999997043 1.199999970
+9.129032258 7.967741935 19.999997043 1.199999970
+9.129032258 8.258064516 19.999997043 1.199999970
+9.129032258 8.548387097 19.999997043 1.199999970
+9.129032258 8.838709677 19.999997043 1.199999970
+9.129032258 9.129032258 19.999997043 1.199999970
+9.129032258 9.419354839 19.999997043 1.199999970
+9.129032258 9.709677419 19.999997043 1.199999970
+9.129032258 10.000000000 19.999997043 1.199999970
+9.419354839 1.000000000 15.000000000 1.150000000
+9.419354839 1.290322581 15.000000000 1.150000000
+9.419354839 1.580645161 15.000000000 1.150000000
+9.419354839 1.870967742 15.000000000 1.150000000
+9.419354839 2.161290323 15.000000000 1.150000000
+9.419354839 2.451612903 15.000000000 1.150000000
+9.419354839 2.741935484 15.000000000 1.150000000
+9.419354839 3.032258065 15.103574890 1.151035749
+9.419354839 3.322580645 15.708449495 1.157084495
+9.419354839 3.612903226 16.133823742 1.161338237
+9.419354839 3.903225806 16.479227686 1.164792277
+9.419354839 4.193548387 16.778452741 1.167784527
+9.419354839 4.483870968 17.050023823 1.170500238
+9.419354839 4.774193548 17.305719073 1.173057191
+9.419354839 5.064516129 17.555546435 1.175555464
+9.419354839 5.354838710 17.806398651 1.178063987
+9.419354839 5.645161290 18.068098179 1.180680982
+9.419354839 5.935483871 18.349962605 1.183499626
+9.419354839 6.225806452 18.667017714 1.186670177
+9.419354839 6.516129032 19.041899081 1.190418991
+9.419354839 6.806451613 19.524964154 1.195249642
+9.419354839 7.096774194 19.999997043 1.199999970
+9.419354839 7.387096774 19.999997043 1.199999970
+9.419354839 7.677419355 19.999997043 1.199999970
+9.419354839 7.967741935 19.999997043 1.199999970
+9.419354839 8.258064516 19.999997043 1.199999970
+9.419354839 8.548387097 19.999997043 1.199999970
+9.419354839 8.838709677 19.999997043 1.199999970
+9.419354839 9.129032258 19.999997043 1.199999970
+9.419354839 9.419354839 19.999997043 1.199999970
+9.419354839 9.709677419 19.999997043 1.199999970
+9.419354839 10.000000000 19.999997043 1.199999970
+9.709677419 1.000000000 15.000000000 1.150000000
+9.709677419 1.290322581 15.000000000 1.150000000
+9.709677419 1.580645161 15.000000000 1.150000000
+9.709677419 1.870967742 15.000000000 1.150000000
+9.709677419 2.161290323 15.000000000 1.150000000
+9.709677419 2.451612903 15.000000000 1.150000000
+9.709677419 2.741935484 15.000000000 1.150000000
+9.709677419 3.032258065 15.103574890 1.151035749
+9.709677419 3.322580645 15.708449495 1.157084495
+9.709677419 3.612903226 16.133823742 1.161338237
+9.709677419 3.903225806 16.479227686 1.164792277
+9.709677419 4.193548387 16.778452741 1.167784527
+9.709677419 4.483870968 17.050023823 1.170500238
+9.709677419 4.774193548 17.305719073 1.173057191
+9.709677419 5.064516129 17.555546435 1.175555464
+9.709677419 5.354838710 17.806398651 1.178063987
+9.709677419 5.645161290 18.068098179 1.180680982
+9.709677419 5.935483871 18.349962605 1.183499626
+9.709677419 6.225806452 18.667017714 1.186670177
+9.709677419 6.516129032 19.041899081 1.190418991
+9.709677419 6.806451613 19.524964154 1.195249642
+9.709677419 7.096774194 19.999997043 1.199999970
+9.709677419 7.387096774 19.999997043 1.199999970
+9.709677419 7.677419355 19.999997043 1.199999970
+9.709677419 7.967741935 19.999997043 1.199999970
+9.709677419 8.258064516 19.999997043 1.199999970
+9.709677419 8.548387097 19.999997043 1.199999970
+9.709677419 8.838709677 19.999997043 1.199999970
+9.709677419 9.129032258 19.999997043 1.199999970
+9.709677419 9.419354839 19.999997043 1.199999970
+9.709677419 9.709677419 19.999997043 1.199999970
+9.709677419 10.000000000 19.999997043 1.199999970
+10.000000000 1.000000000 15.000000000 1.150000000
+10.000000000 1.290322581 15.000000000 1.150000000
+10.000000000 1.580645161 15.000000000 1.150000000
+10.000000000 1.870967742 15.000000000 1.150000000
+10.000000000 2.161290323 15.000000000 1.150000000
+10.000000000 2.451612903 15.000000000 1.150000000
+10.000000000 2.741935484 15.000000000 1.150000000
+10.000000000 3.032258065 15.103574890 1.151035749
+10.000000000 3.322580645 15.708449495 1.157084495
+10.000000000 3.612903226 16.133823742 1.161338237
+10.000000000 3.903225806 16.479227686 1.164792277
+10.000000000 4.193548387 16.778452741 1.167784527
+10.000000000 4.483870968 17.050023823 1.170500238
+10.000000000 4.774193548 17.305719073 1.173057191
+10.000000000 5.064516129 17.555546435 1.175555464
+10.000000000 5.354838710 17.806398651 1.178063987
+10.000000000 5.645161290 18.068098179 1.180680982
+10.000000000 5.935483871 18.349962605 1.183499626
+10.000000000 6.225806452 18.667017714 1.186670177
+10.000000000 6.516129032 19.041899081 1.190418991
+10.000000000 6.806451613 19.524964154 1.195249642
+10.000000000 7.096774194 19.999997043 1.199999970
+10.000000000 7.387096774 19.999997043 1.199999970
+10.000000000 7.677419355 19.999997043 1.199999970
+10.000000000 7.967741935 19.999997043 1.199999970
+10.000000000 8.258064516 19.999997043 1.199999970
+10.000000000 8.548387097 19.999997043 1.199999970
+10.000000000 8.838709677 19.999997043 1.199999970
+10.000000000 9.129032258 19.999997043 1.199999970
+10.000000000 9.419354839 19.999997043 1.199999970
+10.000000000 9.709677419 19.999997043 1.199999970
+10.000000000 10.000000000 19.999997043 1.199999970
diff --git a/examples/mamdani/octave/mamdani_tip_calculator.fll b/examples/mamdani/octave/mamdani_tip_calculator.fll
index b6c1920..516d870 100644
--- a/examples/mamdani/octave/mamdani_tip_calculator.fll
+++ b/examples/mamdani/octave/mamdani_tip_calculator.fll
@@ -1,33 +1,35 @@
-Engine: Mamdani-Tip-Calculator
+Engine: mamdani_tip_calculator
InputVariable: FoodQuality
enabled: true
range: 1.000 10.000
+ lock-range: false
term: Bad Trapezoid 0.000 1.000 3.000 7.000
term: Good Trapezoid 3.000 7.000 10.000 11.000
InputVariable: Service
enabled: true
range: 1.000 10.000
+ lock-range: false
term: Bad Trapezoid 0.000 1.000 3.000 7.000
term: Good Trapezoid 3.000 7.000 10.000 11.000
OutputVariable: Tip
enabled: true
range: 0.000 30.000
- accumulation: AlgebraicSum
+ lock-range: false
+ aggregation: AlgebraicSum
defuzzifier: Centroid 200
default: nan
lock-previous: false
- lock-range: false
term: AboutTenPercent Gaussian 10.000 2.000
term: AboutFifteenPercent Gaussian 15.000 2.000
term: AboutTwentyPercent Gaussian 20.000 2.000
OutputVariable: CheckPlusTip
enabled: true
range: 1.000 1.300
- accumulation: AlgebraicSum
+ lock-range: false
+ aggregation: AlgebraicSum
defuzzifier: Centroid 200
default: nan
lock-previous: false
- lock-range: false
term: PlusAboutTenPercent Gaussian 1.100 0.020
term: PlusAboutFifteenPercent Gaussian 1.150 0.020
term: PlusAboutTwentyPercent Gaussian 1.200 0.020
@@ -35,7 +37,8 @@ RuleBlock:
enabled: true
conjunction: AlgebraicProduct
disjunction: Maximum
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if FoodQuality is Bad and Service is Bad then Tip is AboutTenPercent and CheckPlusTip is PlusAboutTenPercent
rule: if FoodQuality is Bad and Service is Good then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent
rule: if FoodQuality is Good and Service is Bad then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent
diff --git a/examples/mamdani/octave/mamdani_tip_calculator.java b/examples/mamdani/octave/mamdani_tip_calculator.java
index bea319b..faea466 100644
--- a/examples/mamdani/octave/mamdani_tip_calculator.java
+++ b/examples/mamdani/octave/mamdani_tip_calculator.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,59 +13,70 @@ import com.fuzzylite.variable.*;
public class mamdani_tip_calculator{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("Mamdani-Tip-Calculator");
+engine.setName("mamdani_tip_calculator");
+engine.setDescription("");
-InputVariable inputVariable1 = new InputVariable();
-inputVariable1.setEnabled(true);
-inputVariable1.setName("FoodQuality");
-inputVariable1.setRange(1.000, 10.000);
-inputVariable1.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable1.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine.addInputVariable(inputVariable1);
+InputVariable FoodQuality = new InputVariable();
+FoodQuality.setName("FoodQuality");
+FoodQuality.setDescription("");
+FoodQuality.setEnabled(true);
+FoodQuality.setRange(1.000, 10.000);
+FoodQuality.setLockValueInRange(false);
+FoodQuality.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+FoodQuality.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine.addInputVariable(FoodQuality);
-InputVariable inputVariable2 = new InputVariable();
-inputVariable2.setEnabled(true);
-inputVariable2.setName("Service");
-inputVariable2.setRange(1.000, 10.000);
-inputVariable2.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable2.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine.addInputVariable(inputVariable2);
+InputVariable Service = new InputVariable();
+Service.setName("Service");
+Service.setDescription("");
+Service.setEnabled(true);
+Service.setRange(1.000, 10.000);
+Service.setLockValueInRange(false);
+Service.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+Service.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine.addInputVariable(Service);
-OutputVariable outputVariable1 = new OutputVariable();
-outputVariable1.setEnabled(true);
-outputVariable1.setName("Tip");
-outputVariable1.setRange(0.000, 30.000);
-outputVariable1.fuzzyOutput().setAccumulation(new AlgebraicSum());
-outputVariable1.setDefuzzifier(new Centroid(200));
-outputVariable1.setDefaultValue(Double.NaN);
-outputVariable1.setLockPreviousOutputValue(false);
-outputVariable1.setLockOutputValueInRange(false);
-outputVariable1.addTerm(new Gaussian("AboutTenPercent", 10.000, 2.000));
-outputVariable1.addTerm(new Gaussian("AboutFifteenPercent", 15.000, 2.000));
-outputVariable1.addTerm(new Gaussian("AboutTwentyPercent", 20.000, 2.000));
-engine.addOutputVariable(outputVariable1);
+OutputVariable Tip = new OutputVariable();
+Tip.setName("Tip");
+Tip.setDescription("");
+Tip.setEnabled(true);
+Tip.setRange(0.000, 30.000);
+Tip.setLockValueInRange(false);
+Tip.setAggregation(new AlgebraicSum());
+Tip.setDefuzzifier(new Centroid(200));
+Tip.setDefaultValue(Double.NaN);
+Tip.setLockPreviousValue(false);
+Tip.addTerm(new Gaussian("AboutTenPercent", 10.000, 2.000));
+Tip.addTerm(new Gaussian("AboutFifteenPercent", 15.000, 2.000));
+Tip.addTerm(new Gaussian("AboutTwentyPercent", 20.000, 2.000));
+engine.addOutputVariable(Tip);
-OutputVariable outputVariable2 = new OutputVariable();
-outputVariable2.setEnabled(true);
-outputVariable2.setName("CheckPlusTip");
-outputVariable2.setRange(1.000, 1.300);
-outputVariable2.fuzzyOutput().setAccumulation(new AlgebraicSum());
-outputVariable2.setDefuzzifier(new Centroid(200));
-outputVariable2.setDefaultValue(Double.NaN);
-outputVariable2.setLockPreviousOutputValue(false);
-outputVariable2.setLockOutputValueInRange(false);
-outputVariable2.addTerm(new Gaussian("PlusAboutTenPercent", 1.100, 0.020));
-outputVariable2.addTerm(new Gaussian("PlusAboutFifteenPercent", 1.150, 0.020));
-outputVariable2.addTerm(new Gaussian("PlusAboutTwentyPercent", 1.200, 0.020));
-engine.addOutputVariable(outputVariable2);
+OutputVariable CheckPlusTip = new OutputVariable();
+CheckPlusTip.setName("CheckPlusTip");
+CheckPlusTip.setDescription("");
+CheckPlusTip.setEnabled(true);
+CheckPlusTip.setRange(1.000, 1.300);
+CheckPlusTip.setLockValueInRange(false);
+CheckPlusTip.setAggregation(new AlgebraicSum());
+CheckPlusTip.setDefuzzifier(new Centroid(200));
+CheckPlusTip.setDefaultValue(Double.NaN);
+CheckPlusTip.setLockPreviousValue(false);
+CheckPlusTip.addTerm(new Gaussian("PlusAboutTenPercent", 1.100, 0.020));
+CheckPlusTip.addTerm(new Gaussian("PlusAboutFifteenPercent", 1.150, 0.020));
+CheckPlusTip.addTerm(new Gaussian("PlusAboutTwentyPercent", 1.200, 0.020));
+engine.addOutputVariable(CheckPlusTip);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(new AlgebraicProduct());
ruleBlock.setDisjunction(new Maximum());
-ruleBlock.setActivation(new Minimum());
+ruleBlock.setImplication(new Minimum());
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if FoodQuality is Bad and Service is Bad then Tip is AboutTenPercent and CheckPlusTip is PlusAboutTenPercent", engine));
ruleBlock.addRule(Rule.parse("if FoodQuality is Bad and Service is Good then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent", engine));
ruleBlock.addRule(Rule.parse("if FoodQuality is Good and Service is Bad then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent", engine));
diff --git a/examples/mamdani/octave/mamdani_tip_calculator.pdf b/examples/mamdani/octave/mamdani_tip_calculator.pdf
new file mode 100644
index 0000000..d62a142
--- /dev/null
+++ b/examples/mamdani/octave/mamdani_tip_calculator.pdf
Binary files differ
diff --git a/examples/original/mamdani/AllTerms.fll b/examples/original/mamdani/AllTerms.fll
index 58d5705..bed89c8 100644
--- a/examples/original/mamdani/AllTerms.fll
+++ b/examples/original/mamdani/AllTerms.fll
@@ -1,4 +1,4 @@
-Engine: qtfuzzylite
+Engine: AllTerms
InputVariable: AllInputTerms
enabled: true
range: 0.000 6.500
@@ -25,7 +25,7 @@ InputVariable: AllInputTerms
OutputVariable: AllOutputTerms
enabled: true
range: 0.000 6.500
- accumulation: Maximum
+ aggregation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
@@ -54,7 +54,8 @@ RuleBlock:
enabled: true
conjunction: Minimum
disjunction: Maximum
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if AllInputTerms is A then AllOutputTerms is T
rule: if AllInputTerms is B then AllOutputTerms is S
rule: if AllInputTerms is C then AllOutputTerms is R
@@ -74,4 +75,4 @@ RuleBlock:
rule: if AllInputTerms is Q then AllOutputTerms is D
rule: if AllInputTerms is R then AllOutputTerms is C
rule: if AllInputTerms is S then AllOutputTerms is B
- rule: if AllInputTerms is T then AllOutputTerms is A \ No newline at end of file
+ rule: if AllInputTerms is T then AllOutputTerms is A
diff --git a/examples/original/mamdani/Laundry.fll b/examples/original/mamdani/Laundry.fll
index cc002bb..36e67d5 100644
--- a/examples/original/mamdani/Laundry.fll
+++ b/examples/original/mamdani/Laundry.fll
@@ -12,7 +12,7 @@ InputVariable: Dirt
OutputVariable: Detergent
enabled: true
range: 0.000 80.000
- accumulation: Maximum
+ aggregation: Maximum
defuzzifier: MeanOfMaximum 500
default: nan
lock-previous: false
@@ -23,7 +23,7 @@ OutputVariable: Detergent
OutputVariable: Cycle
enabled: true
range: 0.000 20.000
- accumulation: Maximum
+ aggregation: Maximum
defuzzifier: MeanOfMaximum 500
default: nan
lock-previous: false
@@ -34,10 +34,11 @@ RuleBlock:
enabled: true
conjunction: Minimum
disjunction: Maximum
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if Load is small and Dirt is not high then Detergent is less_than_usual
rule: if Load is small and Dirt is high then Detergent is usual
rule: if Load is normal and Dirt is low then Detergent is less_than_usual
rule: if Load is normal and Dirt is high then Detergent is more_than_usual
rule: if Detergent is usual or Detergent is less_than_usual then Cycle is short
- rule: if Detergent is more_than_usual then Cycle is long \ No newline at end of file
+ rule: if Detergent is more_than_usual then Cycle is long
diff --git a/examples/original/mamdani/SimpleDimmer.fll b/examples/original/mamdani/SimpleDimmer.fll
index 3a4f8f9..ab91b72 100644
--- a/examples/original/mamdani/SimpleDimmer.fll
+++ b/examples/original/mamdani/SimpleDimmer.fll
@@ -1,4 +1,4 @@
-Engine: simple-dimmer
+Engine: SimpleDimmer
InputVariable: Ambient
enabled: true
range: 0.000 1.000
@@ -8,7 +8,7 @@ InputVariable: Ambient
OutputVariable: Power
enabled: true
range: 0.000 1.000
- accumulation: Maximum
+ aggregation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
@@ -20,7 +20,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if Ambient is DARK then Power is HIGH
rule: if Ambient is MEDIUM then Power is MEDIUM
- rule: if Ambient is BRIGHT then Power is LOW \ No newline at end of file
+ rule: if Ambient is BRIGHT then Power is LOW
diff --git a/examples/original/mamdani/SimpleDimmerInverse.fll b/examples/original/mamdani/SimpleDimmerInverse.fll
index fd6b945..3cd7a4a 100644
--- a/examples/original/mamdani/SimpleDimmerInverse.fll
+++ b/examples/original/mamdani/SimpleDimmerInverse.fll
@@ -1,4 +1,4 @@
-Engine: simple-dimmer
+Engine: SimpleDimmerInverse
InputVariable: Ambient
enabled: true
range: 0.000 1.000
@@ -8,7 +8,7 @@ InputVariable: Ambient
OutputVariable: Power
enabled: true
range: 0.000 1.000
- accumulation: Maximum
+ aggregation: Maximum
defuzzifier: Centroid 200
default: nan
lock-previous: false
@@ -19,7 +19,7 @@ OutputVariable: Power
OutputVariable: InversePower
enabled: true
range: 0.000 1.000
- accumulation: Maximum
+ aggregation: Maximum
defuzzifier: Centroid 500
default: nan
lock-previous: false
@@ -31,10 +31,11 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if Ambient is DARK then Power is HIGH
rule: if Ambient is MEDIUM then Power is MEDIUM
rule: if Ambient is BRIGHT then Power is LOW
rule: if Power is LOW then InversePower is HIGH
rule: if Power is MEDIUM then InversePower is MEDIUM
- rule: if Power is HIGH then InversePower is LOW \ No newline at end of file
+ rule: if Power is HIGH then InversePower is LOW
diff --git a/examples/original/mamdani/octave/investment_portfolio.fll b/examples/original/mamdani/octave/investment_portfolio.fll
index 4bb14e1..a383512 100644
--- a/examples/original/mamdani/octave/investment_portfolio.fll
+++ b/examples/original/mamdani/octave/investment_portfolio.fll
@@ -1,4 +1,4 @@
-Engine: Investment-Portfolio
+Engine: investment_portfolio
InputVariable: Age
enabled: true
range: 20.000 100.000
@@ -12,7 +12,7 @@ InputVariable: RiskTolerance
OutputVariable: PercentageInStocks
enabled: true
range: 0.000 100.000
- accumulation: EinsteinSum
+ aggregation: EinsteinSum
defuzzifier: Centroid 200
default: nan
lock-previous: false
@@ -24,8 +24,9 @@ RuleBlock:
enabled: true
conjunction: EinsteinProduct
disjunction: EinsteinSum
- activation: EinsteinProduct
+ implication: EinsteinProduct
+ activation: General
rule: if Age is Young or RiskTolerance is High then PercentageInStocks is AboutEightyFive
rule: if Age is Old or RiskTolerance is Low then PercentageInStocks is AboutFifteen
rule: if Age is not extremely Old and RiskTolerance is not extremely Low then PercentageInStocks is AboutFifty with 0.500
- rule: if Age is not extremely Young and RiskTolerance is not extremely High then PercentageInStocks is AboutFifty with 0.500 \ No newline at end of file
+ rule: if Age is not extremely Young and RiskTolerance is not extremely High then PercentageInStocks is AboutFifty with 0.500
diff --git a/examples/original/mamdani/octave/mamdani_tip_calculator.fll b/examples/original/mamdani/octave/mamdani_tip_calculator.fll
index b6c1920..15a94b9 100644
--- a/examples/original/mamdani/octave/mamdani_tip_calculator.fll
+++ b/examples/original/mamdani/octave/mamdani_tip_calculator.fll
@@ -1,4 +1,4 @@
-Engine: Mamdani-Tip-Calculator
+Engine: mamdani_tip_calculator
InputVariable: FoodQuality
enabled: true
range: 1.000 10.000
@@ -12,7 +12,7 @@ InputVariable: Service
OutputVariable: Tip
enabled: true
range: 0.000 30.000
- accumulation: AlgebraicSum
+ aggregation: AlgebraicSum
defuzzifier: Centroid 200
default: nan
lock-previous: false
@@ -23,7 +23,7 @@ OutputVariable: Tip
OutputVariable: CheckPlusTip
enabled: true
range: 1.000 1.300
- accumulation: AlgebraicSum
+ aggregation: AlgebraicSum
defuzzifier: Centroid 200
default: nan
lock-previous: false
@@ -35,8 +35,9 @@ RuleBlock:
enabled: true
conjunction: AlgebraicProduct
disjunction: Maximum
- activation: Minimum
+ implication: Minimum
+ activation: General
rule: if FoodQuality is Bad and Service is Bad then Tip is AboutTenPercent and CheckPlusTip is PlusAboutTenPercent
rule: if FoodQuality is Bad and Service is Good then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent
rule: if FoodQuality is Good and Service is Bad then Tip is AboutFifteenPercent and CheckPlusTip is PlusAboutFifteenPercent
- rule: if FoodQuality is Good and Service is Good then Tip is AboutTwentyPercent and CheckPlusTip is PlusAboutTwentyPercent \ No newline at end of file
+ rule: if FoodQuality is Good and Service is Good then Tip is AboutTwentyPercent and CheckPlusTip is PlusAboutTwentyPercent
diff --git a/examples/original/takagi-sugeno/SimpleDimmer.fll b/examples/original/takagi-sugeno/SimpleDimmer.fll
index 15050ee..dc46ec8 100644
--- a/examples/original/takagi-sugeno/SimpleDimmer.fll
+++ b/examples/original/takagi-sugeno/SimpleDimmer.fll
@@ -1,4 +1,4 @@
-Engine: simple-dimmer
+Engine: SimpleDimmer
InputVariable: Ambient
enabled: true
range: 0.000 1.000
@@ -8,7 +8,7 @@ InputVariable: Ambient
OutputVariable: Power
enabled: true
range: 0.000 1.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
@@ -20,7 +20,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if Ambient is DARK then Power is HIGH
rule: if Ambient is MEDIUM then Power is MEDIUM
rule: if Ambient is BRIGHT then Power is LOW
diff --git a/examples/original/takagi-sugeno/approximation.fll b/examples/original/takagi-sugeno/approximation.fll
index 66fb813..63964dc 100644
--- a/examples/original/takagi-sugeno/approximation.fll
+++ b/examples/original/takagi-sugeno/approximation.fll
@@ -1,4 +1,4 @@
-Engine: approximation of sin(x)/x
+Engine: approximation
InputVariable: inputX
enabled: true
range: 0.000 10.000
@@ -14,7 +14,7 @@ InputVariable: inputX
OutputVariable: outputFx
enabled: true
range: -1.000 1.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: true
@@ -31,7 +31,7 @@ OutputVariable: outputFx
OutputVariable: trueFx
enabled: true
range: -1.000 1.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage
default: nan
lock-previous: true
@@ -40,7 +40,7 @@ OutputVariable: trueFx
OutputVariable: diffFx
enabled: true
range: -1.000 1.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage
default: nan
lock-previous: false
@@ -50,7 +50,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if inputX is NEAR_1 then outputFx is f1
rule: if inputX is NEAR_2 then outputFx is f2
rule: if inputX is NEAR_3 then outputFx is f3
diff --git a/examples/original/takagi-sugeno/octave/cubic_approximator.fll b/examples/original/takagi-sugeno/octave/cubic_approximator.fll
index 28ba40a..7d2c157 100644
--- a/examples/original/takagi-sugeno/octave/cubic_approximator.fll
+++ b/examples/original/takagi-sugeno/octave/cubic_approximator.fll
@@ -1,4 +1,4 @@
-Engine: Cubic-Approximator
+Engine: cubic_approximator
InputVariable: X
enabled: true
range: -5.000 5.000
@@ -16,7 +16,7 @@ InputVariable: X
OutputVariable: ApproxXCubed
enabled: true
range: -5.000 5.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
@@ -36,7 +36,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if X is AboutNegFive then ApproxXCubed is TangentatNegFive
rule: if X is AboutNegFour then ApproxXCubed is TangentatNegFour
rule: if X is AboutNegThree then ApproxXCubed is TangentatNegThree
diff --git a/examples/original/takagi-sugeno/octave/heart_disease_risk.fll b/examples/original/takagi-sugeno/octave/heart_disease_risk.fll
index c401dd4..4c60466 100644
--- a/examples/original/takagi-sugeno/octave/heart_disease_risk.fll
+++ b/examples/original/takagi-sugeno/octave/heart_disease_risk.fll
@@ -1,4 +1,4 @@
-Engine: Heart-Disease-Risk
+Engine: heart_disease_risk
InputVariable: LDLLevel
enabled: true
range: 0.000 300.000
@@ -16,7 +16,7 @@ InputVariable: HDLLevel
OutputVariable: HeartDiseaseRisk
enabled: true
range: 0.000 10.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
@@ -30,7 +30,8 @@ RuleBlock:
enabled: true
conjunction: Minimum
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if LDLLevel is Low and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk
rule: if LDLLevel is Low and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk
rule: if LDLLevel is Low and HDLLevel is HighHDL then HeartDiseaseRisk is NoRisk
diff --git a/examples/original/takagi-sugeno/octave/linear_tip_calculator.fll b/examples/original/takagi-sugeno/octave/linear_tip_calculator.fll
index 34b0334..3b99fc9 100644
--- a/examples/original/takagi-sugeno/octave/linear_tip_calculator.fll
+++ b/examples/original/takagi-sugeno/octave/linear_tip_calculator.fll
@@ -1,4 +1,4 @@
-Engine: Linear-Tip-Calculator
+Engine: linear_tip_calculator
InputVariable: FoodQuality
enabled: true
range: 1.000 10.000
@@ -12,7 +12,7 @@ InputVariable: Service
OutputVariable: Tip
enabled: true
range: 10.000 20.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
@@ -24,7 +24,8 @@ RuleBlock:
enabled: true
conjunction: Minimum
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if FoodQuality is Bad and Service is Bad then Tip is TenPercent
rule: if FoodQuality is Bad and Service is Good then Tip is FifteenPercent
rule: if FoodQuality is Good and Service is Bad then Tip is FifteenPercent
diff --git a/examples/original/takagi-sugeno/octave/sugeno_tip_calculator.fll b/examples/original/takagi-sugeno/octave/sugeno_tip_calculator.fll
index 2006e71..19c5875 100644
--- a/examples/original/takagi-sugeno/octave/sugeno_tip_calculator.fll
+++ b/examples/original/takagi-sugeno/octave/sugeno_tip_calculator.fll
@@ -1,4 +1,4 @@
-Engine: Sugeno-Tip-Calculator
+Engine: sugeno_tip_calculator
InputVariable: FoodQuality
enabled: true
range: 1.000 10.000
@@ -12,7 +12,7 @@ InputVariable: Service
OutputVariable: CheapTip
enabled: true
range: 5.000 25.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
@@ -23,7 +23,7 @@ OutputVariable: CheapTip
OutputVariable: AverageTip
enabled: true
range: 5.000 25.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
@@ -34,7 +34,7 @@ OutputVariable: AverageTip
OutputVariable: GenerousTip
enabled: true
range: 5.000 25.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
@@ -46,7 +46,8 @@ RuleBlock:
enabled: true
conjunction: EinsteinProduct
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if FoodQuality is extremely Bad and Service is extremely Bad then CheapTip is extremely Low and AverageTip is very Low and GenerousTip is Low
rule: if FoodQuality is Good and Service is extremely Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium
rule: if FoodQuality is very Good and Service is very Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High
diff --git a/examples/original/tsukamoto/tsukamoto.fll b/examples/original/tsukamoto/tsukamoto.fll
index 1811b81..b8acf99 100644
--- a/examples/original/tsukamoto/tsukamoto.fll
+++ b/examples/original/tsukamoto/tsukamoto.fll
@@ -1,4 +1,4 @@
-Engine:
+Engine: tsukamoto
InputVariable: X
enabled: true
range: -10.000 10.000
@@ -8,7 +8,7 @@ InputVariable: X
OutputVariable: Ramps
enabled: true
range: 0.000 1.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage
default: nan
lock-previous: false
@@ -19,7 +19,7 @@ OutputVariable: Ramps
OutputVariable: Sigmoids
enabled: true
range: 0.020 1.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage
default: nan
lock-previous: false
@@ -30,7 +30,7 @@ OutputVariable: Sigmoids
OutputVariable: ZSShapes
enabled: true
range: 0.000 1.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage
default: nan
lock-previous: false
@@ -41,7 +41,7 @@ OutputVariable: ZSShapes
OutputVariable: Concaves
enabled: true
range: 0.000 1.000
- accumulation: none
+ aggregation: none
defuzzifier: WeightedAverage
default: nan
lock-previous: false
@@ -53,7 +53,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if X is small then Ramps is a and Sigmoids is a and ZSShapes is a and Concaves is a
rule: if X is medium then Ramps is b and Sigmoids is b and ZSShapes is b and Concaves is b
- rule: if X is large then Ramps is c and Sigmoids is c and ZSShapes is c and Concaves is c \ No newline at end of file
+ rule: if X is large then Ramps is c and Sigmoids is c and ZSShapes is c and Concaves is c
diff --git a/examples/takagi-sugeno/ObstacleAvoidance.R b/examples/takagi-sugeno/ObstacleAvoidance.R
new file mode 100644
index 0000000..eb96813
--- /dev/null
+++ b/examples/takagi-sugeno/ObstacleAvoidance.R
@@ -0,0 +1,57 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "ObstacleAvoidance"
+engine.fll = "Engine: ObstacleAvoidance
+InputVariable: obstacle
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: tsSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: left Constant 0.333
+ term: right Constant 0.666
+RuleBlock: takagiSugeno
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if obstacle is left then tsSteer is right
+ rule: if obstacle is right then tsSteer is left"
+
+engine.fldFile = "ObstacleAvoidance.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(obstacle, tsSteer)) +
+ geom_line(aes(color=tsSteer), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("obstacle vs tsSteer")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(obstacle, tsSteer)) +
+ geom_line(aes(color=tsSteer), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("tsSteer vs obstacle")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/takagi-sugeno/ObstacleAvoidance.cpp b/examples/takagi-sugeno/ObstacleAvoidance.cpp
new file mode 100644
index 0000000..32d6ba9
--- /dev/null
+++ b/examples/takagi-sugeno/ObstacleAvoidance.cpp
@@ -0,0 +1,49 @@
+#include <fl/Headers.h>
+
+int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
+using namespace fl;
+
+Engine* engine = new Engine;
+engine->setName("ObstacleAvoidance");
+engine->setDescription("");
+
+InputVariable* obstacle = new InputVariable;
+obstacle->setName("obstacle");
+obstacle->setDescription("");
+obstacle->setEnabled(true);
+obstacle->setRange(0.000, 1.000);
+obstacle->setLockValueInRange(false);
+obstacle->addTerm(new Ramp("left", 1.000, 0.000));
+obstacle->addTerm(new Ramp("right", 0.000, 1.000));
+engine->addInputVariable(obstacle);
+
+OutputVariable* tsSteer = new OutputVariable;
+tsSteer->setName("tsSteer");
+tsSteer->setDescription("");
+tsSteer->setEnabled(true);
+tsSteer->setRange(0.000, 1.000);
+tsSteer->setLockValueInRange(false);
+tsSteer->setAggregation(new Maximum);
+tsSteer->setDefuzzifier(new WeightedAverage("Automatic"));
+tsSteer->setDefaultValue(fl::nan);
+tsSteer->setLockPreviousValue(false);
+tsSteer->addTerm(new Constant("left", 0.333));
+tsSteer->addTerm(new Constant("right", 0.666));
+engine->addOutputVariable(tsSteer);
+
+RuleBlock* takagiSugeno = new RuleBlock;
+takagiSugeno->setName("takagiSugeno");
+takagiSugeno->setDescription("");
+takagiSugeno->setEnabled(true);
+takagiSugeno->setConjunction(fl::null);
+takagiSugeno->setDisjunction(fl::null);
+takagiSugeno->setImplication(fl::null);
+takagiSugeno->setActivation(new General);
+takagiSugeno->addRule(Rule::parse("if obstacle is left then tsSteer is right", engine));
+takagiSugeno->addRule(Rule::parse("if obstacle is right then tsSteer is left", engine));
+engine->addRuleBlock(takagiSugeno);
+
+
+}
diff --git a/examples/takagi-sugeno/ObstacleAvoidance.fcl b/examples/takagi-sugeno/ObstacleAvoidance.fcl
new file mode 100644
index 0000000..fc4348b
--- /dev/null
+++ b/examples/takagi-sugeno/ObstacleAvoidance.fcl
@@ -0,0 +1,33 @@
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK ObstacleAvoidance
+
+VAR_INPUT
+ obstacle: REAL;
+END_VAR
+
+VAR_OUTPUT
+ tsSteer: REAL;
+END_VAR
+
+FUZZIFY obstacle
+ RANGE := (0.000 .. 1.000);
+ TERM left := Ramp 1.000 0.000;
+ TERM right := Ramp 0.000 1.000;
+END_FUZZIFY
+
+DEFUZZIFY tsSteer
+ RANGE := (0.000 .. 1.000);
+ TERM left := 0.333;
+ TERM right := 0.666;
+ METHOD : COGS;
+ ACCU : MAX;
+ DEFAULT := nan;
+END_DEFUZZIFY
+
+RULEBLOCK takagiSugeno
+ RULE 1 : if obstacle is left then tsSteer is right
+ RULE 2 : if obstacle is right then tsSteer is left
+END_RULEBLOCK
+
+END_FUNCTION_BLOCK
diff --git a/examples/takagi-sugeno/ObstacleAvoidance.fis b/examples/takagi-sugeno/ObstacleAvoidance.fis
new file mode 100644
index 0000000..16c5791
--- /dev/null
+++ b/examples/takagi-sugeno/ObstacleAvoidance.fis
@@ -0,0 +1,32 @@
+#Code automatically generated with fuzzylite 6.0.
+
+[System]
+Name='ObstacleAvoidance'
+Type='sugeno'
+Version=6.0
+NumInputs=1
+NumOutputs=1
+NumRules=2
+AndMethod='min'
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
+DefuzzMethod='wtaver'
+
+[Input1]
+Name='obstacle'
+Range=[0.000 1.000]
+NumMFs=2
+MF1='left':'rampmf',[1.000 0.000]
+MF2='right':'rampmf',[0.000 1.000]
+
+[Output1]
+Name='tsSteer'
+Range=[0.000 1.000]
+NumMFs=2
+MF1='left':'constant',[0.333]
+MF2='right':'constant',[0.666]
+
+[Rules]
+1.000 , 2.000 (1.000) : 1
+2.000 , 1.000 (1.000) : 1
diff --git a/examples/takagi-sugeno/ObstacleAvoidance.fld b/examples/takagi-sugeno/ObstacleAvoidance.fld
new file mode 100644
index 0000000..00467f3
--- /dev/null
+++ b/examples/takagi-sugeno/ObstacleAvoidance.fld
@@ -0,0 +1,1025 @@
+obstacle tsSteer
+0.000000000 0.666000000
+0.000977517 0.665674487
+0.001955034 0.665348974
+0.002932551 0.665023460
+0.003910068 0.664697947
+0.004887586 0.664372434
+0.005865103 0.664046921
+0.006842620 0.663721408
+0.007820137 0.663395894
+0.008797654 0.663070381
+0.009775171 0.662744868
+0.010752688 0.662419355
+0.011730205 0.662093842
+0.012707722 0.661768328
+0.013685239 0.661442815
+0.014662757 0.661117302
+0.015640274 0.660791789
+0.016617791 0.660466276
+0.017595308 0.660140762
+0.018572825 0.659815249
+0.019550342 0.659489736
+0.020527859 0.659164223
+0.021505376 0.658838710
+0.022482893 0.658513196
+0.023460411 0.658187683
+0.024437928 0.657862170
+0.025415445 0.657536657
+0.026392962 0.657211144
+0.027370479 0.656885630
+0.028347996 0.656560117
+0.029325513 0.656234604
+0.030303030 0.655909091
+0.031280547 0.655583578
+0.032258065 0.655258065
+0.033235582 0.654932551
+0.034213099 0.654607038
+0.035190616 0.654281525
+0.036168133 0.653956012
+0.037145650 0.653630499
+0.038123167 0.653304985
+0.039100684 0.652979472
+0.040078201 0.652653959
+0.041055718 0.652328446
+0.042033236 0.652002933
+0.043010753 0.651677419
+0.043988270 0.651351906
+0.044965787 0.651026393
+0.045943304 0.650700880
+0.046920821 0.650375367
+0.047898338 0.650049853
+0.048875855 0.649724340
+0.049853372 0.649398827
+0.050830890 0.649073314
+0.051808407 0.648747801
+0.052785924 0.648422287
+0.053763441 0.648096774
+0.054740958 0.647771261
+0.055718475 0.647445748
+0.056695992 0.647120235
+0.057673509 0.646794721
+0.058651026 0.646469208
+0.059628543 0.646143695
+0.060606061 0.645818182
+0.061583578 0.645492669
+0.062561095 0.645167155
+0.063538612 0.644841642
+0.064516129 0.644516129
+0.065493646 0.644190616
+0.066471163 0.643865103
+0.067448680 0.643539589
+0.068426197 0.643214076
+0.069403715 0.642888563
+0.070381232 0.642563050
+0.071358749 0.642237537
+0.072336266 0.641912023
+0.073313783 0.641586510
+0.074291300 0.641260997
+0.075268817 0.640935484
+0.076246334 0.640609971
+0.077223851 0.640284457
+0.078201369 0.639958944
+0.079178886 0.639633431
+0.080156403 0.639307918
+0.081133920 0.638982405
+0.082111437 0.638656891
+0.083088954 0.638331378
+0.084066471 0.638005865
+0.085043988 0.637680352
+0.086021505 0.637354839
+0.086999022 0.637029326
+0.087976540 0.636703812
+0.088954057 0.636378299
+0.089931574 0.636052786
+0.090909091 0.635727273
+0.091886608 0.635401760
+0.092864125 0.635076246
+0.093841642 0.634750733
+0.094819159 0.634425220
+0.095796676 0.634099707
+0.096774194 0.633774194
+0.097751711 0.633448680
+0.098729228 0.633123167
+0.099706745 0.632797654
+0.100684262 0.632472141
+0.101661779 0.632146628
+0.102639296 0.631821114
+0.103616813 0.631495601
+0.104594330 0.631170088
+0.105571848 0.630844575
+0.106549365 0.630519062
+0.107526882 0.630193548
+0.108504399 0.629868035
+0.109481916 0.629542522
+0.110459433 0.629217009
+0.111436950 0.628891496
+0.112414467 0.628565982
+0.113391984 0.628240469
+0.114369501 0.627914956
+0.115347019 0.627589443
+0.116324536 0.627263930
+0.117302053 0.626938416
+0.118279570 0.626612903
+0.119257087 0.626287390
+0.120234604 0.625961877
+0.121212121 0.625636364
+0.122189638 0.625310850
+0.123167155 0.624985337
+0.124144673 0.624659824
+0.125122190 0.624334311
+0.126099707 0.624008798
+0.127077224 0.623683284
+0.128054741 0.623357771
+0.129032258 0.623032258
+0.130009775 0.622706745
+0.130987292 0.622381232
+0.131964809 0.622055718
+0.132942326 0.621730205
+0.133919844 0.621404692
+0.134897361 0.621079179
+0.135874878 0.620753666
+0.136852395 0.620428152
+0.137829912 0.620102639
+0.138807429 0.619777126
+0.139784946 0.619451613
+0.140762463 0.619126100
+0.141739980 0.618800587
+0.142717498 0.618475073
+0.143695015 0.618149560
+0.144672532 0.617824047
+0.145650049 0.617498534
+0.146627566 0.617173021
+0.147605083 0.616847507
+0.148582600 0.616521994
+0.149560117 0.616196481
+0.150537634 0.615870968
+0.151515152 0.615545455
+0.152492669 0.615219941
+0.153470186 0.614894428
+0.154447703 0.614568915
+0.155425220 0.614243402
+0.156402737 0.613917889
+0.157380254 0.613592375
+0.158357771 0.613266862
+0.159335288 0.612941349
+0.160312805 0.612615836
+0.161290323 0.612290323
+0.162267840 0.611964809
+0.163245357 0.611639296
+0.164222874 0.611313783
+0.165200391 0.610988270
+0.166177908 0.610662757
+0.167155425 0.610337243
+0.168132942 0.610011730
+0.169110459 0.609686217
+0.170087977 0.609360704
+0.171065494 0.609035191
+0.172043011 0.608709677
+0.173020528 0.608384164
+0.173998045 0.608058651
+0.174975562 0.607733138
+0.175953079 0.607407625
+0.176930596 0.607082111
+0.177908113 0.606756598
+0.178885630 0.606431085
+0.179863148 0.606105572
+0.180840665 0.605780059
+0.181818182 0.605454545
+0.182795699 0.605129032
+0.183773216 0.604803519
+0.184750733 0.604478006
+0.185728250 0.604152493
+0.186705767 0.603826979
+0.187683284 0.603501466
+0.188660802 0.603175953
+0.189638319 0.602850440
+0.190615836 0.602524927
+0.191593353 0.602199413
+0.192570870 0.601873900
+0.193548387 0.601548387
+0.194525904 0.601222874
+0.195503421 0.600897361
+0.196480938 0.600571848
+0.197458456 0.600246334
+0.198435973 0.599920821
+0.199413490 0.599595308
+0.200391007 0.599269795
+0.201368524 0.598944282
+0.202346041 0.598618768
+0.203323558 0.598293255
+0.204301075 0.597967742
+0.205278592 0.597642229
+0.206256109 0.597316716
+0.207233627 0.596991202
+0.208211144 0.596665689
+0.209188661 0.596340176
+0.210166178 0.596014663
+0.211143695 0.595689150
+0.212121212 0.595363636
+0.213098729 0.595038123
+0.214076246 0.594712610
+0.215053763 0.594387097
+0.216031281 0.594061584
+0.217008798 0.593736070
+0.217986315 0.593410557
+0.218963832 0.593085044
+0.219941349 0.592759531
+0.220918866 0.592434018
+0.221896383 0.592108504
+0.222873900 0.591782991
+0.223851417 0.591457478
+0.224828935 0.591131965
+0.225806452 0.590806452
+0.226783969 0.590480938
+0.227761486 0.590155425
+0.228739003 0.589829912
+0.229716520 0.589504399
+0.230694037 0.589178886
+0.231671554 0.588853372
+0.232649071 0.588527859
+0.233626588 0.588202346
+0.234604106 0.587876833
+0.235581623 0.587551320
+0.236559140 0.587225806
+0.237536657 0.586900293
+0.238514174 0.586574780
+0.239491691 0.586249267
+0.240469208 0.585923754
+0.241446725 0.585598240
+0.242424242 0.585272727
+0.243401760 0.584947214
+0.244379277 0.584621701
+0.245356794 0.584296188
+0.246334311 0.583970674
+0.247311828 0.583645161
+0.248289345 0.583319648
+0.249266862 0.582994135
+0.250244379 0.582668622
+0.251221896 0.582343109
+0.252199413 0.582017595
+0.253176931 0.581692082
+0.254154448 0.581366569
+0.255131965 0.581041056
+0.256109482 0.580715543
+0.257086999 0.580390029
+0.258064516 0.580064516
+0.259042033 0.579739003
+0.260019550 0.579413490
+0.260997067 0.579087977
+0.261974585 0.578762463
+0.262952102 0.578436950
+0.263929619 0.578111437
+0.264907136 0.577785924
+0.265884653 0.577460411
+0.266862170 0.577134897
+0.267839687 0.576809384
+0.268817204 0.576483871
+0.269794721 0.576158358
+0.270772239 0.575832845
+0.271749756 0.575507331
+0.272727273 0.575181818
+0.273704790 0.574856305
+0.274682307 0.574530792
+0.275659824 0.574205279
+0.276637341 0.573879765
+0.277614858 0.573554252
+0.278592375 0.573228739
+0.279569892 0.572903226
+0.280547410 0.572577713
+0.281524927 0.572252199
+0.282502444 0.571926686
+0.283479961 0.571601173
+0.284457478 0.571275660
+0.285434995 0.570950147
+0.286412512 0.570624633
+0.287390029 0.570299120
+0.288367546 0.569973607
+0.289345064 0.569648094
+0.290322581 0.569322581
+0.291300098 0.568997067
+0.292277615 0.568671554
+0.293255132 0.568346041
+0.294232649 0.568020528
+0.295210166 0.567695015
+0.296187683 0.567369501
+0.297165200 0.567043988
+0.298142717 0.566718475
+0.299120235 0.566392962
+0.300097752 0.566067449
+0.301075269 0.565741935
+0.302052786 0.565416422
+0.303030303 0.565090909
+0.304007820 0.564765396
+0.304985337 0.564439883
+0.305962854 0.564114370
+0.306940371 0.563788856
+0.307917889 0.563463343
+0.308895406 0.563137830
+0.309872923 0.562812317
+0.310850440 0.562486804
+0.311827957 0.562161290
+0.312805474 0.561835777
+0.313782991 0.561510264
+0.314760508 0.561184751
+0.315738025 0.560859238
+0.316715543 0.560533724
+0.317693060 0.560208211
+0.318670577 0.559882698
+0.319648094 0.559557185
+0.320625611 0.559231672
+0.321603128 0.558906158
+0.322580645 0.558580645
+0.323558162 0.558255132
+0.324535679 0.557929619
+0.325513196 0.557604106
+0.326490714 0.557278592
+0.327468231 0.556953079
+0.328445748 0.556627566
+0.329423265 0.556302053
+0.330400782 0.555976540
+0.331378299 0.555651026
+0.332355816 0.555325513
+0.333333333 0.555000000
+0.334310850 0.554674487
+0.335288368 0.554348974
+0.336265885 0.554023460
+0.337243402 0.553697947
+0.338220919 0.553372434
+0.339198436 0.553046921
+0.340175953 0.552721408
+0.341153470 0.552395894
+0.342130987 0.552070381
+0.343108504 0.551744868
+0.344086022 0.551419355
+0.345063539 0.551093842
+0.346041056 0.550768328
+0.347018573 0.550442815
+0.347996090 0.550117302
+0.348973607 0.549791789
+0.349951124 0.549466276
+0.350928641 0.549140762
+0.351906158 0.548815249
+0.352883675 0.548489736
+0.353861193 0.548164223
+0.354838710 0.547838710
+0.355816227 0.547513196
+0.356793744 0.547187683
+0.357771261 0.546862170
+0.358748778 0.546536657
+0.359726295 0.546211144
+0.360703812 0.545885630
+0.361681329 0.545560117
+0.362658847 0.545234604
+0.363636364 0.544909091
+0.364613881 0.544583578
+0.365591398 0.544258065
+0.366568915 0.543932551
+0.367546432 0.543607038
+0.368523949 0.543281525
+0.369501466 0.542956012
+0.370478983 0.542630499
+0.371456500 0.542304985
+0.372434018 0.541979472
+0.373411535 0.541653959
+0.374389052 0.541328446
+0.375366569 0.541002933
+0.376344086 0.540677419
+0.377321603 0.540351906
+0.378299120 0.540026393
+0.379276637 0.539700880
+0.380254154 0.539375367
+0.381231672 0.539049853
+0.382209189 0.538724340
+0.383186706 0.538398827
+0.384164223 0.538073314
+0.385141740 0.537747801
+0.386119257 0.537422287
+0.387096774 0.537096774
+0.388074291 0.536771261
+0.389051808 0.536445748
+0.390029326 0.536120235
+0.391006843 0.535794721
+0.391984360 0.535469208
+0.392961877 0.535143695
+0.393939394 0.534818182
+0.394916911 0.534492669
+0.395894428 0.534167155
+0.396871945 0.533841642
+0.397849462 0.533516129
+0.398826979 0.533190616
+0.399804497 0.532865103
+0.400782014 0.532539589
+0.401759531 0.532214076
+0.402737048 0.531888563
+0.403714565 0.531563050
+0.404692082 0.531237537
+0.405669599 0.530912023
+0.406647116 0.530586510
+0.407624633 0.530260997
+0.408602151 0.529935484
+0.409579668 0.529609971
+0.410557185 0.529284457
+0.411534702 0.528958944
+0.412512219 0.528633431
+0.413489736 0.528307918
+0.414467253 0.527982405
+0.415444770 0.527656891
+0.416422287 0.527331378
+0.417399804 0.527005865
+0.418377322 0.526680352
+0.419354839 0.526354839
+0.420332356 0.526029326
+0.421309873 0.525703812
+0.422287390 0.525378299
+0.423264907 0.525052786
+0.424242424 0.524727273
+0.425219941 0.524401760
+0.426197458 0.524076246
+0.427174976 0.523750733
+0.428152493 0.523425220
+0.429130010 0.523099707
+0.430107527 0.522774194
+0.431085044 0.522448680
+0.432062561 0.522123167
+0.433040078 0.521797654
+0.434017595 0.521472141
+0.434995112 0.521146628
+0.435972630 0.520821114
+0.436950147 0.520495601
+0.437927664 0.520170088
+0.438905181 0.519844575
+0.439882698 0.519519062
+0.440860215 0.519193548
+0.441837732 0.518868035
+0.442815249 0.518542522
+0.443792766 0.518217009
+0.444770283 0.517891496
+0.445747801 0.517565982
+0.446725318 0.517240469
+0.447702835 0.516914956
+0.448680352 0.516589443
+0.449657869 0.516263930
+0.450635386 0.515938416
+0.451612903 0.515612903
+0.452590420 0.515287390
+0.453567937 0.514961877
+0.454545455 0.514636364
+0.455522972 0.514310850
+0.456500489 0.513985337
+0.457478006 0.513659824
+0.458455523 0.513334311
+0.459433040 0.513008798
+0.460410557 0.512683284
+0.461388074 0.512357771
+0.462365591 0.512032258
+0.463343109 0.511706745
+0.464320626 0.511381232
+0.465298143 0.511055718
+0.466275660 0.510730205
+0.467253177 0.510404692
+0.468230694 0.510079179
+0.469208211 0.509753666
+0.470185728 0.509428152
+0.471163245 0.509102639
+0.472140762 0.508777126
+0.473118280 0.508451613
+0.474095797 0.508126100
+0.475073314 0.507800587
+0.476050831 0.507475073
+0.477028348 0.507149560
+0.478005865 0.506824047
+0.478983382 0.506498534
+0.479960899 0.506173021
+0.480938416 0.505847507
+0.481915934 0.505521994
+0.482893451 0.505196481
+0.483870968 0.504870968
+0.484848485 0.504545455
+0.485826002 0.504219941
+0.486803519 0.503894428
+0.487781036 0.503568915
+0.488758553 0.503243402
+0.489736070 0.502917889
+0.490713587 0.502592375
+0.491691105 0.502266862
+0.492668622 0.501941349
+0.493646139 0.501615836
+0.494623656 0.501290323
+0.495601173 0.500964809
+0.496578690 0.500639296
+0.497556207 0.500313783
+0.498533724 0.499988270
+0.499511241 0.499662757
+0.500488759 0.499337243
+0.501466276 0.499011730
+0.502443793 0.498686217
+0.503421310 0.498360704
+0.504398827 0.498035191
+0.505376344 0.497709677
+0.506353861 0.497384164
+0.507331378 0.497058651
+0.508308895 0.496733138
+0.509286413 0.496407625
+0.510263930 0.496082111
+0.511241447 0.495756598
+0.512218964 0.495431085
+0.513196481 0.495105572
+0.514173998 0.494780059
+0.515151515 0.494454545
+0.516129032 0.494129032
+0.517106549 0.493803519
+0.518084066 0.493478006
+0.519061584 0.493152493
+0.520039101 0.492826979
+0.521016618 0.492501466
+0.521994135 0.492175953
+0.522971652 0.491850440
+0.523949169 0.491524927
+0.524926686 0.491199413
+0.525904203 0.490873900
+0.526881720 0.490548387
+0.527859238 0.490222874
+0.528836755 0.489897361
+0.529814272 0.489571848
+0.530791789 0.489246334
+0.531769306 0.488920821
+0.532746823 0.488595308
+0.533724340 0.488269795
+0.534701857 0.487944282
+0.535679374 0.487618768
+0.536656891 0.487293255
+0.537634409 0.486967742
+0.538611926 0.486642229
+0.539589443 0.486316716
+0.540566960 0.485991202
+0.541544477 0.485665689
+0.542521994 0.485340176
+0.543499511 0.485014663
+0.544477028 0.484689150
+0.545454545 0.484363636
+0.546432063 0.484038123
+0.547409580 0.483712610
+0.548387097 0.483387097
+0.549364614 0.483061584
+0.550342131 0.482736070
+0.551319648 0.482410557
+0.552297165 0.482085044
+0.553274682 0.481759531
+0.554252199 0.481434018
+0.555229717 0.481108504
+0.556207234 0.480782991
+0.557184751 0.480457478
+0.558162268 0.480131965
+0.559139785 0.479806452
+0.560117302 0.479480938
+0.561094819 0.479155425
+0.562072336 0.478829912
+0.563049853 0.478504399
+0.564027370 0.478178886
+0.565004888 0.477853372
+0.565982405 0.477527859
+0.566959922 0.477202346
+0.567937439 0.476876833
+0.568914956 0.476551320
+0.569892473 0.476225806
+0.570869990 0.475900293
+0.571847507 0.475574780
+0.572825024 0.475249267
+0.573802542 0.474923754
+0.574780059 0.474598240
+0.575757576 0.474272727
+0.576735093 0.473947214
+0.577712610 0.473621701
+0.578690127 0.473296188
+0.579667644 0.472970674
+0.580645161 0.472645161
+0.581622678 0.472319648
+0.582600196 0.471994135
+0.583577713 0.471668622
+0.584555230 0.471343109
+0.585532747 0.471017595
+0.586510264 0.470692082
+0.587487781 0.470366569
+0.588465298 0.470041056
+0.589442815 0.469715543
+0.590420332 0.469390029
+0.591397849 0.469064516
+0.592375367 0.468739003
+0.593352884 0.468413490
+0.594330401 0.468087977
+0.595307918 0.467762463
+0.596285435 0.467436950
+0.597262952 0.467111437
+0.598240469 0.466785924
+0.599217986 0.466460411
+0.600195503 0.466134897
+0.601173021 0.465809384
+0.602150538 0.465483871
+0.603128055 0.465158358
+0.604105572 0.464832845
+0.605083089 0.464507331
+0.606060606 0.464181818
+0.607038123 0.463856305
+0.608015640 0.463530792
+0.608993157 0.463205279
+0.609970674 0.462879765
+0.610948192 0.462554252
+0.611925709 0.462228739
+0.612903226 0.461903226
+0.613880743 0.461577713
+0.614858260 0.461252199
+0.615835777 0.460926686
+0.616813294 0.460601173
+0.617790811 0.460275660
+0.618768328 0.459950147
+0.619745846 0.459624633
+0.620723363 0.459299120
+0.621700880 0.458973607
+0.622678397 0.458648094
+0.623655914 0.458322581
+0.624633431 0.457997067
+0.625610948 0.457671554
+0.626588465 0.457346041
+0.627565982 0.457020528
+0.628543500 0.456695015
+0.629521017 0.456369501
+0.630498534 0.456043988
+0.631476051 0.455718475
+0.632453568 0.455392962
+0.633431085 0.455067449
+0.634408602 0.454741935
+0.635386119 0.454416422
+0.636363636 0.454090909
+0.637341153 0.453765396
+0.638318671 0.453439883
+0.639296188 0.453114370
+0.640273705 0.452788856
+0.641251222 0.452463343
+0.642228739 0.452137830
+0.643206256 0.451812317
+0.644183773 0.451486804
+0.645161290 0.451161290
+0.646138807 0.450835777
+0.647116325 0.450510264
+0.648093842 0.450184751
+0.649071359 0.449859238
+0.650048876 0.449533724
+0.651026393 0.449208211
+0.652003910 0.448882698
+0.652981427 0.448557185
+0.653958944 0.448231672
+0.654936461 0.447906158
+0.655913978 0.447580645
+0.656891496 0.447255132
+0.657869013 0.446929619
+0.658846530 0.446604106
+0.659824047 0.446278592
+0.660801564 0.445953079
+0.661779081 0.445627566
+0.662756598 0.445302053
+0.663734115 0.444976540
+0.664711632 0.444651026
+0.665689150 0.444325513
+0.666666667 0.444000000
+0.667644184 0.443674487
+0.668621701 0.443348974
+0.669599218 0.443023460
+0.670576735 0.442697947
+0.671554252 0.442372434
+0.672531769 0.442046921
+0.673509286 0.441721408
+0.674486804 0.441395894
+0.675464321 0.441070381
+0.676441838 0.440744868
+0.677419355 0.440419355
+0.678396872 0.440093842
+0.679374389 0.439768328
+0.680351906 0.439442815
+0.681329423 0.439117302
+0.682306940 0.438791789
+0.683284457 0.438466276
+0.684261975 0.438140762
+0.685239492 0.437815249
+0.686217009 0.437489736
+0.687194526 0.437164223
+0.688172043 0.436838710
+0.689149560 0.436513196
+0.690127077 0.436187683
+0.691104594 0.435862170
+0.692082111 0.435536657
+0.693059629 0.435211144
+0.694037146 0.434885630
+0.695014663 0.434560117
+0.695992180 0.434234604
+0.696969697 0.433909091
+0.697947214 0.433583578
+0.698924731 0.433258065
+0.699902248 0.432932551
+0.700879765 0.432607038
+0.701857283 0.432281525
+0.702834800 0.431956012
+0.703812317 0.431630499
+0.704789834 0.431304985
+0.705767351 0.430979472
+0.706744868 0.430653959
+0.707722385 0.430328446
+0.708699902 0.430002933
+0.709677419 0.429677419
+0.710654936 0.429351906
+0.711632454 0.429026393
+0.712609971 0.428700880
+0.713587488 0.428375367
+0.714565005 0.428049853
+0.715542522 0.427724340
+0.716520039 0.427398827
+0.717497556 0.427073314
+0.718475073 0.426747801
+0.719452590 0.426422287
+0.720430108 0.426096774
+0.721407625 0.425771261
+0.722385142 0.425445748
+0.723362659 0.425120235
+0.724340176 0.424794721
+0.725317693 0.424469208
+0.726295210 0.424143695
+0.727272727 0.423818182
+0.728250244 0.423492669
+0.729227761 0.423167155
+0.730205279 0.422841642
+0.731182796 0.422516129
+0.732160313 0.422190616
+0.733137830 0.421865103
+0.734115347 0.421539589
+0.735092864 0.421214076
+0.736070381 0.420888563
+0.737047898 0.420563050
+0.738025415 0.420237537
+0.739002933 0.419912023
+0.739980450 0.419586510
+0.740957967 0.419260997
+0.741935484 0.418935484
+0.742913001 0.418609971
+0.743890518 0.418284457
+0.744868035 0.417958944
+0.745845552 0.417633431
+0.746823069 0.417307918
+0.747800587 0.416982405
+0.748778104 0.416656891
+0.749755621 0.416331378
+0.750733138 0.416005865
+0.751710655 0.415680352
+0.752688172 0.415354839
+0.753665689 0.415029326
+0.754643206 0.414703812
+0.755620723 0.414378299
+0.756598240 0.414052786
+0.757575758 0.413727273
+0.758553275 0.413401760
+0.759530792 0.413076246
+0.760508309 0.412750733
+0.761485826 0.412425220
+0.762463343 0.412099707
+0.763440860 0.411774194
+0.764418377 0.411448680
+0.765395894 0.411123167
+0.766373412 0.410797654
+0.767350929 0.410472141
+0.768328446 0.410146628
+0.769305963 0.409821114
+0.770283480 0.409495601
+0.771260997 0.409170088
+0.772238514 0.408844575
+0.773216031 0.408519062
+0.774193548 0.408193548
+0.775171065 0.407868035
+0.776148583 0.407542522
+0.777126100 0.407217009
+0.778103617 0.406891496
+0.779081134 0.406565982
+0.780058651 0.406240469
+0.781036168 0.405914956
+0.782013685 0.405589443
+0.782991202 0.405263930
+0.783968719 0.404938416
+0.784946237 0.404612903
+0.785923754 0.404287390
+0.786901271 0.403961877
+0.787878788 0.403636364
+0.788856305 0.403310850
+0.789833822 0.402985337
+0.790811339 0.402659824
+0.791788856 0.402334311
+0.792766373 0.402008798
+0.793743891 0.401683284
+0.794721408 0.401357771
+0.795698925 0.401032258
+0.796676442 0.400706745
+0.797653959 0.400381232
+0.798631476 0.400055718
+0.799608993 0.399730205
+0.800586510 0.399404692
+0.801564027 0.399079179
+0.802541544 0.398753666
+0.803519062 0.398428152
+0.804496579 0.398102639
+0.805474096 0.397777126
+0.806451613 0.397451613
+0.807429130 0.397126100
+0.808406647 0.396800587
+0.809384164 0.396475073
+0.810361681 0.396149560
+0.811339198 0.395824047
+0.812316716 0.395498534
+0.813294233 0.395173021
+0.814271750 0.394847507
+0.815249267 0.394521994
+0.816226784 0.394196481
+0.817204301 0.393870968
+0.818181818 0.393545455
+0.819159335 0.393219941
+0.820136852 0.392894428
+0.821114370 0.392568915
+0.822091887 0.392243402
+0.823069404 0.391917889
+0.824046921 0.391592375
+0.825024438 0.391266862
+0.826001955 0.390941349
+0.826979472 0.390615836
+0.827956989 0.390290323
+0.828934506 0.389964809
+0.829912023 0.389639296
+0.830889541 0.389313783
+0.831867058 0.388988270
+0.832844575 0.388662757
+0.833822092 0.388337243
+0.834799609 0.388011730
+0.835777126 0.387686217
+0.836754643 0.387360704
+0.837732160 0.387035191
+0.838709677 0.386709677
+0.839687195 0.386384164
+0.840664712 0.386058651
+0.841642229 0.385733138
+0.842619746 0.385407625
+0.843597263 0.385082111
+0.844574780 0.384756598
+0.845552297 0.384431085
+0.846529814 0.384105572
+0.847507331 0.383780059
+0.848484848 0.383454545
+0.849462366 0.383129032
+0.850439883 0.382803519
+0.851417400 0.382478006
+0.852394917 0.382152493
+0.853372434 0.381826979
+0.854349951 0.381501466
+0.855327468 0.381175953
+0.856304985 0.380850440
+0.857282502 0.380524927
+0.858260020 0.380199413
+0.859237537 0.379873900
+0.860215054 0.379548387
+0.861192571 0.379222874
+0.862170088 0.378897361
+0.863147605 0.378571848
+0.864125122 0.378246334
+0.865102639 0.377920821
+0.866080156 0.377595308
+0.867057674 0.377269795
+0.868035191 0.376944282
+0.869012708 0.376618768
+0.869990225 0.376293255
+0.870967742 0.375967742
+0.871945259 0.375642229
+0.872922776 0.375316716
+0.873900293 0.374991202
+0.874877810 0.374665689
+0.875855327 0.374340176
+0.876832845 0.374014663
+0.877810362 0.373689150
+0.878787879 0.373363636
+0.879765396 0.373038123
+0.880742913 0.372712610
+0.881720430 0.372387097
+0.882697947 0.372061584
+0.883675464 0.371736070
+0.884652981 0.371410557
+0.885630499 0.371085044
+0.886608016 0.370759531
+0.887585533 0.370434018
+0.888563050 0.370108504
+0.889540567 0.369782991
+0.890518084 0.369457478
+0.891495601 0.369131965
+0.892473118 0.368806452
+0.893450635 0.368480938
+0.894428152 0.368155425
+0.895405670 0.367829912
+0.896383187 0.367504399
+0.897360704 0.367178886
+0.898338221 0.366853372
+0.899315738 0.366527859
+0.900293255 0.366202346
+0.901270772 0.365876833
+0.902248289 0.365551320
+0.903225806 0.365225806
+0.904203324 0.364900293
+0.905180841 0.364574780
+0.906158358 0.364249267
+0.907135875 0.363923754
+0.908113392 0.363598240
+0.909090909 0.363272727
+0.910068426 0.362947214
+0.911045943 0.362621701
+0.912023460 0.362296188
+0.913000978 0.361970674
+0.913978495 0.361645161
+0.914956012 0.361319648
+0.915933529 0.360994135
+0.916911046 0.360668622
+0.917888563 0.360343109
+0.918866080 0.360017595
+0.919843597 0.359692082
+0.920821114 0.359366569
+0.921798631 0.359041056
+0.922776149 0.358715543
+0.923753666 0.358390029
+0.924731183 0.358064516
+0.925708700 0.357739003
+0.926686217 0.357413490
+0.927663734 0.357087977
+0.928641251 0.356762463
+0.929618768 0.356436950
+0.930596285 0.356111437
+0.931573803 0.355785924
+0.932551320 0.355460411
+0.933528837 0.355134897
+0.934506354 0.354809384
+0.935483871 0.354483871
+0.936461388 0.354158358
+0.937438905 0.353832845
+0.938416422 0.353507331
+0.939393939 0.353181818
+0.940371457 0.352856305
+0.941348974 0.352530792
+0.942326491 0.352205279
+0.943304008 0.351879765
+0.944281525 0.351554252
+0.945259042 0.351228739
+0.946236559 0.350903226
+0.947214076 0.350577713
+0.948191593 0.350252199
+0.949169110 0.349926686
+0.950146628 0.349601173
+0.951124145 0.349275660
+0.952101662 0.348950147
+0.953079179 0.348624633
+0.954056696 0.348299120
+0.955034213 0.347973607
+0.956011730 0.347648094
+0.956989247 0.347322581
+0.957966764 0.346997067
+0.958944282 0.346671554
+0.959921799 0.346346041
+0.960899316 0.346020528
+0.961876833 0.345695015
+0.962854350 0.345369501
+0.963831867 0.345043988
+0.964809384 0.344718475
+0.965786901 0.344392962
+0.966764418 0.344067449
+0.967741935 0.343741935
+0.968719453 0.343416422
+0.969696970 0.343090909
+0.970674487 0.342765396
+0.971652004 0.342439883
+0.972629521 0.342114370
+0.973607038 0.341788856
+0.974584555 0.341463343
+0.975562072 0.341137830
+0.976539589 0.340812317
+0.977517107 0.340486804
+0.978494624 0.340161290
+0.979472141 0.339835777
+0.980449658 0.339510264
+0.981427175 0.339184751
+0.982404692 0.338859238
+0.983382209 0.338533724
+0.984359726 0.338208211
+0.985337243 0.337882698
+0.986314761 0.337557185
+0.987292278 0.337231672
+0.988269795 0.336906158
+0.989247312 0.336580645
+0.990224829 0.336255132
+0.991202346 0.335929619
+0.992179863 0.335604106
+0.993157380 0.335278592
+0.994134897 0.334953079
+0.995112414 0.334627566
+0.996089932 0.334302053
+0.997067449 0.333976540
+0.998044966 0.333651026
+0.999022483 0.333325513
+1.000000000 0.333000000
diff --git a/examples/takagi-sugeno/ObstacleAvoidance.fll b/examples/takagi-sugeno/ObstacleAvoidance.fll
new file mode 100644
index 0000000..10b53f4
--- /dev/null
+++ b/examples/takagi-sugeno/ObstacleAvoidance.fll
@@ -0,0 +1,25 @@
+Engine: ObstacleAvoidance
+InputVariable: obstacle
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: left Ramp 1.000 0.000
+ term: right Ramp 0.000 1.000
+OutputVariable: tsSteer
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: left Constant 0.333
+ term: right Constant 0.666
+RuleBlock: takagiSugeno
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if obstacle is left then tsSteer is right
+ rule: if obstacle is right then tsSteer is left \ No newline at end of file
diff --git a/examples/takagi-sugeno/ObstacleAvoidance.java b/examples/takagi-sugeno/ObstacleAvoidance.java
new file mode 100644
index 0000000..c7c7f67
--- /dev/null
+++ b/examples/takagi-sugeno/ObstacleAvoidance.java
@@ -0,0 +1,60 @@
+import com.fuzzylite.*;
+import com.fuzzylite.activation.*
+import com.fuzzylite.defuzzifier.*;
+import com.fuzzylite.factory.*;
+import com.fuzzylite.hedge.*;
+import com.fuzzylite.imex.*;
+import com.fuzzylite.norm.*;
+import com.fuzzylite.norm.s.*;
+import com.fuzzylite.norm.t.*;
+import com.fuzzylite.rule.*;
+import com.fuzzylite.term.*;
+import com.fuzzylite.variable.*;
+
+public class ObstacleAvoidance{
+public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
+Engine engine = new Engine();
+engine.setName("ObstacleAvoidance");
+engine.setDescription("");
+
+InputVariable obstacle = new InputVariable();
+obstacle.setName("obstacle");
+obstacle.setDescription("");
+obstacle.setEnabled(true);
+obstacle.setRange(0.000, 1.000);
+obstacle.setLockValueInRange(false);
+obstacle.addTerm(new Ramp("left", 1.000, 0.000));
+obstacle.addTerm(new Ramp("right", 0.000, 1.000));
+engine.addInputVariable(obstacle);
+
+OutputVariable tsSteer = new OutputVariable();
+tsSteer.setName("tsSteer");
+tsSteer.setDescription("");
+tsSteer.setEnabled(true);
+tsSteer.setRange(0.000, 1.000);
+tsSteer.setLockValueInRange(false);
+tsSteer.setAggregation(new Maximum());
+tsSteer.setDefuzzifier(new WeightedAverage("Automatic"));
+tsSteer.setDefaultValue(Double.NaN);
+tsSteer.setLockPreviousValue(false);
+tsSteer.addTerm(new Constant("left", 0.333));
+tsSteer.addTerm(new Constant("right", 0.666));
+engine.addOutputVariable(tsSteer);
+
+RuleBlock takagiSugeno = new RuleBlock();
+takagiSugeno.setName("takagiSugeno");
+takagiSugeno.setDescription("");
+takagiSugeno.setEnabled(true);
+takagiSugeno.setConjunction(null);
+takagiSugeno.setDisjunction(null);
+takagiSugeno.setImplication(null);
+takagiSugeno.setActivation(new General());
+takagiSugeno.addRule(Rule.parse("if obstacle is left then tsSteer is right", engine));
+takagiSugeno.addRule(Rule.parse("if obstacle is right then tsSteer is left", engine));
+engine.addRuleBlock(takagiSugeno);
+
+
+}
+}
diff --git a/examples/takagi-sugeno/ObstacleAvoidance.pdf b/examples/takagi-sugeno/ObstacleAvoidance.pdf
new file mode 100644
index 0000000..28d0a7a
--- /dev/null
+++ b/examples/takagi-sugeno/ObstacleAvoidance.pdf
Binary files differ
diff --git a/examples/takagi-sugeno/SimpleDimmer.R b/examples/takagi-sugeno/SimpleDimmer.R
new file mode 100644
index 0000000..8502922
--- /dev/null
+++ b/examples/takagi-sugeno/SimpleDimmer.R
@@ -0,0 +1,60 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "SimpleDimmer"
+engine.fll = "Engine: SimpleDimmer
+InputVariable: Ambient
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ term: DARK Triangle 0.000 0.250 0.500
+ term: MEDIUM Triangle 0.250 0.500 0.750
+ term: BRIGHT Triangle 0.500 0.750 1.000
+OutputVariable: Power
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: LOW Constant 0.250
+ term: MEDIUM Constant 0.500
+ term: HIGH Constant 0.750
+RuleBlock:
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if Ambient is DARK then Power is HIGH
+ rule: if Ambient is MEDIUM then Power is MEDIUM
+ rule: if Ambient is BRIGHT then Power is LOW"
+
+engine.fldFile = "SimpleDimmer.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(Ambient, Power)) +
+ geom_line(aes(color=Power), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("Ambient vs Power")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(Ambient, Power)) +
+ geom_line(aes(color=Power), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("Power vs Ambient")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/takagi-sugeno/SimpleDimmer.cpp b/examples/takagi-sugeno/SimpleDimmer.cpp
index bd7e6ee..735096b 100644
--- a/examples/takagi-sugeno/SimpleDimmer.cpp
+++ b/examples/takagi-sugeno/SimpleDimmer.cpp
@@ -1,43 +1,51 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("simple-dimmer");
-
-InputVariable* inputVariable = new InputVariable;
-inputVariable->setEnabled(true);
-inputVariable->setName("Ambient");
-inputVariable->setRange(0.000, 1.000);
-inputVariable->addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
-inputVariable->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-inputVariable->addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
-engine->addInputVariable(inputVariable);
-
-OutputVariable* outputVariable = new OutputVariable;
-outputVariable->setEnabled(true);
-outputVariable->setName("Power");
-outputVariable->setRange(0.000, 1.000);
-outputVariable->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable->setDefaultValue(fl::nan);
-outputVariable->setLockPreviousOutputValue(false);
-outputVariable->setLockOutputValueInRange(false);
-outputVariable->addTerm(new Constant("LOW", 0.250));
-outputVariable->addTerm(new Constant("MEDIUM", 0.500));
-outputVariable->addTerm(new Constant("HIGH", 0.750));
-engine->addOutputVariable(outputVariable);
+engine->setName("SimpleDimmer");
+engine->setDescription("");
+
+InputVariable* Ambient = new InputVariable;
+Ambient->setName("Ambient");
+Ambient->setDescription("");
+Ambient->setEnabled(true);
+Ambient->setRange(0.000, 1.000);
+Ambient->setLockValueInRange(false);
+Ambient->addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+Ambient->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Ambient->addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+engine->addInputVariable(Ambient);
+
+OutputVariable* Power = new OutputVariable;
+Power->setName("Power");
+Power->setDescription("");
+Power->setEnabled(true);
+Power->setRange(0.000, 1.000);
+Power->setLockValueInRange(false);
+Power->setAggregation(fl::null);
+Power->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+Power->setDefaultValue(fl::nan);
+Power->setLockPreviousValue(false);
+Power->addTerm(new Constant("LOW", 0.250));
+Power->addTerm(new Constant("MEDIUM", 0.500));
+Power->addTerm(new Constant("HIGH", 0.750));
+engine->addOutputVariable(Power);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(fl::null);
ruleBlock->setDisjunction(fl::null);
-ruleBlock->setActivation(fl::null);
-ruleBlock->addRule(fl::Rule::parse("if Ambient is DARK then Power is HIGH", engine));
-ruleBlock->addRule(fl::Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
-ruleBlock->addRule(fl::Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
+ruleBlock->setImplication(fl::null);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if Ambient is DARK then Power is HIGH", engine));
+ruleBlock->addRule(Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
+ruleBlock->addRule(Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/takagi-sugeno/SimpleDimmer.fcl b/examples/takagi-sugeno/SimpleDimmer.fcl
index 65ccd94..a30f2c9 100644
--- a/examples/takagi-sugeno/SimpleDimmer.fcl
+++ b/examples/takagi-sugeno/SimpleDimmer.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK simple-dimmer
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK SimpleDimmer
VAR_INPUT
Ambient: REAL;
diff --git a/examples/takagi-sugeno/SimpleDimmer.fis b/examples/takagi-sugeno/SimpleDimmer.fis
index 9557f61..3988290 100644
--- a/examples/takagi-sugeno/SimpleDimmer.fis
+++ b/examples/takagi-sugeno/SimpleDimmer.fis
@@ -1,13 +1,16 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='simple-dimmer'
+Name='SimpleDimmer'
Type='sugeno'
+Version=6.0
NumInputs=1
NumOutputs=1
NumRules=3
-AndMethod=''
-OrMethod=''
-ImpMethod=''
-AggMethod=''
+AndMethod='min'
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
DefuzzMethod='wtaver'
[Input1]
diff --git a/examples/takagi-sugeno/SimpleDimmer.fld b/examples/takagi-sugeno/SimpleDimmer.fld
index 6efef0a..9c2d25b 100644
--- a/examples/takagi-sugeno/SimpleDimmer.fld
+++ b/examples/takagi-sugeno/SimpleDimmer.fld
@@ -1,1026 +1,1025 @@
-#@Engine: simple-dimmer;
-#@InputVariable: Ambient; @OutputVariable: Power;
-0.00000000 nan
-0.00097752 0.75000000
-0.00195503 0.75000000
-0.00293255 0.75000000
-0.00391007 0.75000000
-0.00488759 0.75000000
-0.00586510 0.75000000
-0.00684262 0.75000000
-0.00782014 0.75000000
-0.00879765 0.75000000
-0.00977517 0.75000000
-0.01075269 0.75000000
-0.01173021 0.75000000
-0.01270772 0.75000000
-0.01368524 0.75000000
-0.01466276 0.75000000
-0.01564027 0.75000000
-0.01661779 0.75000000
-0.01759531 0.75000000
-0.01857283 0.75000000
-0.01955034 0.75000000
-0.02052786 0.75000000
-0.02150538 0.75000000
-0.02248289 0.75000000
-0.02346041 0.75000000
-0.02443793 0.75000000
-0.02541544 0.75000000
-0.02639296 0.75000000
-0.02737048 0.75000000
-0.02834800 0.75000000
-0.02932551 0.75000000
-0.03030303 0.75000000
-0.03128055 0.75000000
-0.03225806 0.75000000
-0.03323558 0.75000000
-0.03421310 0.75000000
-0.03519062 0.75000000
-0.03616813 0.75000000
-0.03714565 0.75000000
-0.03812317 0.75000000
-0.03910068 0.75000000
-0.04007820 0.75000000
-0.04105572 0.75000000
-0.04203324 0.75000000
-0.04301075 0.75000000
-0.04398827 0.75000000
-0.04496579 0.75000000
-0.04594330 0.75000000
-0.04692082 0.75000000
-0.04789834 0.75000000
-0.04887586 0.75000000
-0.04985337 0.75000000
-0.05083089 0.75000000
-0.05180841 0.75000000
-0.05278592 0.75000000
-0.05376344 0.75000000
-0.05474096 0.75000000
-0.05571848 0.75000000
-0.05669599 0.75000000
-0.05767351 0.75000000
-0.05865103 0.75000000
-0.05962854 0.75000000
-0.06060606 0.75000000
-0.06158358 0.75000000
-0.06256109 0.75000000
-0.06353861 0.75000000
-0.06451613 0.75000000
-0.06549365 0.75000000
-0.06647116 0.75000000
-0.06744868 0.75000000
-0.06842620 0.75000000
-0.06940371 0.75000000
-0.07038123 0.75000000
-0.07135875 0.75000000
-0.07233627 0.75000000
-0.07331378 0.75000000
-0.07429130 0.75000000
-0.07526882 0.75000000
-0.07624633 0.75000000
-0.07722385 0.75000000
-0.07820137 0.75000000
-0.07917889 0.75000000
-0.08015640 0.75000000
-0.08113392 0.75000000
-0.08211144 0.75000000
-0.08308895 0.75000000
-0.08406647 0.75000000
-0.08504399 0.75000000
-0.08602151 0.75000000
-0.08699902 0.75000000
-0.08797654 0.75000000
-0.08895406 0.75000000
-0.08993157 0.75000000
-0.09090909 0.75000000
-0.09188661 0.75000000
-0.09286413 0.75000000
-0.09384164 0.75000000
-0.09481916 0.75000000
-0.09579668 0.75000000
-0.09677419 0.75000000
-0.09775171 0.75000000
-0.09872923 0.75000000
-0.09970674 0.75000000
-0.10068426 0.75000000
-0.10166178 0.75000000
-0.10263930 0.75000000
-0.10361681 0.75000000
-0.10459433 0.75000000
-0.10557185 0.75000000
-0.10654936 0.75000000
-0.10752688 0.75000000
-0.10850440 0.75000000
-0.10948192 0.75000000
-0.11045943 0.75000000
-0.11143695 0.75000000
-0.11241447 0.75000000
-0.11339198 0.75000000
-0.11436950 0.75000000
-0.11534702 0.75000000
-0.11632454 0.75000000
-0.11730205 0.75000000
-0.11827957 0.75000000
-0.11925709 0.75000000
-0.12023460 0.75000000
-0.12121212 0.75000000
-0.12218964 0.75000000
-0.12316716 0.75000000
-0.12414467 0.75000000
-0.12512219 0.75000000
-0.12609971 0.75000000
-0.12707722 0.75000000
-0.12805474 0.75000000
-0.12903226 0.75000000
-0.13000978 0.75000000
-0.13098729 0.75000000
-0.13196481 0.75000000
-0.13294233 0.75000000
-0.13391984 0.75000000
-0.13489736 0.75000000
-0.13587488 0.75000000
-0.13685239 0.75000000
-0.13782991 0.75000000
-0.13880743 0.75000000
-0.13978495 0.75000000
-0.14076246 0.75000000
-0.14173998 0.75000000
-0.14271750 0.75000000
-0.14369501 0.75000000
-0.14467253 0.75000000
-0.14565005 0.75000000
-0.14662757 0.75000000
-0.14760508 0.75000000
-0.14858260 0.75000000
-0.14956012 0.75000000
-0.15053763 0.75000000
-0.15151515 0.75000000
-0.15249267 0.75000000
-0.15347019 0.75000000
-0.15444770 0.75000000
-0.15542522 0.75000000
-0.15640274 0.75000000
-0.15738025 0.75000000
-0.15835777 0.75000000
-0.15933529 0.75000000
-0.16031281 0.75000000
-0.16129032 0.75000000
-0.16226784 0.75000000
-0.16324536 0.75000000
-0.16422287 0.75000000
-0.16520039 0.75000000
-0.16617791 0.75000000
-0.16715543 0.75000000
-0.16813294 0.75000000
-0.16911046 0.75000000
-0.17008798 0.75000000
-0.17106549 0.75000000
-0.17204301 0.75000000
-0.17302053 0.75000000
-0.17399804 0.75000000
-0.17497556 0.75000000
-0.17595308 0.75000000
-0.17693060 0.75000000
-0.17790811 0.75000000
-0.17888563 0.75000000
-0.17986315 0.75000000
-0.18084066 0.75000000
-0.18181818 0.75000000
-0.18279570 0.75000000
-0.18377322 0.75000000
-0.18475073 0.75000000
-0.18572825 0.75000000
-0.18670577 0.75000000
-0.18768328 0.75000000
-0.18866080 0.75000000
-0.18963832 0.75000000
-0.19061584 0.75000000
-0.19159335 0.75000000
-0.19257087 0.75000000
-0.19354839 0.75000000
-0.19452590 0.75000000
-0.19550342 0.75000000
-0.19648094 0.75000000
-0.19745846 0.75000000
-0.19843597 0.75000000
-0.19941349 0.75000000
-0.20039101 0.75000000
-0.20136852 0.75000000
-0.20234604 0.75000000
-0.20332356 0.75000000
-0.20430108 0.75000000
-0.20527859 0.75000000
-0.20625611 0.75000000
-0.20723363 0.75000000
-0.20821114 0.75000000
-0.20918866 0.75000000
-0.21016618 0.75000000
-0.21114370 0.75000000
-0.21212121 0.75000000
-0.21309873 0.75000000
-0.21407625 0.75000000
-0.21505376 0.75000000
-0.21603128 0.75000000
-0.21700880 0.75000000
-0.21798631 0.75000000
-0.21896383 0.75000000
-0.21994135 0.75000000
-0.22091887 0.75000000
-0.22189638 0.75000000
-0.22287390 0.75000000
-0.22385142 0.75000000
-0.22482893 0.75000000
-0.22580645 0.75000000
-0.22678397 0.75000000
-0.22776149 0.75000000
-0.22873900 0.75000000
-0.22971652 0.75000000
-0.23069404 0.75000000
-0.23167155 0.75000000
-0.23264907 0.75000000
-0.23362659 0.75000000
-0.23460411 0.75000000
-0.23558162 0.75000000
-0.23655914 0.75000000
-0.23753666 0.75000000
-0.23851417 0.75000000
-0.23949169 0.75000000
-0.24046921 0.75000000
-0.24144673 0.75000000
-0.24242424 0.75000000
-0.24340176 0.75000000
-0.24437928 0.75000000
-0.24535679 0.75000000
-0.24633431 0.75000000
-0.24731183 0.75000000
-0.24828935 0.75000000
-0.24926686 0.75000000
-0.25024438 0.74975562
-0.25122190 0.74877810
-0.25219941 0.74780059
-0.25317693 0.74682307
-0.25415445 0.74584555
-0.25513196 0.74486804
-0.25610948 0.74389052
-0.25708700 0.74291300
-0.25806452 0.74193548
-0.25904203 0.74095797
-0.26001955 0.73998045
-0.26099707 0.73900293
-0.26197458 0.73802542
-0.26295210 0.73704790
-0.26392962 0.73607038
-0.26490714 0.73509286
-0.26588465 0.73411535
-0.26686217 0.73313783
-0.26783969 0.73216031
-0.26881720 0.73118280
-0.26979472 0.73020528
-0.27077224 0.72922776
-0.27174976 0.72825024
-0.27272727 0.72727273
-0.27370479 0.72629521
-0.27468231 0.72531769
-0.27565982 0.72434018
-0.27663734 0.72336266
-0.27761486 0.72238514
-0.27859238 0.72140762
-0.27956989 0.72043011
-0.28054741 0.71945259
-0.28152493 0.71847507
-0.28250244 0.71749756
-0.28347996 0.71652004
-0.28445748 0.71554252
-0.28543500 0.71456500
-0.28641251 0.71358749
-0.28739003 0.71260997
-0.28836755 0.71163245
-0.28934506 0.71065494
-0.29032258 0.70967742
-0.29130010 0.70869990
-0.29227761 0.70772239
-0.29325513 0.70674487
-0.29423265 0.70576735
-0.29521017 0.70478983
-0.29618768 0.70381232
-0.29716520 0.70283480
-0.29814272 0.70185728
-0.29912023 0.70087977
-0.30009775 0.69990225
-0.30107527 0.69892473
-0.30205279 0.69794721
-0.30303030 0.69696970
-0.30400782 0.69599218
-0.30498534 0.69501466
-0.30596285 0.69403715
-0.30694037 0.69305963
-0.30791789 0.69208211
-0.30889541 0.69110459
-0.30987292 0.69012708
-0.31085044 0.68914956
-0.31182796 0.68817204
-0.31280547 0.68719453
-0.31378299 0.68621701
-0.31476051 0.68523949
-0.31573803 0.68426197
-0.31671554 0.68328446
-0.31769306 0.68230694
-0.31867058 0.68132942
-0.31964809 0.68035191
-0.32062561 0.67937439
-0.32160313 0.67839687
-0.32258065 0.67741935
-0.32355816 0.67644184
-0.32453568 0.67546432
-0.32551320 0.67448680
-0.32649071 0.67350929
-0.32746823 0.67253177
-0.32844575 0.67155425
-0.32942326 0.67057674
-0.33040078 0.66959922
-0.33137830 0.66862170
-0.33235582 0.66764418
-0.33333333 0.66666667
-0.33431085 0.66568915
-0.33528837 0.66471163
-0.33626588 0.66373412
-0.33724340 0.66275660
-0.33822092 0.66177908
-0.33919844 0.66080156
-0.34017595 0.65982405
-0.34115347 0.65884653
-0.34213099 0.65786901
-0.34310850 0.65689150
-0.34408602 0.65591398
-0.34506354 0.65493646
-0.34604106 0.65395894
-0.34701857 0.65298143
-0.34799609 0.65200391
-0.34897361 0.65102639
-0.34995112 0.65004888
-0.35092864 0.64907136
-0.35190616 0.64809384
-0.35288368 0.64711632
-0.35386119 0.64613881
-0.35483871 0.64516129
-0.35581623 0.64418377
-0.35679374 0.64320626
-0.35777126 0.64222874
-0.35874878 0.64125122
-0.35972630 0.64027370
-0.36070381 0.63929619
-0.36168133 0.63831867
-0.36265885 0.63734115
-0.36363636 0.63636364
-0.36461388 0.63538612
-0.36559140 0.63440860
-0.36656891 0.63343109
-0.36754643 0.63245357
-0.36852395 0.63147605
-0.36950147 0.63049853
-0.37047898 0.62952102
-0.37145650 0.62854350
-0.37243402 0.62756598
-0.37341153 0.62658847
-0.37438905 0.62561095
-0.37536657 0.62463343
-0.37634409 0.62365591
-0.37732160 0.62267840
-0.37829912 0.62170088
-0.37927664 0.62072336
-0.38025415 0.61974585
-0.38123167 0.61876833
-0.38220919 0.61779081
-0.38318671 0.61681329
-0.38416422 0.61583578
-0.38514174 0.61485826
-0.38611926 0.61388074
-0.38709677 0.61290323
-0.38807429 0.61192571
-0.38905181 0.61094819
-0.39002933 0.60997067
-0.39100684 0.60899316
-0.39198436 0.60801564
-0.39296188 0.60703812
-0.39393939 0.60606061
-0.39491691 0.60508309
-0.39589443 0.60410557
-0.39687195 0.60312805
-0.39784946 0.60215054
-0.39882698 0.60117302
-0.39980450 0.60019550
-0.40078201 0.59921799
-0.40175953 0.59824047
-0.40273705 0.59726295
-0.40371457 0.59628543
-0.40469208 0.59530792
-0.40566960 0.59433040
-0.40664712 0.59335288
-0.40762463 0.59237537
-0.40860215 0.59139785
-0.40957967 0.59042033
-0.41055718 0.58944282
-0.41153470 0.58846530
-0.41251222 0.58748778
-0.41348974 0.58651026
-0.41446725 0.58553275
-0.41544477 0.58455523
-0.41642229 0.58357771
-0.41739980 0.58260020
-0.41837732 0.58162268
-0.41935484 0.58064516
-0.42033236 0.57966764
-0.42130987 0.57869013
-0.42228739 0.57771261
-0.42326491 0.57673509
-0.42424242 0.57575758
-0.42521994 0.57478006
-0.42619746 0.57380254
-0.42717498 0.57282502
-0.42815249 0.57184751
-0.42913001 0.57086999
-0.43010753 0.56989247
-0.43108504 0.56891496
-0.43206256 0.56793744
-0.43304008 0.56695992
-0.43401760 0.56598240
-0.43499511 0.56500489
-0.43597263 0.56402737
-0.43695015 0.56304985
-0.43792766 0.56207234
-0.43890518 0.56109482
-0.43988270 0.56011730
-0.44086022 0.55913978
-0.44183773 0.55816227
-0.44281525 0.55718475
-0.44379277 0.55620723
-0.44477028 0.55522972
-0.44574780 0.55425220
-0.44672532 0.55327468
-0.44770283 0.55229717
-0.44868035 0.55131965
-0.44965787 0.55034213
-0.45063539 0.54936461
-0.45161290 0.54838710
-0.45259042 0.54740958
-0.45356794 0.54643206
-0.45454545 0.54545455
-0.45552297 0.54447703
-0.45650049 0.54349951
-0.45747801 0.54252199
-0.45845552 0.54154448
-0.45943304 0.54056696
-0.46041056 0.53958944
-0.46138807 0.53861193
-0.46236559 0.53763441
-0.46334311 0.53665689
-0.46432063 0.53567937
-0.46529814 0.53470186
-0.46627566 0.53372434
-0.46725318 0.53274682
-0.46823069 0.53176931
-0.46920821 0.53079179
-0.47018573 0.52981427
-0.47116325 0.52883675
-0.47214076 0.52785924
-0.47311828 0.52688172
-0.47409580 0.52590420
-0.47507331 0.52492669
-0.47605083 0.52394917
-0.47702835 0.52297165
-0.47800587 0.52199413
-0.47898338 0.52101662
-0.47996090 0.52003910
-0.48093842 0.51906158
-0.48191593 0.51808407
-0.48289345 0.51710655
-0.48387097 0.51612903
-0.48484848 0.51515152
-0.48582600 0.51417400
-0.48680352 0.51319648
-0.48778104 0.51221896
-0.48875855 0.51124145
-0.48973607 0.51026393
-0.49071359 0.50928641
-0.49169110 0.50830890
-0.49266862 0.50733138
-0.49364614 0.50635386
-0.49462366 0.50537634
-0.49560117 0.50439883
-0.49657869 0.50342131
-0.49755621 0.50244379
-0.49853372 0.50146628
-0.49951124 0.50048876
-0.50048876 0.49951124
-0.50146628 0.49853372
-0.50244379 0.49755621
-0.50342131 0.49657869
-0.50439883 0.49560117
-0.50537634 0.49462366
-0.50635386 0.49364614
-0.50733138 0.49266862
-0.50830890 0.49169110
-0.50928641 0.49071359
-0.51026393 0.48973607
-0.51124145 0.48875855
-0.51221896 0.48778104
-0.51319648 0.48680352
-0.51417400 0.48582600
-0.51515152 0.48484848
-0.51612903 0.48387097
-0.51710655 0.48289345
-0.51808407 0.48191593
-0.51906158 0.48093842
-0.52003910 0.47996090
-0.52101662 0.47898338
-0.52199413 0.47800587
-0.52297165 0.47702835
-0.52394917 0.47605083
-0.52492669 0.47507331
-0.52590420 0.47409580
-0.52688172 0.47311828
-0.52785924 0.47214076
-0.52883675 0.47116325
-0.52981427 0.47018573
-0.53079179 0.46920821
-0.53176931 0.46823069
-0.53274682 0.46725318
-0.53372434 0.46627566
-0.53470186 0.46529814
-0.53567937 0.46432063
-0.53665689 0.46334311
-0.53763441 0.46236559
-0.53861193 0.46138807
-0.53958944 0.46041056
-0.54056696 0.45943304
-0.54154448 0.45845552
-0.54252199 0.45747801
-0.54349951 0.45650049
-0.54447703 0.45552297
-0.54545455 0.45454545
-0.54643206 0.45356794
-0.54740958 0.45259042
-0.54838710 0.45161290
-0.54936461 0.45063539
-0.55034213 0.44965787
-0.55131965 0.44868035
-0.55229717 0.44770283
-0.55327468 0.44672532
-0.55425220 0.44574780
-0.55522972 0.44477028
-0.55620723 0.44379277
-0.55718475 0.44281525
-0.55816227 0.44183773
-0.55913978 0.44086022
-0.56011730 0.43988270
-0.56109482 0.43890518
-0.56207234 0.43792766
-0.56304985 0.43695015
-0.56402737 0.43597263
-0.56500489 0.43499511
-0.56598240 0.43401760
-0.56695992 0.43304008
-0.56793744 0.43206256
-0.56891496 0.43108504
-0.56989247 0.43010753
-0.57086999 0.42913001
-0.57184751 0.42815249
-0.57282502 0.42717498
-0.57380254 0.42619746
-0.57478006 0.42521994
-0.57575758 0.42424242
-0.57673509 0.42326491
-0.57771261 0.42228739
-0.57869013 0.42130987
-0.57966764 0.42033236
-0.58064516 0.41935484
-0.58162268 0.41837732
-0.58260020 0.41739980
-0.58357771 0.41642229
-0.58455523 0.41544477
-0.58553275 0.41446725
-0.58651026 0.41348974
-0.58748778 0.41251222
-0.58846530 0.41153470
-0.58944282 0.41055718
-0.59042033 0.40957967
-0.59139785 0.40860215
-0.59237537 0.40762463
-0.59335288 0.40664712
-0.59433040 0.40566960
-0.59530792 0.40469208
-0.59628543 0.40371457
-0.59726295 0.40273705
-0.59824047 0.40175953
-0.59921799 0.40078201
-0.60019550 0.39980450
-0.60117302 0.39882698
-0.60215054 0.39784946
-0.60312805 0.39687195
-0.60410557 0.39589443
-0.60508309 0.39491691
-0.60606061 0.39393939
-0.60703812 0.39296188
-0.60801564 0.39198436
-0.60899316 0.39100684
-0.60997067 0.39002933
-0.61094819 0.38905181
-0.61192571 0.38807429
-0.61290323 0.38709677
-0.61388074 0.38611926
-0.61485826 0.38514174
-0.61583578 0.38416422
-0.61681329 0.38318671
-0.61779081 0.38220919
-0.61876833 0.38123167
-0.61974585 0.38025415
-0.62072336 0.37927664
-0.62170088 0.37829912
-0.62267840 0.37732160
-0.62365591 0.37634409
-0.62463343 0.37536657
-0.62561095 0.37438905
-0.62658847 0.37341153
-0.62756598 0.37243402
-0.62854350 0.37145650
-0.62952102 0.37047898
-0.63049853 0.36950147
-0.63147605 0.36852395
-0.63245357 0.36754643
-0.63343109 0.36656891
-0.63440860 0.36559140
-0.63538612 0.36461388
-0.63636364 0.36363636
-0.63734115 0.36265885
-0.63831867 0.36168133
-0.63929619 0.36070381
-0.64027370 0.35972630
-0.64125122 0.35874878
-0.64222874 0.35777126
-0.64320626 0.35679374
-0.64418377 0.35581623
-0.64516129 0.35483871
-0.64613881 0.35386119
-0.64711632 0.35288368
-0.64809384 0.35190616
-0.64907136 0.35092864
-0.65004888 0.34995112
-0.65102639 0.34897361
-0.65200391 0.34799609
-0.65298143 0.34701857
-0.65395894 0.34604106
-0.65493646 0.34506354
-0.65591398 0.34408602
-0.65689150 0.34310850
-0.65786901 0.34213099
-0.65884653 0.34115347
-0.65982405 0.34017595
-0.66080156 0.33919844
-0.66177908 0.33822092
-0.66275660 0.33724340
-0.66373412 0.33626588
-0.66471163 0.33528837
-0.66568915 0.33431085
-0.66666667 0.33333333
-0.66764418 0.33235582
-0.66862170 0.33137830
-0.66959922 0.33040078
-0.67057674 0.32942326
-0.67155425 0.32844575
-0.67253177 0.32746823
-0.67350929 0.32649071
-0.67448680 0.32551320
-0.67546432 0.32453568
-0.67644184 0.32355816
-0.67741935 0.32258065
-0.67839687 0.32160313
-0.67937439 0.32062561
-0.68035191 0.31964809
-0.68132942 0.31867058
-0.68230694 0.31769306
-0.68328446 0.31671554
-0.68426197 0.31573803
-0.68523949 0.31476051
-0.68621701 0.31378299
-0.68719453 0.31280547
-0.68817204 0.31182796
-0.68914956 0.31085044
-0.69012708 0.30987292
-0.69110459 0.30889541
-0.69208211 0.30791789
-0.69305963 0.30694037
-0.69403715 0.30596285
-0.69501466 0.30498534
-0.69599218 0.30400782
-0.69696970 0.30303030
-0.69794721 0.30205279
-0.69892473 0.30107527
-0.69990225 0.30009775
-0.70087977 0.29912023
-0.70185728 0.29814272
-0.70283480 0.29716520
-0.70381232 0.29618768
-0.70478983 0.29521017
-0.70576735 0.29423265
-0.70674487 0.29325513
-0.70772239 0.29227761
-0.70869990 0.29130010
-0.70967742 0.29032258
-0.71065494 0.28934506
-0.71163245 0.28836755
-0.71260997 0.28739003
-0.71358749 0.28641251
-0.71456500 0.28543500
-0.71554252 0.28445748
-0.71652004 0.28347996
-0.71749756 0.28250244
-0.71847507 0.28152493
-0.71945259 0.28054741
-0.72043011 0.27956989
-0.72140762 0.27859238
-0.72238514 0.27761486
-0.72336266 0.27663734
-0.72434018 0.27565982
-0.72531769 0.27468231
-0.72629521 0.27370479
-0.72727273 0.27272727
-0.72825024 0.27174976
-0.72922776 0.27077224
-0.73020528 0.26979472
-0.73118280 0.26881720
-0.73216031 0.26783969
-0.73313783 0.26686217
-0.73411535 0.26588465
-0.73509286 0.26490714
-0.73607038 0.26392962
-0.73704790 0.26295210
-0.73802542 0.26197458
-0.73900293 0.26099707
-0.73998045 0.26001955
-0.74095797 0.25904203
-0.74193548 0.25806452
-0.74291300 0.25708700
-0.74389052 0.25610948
-0.74486804 0.25513196
-0.74584555 0.25415445
-0.74682307 0.25317693
-0.74780059 0.25219941
-0.74877810 0.25122190
-0.74975562 0.25024438
-0.75073314 0.25000000
-0.75171065 0.25000000
-0.75268817 0.25000000
-0.75366569 0.25000000
-0.75464321 0.25000000
-0.75562072 0.25000000
-0.75659824 0.25000000
-0.75757576 0.25000000
-0.75855327 0.25000000
-0.75953079 0.25000000
-0.76050831 0.25000000
-0.76148583 0.25000000
-0.76246334 0.25000000
-0.76344086 0.25000000
-0.76441838 0.25000000
-0.76539589 0.25000000
-0.76637341 0.25000000
-0.76735093 0.25000000
-0.76832845 0.25000000
-0.76930596 0.25000000
-0.77028348 0.25000000
-0.77126100 0.25000000
-0.77223851 0.25000000
-0.77321603 0.25000000
-0.77419355 0.25000000
-0.77517107 0.25000000
-0.77614858 0.25000000
-0.77712610 0.25000000
-0.77810362 0.25000000
-0.77908113 0.25000000
-0.78005865 0.25000000
-0.78103617 0.25000000
-0.78201369 0.25000000
-0.78299120 0.25000000
-0.78396872 0.25000000
-0.78494624 0.25000000
-0.78592375 0.25000000
-0.78690127 0.25000000
-0.78787879 0.25000000
-0.78885630 0.25000000
-0.78983382 0.25000000
-0.79081134 0.25000000
-0.79178886 0.25000000
-0.79276637 0.25000000
-0.79374389 0.25000000
-0.79472141 0.25000000
-0.79569892 0.25000000
-0.79667644 0.25000000
-0.79765396 0.25000000
-0.79863148 0.25000000
-0.79960899 0.25000000
-0.80058651 0.25000000
-0.80156403 0.25000000
-0.80254154 0.25000000
-0.80351906 0.25000000
-0.80449658 0.25000000
-0.80547410 0.25000000
-0.80645161 0.25000000
-0.80742913 0.25000000
-0.80840665 0.25000000
-0.80938416 0.25000000
-0.81036168 0.25000000
-0.81133920 0.25000000
-0.81231672 0.25000000
-0.81329423 0.25000000
-0.81427175 0.25000000
-0.81524927 0.25000000
-0.81622678 0.25000000
-0.81720430 0.25000000
-0.81818182 0.25000000
-0.81915934 0.25000000
-0.82013685 0.25000000
-0.82111437 0.25000000
-0.82209189 0.25000000
-0.82306940 0.25000000
-0.82404692 0.25000000
-0.82502444 0.25000000
-0.82600196 0.25000000
-0.82697947 0.25000000
-0.82795699 0.25000000
-0.82893451 0.25000000
-0.82991202 0.25000000
-0.83088954 0.25000000
-0.83186706 0.25000000
-0.83284457 0.25000000
-0.83382209 0.25000000
-0.83479961 0.25000000
-0.83577713 0.25000000
-0.83675464 0.25000000
-0.83773216 0.25000000
-0.83870968 0.25000000
-0.83968719 0.25000000
-0.84066471 0.25000000
-0.84164223 0.25000000
-0.84261975 0.25000000
-0.84359726 0.25000000
-0.84457478 0.25000000
-0.84555230 0.25000000
-0.84652981 0.25000000
-0.84750733 0.25000000
-0.84848485 0.25000000
-0.84946237 0.25000000
-0.85043988 0.25000000
-0.85141740 0.25000000
-0.85239492 0.25000000
-0.85337243 0.25000000
-0.85434995 0.25000000
-0.85532747 0.25000000
-0.85630499 0.25000000
-0.85728250 0.25000000
-0.85826002 0.25000000
-0.85923754 0.25000000
-0.86021505 0.25000000
-0.86119257 0.25000000
-0.86217009 0.25000000
-0.86314761 0.25000000
-0.86412512 0.25000000
-0.86510264 0.25000000
-0.86608016 0.25000000
-0.86705767 0.25000000
-0.86803519 0.25000000
-0.86901271 0.25000000
-0.86999022 0.25000000
-0.87096774 0.25000000
-0.87194526 0.25000000
-0.87292278 0.25000000
-0.87390029 0.25000000
-0.87487781 0.25000000
-0.87585533 0.25000000
-0.87683284 0.25000000
-0.87781036 0.25000000
-0.87878788 0.25000000
-0.87976540 0.25000000
-0.88074291 0.25000000
-0.88172043 0.25000000
-0.88269795 0.25000000
-0.88367546 0.25000000
-0.88465298 0.25000000
-0.88563050 0.25000000
-0.88660802 0.25000000
-0.88758553 0.25000000
-0.88856305 0.25000000
-0.88954057 0.25000000
-0.89051808 0.25000000
-0.89149560 0.25000000
-0.89247312 0.25000000
-0.89345064 0.25000000
-0.89442815 0.25000000
-0.89540567 0.25000000
-0.89638319 0.25000000
-0.89736070 0.25000000
-0.89833822 0.25000000
-0.89931574 0.25000000
-0.90029326 0.25000000
-0.90127077 0.25000000
-0.90224829 0.25000000
-0.90322581 0.25000000
-0.90420332 0.25000000
-0.90518084 0.25000000
-0.90615836 0.25000000
-0.90713587 0.25000000
-0.90811339 0.25000000
-0.90909091 0.25000000
-0.91006843 0.25000000
-0.91104594 0.25000000
-0.91202346 0.25000000
-0.91300098 0.25000000
-0.91397849 0.25000000
-0.91495601 0.25000000
-0.91593353 0.25000000
-0.91691105 0.25000000
-0.91788856 0.25000000
-0.91886608 0.25000000
-0.91984360 0.25000000
-0.92082111 0.25000000
-0.92179863 0.25000000
-0.92277615 0.25000000
-0.92375367 0.25000000
-0.92473118 0.25000000
-0.92570870 0.25000000
-0.92668622 0.25000000
-0.92766373 0.25000000
-0.92864125 0.25000000
-0.92961877 0.25000000
-0.93059629 0.25000000
-0.93157380 0.25000000
-0.93255132 0.25000000
-0.93352884 0.25000000
-0.93450635 0.25000000
-0.93548387 0.25000000
-0.93646139 0.25000000
-0.93743891 0.25000000
-0.93841642 0.25000000
-0.93939394 0.25000000
-0.94037146 0.25000000
-0.94134897 0.25000000
-0.94232649 0.25000000
-0.94330401 0.25000000
-0.94428152 0.25000000
-0.94525904 0.25000000
-0.94623656 0.25000000
-0.94721408 0.25000000
-0.94819159 0.25000000
-0.94916911 0.25000000
-0.95014663 0.25000000
-0.95112414 0.25000000
-0.95210166 0.25000000
-0.95307918 0.25000000
-0.95405670 0.25000000
-0.95503421 0.25000000
-0.95601173 0.25000000
-0.95698925 0.25000000
-0.95796676 0.25000000
-0.95894428 0.25000000
-0.95992180 0.25000000
-0.96089932 0.25000000
-0.96187683 0.25000000
-0.96285435 0.25000000
-0.96383187 0.25000000
-0.96480938 0.25000000
-0.96578690 0.25000000
-0.96676442 0.25000000
-0.96774194 0.25000000
-0.96871945 0.25000000
-0.96969697 0.25000000
-0.97067449 0.25000000
-0.97165200 0.25000000
-0.97262952 0.25000000
-0.97360704 0.25000000
-0.97458456 0.25000000
-0.97556207 0.25000000
-0.97653959 0.25000000
-0.97751711 0.25000000
-0.97849462 0.25000000
-0.97947214 0.25000000
-0.98044966 0.25000000
-0.98142717 0.25000000
-0.98240469 0.25000000
-0.98338221 0.25000000
-0.98435973 0.25000000
-0.98533724 0.25000000
-0.98631476 0.25000000
-0.98729228 0.25000000
-0.98826979 0.25000000
-0.98924731 0.25000000
-0.99022483 0.25000000
-0.99120235 0.25000000
-0.99217986 0.25000000
-0.99315738 0.25000000
-0.99413490 0.25000000
-0.99511241 0.25000000
-0.99608993 0.25000000
-0.99706745 0.25000000
-0.99804497 0.25000000
-0.99902248 0.25000000
-1.00000000 nan
+Ambient Power
+0.000000000 nan
+0.000977517 0.750000000
+0.001955034 0.750000000
+0.002932551 0.750000000
+0.003910068 0.750000000
+0.004887586 0.750000000
+0.005865103 0.750000000
+0.006842620 0.750000000
+0.007820137 0.750000000
+0.008797654 0.750000000
+0.009775171 0.750000000
+0.010752688 0.750000000
+0.011730205 0.750000000
+0.012707722 0.750000000
+0.013685239 0.750000000
+0.014662757 0.750000000
+0.015640274 0.750000000
+0.016617791 0.750000000
+0.017595308 0.750000000
+0.018572825 0.750000000
+0.019550342 0.750000000
+0.020527859 0.750000000
+0.021505376 0.750000000
+0.022482893 0.750000000
+0.023460411 0.750000000
+0.024437928 0.750000000
+0.025415445 0.750000000
+0.026392962 0.750000000
+0.027370479 0.750000000
+0.028347996 0.750000000
+0.029325513 0.750000000
+0.030303030 0.750000000
+0.031280547 0.750000000
+0.032258065 0.750000000
+0.033235582 0.750000000
+0.034213099 0.750000000
+0.035190616 0.750000000
+0.036168133 0.750000000
+0.037145650 0.750000000
+0.038123167 0.750000000
+0.039100684 0.750000000
+0.040078201 0.750000000
+0.041055718 0.750000000
+0.042033236 0.750000000
+0.043010753 0.750000000
+0.043988270 0.750000000
+0.044965787 0.750000000
+0.045943304 0.750000000
+0.046920821 0.750000000
+0.047898338 0.750000000
+0.048875855 0.750000000
+0.049853372 0.750000000
+0.050830890 0.750000000
+0.051808407 0.750000000
+0.052785924 0.750000000
+0.053763441 0.750000000
+0.054740958 0.750000000
+0.055718475 0.750000000
+0.056695992 0.750000000
+0.057673509 0.750000000
+0.058651026 0.750000000
+0.059628543 0.750000000
+0.060606061 0.750000000
+0.061583578 0.750000000
+0.062561095 0.750000000
+0.063538612 0.750000000
+0.064516129 0.750000000
+0.065493646 0.750000000
+0.066471163 0.750000000
+0.067448680 0.750000000
+0.068426197 0.750000000
+0.069403715 0.750000000
+0.070381232 0.750000000
+0.071358749 0.750000000
+0.072336266 0.750000000
+0.073313783 0.750000000
+0.074291300 0.750000000
+0.075268817 0.750000000
+0.076246334 0.750000000
+0.077223851 0.750000000
+0.078201369 0.750000000
+0.079178886 0.750000000
+0.080156403 0.750000000
+0.081133920 0.750000000
+0.082111437 0.750000000
+0.083088954 0.750000000
+0.084066471 0.750000000
+0.085043988 0.750000000
+0.086021505 0.750000000
+0.086999022 0.750000000
+0.087976540 0.750000000
+0.088954057 0.750000000
+0.089931574 0.750000000
+0.090909091 0.750000000
+0.091886608 0.750000000
+0.092864125 0.750000000
+0.093841642 0.750000000
+0.094819159 0.750000000
+0.095796676 0.750000000
+0.096774194 0.750000000
+0.097751711 0.750000000
+0.098729228 0.750000000
+0.099706745 0.750000000
+0.100684262 0.750000000
+0.101661779 0.750000000
+0.102639296 0.750000000
+0.103616813 0.750000000
+0.104594330 0.750000000
+0.105571848 0.750000000
+0.106549365 0.750000000
+0.107526882 0.750000000
+0.108504399 0.750000000
+0.109481916 0.750000000
+0.110459433 0.750000000
+0.111436950 0.750000000
+0.112414467 0.750000000
+0.113391984 0.750000000
+0.114369501 0.750000000
+0.115347019 0.750000000
+0.116324536 0.750000000
+0.117302053 0.750000000
+0.118279570 0.750000000
+0.119257087 0.750000000
+0.120234604 0.750000000
+0.121212121 0.750000000
+0.122189638 0.750000000
+0.123167155 0.750000000
+0.124144673 0.750000000
+0.125122190 0.750000000
+0.126099707 0.750000000
+0.127077224 0.750000000
+0.128054741 0.750000000
+0.129032258 0.750000000
+0.130009775 0.750000000
+0.130987292 0.750000000
+0.131964809 0.750000000
+0.132942326 0.750000000
+0.133919844 0.750000000
+0.134897361 0.750000000
+0.135874878 0.750000000
+0.136852395 0.750000000
+0.137829912 0.750000000
+0.138807429 0.750000000
+0.139784946 0.750000000
+0.140762463 0.750000000
+0.141739980 0.750000000
+0.142717498 0.750000000
+0.143695015 0.750000000
+0.144672532 0.750000000
+0.145650049 0.750000000
+0.146627566 0.750000000
+0.147605083 0.750000000
+0.148582600 0.750000000
+0.149560117 0.750000000
+0.150537634 0.750000000
+0.151515152 0.750000000
+0.152492669 0.750000000
+0.153470186 0.750000000
+0.154447703 0.750000000
+0.155425220 0.750000000
+0.156402737 0.750000000
+0.157380254 0.750000000
+0.158357771 0.750000000
+0.159335288 0.750000000
+0.160312805 0.750000000
+0.161290323 0.750000000
+0.162267840 0.750000000
+0.163245357 0.750000000
+0.164222874 0.750000000
+0.165200391 0.750000000
+0.166177908 0.750000000
+0.167155425 0.750000000
+0.168132942 0.750000000
+0.169110459 0.750000000
+0.170087977 0.750000000
+0.171065494 0.750000000
+0.172043011 0.750000000
+0.173020528 0.750000000
+0.173998045 0.750000000
+0.174975562 0.750000000
+0.175953079 0.750000000
+0.176930596 0.750000000
+0.177908113 0.750000000
+0.178885630 0.750000000
+0.179863148 0.750000000
+0.180840665 0.750000000
+0.181818182 0.750000000
+0.182795699 0.750000000
+0.183773216 0.750000000
+0.184750733 0.750000000
+0.185728250 0.750000000
+0.186705767 0.750000000
+0.187683284 0.750000000
+0.188660802 0.750000000
+0.189638319 0.750000000
+0.190615836 0.750000000
+0.191593353 0.750000000
+0.192570870 0.750000000
+0.193548387 0.750000000
+0.194525904 0.750000000
+0.195503421 0.750000000
+0.196480938 0.750000000
+0.197458456 0.750000000
+0.198435973 0.750000000
+0.199413490 0.750000000
+0.200391007 0.750000000
+0.201368524 0.750000000
+0.202346041 0.750000000
+0.203323558 0.750000000
+0.204301075 0.750000000
+0.205278592 0.750000000
+0.206256109 0.750000000
+0.207233627 0.750000000
+0.208211144 0.750000000
+0.209188661 0.750000000
+0.210166178 0.750000000
+0.211143695 0.750000000
+0.212121212 0.750000000
+0.213098729 0.750000000
+0.214076246 0.750000000
+0.215053763 0.750000000
+0.216031281 0.750000000
+0.217008798 0.750000000
+0.217986315 0.750000000
+0.218963832 0.750000000
+0.219941349 0.750000000
+0.220918866 0.750000000
+0.221896383 0.750000000
+0.222873900 0.750000000
+0.223851417 0.750000000
+0.224828935 0.750000000
+0.225806452 0.750000000
+0.226783969 0.750000000
+0.227761486 0.750000000
+0.228739003 0.750000000
+0.229716520 0.750000000
+0.230694037 0.750000000
+0.231671554 0.750000000
+0.232649071 0.750000000
+0.233626588 0.750000000
+0.234604106 0.750000000
+0.235581623 0.750000000
+0.236559140 0.750000000
+0.237536657 0.750000000
+0.238514174 0.750000000
+0.239491691 0.750000000
+0.240469208 0.750000000
+0.241446725 0.750000000
+0.242424242 0.750000000
+0.243401760 0.750000000
+0.244379277 0.750000000
+0.245356794 0.750000000
+0.246334311 0.750000000
+0.247311828 0.750000000
+0.248289345 0.750000000
+0.249266862 0.750000000
+0.250244379 0.749755621
+0.251221896 0.748778104
+0.252199413 0.747800587
+0.253176931 0.746823069
+0.254154448 0.745845552
+0.255131965 0.744868035
+0.256109482 0.743890518
+0.257086999 0.742913001
+0.258064516 0.741935484
+0.259042033 0.740957967
+0.260019550 0.739980450
+0.260997067 0.739002933
+0.261974585 0.738025415
+0.262952102 0.737047898
+0.263929619 0.736070381
+0.264907136 0.735092864
+0.265884653 0.734115347
+0.266862170 0.733137830
+0.267839687 0.732160313
+0.268817204 0.731182796
+0.269794721 0.730205279
+0.270772239 0.729227761
+0.271749756 0.728250244
+0.272727273 0.727272727
+0.273704790 0.726295210
+0.274682307 0.725317693
+0.275659824 0.724340176
+0.276637341 0.723362659
+0.277614858 0.722385142
+0.278592375 0.721407625
+0.279569892 0.720430108
+0.280547410 0.719452590
+0.281524927 0.718475073
+0.282502444 0.717497556
+0.283479961 0.716520039
+0.284457478 0.715542522
+0.285434995 0.714565005
+0.286412512 0.713587488
+0.287390029 0.712609971
+0.288367546 0.711632454
+0.289345064 0.710654936
+0.290322581 0.709677419
+0.291300098 0.708699902
+0.292277615 0.707722385
+0.293255132 0.706744868
+0.294232649 0.705767351
+0.295210166 0.704789834
+0.296187683 0.703812317
+0.297165200 0.702834800
+0.298142717 0.701857283
+0.299120235 0.700879765
+0.300097752 0.699902248
+0.301075269 0.698924731
+0.302052786 0.697947214
+0.303030303 0.696969697
+0.304007820 0.695992180
+0.304985337 0.695014663
+0.305962854 0.694037146
+0.306940371 0.693059629
+0.307917889 0.692082111
+0.308895406 0.691104594
+0.309872923 0.690127077
+0.310850440 0.689149560
+0.311827957 0.688172043
+0.312805474 0.687194526
+0.313782991 0.686217009
+0.314760508 0.685239492
+0.315738025 0.684261975
+0.316715543 0.683284457
+0.317693060 0.682306940
+0.318670577 0.681329423
+0.319648094 0.680351906
+0.320625611 0.679374389
+0.321603128 0.678396872
+0.322580645 0.677419355
+0.323558162 0.676441838
+0.324535679 0.675464321
+0.325513196 0.674486804
+0.326490714 0.673509286
+0.327468231 0.672531769
+0.328445748 0.671554252
+0.329423265 0.670576735
+0.330400782 0.669599218
+0.331378299 0.668621701
+0.332355816 0.667644184
+0.333333333 0.666666667
+0.334310850 0.665689150
+0.335288368 0.664711632
+0.336265885 0.663734115
+0.337243402 0.662756598
+0.338220919 0.661779081
+0.339198436 0.660801564
+0.340175953 0.659824047
+0.341153470 0.658846530
+0.342130987 0.657869013
+0.343108504 0.656891496
+0.344086022 0.655913978
+0.345063539 0.654936461
+0.346041056 0.653958944
+0.347018573 0.652981427
+0.347996090 0.652003910
+0.348973607 0.651026393
+0.349951124 0.650048876
+0.350928641 0.649071359
+0.351906158 0.648093842
+0.352883675 0.647116325
+0.353861193 0.646138807
+0.354838710 0.645161290
+0.355816227 0.644183773
+0.356793744 0.643206256
+0.357771261 0.642228739
+0.358748778 0.641251222
+0.359726295 0.640273705
+0.360703812 0.639296188
+0.361681329 0.638318671
+0.362658847 0.637341153
+0.363636364 0.636363636
+0.364613881 0.635386119
+0.365591398 0.634408602
+0.366568915 0.633431085
+0.367546432 0.632453568
+0.368523949 0.631476051
+0.369501466 0.630498534
+0.370478983 0.629521017
+0.371456500 0.628543500
+0.372434018 0.627565982
+0.373411535 0.626588465
+0.374389052 0.625610948
+0.375366569 0.624633431
+0.376344086 0.623655914
+0.377321603 0.622678397
+0.378299120 0.621700880
+0.379276637 0.620723363
+0.380254154 0.619745846
+0.381231672 0.618768328
+0.382209189 0.617790811
+0.383186706 0.616813294
+0.384164223 0.615835777
+0.385141740 0.614858260
+0.386119257 0.613880743
+0.387096774 0.612903226
+0.388074291 0.611925709
+0.389051808 0.610948192
+0.390029326 0.609970674
+0.391006843 0.608993157
+0.391984360 0.608015640
+0.392961877 0.607038123
+0.393939394 0.606060606
+0.394916911 0.605083089
+0.395894428 0.604105572
+0.396871945 0.603128055
+0.397849462 0.602150538
+0.398826979 0.601173021
+0.399804497 0.600195503
+0.400782014 0.599217986
+0.401759531 0.598240469
+0.402737048 0.597262952
+0.403714565 0.596285435
+0.404692082 0.595307918
+0.405669599 0.594330401
+0.406647116 0.593352884
+0.407624633 0.592375367
+0.408602151 0.591397849
+0.409579668 0.590420332
+0.410557185 0.589442815
+0.411534702 0.588465298
+0.412512219 0.587487781
+0.413489736 0.586510264
+0.414467253 0.585532747
+0.415444770 0.584555230
+0.416422287 0.583577713
+0.417399804 0.582600196
+0.418377322 0.581622678
+0.419354839 0.580645161
+0.420332356 0.579667644
+0.421309873 0.578690127
+0.422287390 0.577712610
+0.423264907 0.576735093
+0.424242424 0.575757576
+0.425219941 0.574780059
+0.426197458 0.573802542
+0.427174976 0.572825024
+0.428152493 0.571847507
+0.429130010 0.570869990
+0.430107527 0.569892473
+0.431085044 0.568914956
+0.432062561 0.567937439
+0.433040078 0.566959922
+0.434017595 0.565982405
+0.434995112 0.565004888
+0.435972630 0.564027370
+0.436950147 0.563049853
+0.437927664 0.562072336
+0.438905181 0.561094819
+0.439882698 0.560117302
+0.440860215 0.559139785
+0.441837732 0.558162268
+0.442815249 0.557184751
+0.443792766 0.556207234
+0.444770283 0.555229717
+0.445747801 0.554252199
+0.446725318 0.553274682
+0.447702835 0.552297165
+0.448680352 0.551319648
+0.449657869 0.550342131
+0.450635386 0.549364614
+0.451612903 0.548387097
+0.452590420 0.547409580
+0.453567937 0.546432063
+0.454545455 0.545454545
+0.455522972 0.544477028
+0.456500489 0.543499511
+0.457478006 0.542521994
+0.458455523 0.541544477
+0.459433040 0.540566960
+0.460410557 0.539589443
+0.461388074 0.538611926
+0.462365591 0.537634409
+0.463343109 0.536656891
+0.464320626 0.535679374
+0.465298143 0.534701857
+0.466275660 0.533724340
+0.467253177 0.532746823
+0.468230694 0.531769306
+0.469208211 0.530791789
+0.470185728 0.529814272
+0.471163245 0.528836755
+0.472140762 0.527859238
+0.473118280 0.526881720
+0.474095797 0.525904203
+0.475073314 0.524926686
+0.476050831 0.523949169
+0.477028348 0.522971652
+0.478005865 0.521994135
+0.478983382 0.521016618
+0.479960899 0.520039101
+0.480938416 0.519061584
+0.481915934 0.518084066
+0.482893451 0.517106549
+0.483870968 0.516129032
+0.484848485 0.515151515
+0.485826002 0.514173998
+0.486803519 0.513196481
+0.487781036 0.512218964
+0.488758553 0.511241447
+0.489736070 0.510263930
+0.490713587 0.509286413
+0.491691105 0.508308895
+0.492668622 0.507331378
+0.493646139 0.506353861
+0.494623656 0.505376344
+0.495601173 0.504398827
+0.496578690 0.503421310
+0.497556207 0.502443793
+0.498533724 0.501466276
+0.499511241 0.500488759
+0.500488759 0.499511241
+0.501466276 0.498533724
+0.502443793 0.497556207
+0.503421310 0.496578690
+0.504398827 0.495601173
+0.505376344 0.494623656
+0.506353861 0.493646139
+0.507331378 0.492668622
+0.508308895 0.491691105
+0.509286413 0.490713587
+0.510263930 0.489736070
+0.511241447 0.488758553
+0.512218964 0.487781036
+0.513196481 0.486803519
+0.514173998 0.485826002
+0.515151515 0.484848485
+0.516129032 0.483870968
+0.517106549 0.482893451
+0.518084066 0.481915934
+0.519061584 0.480938416
+0.520039101 0.479960899
+0.521016618 0.478983382
+0.521994135 0.478005865
+0.522971652 0.477028348
+0.523949169 0.476050831
+0.524926686 0.475073314
+0.525904203 0.474095797
+0.526881720 0.473118280
+0.527859238 0.472140762
+0.528836755 0.471163245
+0.529814272 0.470185728
+0.530791789 0.469208211
+0.531769306 0.468230694
+0.532746823 0.467253177
+0.533724340 0.466275660
+0.534701857 0.465298143
+0.535679374 0.464320626
+0.536656891 0.463343109
+0.537634409 0.462365591
+0.538611926 0.461388074
+0.539589443 0.460410557
+0.540566960 0.459433040
+0.541544477 0.458455523
+0.542521994 0.457478006
+0.543499511 0.456500489
+0.544477028 0.455522972
+0.545454545 0.454545455
+0.546432063 0.453567937
+0.547409580 0.452590420
+0.548387097 0.451612903
+0.549364614 0.450635386
+0.550342131 0.449657869
+0.551319648 0.448680352
+0.552297165 0.447702835
+0.553274682 0.446725318
+0.554252199 0.445747801
+0.555229717 0.444770283
+0.556207234 0.443792766
+0.557184751 0.442815249
+0.558162268 0.441837732
+0.559139785 0.440860215
+0.560117302 0.439882698
+0.561094819 0.438905181
+0.562072336 0.437927664
+0.563049853 0.436950147
+0.564027370 0.435972630
+0.565004888 0.434995112
+0.565982405 0.434017595
+0.566959922 0.433040078
+0.567937439 0.432062561
+0.568914956 0.431085044
+0.569892473 0.430107527
+0.570869990 0.429130010
+0.571847507 0.428152493
+0.572825024 0.427174976
+0.573802542 0.426197458
+0.574780059 0.425219941
+0.575757576 0.424242424
+0.576735093 0.423264907
+0.577712610 0.422287390
+0.578690127 0.421309873
+0.579667644 0.420332356
+0.580645161 0.419354839
+0.581622678 0.418377322
+0.582600196 0.417399804
+0.583577713 0.416422287
+0.584555230 0.415444770
+0.585532747 0.414467253
+0.586510264 0.413489736
+0.587487781 0.412512219
+0.588465298 0.411534702
+0.589442815 0.410557185
+0.590420332 0.409579668
+0.591397849 0.408602151
+0.592375367 0.407624633
+0.593352884 0.406647116
+0.594330401 0.405669599
+0.595307918 0.404692082
+0.596285435 0.403714565
+0.597262952 0.402737048
+0.598240469 0.401759531
+0.599217986 0.400782014
+0.600195503 0.399804497
+0.601173021 0.398826979
+0.602150538 0.397849462
+0.603128055 0.396871945
+0.604105572 0.395894428
+0.605083089 0.394916911
+0.606060606 0.393939394
+0.607038123 0.392961877
+0.608015640 0.391984360
+0.608993157 0.391006843
+0.609970674 0.390029326
+0.610948192 0.389051808
+0.611925709 0.388074291
+0.612903226 0.387096774
+0.613880743 0.386119257
+0.614858260 0.385141740
+0.615835777 0.384164223
+0.616813294 0.383186706
+0.617790811 0.382209189
+0.618768328 0.381231672
+0.619745846 0.380254154
+0.620723363 0.379276637
+0.621700880 0.378299120
+0.622678397 0.377321603
+0.623655914 0.376344086
+0.624633431 0.375366569
+0.625610948 0.374389052
+0.626588465 0.373411535
+0.627565982 0.372434018
+0.628543500 0.371456500
+0.629521017 0.370478983
+0.630498534 0.369501466
+0.631476051 0.368523949
+0.632453568 0.367546432
+0.633431085 0.366568915
+0.634408602 0.365591398
+0.635386119 0.364613881
+0.636363636 0.363636364
+0.637341153 0.362658847
+0.638318671 0.361681329
+0.639296188 0.360703812
+0.640273705 0.359726295
+0.641251222 0.358748778
+0.642228739 0.357771261
+0.643206256 0.356793744
+0.644183773 0.355816227
+0.645161290 0.354838710
+0.646138807 0.353861193
+0.647116325 0.352883675
+0.648093842 0.351906158
+0.649071359 0.350928641
+0.650048876 0.349951124
+0.651026393 0.348973607
+0.652003910 0.347996090
+0.652981427 0.347018573
+0.653958944 0.346041056
+0.654936461 0.345063539
+0.655913978 0.344086022
+0.656891496 0.343108504
+0.657869013 0.342130987
+0.658846530 0.341153470
+0.659824047 0.340175953
+0.660801564 0.339198436
+0.661779081 0.338220919
+0.662756598 0.337243402
+0.663734115 0.336265885
+0.664711632 0.335288368
+0.665689150 0.334310850
+0.666666667 0.333333333
+0.667644184 0.332355816
+0.668621701 0.331378299
+0.669599218 0.330400782
+0.670576735 0.329423265
+0.671554252 0.328445748
+0.672531769 0.327468231
+0.673509286 0.326490714
+0.674486804 0.325513196
+0.675464321 0.324535679
+0.676441838 0.323558162
+0.677419355 0.322580645
+0.678396872 0.321603128
+0.679374389 0.320625611
+0.680351906 0.319648094
+0.681329423 0.318670577
+0.682306940 0.317693060
+0.683284457 0.316715543
+0.684261975 0.315738025
+0.685239492 0.314760508
+0.686217009 0.313782991
+0.687194526 0.312805474
+0.688172043 0.311827957
+0.689149560 0.310850440
+0.690127077 0.309872923
+0.691104594 0.308895406
+0.692082111 0.307917889
+0.693059629 0.306940371
+0.694037146 0.305962854
+0.695014663 0.304985337
+0.695992180 0.304007820
+0.696969697 0.303030303
+0.697947214 0.302052786
+0.698924731 0.301075269
+0.699902248 0.300097752
+0.700879765 0.299120235
+0.701857283 0.298142717
+0.702834800 0.297165200
+0.703812317 0.296187683
+0.704789834 0.295210166
+0.705767351 0.294232649
+0.706744868 0.293255132
+0.707722385 0.292277615
+0.708699902 0.291300098
+0.709677419 0.290322581
+0.710654936 0.289345064
+0.711632454 0.288367546
+0.712609971 0.287390029
+0.713587488 0.286412512
+0.714565005 0.285434995
+0.715542522 0.284457478
+0.716520039 0.283479961
+0.717497556 0.282502444
+0.718475073 0.281524927
+0.719452590 0.280547410
+0.720430108 0.279569892
+0.721407625 0.278592375
+0.722385142 0.277614858
+0.723362659 0.276637341
+0.724340176 0.275659824
+0.725317693 0.274682307
+0.726295210 0.273704790
+0.727272727 0.272727273
+0.728250244 0.271749756
+0.729227761 0.270772239
+0.730205279 0.269794721
+0.731182796 0.268817204
+0.732160313 0.267839687
+0.733137830 0.266862170
+0.734115347 0.265884653
+0.735092864 0.264907136
+0.736070381 0.263929619
+0.737047898 0.262952102
+0.738025415 0.261974585
+0.739002933 0.260997067
+0.739980450 0.260019550
+0.740957967 0.259042033
+0.741935484 0.258064516
+0.742913001 0.257086999
+0.743890518 0.256109482
+0.744868035 0.255131965
+0.745845552 0.254154448
+0.746823069 0.253176931
+0.747800587 0.252199413
+0.748778104 0.251221896
+0.749755621 0.250244379
+0.750733138 0.250000000
+0.751710655 0.250000000
+0.752688172 0.250000000
+0.753665689 0.250000000
+0.754643206 0.250000000
+0.755620723 0.250000000
+0.756598240 0.250000000
+0.757575758 0.250000000
+0.758553275 0.250000000
+0.759530792 0.250000000
+0.760508309 0.250000000
+0.761485826 0.250000000
+0.762463343 0.250000000
+0.763440860 0.250000000
+0.764418377 0.250000000
+0.765395894 0.250000000
+0.766373412 0.250000000
+0.767350929 0.250000000
+0.768328446 0.250000000
+0.769305963 0.250000000
+0.770283480 0.250000000
+0.771260997 0.250000000
+0.772238514 0.250000000
+0.773216031 0.250000000
+0.774193548 0.250000000
+0.775171065 0.250000000
+0.776148583 0.250000000
+0.777126100 0.250000000
+0.778103617 0.250000000
+0.779081134 0.250000000
+0.780058651 0.250000000
+0.781036168 0.250000000
+0.782013685 0.250000000
+0.782991202 0.250000000
+0.783968719 0.250000000
+0.784946237 0.250000000
+0.785923754 0.250000000
+0.786901271 0.250000000
+0.787878788 0.250000000
+0.788856305 0.250000000
+0.789833822 0.250000000
+0.790811339 0.250000000
+0.791788856 0.250000000
+0.792766373 0.250000000
+0.793743891 0.250000000
+0.794721408 0.250000000
+0.795698925 0.250000000
+0.796676442 0.250000000
+0.797653959 0.250000000
+0.798631476 0.250000000
+0.799608993 0.250000000
+0.800586510 0.250000000
+0.801564027 0.250000000
+0.802541544 0.250000000
+0.803519062 0.250000000
+0.804496579 0.250000000
+0.805474096 0.250000000
+0.806451613 0.250000000
+0.807429130 0.250000000
+0.808406647 0.250000000
+0.809384164 0.250000000
+0.810361681 0.250000000
+0.811339198 0.250000000
+0.812316716 0.250000000
+0.813294233 0.250000000
+0.814271750 0.250000000
+0.815249267 0.250000000
+0.816226784 0.250000000
+0.817204301 0.250000000
+0.818181818 0.250000000
+0.819159335 0.250000000
+0.820136852 0.250000000
+0.821114370 0.250000000
+0.822091887 0.250000000
+0.823069404 0.250000000
+0.824046921 0.250000000
+0.825024438 0.250000000
+0.826001955 0.250000000
+0.826979472 0.250000000
+0.827956989 0.250000000
+0.828934506 0.250000000
+0.829912023 0.250000000
+0.830889541 0.250000000
+0.831867058 0.250000000
+0.832844575 0.250000000
+0.833822092 0.250000000
+0.834799609 0.250000000
+0.835777126 0.250000000
+0.836754643 0.250000000
+0.837732160 0.250000000
+0.838709677 0.250000000
+0.839687195 0.250000000
+0.840664712 0.250000000
+0.841642229 0.250000000
+0.842619746 0.250000000
+0.843597263 0.250000000
+0.844574780 0.250000000
+0.845552297 0.250000000
+0.846529814 0.250000000
+0.847507331 0.250000000
+0.848484848 0.250000000
+0.849462366 0.250000000
+0.850439883 0.250000000
+0.851417400 0.250000000
+0.852394917 0.250000000
+0.853372434 0.250000000
+0.854349951 0.250000000
+0.855327468 0.250000000
+0.856304985 0.250000000
+0.857282502 0.250000000
+0.858260020 0.250000000
+0.859237537 0.250000000
+0.860215054 0.250000000
+0.861192571 0.250000000
+0.862170088 0.250000000
+0.863147605 0.250000000
+0.864125122 0.250000000
+0.865102639 0.250000000
+0.866080156 0.250000000
+0.867057674 0.250000000
+0.868035191 0.250000000
+0.869012708 0.250000000
+0.869990225 0.250000000
+0.870967742 0.250000000
+0.871945259 0.250000000
+0.872922776 0.250000000
+0.873900293 0.250000000
+0.874877810 0.250000000
+0.875855327 0.250000000
+0.876832845 0.250000000
+0.877810362 0.250000000
+0.878787879 0.250000000
+0.879765396 0.250000000
+0.880742913 0.250000000
+0.881720430 0.250000000
+0.882697947 0.250000000
+0.883675464 0.250000000
+0.884652981 0.250000000
+0.885630499 0.250000000
+0.886608016 0.250000000
+0.887585533 0.250000000
+0.888563050 0.250000000
+0.889540567 0.250000000
+0.890518084 0.250000000
+0.891495601 0.250000000
+0.892473118 0.250000000
+0.893450635 0.250000000
+0.894428152 0.250000000
+0.895405670 0.250000000
+0.896383187 0.250000000
+0.897360704 0.250000000
+0.898338221 0.250000000
+0.899315738 0.250000000
+0.900293255 0.250000000
+0.901270772 0.250000000
+0.902248289 0.250000000
+0.903225806 0.250000000
+0.904203324 0.250000000
+0.905180841 0.250000000
+0.906158358 0.250000000
+0.907135875 0.250000000
+0.908113392 0.250000000
+0.909090909 0.250000000
+0.910068426 0.250000000
+0.911045943 0.250000000
+0.912023460 0.250000000
+0.913000978 0.250000000
+0.913978495 0.250000000
+0.914956012 0.250000000
+0.915933529 0.250000000
+0.916911046 0.250000000
+0.917888563 0.250000000
+0.918866080 0.250000000
+0.919843597 0.250000000
+0.920821114 0.250000000
+0.921798631 0.250000000
+0.922776149 0.250000000
+0.923753666 0.250000000
+0.924731183 0.250000000
+0.925708700 0.250000000
+0.926686217 0.250000000
+0.927663734 0.250000000
+0.928641251 0.250000000
+0.929618768 0.250000000
+0.930596285 0.250000000
+0.931573803 0.250000000
+0.932551320 0.250000000
+0.933528837 0.250000000
+0.934506354 0.250000000
+0.935483871 0.250000000
+0.936461388 0.250000000
+0.937438905 0.250000000
+0.938416422 0.250000000
+0.939393939 0.250000000
+0.940371457 0.250000000
+0.941348974 0.250000000
+0.942326491 0.250000000
+0.943304008 0.250000000
+0.944281525 0.250000000
+0.945259042 0.250000000
+0.946236559 0.250000000
+0.947214076 0.250000000
+0.948191593 0.250000000
+0.949169110 0.250000000
+0.950146628 0.250000000
+0.951124145 0.250000000
+0.952101662 0.250000000
+0.953079179 0.250000000
+0.954056696 0.250000000
+0.955034213 0.250000000
+0.956011730 0.250000000
+0.956989247 0.250000000
+0.957966764 0.250000000
+0.958944282 0.250000000
+0.959921799 0.250000000
+0.960899316 0.250000000
+0.961876833 0.250000000
+0.962854350 0.250000000
+0.963831867 0.250000000
+0.964809384 0.250000000
+0.965786901 0.250000000
+0.966764418 0.250000000
+0.967741935 0.250000000
+0.968719453 0.250000000
+0.969696970 0.250000000
+0.970674487 0.250000000
+0.971652004 0.250000000
+0.972629521 0.250000000
+0.973607038 0.250000000
+0.974584555 0.250000000
+0.975562072 0.250000000
+0.976539589 0.250000000
+0.977517107 0.250000000
+0.978494624 0.250000000
+0.979472141 0.250000000
+0.980449658 0.250000000
+0.981427175 0.250000000
+0.982404692 0.250000000
+0.983382209 0.250000000
+0.984359726 0.250000000
+0.985337243 0.250000000
+0.986314761 0.250000000
+0.987292278 0.250000000
+0.988269795 0.250000000
+0.989247312 0.250000000
+0.990224829 0.250000000
+0.991202346 0.250000000
+0.992179863 0.250000000
+0.993157380 0.250000000
+0.994134897 0.250000000
+0.995112414 0.250000000
+0.996089932 0.250000000
+0.997067449 0.250000000
+0.998044966 0.250000000
+0.999022483 0.250000000
+1.000000000 nan
diff --git a/examples/takagi-sugeno/SimpleDimmer.fll b/examples/takagi-sugeno/SimpleDimmer.fll
index 038c785..f08e563 100644
--- a/examples/takagi-sugeno/SimpleDimmer.fll
+++ b/examples/takagi-sugeno/SimpleDimmer.fll
@@ -1,18 +1,19 @@
-Engine: simple-dimmer
+Engine: SimpleDimmer
InputVariable: Ambient
enabled: true
range: 0.000 1.000
+ lock-range: false
term: DARK Triangle 0.000 0.250 0.500
term: MEDIUM Triangle 0.250 0.500 0.750
term: BRIGHT Triangle 0.500 0.750 1.000
OutputVariable: Power
enabled: true
range: 0.000 1.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
- lock-range: false
term: LOW Constant 0.250
term: MEDIUM Constant 0.500
term: HIGH Constant 0.750
@@ -20,7 +21,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if Ambient is DARK then Power is HIGH
rule: if Ambient is MEDIUM then Power is MEDIUM
rule: if Ambient is BRIGHT then Power is LOW \ No newline at end of file
diff --git a/examples/takagi-sugeno/SimpleDimmer.java b/examples/takagi-sugeno/SimpleDimmer.java
index 6d60f0e..c3c53e9 100644
--- a/examples/takagi-sugeno/SimpleDimmer.java
+++ b/examples/takagi-sugeno/SimpleDimmer.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,38 +13,46 @@ import com.fuzzylite.variable.*;
public class SimpleDimmer{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("simple-dimmer");
+engine.setName("SimpleDimmer");
+engine.setDescription("");
-InputVariable inputVariable = new InputVariable();
-inputVariable.setEnabled(true);
-inputVariable.setName("Ambient");
-inputVariable.setRange(0.000, 1.000);
-inputVariable.addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
-inputVariable.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
-inputVariable.addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
-engine.addInputVariable(inputVariable);
+InputVariable Ambient = new InputVariable();
+Ambient.setName("Ambient");
+Ambient.setDescription("");
+Ambient.setEnabled(true);
+Ambient.setRange(0.000, 1.000);
+Ambient.setLockValueInRange(false);
+Ambient.addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+Ambient.addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+Ambient.addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+engine.addInputVariable(Ambient);
-OutputVariable outputVariable = new OutputVariable();
-outputVariable.setEnabled(true);
-outputVariable.setName("Power");
-outputVariable.setRange(0.000, 1.000);
-outputVariable.fuzzyOutput().setAccumulation(null);
-outputVariable.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable.setDefaultValue(Double.NaN);
-outputVariable.setLockPreviousOutputValue(false);
-outputVariable.setLockOutputValueInRange(false);
-outputVariable.addTerm(new Constant("LOW", 0.250));
-outputVariable.addTerm(new Constant("MEDIUM", 0.500));
-outputVariable.addTerm(new Constant("HIGH", 0.750));
-engine.addOutputVariable(outputVariable);
+OutputVariable Power = new OutputVariable();
+Power.setName("Power");
+Power.setDescription("");
+Power.setEnabled(true);
+Power.setRange(0.000, 1.000);
+Power.setLockValueInRange(false);
+Power.setAggregation(null);
+Power.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+Power.setDefaultValue(Double.NaN);
+Power.setLockPreviousValue(false);
+Power.addTerm(new Constant("LOW", 0.250));
+Power.addTerm(new Constant("MEDIUM", 0.500));
+Power.addTerm(new Constant("HIGH", 0.750));
+engine.addOutputVariable(Power);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(null);
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(null);
+ruleBlock.setImplication(null);
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if Ambient is DARK then Power is HIGH", engine));
ruleBlock.addRule(Rule.parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
ruleBlock.addRule(Rule.parse("if Ambient is BRIGHT then Power is LOW", engine));
diff --git a/examples/takagi-sugeno/SimpleDimmer.pdf b/examples/takagi-sugeno/SimpleDimmer.pdf
new file mode 100644
index 0000000..f35dec9
--- /dev/null
+++ b/examples/takagi-sugeno/SimpleDimmer.pdf
Binary files differ
diff --git a/examples/takagi-sugeno/approximation.R b/examples/takagi-sugeno/approximation.R
new file mode 100644
index 0000000..89c0654
--- /dev/null
+++ b/examples/takagi-sugeno/approximation.R
@@ -0,0 +1,119 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "approximation"
+engine.fll = "Engine: approximation
+InputVariable: inputX
+ enabled: true
+ range: 0.000 10.000
+ lock-range: false
+ term: NEAR_1 Triangle 0.000 1.000 2.000
+ term: NEAR_2 Triangle 1.000 2.000 3.000
+ term: NEAR_3 Triangle 2.000 3.000 4.000
+ term: NEAR_4 Triangle 3.000 4.000 5.000
+ term: NEAR_5 Triangle 4.000 5.000 6.000
+ term: NEAR_6 Triangle 5.000 6.000 7.000
+ term: NEAR_7 Triangle 6.000 7.000 8.000
+ term: NEAR_8 Triangle 7.000 8.000 9.000
+ term: NEAR_9 Triangle 8.000 9.000 10.000
+OutputVariable: outputFx
+ enabled: true
+ range: -1.000 1.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: true
+ term: f1 Constant 0.840
+ term: f2 Constant 0.450
+ term: f3 Constant 0.040
+ term: f4 Constant -0.180
+ term: f5 Constant -0.190
+ term: f6 Constant -0.040
+ term: f7 Constant 0.090
+ term: f8 Constant 0.120
+ term: f9 Constant 0.040
+OutputVariable: trueFx
+ enabled: true
+ range: -1.000 1.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: true
+ term: fx Function sin(inputX)/inputX
+OutputVariable: diffFx
+ enabled: true
+ range: -1.000 1.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: diff Function fabs(outputFx-trueFx)
+RuleBlock:
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if inputX is NEAR_1 then outputFx is f1
+ rule: if inputX is NEAR_2 then outputFx is f2
+ rule: if inputX is NEAR_3 then outputFx is f3
+ rule: if inputX is NEAR_4 then outputFx is f4
+ rule: if inputX is NEAR_5 then outputFx is f5
+ rule: if inputX is NEAR_6 then outputFx is f6
+ rule: if inputX is NEAR_7 then outputFx is f7
+ rule: if inputX is NEAR_8 then outputFx is f8
+ rule: if inputX is NEAR_9 then outputFx is f9
+ rule: if inputX is any then trueFx is fx and diffFx is diff"
+
+engine.fldFile = "approximation.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(inputX, outputFx)) +
+ geom_line(aes(color=outputFx), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("inputX vs outputFx")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(inputX, outputFx)) +
+ geom_line(aes(color=outputFx), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("outputFx vs inputX")
+
+engine.plot.i1_o2 = ggplot(engine.df, aes(inputX, trueFx)) +
+ geom_line(aes(color=trueFx), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("inputX vs trueFx")
+
+engine.plot.o2_i1 = ggplot(engine.df, aes(inputX, trueFx)) +
+ geom_line(aes(color=trueFx), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("trueFx vs inputX")
+
+engine.plot.i1_o3 = ggplot(engine.df, aes(inputX, diffFx)) +
+ geom_line(aes(color=diffFx), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("inputX vs diffFx")
+
+engine.plot.o3_i1 = ggplot(engine.df, aes(inputX, diffFx)) +
+ geom_line(aes(color=diffFx), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("diffFx vs inputX")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, engine.plot.i1_o2, engine.plot.o2_i1, engine.plot.i1_o3, engine.plot.o3_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/takagi-sugeno/approximation.cpp b/examples/takagi-sugeno/approximation.cpp
index 178f162..da0a307 100644
--- a/examples/takagi-sugeno/approximation.cpp
+++ b/examples/takagi-sugeno/approximation.cpp
@@ -1,86 +1,96 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("approximation of sin(x)/x");
+engine->setName("approximation");
+engine->setDescription("");
-InputVariable* inputVariable = new InputVariable;
-inputVariable->setEnabled(true);
-inputVariable->setName("inputX");
-inputVariable->setRange(0.000, 10.000);
-inputVariable->addTerm(new Triangle("NEAR_1", 0.000, 1.000, 2.000));
-inputVariable->addTerm(new Triangle("NEAR_2", 1.000, 2.000, 3.000));
-inputVariable->addTerm(new Triangle("NEAR_3", 2.000, 3.000, 4.000));
-inputVariable->addTerm(new Triangle("NEAR_4", 3.000, 4.000, 5.000));
-inputVariable->addTerm(new Triangle("NEAR_5", 4.000, 5.000, 6.000));
-inputVariable->addTerm(new Triangle("NEAR_6", 5.000, 6.000, 7.000));
-inputVariable->addTerm(new Triangle("NEAR_7", 6.000, 7.000, 8.000));
-inputVariable->addTerm(new Triangle("NEAR_8", 7.000, 8.000, 9.000));
-inputVariable->addTerm(new Triangle("NEAR_9", 8.000, 9.000, 10.000));
-engine->addInputVariable(inputVariable);
+InputVariable* inputX = new InputVariable;
+inputX->setName("inputX");
+inputX->setDescription("");
+inputX->setEnabled(true);
+inputX->setRange(0.000, 10.000);
+inputX->setLockValueInRange(false);
+inputX->addTerm(new Triangle("NEAR_1", 0.000, 1.000, 2.000));
+inputX->addTerm(new Triangle("NEAR_2", 1.000, 2.000, 3.000));
+inputX->addTerm(new Triangle("NEAR_3", 2.000, 3.000, 4.000));
+inputX->addTerm(new Triangle("NEAR_4", 3.000, 4.000, 5.000));
+inputX->addTerm(new Triangle("NEAR_5", 4.000, 5.000, 6.000));
+inputX->addTerm(new Triangle("NEAR_6", 5.000, 6.000, 7.000));
+inputX->addTerm(new Triangle("NEAR_7", 6.000, 7.000, 8.000));
+inputX->addTerm(new Triangle("NEAR_8", 7.000, 8.000, 9.000));
+inputX->addTerm(new Triangle("NEAR_9", 8.000, 9.000, 10.000));
+engine->addInputVariable(inputX);
-OutputVariable* outputVariable1 = new OutputVariable;
-outputVariable1->setEnabled(true);
-outputVariable1->setName("outputFx");
-outputVariable1->setRange(-1.000, 1.000);
-outputVariable1->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable1->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable1->setDefaultValue(fl::nan);
-outputVariable1->setLockPreviousOutputValue(true);
-outputVariable1->setLockOutputValueInRange(false);
-outputVariable1->addTerm(new Constant("f1", 0.840));
-outputVariable1->addTerm(new Constant("f2", 0.450));
-outputVariable1->addTerm(new Constant("f3", 0.040));
-outputVariable1->addTerm(new Constant("f4", -0.180));
-outputVariable1->addTerm(new Constant("f5", -0.190));
-outputVariable1->addTerm(new Constant("f6", -0.040));
-outputVariable1->addTerm(new Constant("f7", 0.090));
-outputVariable1->addTerm(new Constant("f8", 0.120));
-outputVariable1->addTerm(new Constant("f9", 0.040));
-engine->addOutputVariable(outputVariable1);
+OutputVariable* outputFx = new OutputVariable;
+outputFx->setName("outputFx");
+outputFx->setDescription("");
+outputFx->setEnabled(true);
+outputFx->setRange(-1.000, 1.000);
+outputFx->setLockValueInRange(false);
+outputFx->setAggregation(fl::null);
+outputFx->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+outputFx->setDefaultValue(fl::nan);
+outputFx->setLockPreviousValue(true);
+outputFx->addTerm(new Constant("f1", 0.840));
+outputFx->addTerm(new Constant("f2", 0.450));
+outputFx->addTerm(new Constant("f3", 0.040));
+outputFx->addTerm(new Constant("f4", -0.180));
+outputFx->addTerm(new Constant("f5", -0.190));
+outputFx->addTerm(new Constant("f6", -0.040));
+outputFx->addTerm(new Constant("f7", 0.090));
+outputFx->addTerm(new Constant("f8", 0.120));
+outputFx->addTerm(new Constant("f9", 0.040));
+engine->addOutputVariable(outputFx);
-OutputVariable* outputVariable2 = new OutputVariable;
-outputVariable2->setEnabled(true);
-outputVariable2->setName("trueFx");
-outputVariable2->setRange(-1.000, 1.000);
-outputVariable2->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable2->setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable2->setDefaultValue(fl::nan);
-outputVariable2->setLockPreviousOutputValue(true);
-outputVariable2->setLockOutputValueInRange(false);
-outputVariable2->addTerm(Function::create("fx", "sin(inputX)/inputX", engine));
-engine->addOutputVariable(outputVariable2);
+OutputVariable* trueFx = new OutputVariable;
+trueFx->setName("trueFx");
+trueFx->setDescription("");
+trueFx->setEnabled(true);
+trueFx->setRange(-1.000, 1.000);
+trueFx->setLockValueInRange(false);
+trueFx->setAggregation(fl::null);
+trueFx->setDefuzzifier(new WeightedAverage("Automatic"));
+trueFx->setDefaultValue(fl::nan);
+trueFx->setLockPreviousValue(true);
+trueFx->addTerm(Function::create("fx", "sin(inputX)/inputX", engine));
+engine->addOutputVariable(trueFx);
-OutputVariable* outputVariable3 = new OutputVariable;
-outputVariable3->setEnabled(true);
-outputVariable3->setName("diffFx");
-outputVariable3->setRange(-1.000, 1.000);
-outputVariable3->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable3->setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable3->setDefaultValue(fl::nan);
-outputVariable3->setLockPreviousOutputValue(false);
-outputVariable3->setLockOutputValueInRange(false);
-outputVariable3->addTerm(Function::create("diff", "fabs(outputFx-trueFx)", engine));
-engine->addOutputVariable(outputVariable3);
+OutputVariable* diffFx = new OutputVariable;
+diffFx->setName("diffFx");
+diffFx->setDescription("");
+diffFx->setEnabled(true);
+diffFx->setRange(-1.000, 1.000);
+diffFx->setLockValueInRange(false);
+diffFx->setAggregation(fl::null);
+diffFx->setDefuzzifier(new WeightedAverage("Automatic"));
+diffFx->setDefaultValue(fl::nan);
+diffFx->setLockPreviousValue(false);
+diffFx->addTerm(Function::create("diff", "fabs(outputFx-trueFx)", engine));
+engine->addOutputVariable(diffFx);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(fl::null);
ruleBlock->setDisjunction(fl::null);
-ruleBlock->setActivation(fl::null);
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_1 then outputFx is f1", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_2 then outputFx is f2", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_3 then outputFx is f3", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_4 then outputFx is f4", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_5 then outputFx is f5", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_6 then outputFx is f6", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_7 then outputFx is f7", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_8 then outputFx is f8", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is NEAR_9 then outputFx is f9", engine));
-ruleBlock->addRule(fl::Rule::parse("if inputX is any then trueFx is fx and diffFx is diff", engine));
+ruleBlock->setImplication(fl::null);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_1 then outputFx is f1", engine));
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_2 then outputFx is f2", engine));
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_3 then outputFx is f3", engine));
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_4 then outputFx is f4", engine));
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_5 then outputFx is f5", engine));
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_6 then outputFx is f6", engine));
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_7 then outputFx is f7", engine));
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_8 then outputFx is f8", engine));
+ruleBlock->addRule(Rule::parse("if inputX is NEAR_9 then outputFx is f9", engine));
+ruleBlock->addRule(Rule::parse("if inputX is any then trueFx is fx and diffFx is diff", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/takagi-sugeno/approximation.fcl b/examples/takagi-sugeno/approximation.fcl
index 8b5f121..6bf285d 100644
--- a/examples/takagi-sugeno/approximation.fcl
+++ b/examples/takagi-sugeno/approximation.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK approximation of sin(x)/x
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK approximation
VAR_INPUT
inputX: REAL;
diff --git a/examples/takagi-sugeno/approximation.fis b/examples/takagi-sugeno/approximation.fis
index 73075bc..2fcbc8d 100644
--- a/examples/takagi-sugeno/approximation.fis
+++ b/examples/takagi-sugeno/approximation.fis
@@ -1,13 +1,16 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='approximation of sin(x)/x'
+Name='approximation'
Type='sugeno'
+Version=6.0
NumInputs=1
NumOutputs=3
NumRules=10
-AndMethod=''
-OrMethod=''
-ImpMethod=''
-AggMethod=''
+AndMethod='min'
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
DefuzzMethod='wtaver'
[Input1]
@@ -27,7 +30,6 @@ MF9='NEAR_9':'trimf',[8.000 9.000 10.000]
[Output1]
Name='outputFx'
Range=[-1.000 1.000]
-LockPrevious=1
NumMFs=9
MF1='f1':'constant',[0.840]
MF2='f2':'constant',[0.450]
@@ -42,7 +44,6 @@ MF9='f9':'constant',[0.040]
[Output2]
Name='trueFx'
Range=[-1.000 1.000]
-LockPrevious=1
NumMFs=1
MF1='fx':'function',[sin(inputX)/inputX]
diff --git a/examples/takagi-sugeno/approximation.fld b/examples/takagi-sugeno/approximation.fld
index 36bdbd8..1f3ba00 100644
--- a/examples/takagi-sugeno/approximation.fld
+++ b/examples/takagi-sugeno/approximation.fld
@@ -1,1026 +1,1025 @@
-#@Engine: approximation of sin(x)/x;
-#@InputVariable: inputX; @OutputVariable: outputFx; @OutputVariable: trueFx; @OutputVariable: diffFx;
-0.00000000 nan nan nan
-0.00977517 0.84000000 0.99998407 0.15998407
-0.01955034 0.84000000 0.99993630 0.15993630
-0.02932551 0.84000000 0.99985668 0.15985668
-0.03910068 0.84000000 0.99974521 0.15974521
-0.04887586 0.84000000 0.99960191 0.15960191
-0.05865103 0.84000000 0.99942677 0.15942677
-0.06842620 0.84000000 0.99921983 0.15921983
-0.07820137 0.84000000 0.99898107 0.15898107
-0.08797654 0.84000000 0.99871052 0.15871052
-0.09775171 0.84000000 0.99840819 0.15840819
-0.10752688 0.84000000 0.99807411 0.15807411
-0.11730205 0.84000000 0.99770828 0.15770828
-0.12707722 0.84000000 0.99731074 0.15731074
-0.13685239 0.84000000 0.99688149 0.15688149
-0.14662757 0.84000000 0.99642058 0.15642058
-0.15640274 0.84000000 0.99592801 0.15592801
-0.16617791 0.84000000 0.99540383 0.15540383
-0.17595308 0.84000000 0.99484807 0.15484807
-0.18572825 0.84000000 0.99426074 0.15426074
-0.19550342 0.84000000 0.99364190 0.15364190
-0.20527859 0.84000000 0.99299157 0.15299157
-0.21505376 0.84000000 0.99230978 0.15230978
-0.22482893 0.84000000 0.99159659 0.15159659
-0.23460411 0.84000000 0.99085203 0.15085203
-0.24437928 0.84000000 0.99007614 0.15007614
-0.25415445 0.84000000 0.98926897 0.14926897
-0.26392962 0.84000000 0.98843056 0.14843056
-0.27370479 0.84000000 0.98756097 0.14756097
-0.28347996 0.84000000 0.98666023 0.14666023
-0.29325513 0.84000000 0.98572841 0.14572841
-0.30303030 0.84000000 0.98476555 0.14476555
-0.31280547 0.84000000 0.98377172 0.14377172
-0.32258065 0.84000000 0.98274697 0.14274697
-0.33235582 0.84000000 0.98169135 0.14169135
-0.34213099 0.84000000 0.98060493 0.14060493
-0.35190616 0.84000000 0.97948777 0.13948777
-0.36168133 0.84000000 0.97833993 0.13833993
-0.37145650 0.84000000 0.97716148 0.13716148
-0.38123167 0.84000000 0.97595249 0.13595249
-0.39100684 0.84000000 0.97471302 0.13471302
-0.40078201 0.84000000 0.97344315 0.13344315
-0.41055718 0.84000000 0.97214295 0.13214295
-0.42033236 0.84000000 0.97081249 0.13081249
-0.43010753 0.84000000 0.96945185 0.12945185
-0.43988270 0.84000000 0.96806111 0.12806111
-0.44965787 0.84000000 0.96664035 0.12664035
-0.45943304 0.84000000 0.96518964 0.12518964
-0.46920821 0.84000000 0.96370907 0.12370907
-0.47898338 0.84000000 0.96219873 0.12219873
-0.48875855 0.84000000 0.96065870 0.12065870
-0.49853372 0.84000000 0.95908907 0.11908907
-0.50830890 0.84000000 0.95748993 0.11748993
-0.51808407 0.84000000 0.95586137 0.11586137
-0.52785924 0.84000000 0.95420348 0.11420348
-0.53763441 0.84000000 0.95251635 0.11251635
-0.54740958 0.84000000 0.95080010 0.11080010
-0.55718475 0.84000000 0.94905480 0.10905480
-0.56695992 0.84000000 0.94728056 0.10728056
-0.57673509 0.84000000 0.94547749 0.10547749
-0.58651026 0.84000000 0.94364568 0.10364568
-0.59628543 0.84000000 0.94178524 0.10178524
-0.60606061 0.84000000 0.93989628 0.09989628
-0.61583578 0.84000000 0.93797889 0.09797889
-0.62561095 0.84000000 0.93603320 0.09603320
-0.63538612 0.84000000 0.93405932 0.09405932
-0.64516129 0.84000000 0.93205734 0.09205734
-0.65493646 0.84000000 0.93002740 0.09002740
-0.66471163 0.84000000 0.92796960 0.08796960
-0.67448680 0.84000000 0.92588406 0.08588406
-0.68426197 0.84000000 0.92377090 0.08377090
-0.69403715 0.84000000 0.92163024 0.08163024
-0.70381232 0.84000000 0.91946220 0.07946220
-0.71358749 0.84000000 0.91726690 0.07726690
-0.72336266 0.84000000 0.91504448 0.07504448
-0.73313783 0.84000000 0.91279505 0.07279505
-0.74291300 0.84000000 0.91051874 0.07051874
-0.75268817 0.84000000 0.90821568 0.06821568
-0.76246334 0.84000000 0.90588601 0.06588601
-0.77223851 0.84000000 0.90352985 0.06352985
-0.78201369 0.84000000 0.90114734 0.06114734
-0.79178886 0.84000000 0.89873861 0.05873861
-0.80156403 0.84000000 0.89630380 0.05630380
-0.81133920 0.84000000 0.89384305 0.05384305
-0.82111437 0.84000000 0.89135649 0.05135649
-0.83088954 0.84000000 0.88884427 0.04884427
-0.84066471 0.84000000 0.88630653 0.04630653
-0.85043988 0.84000000 0.88374342 0.04374342
-0.86021505 0.84000000 0.88115507 0.04115507
-0.86999022 0.84000000 0.87854163 0.03854163
-0.87976540 0.84000000 0.87590326 0.03590326
-0.88954057 0.84000000 0.87324010 0.03324010
-0.89931574 0.84000000 0.87055230 0.03055230
-0.90909091 0.84000000 0.86784001 0.02784001
-0.91886608 0.84000000 0.86510339 0.02510339
-0.92864125 0.84000000 0.86234258 0.02234258
-0.93841642 0.84000000 0.85955775 0.01955775
-0.94819159 0.84000000 0.85674906 0.01674906
-0.95796676 0.84000000 0.85391665 0.01391665
-0.96774194 0.84000000 0.85106070 0.01106070
-0.97751711 0.84000000 0.84818136 0.00818136
-0.98729228 0.84000000 0.84527878 0.00527878
-0.99706745 0.84000000 0.84235315 0.00235315
-1.00684262 0.83733138 0.83940461 0.00207323
-1.01661779 0.83351906 0.83643334 0.00291428
-1.02639296 0.82970674 0.83343951 0.00373276
-1.03616813 0.82589443 0.83042327 0.00452884
-1.04594330 0.82208211 0.82738481 0.00530270
-1.05571848 0.81826979 0.82432428 0.00605449
-1.06549365 0.81445748 0.82124187 0.00678439
-1.07526882 0.81064516 0.81813774 0.00749258
-1.08504399 0.80683284 0.81501207 0.00817923
-1.09481916 0.80302053 0.81186504 0.00884451
-1.10459433 0.79920821 0.80869682 0.00948860
-1.11436950 0.79539589 0.80550758 0.01011168
-1.12414467 0.79158358 0.80229751 0.01071393
-1.13391984 0.78777126 0.79906678 0.01129552
-1.14369501 0.78395894 0.79581558 0.01185663
-1.15347019 0.78014663 0.79254408 0.01239745
-1.16324536 0.77633431 0.78925248 0.01291816
-1.17302053 0.77252199 0.78594094 0.01341895
-1.18279570 0.76870968 0.78260967 0.01389999
-1.19257087 0.76489736 0.77925884 0.01436147
-1.20234604 0.76108504 0.77588863 0.01480359
-1.21212121 0.75727273 0.77249925 0.01522652
-1.22189638 0.75346041 0.76909087 0.01563046
-1.23167155 0.74964809 0.76566369 0.01601559
-1.24144673 0.74583578 0.76221789 0.01638211
-1.25122190 0.74202346 0.75875367 0.01673021
-1.26099707 0.73821114 0.75527122 0.01706007
-1.27077224 0.73439883 0.75177073 0.01737190
-1.28054741 0.73058651 0.74825240 0.01766589
-1.29032258 0.72677419 0.74471642 0.01794222
-1.30009775 0.72296188 0.74116298 0.01820111
-1.30987292 0.71914956 0.73759230 0.01844274
-1.31964809 0.71533724 0.73400455 0.01866731
-1.32942326 0.71152493 0.73039994 0.01887502
-1.33919844 0.70771261 0.72677868 0.01906607
-1.34897361 0.70390029 0.72314095 0.01924066
-1.35874878 0.70008798 0.71948696 0.01939899
-1.36852395 0.69627566 0.71581692 0.01954126
-1.37829912 0.69246334 0.71213102 0.01966767
-1.38807429 0.68865103 0.70842946 0.01977844
-1.39784946 0.68483871 0.70471246 0.01987375
-1.40762463 0.68102639 0.70098021 0.01995382
-1.41739980 0.67721408 0.69723292 0.02001884
-1.42717498 0.67340176 0.69347080 0.02006904
-1.43695015 0.66958944 0.68969405 0.02010461
-1.44672532 0.66577713 0.68590288 0.02012575
-1.45650049 0.66196481 0.68209750 0.02013269
-1.46627566 0.65815249 0.67827811 0.02012562
-1.47605083 0.65434018 0.67444493 0.02010476
-1.48582600 0.65052786 0.67059817 0.02007031
-1.49560117 0.64671554 0.66673803 0.02002249
-1.50537634 0.64290323 0.66286472 0.01996150
-1.51515152 0.63909091 0.65897847 0.01988756
-1.52492669 0.63527859 0.65507947 0.01980088
-1.53470186 0.63146628 0.65116795 0.01970168
-1.54447703 0.62765396 0.64724411 0.01959016
-1.55425220 0.62384164 0.64330818 0.01946653
-1.56402737 0.62002933 0.63936035 0.01933103
-1.57380254 0.61621701 0.63540086 0.01918385
-1.58357771 0.61240469 0.63142990 0.01902521
-1.59335288 0.60859238 0.62744771 0.01885533
-1.60312805 0.60478006 0.62345448 0.01867443
-1.61290323 0.60096774 0.61945045 0.01848271
-1.62267840 0.59715543 0.61543583 0.01828041
-1.63245357 0.59334311 0.61141083 0.01806772
-1.64222874 0.58953079 0.60737568 0.01784488
-1.65200391 0.58571848 0.60333058 0.01761210
-1.66177908 0.58190616 0.59927576 0.01736960
-1.67155425 0.57809384 0.59521144 0.01711760
-1.68132942 0.57428152 0.59113783 0.01685631
-1.69110459 0.57046921 0.58705516 0.01658596
-1.70087977 0.56665689 0.58296365 0.01630676
-1.71065494 0.56284457 0.57886351 0.01601893
-1.72043011 0.55903226 0.57475496 0.01572270
-1.73020528 0.55521994 0.57063823 0.01541829
-1.73998045 0.55140762 0.56651353 0.01510591
-1.74975562 0.54759531 0.56238109 0.01478578
-1.75953079 0.54378299 0.55824113 0.01445814
-1.76930596 0.53997067 0.55409386 0.01412319
-1.77908113 0.53615836 0.54993952 0.01378116
-1.78885630 0.53234604 0.54577832 0.01343228
-1.79863148 0.52853372 0.54161048 0.01307675
-1.80840665 0.52472141 0.53743622 0.01271481
-1.81818182 0.52090909 0.53325577 0.01234668
-1.82795699 0.51709677 0.52906935 0.01197258
-1.83773216 0.51328446 0.52487718 0.01159273
-1.84750733 0.50947214 0.52067949 0.01120735
-1.85728250 0.50565982 0.51647649 0.01081666
-1.86705767 0.50184751 0.51226841 0.01042090
-1.87683284 0.49803519 0.50805546 0.01002027
-1.88660802 0.49422287 0.50383788 0.00961501
-1.89638319 0.49041056 0.49961589 0.00920533
-1.90615836 0.48659824 0.49538970 0.00879146
-1.91593353 0.48278592 0.49115955 0.00837362
-1.92570870 0.47897361 0.48692564 0.00795203
-1.93548387 0.47516129 0.48268821 0.00752692
-1.94525904 0.47134897 0.47844748 0.00709850
-1.95503421 0.46753666 0.47420366 0.00666700
-1.96480938 0.46372434 0.46995699 0.00623265
-1.97458456 0.45991202 0.46570768 0.00579565
-1.98435973 0.45609971 0.46145595 0.00535624
-1.99413490 0.45228739 0.45720203 0.00491464
-2.00391007 0.44839687 0.45294613 0.00454926
-2.01368524 0.44438905 0.44868849 0.00429944
-2.02346041 0.44038123 0.44442931 0.00404808
-2.03323558 0.43637341 0.44016883 0.00379542
-2.04301075 0.43236559 0.43590726 0.00354167
-2.05278592 0.42835777 0.43164482 0.00328705
-2.06256109 0.42434995 0.42738174 0.00303178
-2.07233627 0.42034213 0.42311822 0.00277609
-2.08211144 0.41633431 0.41885450 0.00252019
-2.09188661 0.41232649 0.41459079 0.00226430
-2.10166178 0.40831867 0.41032731 0.00200864
-2.11143695 0.40431085 0.40606429 0.00175344
-2.12121212 0.40030303 0.40180193 0.00149890
-2.13098729 0.39629521 0.39754045 0.00124524
-2.14076246 0.39228739 0.39328009 0.00099270
-2.15053763 0.38827957 0.38902104 0.00074147
-2.16031281 0.38427175 0.38476354 0.00049179
-2.17008798 0.38026393 0.38050779 0.00024386
-2.17986315 0.37625611 0.37625401 0.00000210
-2.18963832 0.37224829 0.37200242 0.00024587
-2.19941349 0.36824047 0.36775324 0.00048723
-2.20918866 0.36423265 0.36350667 0.00072598
-2.21896383 0.36022483 0.35926294 0.00096189
-2.22873900 0.35621701 0.35502225 0.00119476
-2.23851417 0.35220919 0.35078483 0.00142436
-2.24828935 0.34820137 0.34655088 0.00165049
-2.25806452 0.34419355 0.34232062 0.00187293
-2.26783969 0.34018573 0.33809425 0.00209148
-2.27761486 0.33617791 0.33387200 0.00230591
-2.28739003 0.33217009 0.32965407 0.00251602
-2.29716520 0.32816227 0.32544067 0.00272160
-2.30694037 0.32415445 0.32123201 0.00292244
-2.31671554 0.32014663 0.31702830 0.00311833
-2.32649071 0.31613881 0.31282975 0.00330906
-2.33626588 0.31213099 0.30863657 0.00349442
-2.34604106 0.30812317 0.30444897 0.00367420
-2.35581623 0.30411535 0.30026714 0.00384821
-2.36559140 0.30010753 0.29609130 0.00401622
-2.37536657 0.29609971 0.29192166 0.00417805
-2.38514174 0.29209189 0.28775841 0.00433347
-2.39491691 0.28808407 0.28360177 0.00448230
-2.40469208 0.28407625 0.27945193 0.00462432
-2.41446725 0.28006843 0.27530910 0.00475933
-2.42424242 0.27606061 0.27117348 0.00488713
-2.43401760 0.27205279 0.26704526 0.00500752
-2.44379277 0.26804497 0.26292466 0.00512030
-2.45356794 0.26403715 0.25881187 0.00522527
-2.46334311 0.26002933 0.25470709 0.00532224
-2.47311828 0.25602151 0.25061052 0.00541099
-2.48289345 0.25201369 0.24652234 0.00549134
-2.49266862 0.24800587 0.24244277 0.00556309
-2.50244379 0.24399804 0.23837200 0.00562605
-2.51221896 0.23999022 0.23431022 0.00568001
-2.52199413 0.23598240 0.23025762 0.00572479
-2.53176931 0.23197458 0.22621439 0.00576019
-2.54154448 0.22796676 0.22218074 0.00578602
-2.55131965 0.22395894 0.21815685 0.00580210
-2.56109482 0.21995112 0.21414291 0.00580822
-2.57086999 0.21594330 0.21013910 0.00580420
-2.58064516 0.21193548 0.20614563 0.00578985
-2.59042033 0.20792766 0.20216267 0.00576499
-2.60019550 0.20391984 0.19819042 0.00572942
-2.60997067 0.19991202 0.19422905 0.00568297
-2.61974585 0.19590420 0.19027876 0.00562545
-2.62952102 0.19189638 0.18633972 0.00555666
-2.63929619 0.18788856 0.18241212 0.00547644
-2.64907136 0.18388074 0.17849614 0.00538460
-2.65884653 0.17987292 0.17459196 0.00528096
-2.66862170 0.17586510 0.17069976 0.00516534
-2.67839687 0.17185728 0.16681972 0.00503756
-2.68817204 0.16784946 0.16295202 0.00489744
-2.69794721 0.16384164 0.15909683 0.00474481
-2.70772239 0.15983382 0.15525433 0.00457950
-2.71749756 0.15582600 0.15142469 0.00440132
-2.72727273 0.15181818 0.14760808 0.00421010
-2.73704790 0.14781036 0.14380468 0.00400568
-2.74682307 0.14380254 0.14001466 0.00378788
-2.75659824 0.13979472 0.13623819 0.00355653
-2.76637341 0.13578690 0.13247544 0.00331146
-2.77614858 0.13177908 0.12872657 0.00305251
-2.78592375 0.12777126 0.12499175 0.00277951
-2.79569892 0.12376344 0.12127114 0.00249230
-2.80547410 0.11975562 0.11756492 0.00219070
-2.81524927 0.11574780 0.11387324 0.00187456
-2.82502444 0.11173998 0.11019627 0.00154371
-2.83479961 0.10773216 0.10653416 0.00119801
-2.84457478 0.10372434 0.10288707 0.00083727
-2.85434995 0.09971652 0.09925517 0.00046135
-2.86412512 0.09570870 0.09563860 0.00007010
-2.87390029 0.09170088 0.09203753 0.00033665
-2.88367546 0.08769306 0.08845211 0.00075905
-2.89345064 0.08368524 0.08488250 0.00119726
-2.90322581 0.07967742 0.08132883 0.00165141
-2.91300098 0.07566960 0.07779128 0.00212168
-2.92277615 0.07166178 0.07426997 0.00260819
-2.93255132 0.06765396 0.07076507 0.00311111
-2.94232649 0.06364614 0.06727672 0.00363058
-2.95210166 0.05963832 0.06380506 0.00416674
-2.96187683 0.05563050 0.06035024 0.00471974
-2.97165200 0.05162268 0.05691240 0.00528972
-2.98142717 0.04761486 0.05349169 0.00587683
-2.99120235 0.04360704 0.05008823 0.00648120
-3.00097752 0.03978495 0.04670218 0.00691724
-3.01075269 0.03763441 0.04333367 0.00569927
-3.02052786 0.03548387 0.03998284 0.00449897
-3.03030303 0.03333333 0.03664981 0.00331648
-3.04007820 0.03118280 0.03333473 0.00215193
-3.04985337 0.02903226 0.03003772 0.00100547
-3.05962854 0.02688172 0.02675892 0.00012280
-3.06940371 0.02473118 0.02349846 0.00123272
-3.07917889 0.02258065 0.02025646 0.00232419
-3.08895406 0.02043011 0.01703304 0.00339706
-3.09872923 0.01827957 0.01382835 0.00445122
-3.10850440 0.01612903 0.01064249 0.00548655
-3.11827957 0.01397849 0.00747559 0.00650291
-3.12805474 0.01182796 0.00432777 0.00750019
-3.13782991 0.00967742 0.00119915 0.00847827
-3.14760508 0.00752688 -0.00191015 0.00943703
-3.15738025 0.00537634 -0.00500001 0.01037636
-3.16715543 0.00322581 -0.00807033 0.01129614
-3.17693060 0.00107527 -0.01112098 0.01219625
-3.18670577 -0.00107527 -0.01415186 0.01307659
-3.19648094 -0.00322581 -0.01716285 0.01393705
-3.20625611 -0.00537634 -0.02015385 0.01477750
-3.21603128 -0.00752688 -0.02312474 0.01559786
-3.22580645 -0.00967742 -0.02607543 0.01639801
-3.23558162 -0.01182796 -0.02900580 0.01717785
-3.24535679 -0.01397849 -0.03191576 0.01793727
-3.25513196 -0.01612903 -0.03480520 0.01867617
-3.26490714 -0.01827957 -0.03767402 0.01939445
-3.27468231 -0.02043011 -0.04052213 0.02009202
-3.28445748 -0.02258065 -0.04334942 0.02076878
-3.29423265 -0.02473118 -0.04615581 0.02142462
-3.30400782 -0.02688172 -0.04894118 0.02205946
-3.31378299 -0.02903226 -0.05170547 0.02267321
-3.32355816 -0.03118280 -0.05444857 0.02326577
-3.33333333 -0.03333333 -0.05717039 0.02383706
-3.34310850 -0.03548387 -0.05987085 0.02438698
-3.35288368 -0.03763441 -0.06254985 0.02491545
-3.36265885 -0.03978495 -0.06520733 0.02542238
-3.37243402 -0.04193548 -0.06784318 0.02590770
-3.38220919 -0.04408602 -0.07045733 0.02637131
-3.39198436 -0.04623656 -0.07304971 0.02681315
-3.40175953 -0.04838710 -0.07562022 0.02723313
-3.41153470 -0.05053763 -0.07816880 0.02763117
-3.42130987 -0.05268817 -0.08069537 0.02800720
-3.43108504 -0.05483871 -0.08319985 0.02836114
-3.44086022 -0.05698925 -0.08568218 0.02869293
-3.45063539 -0.05913978 -0.08814228 0.02900249
-3.46041056 -0.06129032 -0.09058008 0.02928975
-3.47018573 -0.06344086 -0.09299551 0.02955465
-3.47996090 -0.06559140 -0.09538852 0.02979712
-3.48973607 -0.06774194 -0.09775902 0.03001709
-3.49951124 -0.06989247 -0.10010698 0.03021450
-3.50928641 -0.07204301 -0.10243231 0.03038930
-3.51906158 -0.07419355 -0.10473496 0.03054141
-3.52883675 -0.07634409 -0.10701487 0.03067079
-3.53861193 -0.07849462 -0.10927199 0.03077737
-3.54838710 -0.08064516 -0.11150627 0.03086111
-3.55816227 -0.08279570 -0.11371764 0.03092194
-3.56793744 -0.08494624 -0.11590606 0.03095982
-3.57771261 -0.08709677 -0.11807147 0.03097470
-3.58748778 -0.08924731 -0.12021383 0.03096652
-3.59726295 -0.09139785 -0.12233310 0.03093525
-3.60703812 -0.09354839 -0.12442922 0.03088083
-3.61681329 -0.09569892 -0.12650215 0.03080322
-3.62658847 -0.09784946 -0.12855185 0.03070239
-3.63636364 -0.10000000 -0.13057828 0.03057828
-3.64613881 -0.10215054 -0.13258140 0.03043086
-3.65591398 -0.10430108 -0.13456118 0.03026010
-3.66568915 -0.10645161 -0.13651757 0.03006596
-3.67546432 -0.10860215 -0.13845055 0.02984840
-3.68523949 -0.11075269 -0.14036007 0.02960739
-3.69501466 -0.11290323 -0.14224612 0.02934290
-3.70478983 -0.11505376 -0.14410866 0.02905490
-3.71456500 -0.11720430 -0.14594766 0.02874336
-3.72434018 -0.11935484 -0.14776310 0.02840827
-3.73411535 -0.12150538 -0.14955496 0.02804958
-3.74389052 -0.12365591 -0.15132320 0.02766729
-3.75366569 -0.12580645 -0.15306781 0.02726136
-3.76344086 -0.12795699 -0.15478877 0.02683178
-3.77321603 -0.13010753 -0.15648606 0.02637853
-3.78299120 -0.13225806 -0.15815967 0.02590160
-3.79276637 -0.13440860 -0.15980957 0.02540097
-3.80254154 -0.13655914 -0.16143576 0.02487662
-3.81231672 -0.13870968 -0.16303823 0.02432855
-3.82209189 -0.14086022 -0.16461696 0.02375674
-3.83186706 -0.14301075 -0.16617194 0.02316119
-3.84164223 -0.14516129 -0.16770318 0.02254189
-3.85141740 -0.14731183 -0.16921065 0.02189883
-3.86119257 -0.14946237 -0.17069437 0.02123200
-3.87096774 -0.15161290 -0.17215432 0.02054142
-3.88074291 -0.15376344 -0.17359052 0.01982707
-3.89051808 -0.15591398 -0.17500294 0.01908896
-3.90029326 -0.15806452 -0.17639161 0.01832710
-3.91006843 -0.16021505 -0.17775652 0.01754147
-3.91984360 -0.16236559 -0.17909769 0.01673209
-3.92961877 -0.16451613 -0.18041510 0.01589898
-3.93939394 -0.16666667 -0.18170879 0.01504212
-3.94916911 -0.16881720 -0.18297875 0.01416154
-3.95894428 -0.17096774 -0.18422500 0.01325725
-3.96871945 -0.17311828 -0.18544754 0.01232926
-3.97849462 -0.17526882 -0.18664641 0.01137759
-3.98826979 -0.17741935 -0.18782160 0.01040225
-3.99804497 -0.17956989 -0.18897315 0.00940326
-4.00782014 -0.18007820 -0.19010107 0.01002287
-4.01759531 -0.18017595 -0.19120537 0.01102942
-4.02737048 -0.18027370 -0.19228609 0.01201239
-4.03714565 -0.18037146 -0.19334325 0.01297180
-4.04692082 -0.18046921 -0.19437687 0.01390767
-4.05669599 -0.18056696 -0.19538698 0.01482002
-4.06647116 -0.18066471 -0.19637361 0.01570890
-4.07624633 -0.18076246 -0.19733679 0.01657433
-4.08602151 -0.18086022 -0.19827655 0.01741634
-4.09579668 -0.18095797 -0.19919292 0.01823496
-4.10557185 -0.18105572 -0.20008595 0.01903023
-4.11534702 -0.18115347 -0.20095565 0.01980218
-4.12512219 -0.18125122 -0.20180208 0.02055085
-4.13489736 -0.18134897 -0.20262526 0.02127629
-4.14467253 -0.18144673 -0.20342525 0.02197853
-4.15444770 -0.18154448 -0.20420208 0.02265761
-4.16422287 -0.18164223 -0.20495580 0.02331357
-4.17399804 -0.18173998 -0.20568645 0.02394647
-4.18377322 -0.18183773 -0.20639408 0.02455635
-4.19354839 -0.18193548 -0.20707873 0.02514325
-4.20332356 -0.18203324 -0.20774046 0.02570722
-4.21309873 -0.18213099 -0.20837931 0.02624832
-4.22287390 -0.18222874 -0.20899534 0.02676660
-4.23264907 -0.18232649 -0.20958860 0.02726211
-4.24242424 -0.18242424 -0.21015915 0.02773490
-4.25219941 -0.18252199 -0.21070703 0.02818504
-4.26197458 -0.18261975 -0.21123232 0.02861257
-4.27174976 -0.18271750 -0.21173506 0.02901757
-4.28152493 -0.18281525 -0.21221533 0.02940008
-4.29130010 -0.18291300 -0.21267317 0.02976017
-4.30107527 -0.18301075 -0.21310866 0.03009790
-4.31085044 -0.18310850 -0.21352185 0.03041335
-4.32062561 -0.18320626 -0.21391282 0.03070656
-4.33040078 -0.18330401 -0.21428163 0.03097762
-4.34017595 -0.18340176 -0.21462835 0.03122659
-4.34995112 -0.18349951 -0.21495305 0.03145354
-4.35972630 -0.18359726 -0.21525580 0.03165853
-4.36950147 -0.18369501 -0.21553667 0.03184165
-4.37927664 -0.18379277 -0.21579574 0.03200297
-4.38905181 -0.18389052 -0.21603308 0.03214256
-4.39882698 -0.18398827 -0.21624877 0.03226050
-4.40860215 -0.18408602 -0.21644288 0.03235686
-4.41837732 -0.18418377 -0.21661550 0.03243173
-4.42815249 -0.18428152 -0.21676671 0.03248518
-4.43792766 -0.18437928 -0.21689658 0.03251730
-4.44770283 -0.18447703 -0.21700520 0.03252817
-4.45747801 -0.18457478 -0.21709266 0.03251788
-4.46725318 -0.18467253 -0.21715903 0.03248650
-4.47702835 -0.18477028 -0.21720441 0.03243413
-4.48680352 -0.18486804 -0.21722888 0.03236085
-4.49657869 -0.18496579 -0.21723254 0.03226675
-4.50635386 -0.18506354 -0.21721546 0.03215193
-4.51612903 -0.18516129 -0.21717775 0.03201646
-4.52590420 -0.18525904 -0.21711950 0.03186046
-4.53567937 -0.18535679 -0.21704079 0.03168400
-4.54545455 -0.18545455 -0.21694173 0.03148718
-4.55522972 -0.18555230 -0.21682241 0.03127011
-4.56500489 -0.18565005 -0.21668292 0.03103288
-4.57478006 -0.18574780 -0.21652338 0.03077558
-4.58455523 -0.18584555 -0.21634386 0.03049831
-4.59433040 -0.18594330 -0.21614448 0.03020118
-4.60410557 -0.18604106 -0.21592534 0.02988429
-4.61388074 -0.18613881 -0.21568654 0.02954774
-4.62365591 -0.18623656 -0.21542819 0.02919163
-4.63343109 -0.18633431 -0.21515038 0.02881607
-4.64320626 -0.18643206 -0.21485322 0.02842116
-4.65298143 -0.18652981 -0.21453683 0.02800702
-4.66275660 -0.18662757 -0.21420131 0.02757374
-4.67253177 -0.18672532 -0.21384677 0.02712145
-4.68230694 -0.18682307 -0.21347331 0.02665024
-4.69208211 -0.18692082 -0.21308106 0.02616024
-4.70185728 -0.18701857 -0.21267012 0.02565154
-4.71163245 -0.18711632 -0.21224060 0.02512428
-4.72140762 -0.18721408 -0.21179263 0.02457855
-4.73118280 -0.18731183 -0.21132631 0.02401448
-4.74095797 -0.18740958 -0.21084176 0.02343218
-4.75073314 -0.18750733 -0.21033910 0.02283177
-4.76050831 -0.18760508 -0.20981845 0.02221337
-4.77028348 -0.18770283 -0.20927993 0.02157709
-4.78005865 -0.18780059 -0.20872365 0.02092306
-4.78983382 -0.18789834 -0.20814974 0.02025140
-4.79960899 -0.18799609 -0.20755831 0.01956222
-4.80938416 -0.18809384 -0.20694950 0.01885566
-4.81915934 -0.18819159 -0.20632342 0.01813183
-4.82893451 -0.18828935 -0.20568021 0.01739086
-4.83870968 -0.18838710 -0.20501998 0.01663288
-4.84848485 -0.18848485 -0.20434286 0.01585801
-4.85826002 -0.18858260 -0.20364897 0.01506637
-4.86803519 -0.18868035 -0.20293846 0.01425811
-4.87781036 -0.18877810 -0.20221144 0.01343334
-4.88758553 -0.18887586 -0.20146804 0.01259219
-4.89736070 -0.18897361 -0.20070840 0.01173480
-4.90713587 -0.18907136 -0.19993265 0.01086129
-4.91691105 -0.18916911 -0.19914091 0.00997180
-4.92668622 -0.18926686 -0.19833333 0.00906647
-4.93646139 -0.18936461 -0.19751003 0.00814542
-4.94623656 -0.18946237 -0.19667115 0.00720878
-4.95601173 -0.18956012 -0.19581682 0.00625670
-4.96578690 -0.18965787 -0.19494718 0.00528931
-4.97556207 -0.18975562 -0.19406237 0.00430675
-4.98533724 -0.18985337 -0.19316252 0.00330915
-4.99511241 -0.18995112 -0.19224777 0.00229665
-5.00488759 -0.18926686 -0.19131826 0.00205140
-5.01466276 -0.18780059 -0.19037413 0.00257355
-5.02443793 -0.18633431 -0.18941552 0.00308121
-5.03421310 -0.18486804 -0.18844257 0.00357453
-5.04398827 -0.18340176 -0.18745541 0.00405365
-5.05376344 -0.18193548 -0.18645420 0.00451871
-5.06353861 -0.18046921 -0.18543907 0.00496986
-5.07331378 -0.17900293 -0.18441017 0.00540723
-5.08308895 -0.17753666 -0.18336763 0.00583098
-5.09286413 -0.17607038 -0.18231162 0.00624123
-5.10263930 -0.17460411 -0.18124226 0.00663815
-5.11241447 -0.17313783 -0.18015970 0.00702187
-5.12218964 -0.17167155 -0.17906410 0.00739254
-5.13196481 -0.17020528 -0.17795559 0.00775031
-5.14173998 -0.16873900 -0.17683432 0.00809532
-5.15151515 -0.16727273 -0.17570045 0.00842772
-5.16129032 -0.16580645 -0.17455411 0.00874766
-5.17106549 -0.16434018 -0.17339546 0.00905528
-5.18084066 -0.16287390 -0.17222464 0.00935074
-5.19061584 -0.16140762 -0.17104181 0.00963419
-5.20039101 -0.15994135 -0.16984711 0.00990576
-5.21016618 -0.15847507 -0.16864070 0.01016562
-5.21994135 -0.15700880 -0.16742272 0.01041392
-5.22971652 -0.15554252 -0.16619332 0.01065080
-5.23949169 -0.15407625 -0.16495267 0.01087642
-5.24926686 -0.15260997 -0.16370090 0.01109093
-5.25904203 -0.15114370 -0.16243817 0.01129447
-5.26881720 -0.14967742 -0.16116463 0.01148721
-5.27859238 -0.14821114 -0.15988044 0.01166930
-5.28836755 -0.14674487 -0.15858575 0.01184088
-5.29814272 -0.14527859 -0.15728071 0.01200212
-5.30791789 -0.14381232 -0.15596547 0.01215316
-5.31769306 -0.14234604 -0.15464020 0.01229416
-5.32746823 -0.14087977 -0.15330504 0.01242527
-5.33724340 -0.13941349 -0.15196015 0.01254666
-5.34701857 -0.13794721 -0.15060568 0.01265846
-5.35679374 -0.13648094 -0.14924179 0.01276085
-5.36656891 -0.13501466 -0.14786863 0.01285397
-5.37634409 -0.13354839 -0.14648637 0.01293798
-5.38611926 -0.13208211 -0.14509515 0.01301304
-5.39589443 -0.13061584 -0.14369513 0.01307929
-5.40566960 -0.12914956 -0.14228647 0.01313691
-5.41544477 -0.12768328 -0.14086932 0.01318604
-5.42521994 -0.12621701 -0.13944384 0.01322684
-5.43499511 -0.12475073 -0.13801019 0.01325946
-5.44477028 -0.12328446 -0.13656853 0.01328407
-5.45454545 -0.12181818 -0.13511901 0.01330082
-5.46432063 -0.12035191 -0.13366178 0.01330987
-5.47409580 -0.11888563 -0.13219701 0.01331138
-5.48387097 -0.11741935 -0.13072485 0.01330550
-5.49364614 -0.11595308 -0.12924546 0.01329238
-5.50342131 -0.11448680 -0.12775900 0.01327220
-5.51319648 -0.11302053 -0.12626563 0.01324510
-5.52297165 -0.11155425 -0.12476550 0.01321124
-5.53274682 -0.11008798 -0.12325876 0.01317079
-5.54252199 -0.10862170 -0.12174559 0.01312389
-5.55229717 -0.10715543 -0.12022613 0.01307070
-5.56207234 -0.10568915 -0.11870054 0.01301139
-5.57184751 -0.10422287 -0.11716899 0.01294611
-5.58162268 -0.10275660 -0.11563162 0.01287502
-5.59139785 -0.10129032 -0.11408860 0.01279827
-5.60117302 -0.09982405 -0.11254008 0.01271603
-5.61094819 -0.09835777 -0.11098622 0.01262845
-5.62072336 -0.09689150 -0.10942718 0.01253568
-5.63049853 -0.09542522 -0.10786312 0.01243790
-5.64027370 -0.09395894 -0.10629418 0.01233524
-5.65004888 -0.09249267 -0.10472054 0.01222787
-5.65982405 -0.09102639 -0.10314235 0.01211595
-5.66959922 -0.08956012 -0.10155975 0.01199964
-5.67937439 -0.08809384 -0.09997292 0.01187908
-5.68914956 -0.08662757 -0.09838201 0.01175444
-5.69892473 -0.08516129 -0.09678716 0.01162587
-5.70869990 -0.08369501 -0.09518855 0.01149354
-5.71847507 -0.08222874 -0.09358632 0.01135758
-5.72825024 -0.08076246 -0.09198064 0.01121817
-5.73802542 -0.07929619 -0.09037165 0.01107546
-5.74780059 -0.07782991 -0.08875951 0.01092960
-5.75757576 -0.07636364 -0.08714438 0.01078074
-5.76735093 -0.07489736 -0.08552641 0.01062905
-5.77712610 -0.07343109 -0.08390576 0.01047468
-5.78690127 -0.07196481 -0.08228258 0.01031777
-5.79667644 -0.07049853 -0.08065703 0.01015849
-5.80645161 -0.06903226 -0.07902925 0.00999699
-5.81622678 -0.06756598 -0.07739941 0.00983343
-5.82600196 -0.06609971 -0.07576765 0.00966794
-5.83577713 -0.06463343 -0.07413413 0.00950070
-5.84555230 -0.06316716 -0.07249901 0.00933185
-5.85532747 -0.06170088 -0.07086242 0.00916154
-5.86510264 -0.06023460 -0.06922454 0.00898993
-5.87487781 -0.05876833 -0.06758550 0.00881717
-5.88465298 -0.05730205 -0.06594545 0.00864340
-5.89442815 -0.05583578 -0.06430456 0.00846878
-5.90420332 -0.05436950 -0.06266296 0.00829346
-5.91397849 -0.05290323 -0.06102082 0.00811759
-5.92375367 -0.05143695 -0.05937827 0.00794132
-5.93352884 -0.04997067 -0.05773547 0.00776480
-5.94330401 -0.04850440 -0.05609257 0.00758817
-5.95307918 -0.04703812 -0.05444971 0.00741159
-5.96285435 -0.04557185 -0.05280704 0.00723519
-5.97262952 -0.04410557 -0.05116471 0.00705914
-5.98240469 -0.04263930 -0.04952287 0.00688358
-5.99217986 -0.04117302 -0.04788166 0.00670864
-6.00195503 -0.03974585 -0.04624123 0.00649539
-6.01173021 -0.03847507 -0.04460173 0.00612665
-6.02150538 -0.03720430 -0.04296329 0.00575898
-6.03128055 -0.03593353 -0.04132606 0.00539253
-6.04105572 -0.03466276 -0.03969019 0.00502743
-6.05083089 -0.03339198 -0.03805582 0.00466383
-6.06060606 -0.03212121 -0.03642309 0.00430187
-6.07038123 -0.03085044 -0.03479214 0.00394170
-6.08015640 -0.02957967 -0.03316312 0.00358345
-6.08993157 -0.02830890 -0.03153616 0.00322727
-6.09970674 -0.02703812 -0.02991141 0.00287329
-6.10948192 -0.02576735 -0.02828901 0.00252166
-6.11925709 -0.02449658 -0.02666909 0.00217251
-6.12903226 -0.02322581 -0.02505179 0.00182599
-6.13880743 -0.02195503 -0.02343726 0.00148222
-6.14858260 -0.02068426 -0.02182562 0.00114136
-6.15835777 -0.01941349 -0.02021702 0.00080353
-6.16813294 -0.01814272 -0.01861158 0.00046886
-6.17790811 -0.01687195 -0.01700945 0.00013751
-6.18768328 -0.01560117 -0.01541076 0.00019041
-6.19745846 -0.01433040 -0.01381565 0.00051476
-6.20723363 -0.01305963 -0.01222423 0.00083539
-6.21700880 -0.01178886 -0.01063666 0.00115219
-6.22678397 -0.01051808 -0.00905306 0.00146503
-6.23655914 -0.00924731 -0.00747356 0.00177376
-6.24633431 -0.00797654 -0.00589828 0.00207826
-6.25610948 -0.00670577 -0.00432737 0.00237839
-6.26588465 -0.00543500 -0.00276095 0.00267405
-6.27565982 -0.00416422 -0.00119914 0.00296508
-6.28543500 -0.00289345 0.00035792 0.00325137
-6.29521017 -0.00162268 0.00191011 0.00353279
-6.30498534 -0.00035191 0.00345731 0.00380922
-6.31476051 0.00091887 0.00499939 0.00408052
-6.32453568 0.00218964 0.00653623 0.00434659
-6.33431085 0.00346041 0.00806769 0.00460728
-6.34408602 0.00473118 0.00959367 0.00486249
-6.35386119 0.00600196 0.01111404 0.00511208
-6.36363636 0.00727273 0.01262868 0.00535595
-6.37341153 0.00854350 0.01413746 0.00559396
-6.38318671 0.00981427 0.01564028 0.00582601
-6.39296188 0.01108504 0.01713700 0.00605196
-6.40273705 0.01235582 0.01862753 0.00627171
-6.41251222 0.01362659 0.02011173 0.00648514
-6.42228739 0.01489736 0.02158949 0.00669213
-6.43206256 0.01616813 0.02306071 0.00689257
-6.44183773 0.01743891 0.02452525 0.00708635
-6.45161290 0.01870968 0.02598302 0.00727335
-6.46138807 0.01998045 0.02743390 0.00745345
-6.47116325 0.02125122 0.02887778 0.00762656
-6.48093842 0.02252199 0.03031455 0.00779256
-6.49071359 0.02379277 0.03174410 0.00795133
-6.50048876 0.02506354 0.03316632 0.00810278
-6.51026393 0.02633431 0.03458110 0.00824679
-6.52003910 0.02760508 0.03598835 0.00838326
-6.52981427 0.02887586 0.03738794 0.00851209
-6.53958944 0.03014663 0.03877979 0.00863316
-6.54936461 0.03141740 0.04016378 0.00874638
-6.55913978 0.03268817 0.04153981 0.00885164
-6.56891496 0.03395894 0.04290779 0.00894884
-6.57869013 0.03522972 0.04426760 0.00903788
-6.58846530 0.03650049 0.04561916 0.00911867
-6.59824047 0.03777126 0.04696236 0.00919110
-6.60801564 0.03904203 0.04829710 0.00925507
-6.61779081 0.04031281 0.04962329 0.00931049
-6.62756598 0.04158358 0.05094084 0.00935726
-6.63734115 0.04285435 0.05224965 0.00939530
-6.64711632 0.04412512 0.05354962 0.00942449
-6.65689150 0.04539589 0.05484066 0.00944477
-6.66666667 0.04666667 0.05612268 0.00945602
-6.67644184 0.04793744 0.05739560 0.00945816
-6.68621701 0.04920821 0.05865932 0.00945111
-6.69599218 0.05047898 0.05991375 0.00943477
-6.70576735 0.05174976 0.06115881 0.00940905
-6.71554252 0.05302053 0.06239440 0.00937388
-6.72531769 0.05429130 0.06362046 0.00932916
-6.73509286 0.05556207 0.06483688 0.00927481
-6.74486804 0.05683284 0.06604359 0.00921074
-6.75464321 0.05810362 0.06724050 0.00913689
-6.76441838 0.05937439 0.06842755 0.00905316
-6.77419355 0.06064516 0.06960463 0.00895947
-6.78396872 0.06191593 0.07077169 0.00885575
-6.79374389 0.06318671 0.07192863 0.00874192
-6.80351906 0.06445748 0.07307538 0.00861790
-6.81329423 0.06572825 0.07421187 0.00848362
-6.82306940 0.06699902 0.07533803 0.00833900
-6.83284457 0.06826979 0.07645377 0.00818397
-6.84261975 0.06954057 0.07755903 0.00801846
-6.85239492 0.07081134 0.07865373 0.00784240
-6.86217009 0.07208211 0.07973782 0.00765571
-6.87194526 0.07335288 0.08081121 0.00745832
-6.88172043 0.07462366 0.08187384 0.00725018
-6.89149560 0.07589443 0.08292564 0.00703121
-6.90127077 0.07716520 0.08396655 0.00680135
-6.91104594 0.07843597 0.08499650 0.00656053
-6.92082111 0.07970674 0.08601544 0.00630869
-6.93059629 0.08097752 0.08702329 0.00604577
-6.94037146 0.08224829 0.08802000 0.00577171
-6.95014663 0.08351906 0.08900551 0.00548645
-6.95992180 0.08478983 0.08997976 0.00518992
-6.96969697 0.08606061 0.09094268 0.00488208
-6.97947214 0.08733138 0.09189424 0.00456286
-6.98924731 0.08860215 0.09283436 0.00423221
-6.99902248 0.08987292 0.09376300 0.00389008
-7.00879765 0.09026393 0.09468010 0.00441617
-7.01857283 0.09055718 0.09558561 0.00502843
-7.02834800 0.09085044 0.09647948 0.00562904
-7.03812317 0.09114370 0.09736167 0.00621797
-7.04789834 0.09143695 0.09823211 0.00679516
-7.05767351 0.09173021 0.09909078 0.00736057
-7.06744868 0.09202346 0.09993761 0.00791415
-7.07722385 0.09231672 0.10077256 0.00845585
-7.08699902 0.09260997 0.10159560 0.00898563
-7.09677419 0.09290323 0.10240667 0.00950345
-7.10654936 0.09319648 0.10320574 0.01000926
-7.11632454 0.09348974 0.10399277 0.01050304
-7.12609971 0.09378299 0.10476772 0.01098473
-7.13587488 0.09407625 0.10553054 0.01145430
-7.14565005 0.09436950 0.10628121 0.01191171
-7.15542522 0.09466276 0.10701969 0.01235693
-7.16520039 0.09495601 0.10774594 0.01278992
-7.17497556 0.09524927 0.10845992 0.01321066
-7.18475073 0.09554252 0.10916162 0.01361910
-7.19452590 0.09583578 0.10985099 0.01401522
-7.20430108 0.09612903 0.11052801 0.01439898
-7.21407625 0.09642229 0.11119265 0.01477036
-7.22385142 0.09671554 0.11184488 0.01512934
-7.23362659 0.09700880 0.11248467 0.01547587
-7.24340176 0.09730205 0.11311200 0.01580995
-7.25317693 0.09759531 0.11372685 0.01613154
-7.26295210 0.09788856 0.11432919 0.01644063
-7.27272727 0.09818182 0.11491900 0.01673719
-7.28250244 0.09847507 0.11549627 0.01702119
-7.29227761 0.09876833 0.11606096 0.01729263
-7.30205279 0.09906158 0.11661306 0.01755148
-7.31182796 0.09935484 0.11715257 0.01779773
-7.32160313 0.09964809 0.11767945 0.01803135
-7.33137830 0.09994135 0.11819370 0.01825235
-7.34115347 0.10023460 0.11869529 0.01846069
-7.35092864 0.10052786 0.11918423 0.01865637
-7.36070381 0.10082111 0.11966050 0.01883938
-7.37047898 0.10111437 0.12012408 0.01900971
-7.38025415 0.10140762 0.12057498 0.01916735
-7.39002933 0.10170088 0.12101317 0.01931229
-7.39980450 0.10199413 0.12143866 0.01944452
-7.40957967 0.10228739 0.12185144 0.01956405
-7.41935484 0.10258065 0.12225150 0.01967085
-7.42913001 0.10287390 0.12263884 0.01976494
-7.43890518 0.10316716 0.12301346 0.01984631
-7.44868035 0.10346041 0.12337536 0.01991495
-7.45845552 0.10375367 0.12372454 0.01997088
-7.46823069 0.10404692 0.12406100 0.02001408
-7.47800587 0.10434018 0.12438474 0.02004456
-7.48778104 0.10463343 0.12469576 0.02006233
-7.49755621 0.10492669 0.12499407 0.02006738
-7.50733138 0.10521994 0.12527968 0.02005974
-7.51710655 0.10551320 0.12555259 0.02003939
-7.52688172 0.10580645 0.12581281 0.02000636
-7.53665689 0.10609971 0.12606034 0.01996064
-7.54643206 0.10639296 0.12629521 0.01990225
-7.55620723 0.10668622 0.12651742 0.01983120
-7.56598240 0.10697947 0.12672698 0.01974751
-7.57575758 0.10727273 0.12692390 0.01965117
-7.58553275 0.10756598 0.12710821 0.01954222
-7.59530792 0.10785924 0.12727991 0.01942067
-7.60508309 0.10815249 0.12743902 0.01928653
-7.61485826 0.10844575 0.12758556 0.01913982
-7.62463343 0.10873900 0.12771955 0.01898055
-7.63440860 0.10903226 0.12784101 0.01880876
-7.64418377 0.10932551 0.12794996 0.01862445
-7.65395894 0.10961877 0.12804642 0.01842766
-7.66373412 0.10991202 0.12813042 0.01821839
-7.67350929 0.11020528 0.12820197 0.01799669
-7.68328446 0.11049853 0.12826111 0.01776257
-7.69305963 0.11079179 0.12830785 0.01751607
-7.70283480 0.11108504 0.12834224 0.01725719
-7.71260997 0.11137830 0.12836428 0.01698599
-7.72238514 0.11167155 0.12837403 0.01670247
-7.73216031 0.11196481 0.12837149 0.01640668
-7.74193548 0.11225806 0.12835671 0.01609865
-7.75171065 0.11255132 0.12832972 0.01577840
-7.76148583 0.11284457 0.12829055 0.01544598
-7.77126100 0.11313783 0.12823924 0.01510141
-7.78103617 0.11343109 0.12817582 0.01474473
-7.79081134 0.11372434 0.12810032 0.01437598
-7.80058651 0.11401760 0.12801279 0.01399519
-7.81036168 0.11431085 0.12791326 0.01360241
-7.82013685 0.11460411 0.12780177 0.01319766
-7.82991202 0.11489736 0.12767836 0.01278100
-7.83968719 0.11519062 0.12754308 0.01235246
-7.84946237 0.11548387 0.12739596 0.01191209
-7.85923754 0.11577713 0.12723705 0.01145992
-7.86901271 0.11607038 0.12706639 0.01099601
-7.87878788 0.11636364 0.12688403 0.01052039
-7.88856305 0.11665689 0.12669001 0.01003312
-7.89833822 0.11695015 0.12648438 0.00953423
-7.90811339 0.11724340 0.12626719 0.00902379
-7.91788856 0.11753666 0.12603848 0.00850182
-7.92766373 0.11782991 0.12579831 0.00796840
-7.93743891 0.11812317 0.12554673 0.00742356
-7.94721408 0.11841642 0.12528378 0.00686736
-7.95698925 0.11870968 0.12500952 0.00629984
-7.96676442 0.11900293 0.12472400 0.00572107
-7.97653959 0.11929619 0.12442729 0.00513110
-7.98631476 0.11958944 0.12411942 0.00452998
-7.99608993 0.11988270 0.12380046 0.00391776
-8.00586510 0.11953079 0.12347046 0.00393967
-8.01564027 0.11874878 0.12312949 0.00438071
-8.02541544 0.11796676 0.12277759 0.00481083
-8.03519062 0.11718475 0.12241483 0.00523008
-8.04496579 0.11640274 0.12204128 0.00563854
-8.05474096 0.11562072 0.12165698 0.00603625
-8.06451613 0.11483871 0.12126200 0.00642329
-8.07429130 0.11405670 0.12085641 0.00679971
-8.08406647 0.11327468 0.12044026 0.00716558
-8.09384164 0.11249267 0.12001362 0.00752095
-8.10361681 0.11171065 0.11957656 0.00786590
-8.11339198 0.11092864 0.11912914 0.00820050
-8.12316716 0.11014663 0.11867143 0.00852480
-8.13294233 0.10936461 0.11820349 0.00883887
-8.14271750 0.10858260 0.11772539 0.00914279
-8.15249267 0.10780059 0.11723720 0.00943662
-8.16226784 0.10701857 0.11673900 0.00972043
-8.17204301 0.10623656 0.11623084 0.00999429
-8.18181818 0.10545455 0.11571281 0.01025827
-8.19159335 0.10467253 0.11518497 0.01051244
-8.20136852 0.10389052 0.11464739 0.01075688
-8.21114370 0.10310850 0.11410016 0.01099165
-8.22091887 0.10232649 0.11354333 0.01121684
-8.23069404 0.10154448 0.11297699 0.01143251
-8.24046921 0.10076246 0.11240121 0.01163875
-8.25024438 0.09998045 0.11181607 0.01183562
-8.26001955 0.09919844 0.11122164 0.01202321
-8.26979472 0.09841642 0.11061800 0.01220158
-8.27956989 0.09763441 0.11000523 0.01237083
-8.28934506 0.09685239 0.10938341 0.01253102
-8.29912023 0.09607038 0.10875261 0.01268223
-8.30889541 0.09528837 0.10811292 0.01282455
-8.31867058 0.09450635 0.10746441 0.01295805
-8.32844575 0.09372434 0.10680716 0.01308282
-8.33822092 0.09294233 0.10614127 0.01319894
-8.34799609 0.09216031 0.10546680 0.01330649
-8.35777126 0.09137830 0.10478385 0.01340555
-8.36754643 0.09059629 0.10409249 0.01349620
-8.37732160 0.08981427 0.10339280 0.01357853
-8.38709677 0.08903226 0.10268489 0.01365263
-8.39687195 0.08825024 0.10196882 0.01371857
-8.40664712 0.08746823 0.10124468 0.01377645
-8.41642229 0.08668622 0.10051256 0.01382634
-8.42619746 0.08590420 0.09977255 0.01386834
-8.43597263 0.08512219 0.09902473 0.01390254
-8.44574780 0.08434018 0.09826919 0.01392901
-8.45552297 0.08355816 0.09750601 0.01394785
-8.46529814 0.08277615 0.09673530 0.01395915
-8.47507331 0.08199413 0.09595712 0.01396299
-8.48484848 0.08121212 0.09517159 0.01395947
-8.49462366 0.08043011 0.09437878 0.01394867
-8.50439883 0.07964809 0.09357878 0.01393068
-8.51417400 0.07886608 0.09277169 0.01390561
-8.52394917 0.07808407 0.09195759 0.01387352
-8.53372434 0.07730205 0.09113658 0.01383453
-8.54349951 0.07652004 0.09030876 0.01378872
-8.55327468 0.07573803 0.08947420 0.01373618
-8.56304985 0.07495601 0.08863301 0.01367700
-8.57282502 0.07417400 0.08778528 0.01361129
-8.58260020 0.07339198 0.08693111 0.01353912
-8.59237537 0.07260997 0.08607058 0.01346060
-8.60215054 0.07182796 0.08520379 0.01337583
-8.61192571 0.07104594 0.08433083 0.01328489
-8.62170088 0.07026393 0.08345181 0.01318788
-8.63147605 0.06948192 0.08256681 0.01308489
-8.64125122 0.06869990 0.08167593 0.01297603
-8.65102639 0.06791789 0.08077927 0.01286138
-8.66080156 0.06713587 0.07987693 0.01274105
-8.67057674 0.06635386 0.07896899 0.01261513
-8.68035191 0.06557185 0.07805557 0.01248372
-8.69012708 0.06478983 0.07713675 0.01234691
-8.69990225 0.06400782 0.07621263 0.01220481
-8.70967742 0.06322581 0.07528331 0.01205750
-8.71945259 0.06244379 0.07434889 0.01190509
-8.72922776 0.06166178 0.07340946 0.01174768
-8.73900293 0.06087977 0.07246513 0.01158537
-8.74877810 0.06009775 0.07151600 0.01141825
-8.75855327 0.05931574 0.07056216 0.01124642
-8.76832845 0.05853372 0.06960370 0.01106998
-8.77810362 0.05775171 0.06864074 0.01088903
-8.78787879 0.05696970 0.06767337 0.01070368
-8.79765396 0.05618768 0.06670170 0.01051401
-8.80742913 0.05540567 0.06572581 0.01032014
-8.81720430 0.05462366 0.06474581 0.01012215
-8.82697947 0.05384164 0.06376180 0.00992016
-8.83675464 0.05305963 0.06277389 0.00971426
-8.84652981 0.05227761 0.06178216 0.00950455
-8.85630499 0.05149560 0.06078673 0.00929113
-8.86608016 0.05071359 0.05978769 0.00907410
-8.87585533 0.04993157 0.05878515 0.00885357
-8.88563050 0.04914956 0.05777919 0.00862963
-8.89540567 0.04836755 0.05676994 0.00840239
-8.90518084 0.04758553 0.05575748 0.00817195
-8.91495601 0.04680352 0.05474192 0.00793841
-8.92473118 0.04602151 0.05372336 0.00770186
-8.93450635 0.04523949 0.05270191 0.00746241
-8.94428152 0.04445748 0.05167765 0.00722017
-8.95405670 0.04367546 0.05065070 0.00697523
-8.96383187 0.04289345 0.04962115 0.00672770
-8.97360704 0.04211144 0.04858911 0.00647767
-8.98338221 0.04132942 0.04755468 0.00622526
-8.99315738 0.04054741 0.04651796 0.00597055
-9.00293255 0.04000000 0.04547905 0.00547905
-9.01270772 0.04000000 0.04443805 0.00443805
-9.02248289 0.04000000 0.04339506 0.00339506
-9.03225806 0.04000000 0.04235019 0.00235019
-9.04203324 0.04000000 0.04130354 0.00130354
-9.05180841 0.04000000 0.04025521 0.00025521
-9.06158358 0.04000000 0.03920529 0.00079471
-9.07135875 0.04000000 0.03815390 0.00184610
-9.08113392 0.04000000 0.03710113 0.00289887
-9.09090909 0.04000000 0.03604708 0.00395292
-9.10068426 0.04000000 0.03499185 0.00500815
-9.11045943 0.04000000 0.03393555 0.00606445
-9.12023460 0.04000000 0.03287827 0.00712173
-9.13000978 0.04000000 0.03182012 0.00817988
-9.13978495 0.04000000 0.03076120 0.00923880
-9.14956012 0.04000000 0.02970160 0.01029840
-9.15933529 0.04000000 0.02864143 0.01135857
-9.16911046 0.04000000 0.02758079 0.01241921
-9.17888563 0.04000000 0.02651977 0.01348023
-9.18866080 0.04000000 0.02545848 0.01454152
-9.19843597 0.04000000 0.02439701 0.01560299
-9.20821114 0.04000000 0.02333547 0.01666453
-9.21798631 0.04000000 0.02227395 0.01772605
-9.22776149 0.04000000 0.02121255 0.01878745
-9.23753666 0.04000000 0.02015138 0.01984862
-9.24731183 0.04000000 0.01909053 0.02090947
-9.25708700 0.04000000 0.01803009 0.02196991
-9.26686217 0.04000000 0.01697018 0.02302982
-9.27663734 0.04000000 0.01591087 0.02408913
-9.28641251 0.04000000 0.01485228 0.02514772
-9.29618768 0.04000000 0.01379449 0.02620551
-9.30596285 0.04000000 0.01273761 0.02726239
-9.31573803 0.04000000 0.01168174 0.02831826
-9.32551320 0.04000000 0.01062696 0.02937304
-9.33528837 0.04000000 0.00957337 0.03042663
-9.34506354 0.04000000 0.00852108 0.03147892
-9.35483871 0.04000000 0.00747017 0.03252983
-9.36461388 0.04000000 0.00642074 0.03357926
-9.37438905 0.04000000 0.00537289 0.03462711
-9.38416422 0.04000000 0.00432671 0.03567329
-9.39393939 0.04000000 0.00328229 0.03671771
-9.40371457 0.04000000 0.00223974 0.03776026
-9.41348974 0.04000000 0.00119913 0.03880087
-9.42326491 0.04000000 0.00016057 0.03983943
-9.43304008 0.04000000 -0.00087586 0.04087586
-9.44281525 0.04000000 -0.00191006 0.04191006
-9.45259042 0.04000000 -0.00294193 0.04294193
-9.46236559 0.04000000 -0.00397139 0.04397139
-9.47214076 0.04000000 -0.00499835 0.04499835
-9.48191593 0.04000000 -0.00602272 0.04602272
-9.49169110 0.04000000 -0.00704440 0.04704440
-9.50146628 0.04000000 -0.00806330 0.04806330
-9.51124145 0.04000000 -0.00907934 0.04907934
-9.52101662 0.04000000 -0.01009243 0.05009243
-9.53079179 0.04000000 -0.01110247 0.05110247
-9.54056696 0.04000000 -0.01210939 0.05210939
-9.55034213 0.04000000 -0.01311309 0.05311309
-9.56011730 0.04000000 -0.01411348 0.05411348
-9.56989247 0.04000000 -0.01511049 0.05511049
-9.57966764 0.04000000 -0.01610401 0.05610401
-9.58944282 0.04000000 -0.01709398 0.05709398
-9.59921799 0.04000000 -0.01808029 0.05808029
-9.60899316 0.04000000 -0.01906288 0.05906288
-9.61876833 0.04000000 -0.02004164 0.06004164
-9.62854350 0.04000000 -0.02101651 0.06101651
-9.63831867 0.04000000 -0.02198739 0.06198739
-9.64809384 0.04000000 -0.02295421 0.06295421
-9.65786901 0.04000000 -0.02391688 0.06391688
-9.66764418 0.04000000 -0.02487532 0.06487532
-9.67741935 0.04000000 -0.02582945 0.06582945
-9.68719453 0.04000000 -0.02677918 0.06677918
-9.69696970 0.04000000 -0.02772445 0.06772445
-9.70674487 0.04000000 -0.02866516 0.06866516
-9.71652004 0.04000000 -0.02960125 0.06960125
-9.72629521 0.04000000 -0.03053263 0.07053263
-9.73607038 0.04000000 -0.03145922 0.07145922
-9.74584555 0.04000000 -0.03238095 0.07238095
-9.75562072 0.04000000 -0.03329775 0.07329775
-9.76539589 0.04000000 -0.03420953 0.07420953
-9.77517107 0.04000000 -0.03511622 0.07511622
-9.78494624 0.04000000 -0.03601775 0.07601775
-9.79472141 0.04000000 -0.03691404 0.07691404
-9.80449658 0.04000000 -0.03780502 0.07780502
-9.81427175 0.04000000 -0.03869061 0.07869061
-9.82404692 0.04000000 -0.03957075 0.07957075
-9.83382209 0.04000000 -0.04044536 0.08044536
-9.84359726 0.04000000 -0.04131438 0.08131438
-9.85337243 0.04000000 -0.04217772 0.08217772
-9.86314761 0.04000000 -0.04303533 0.08303533
-9.87292278 0.04000000 -0.04388713 0.08388713
-9.88269795 0.04000000 -0.04473306 0.08473306
-9.89247312 0.04000000 -0.04557305 0.08557305
-9.90224829 0.04000000 -0.04640703 0.08640703
-9.91202346 0.04000000 -0.04723493 0.08723493
-9.92179863 0.04000000 -0.04805669 0.08805669
-9.93157380 0.04000000 -0.04887225 0.08887225
-9.94134897 0.04000000 -0.04968154 0.08968154
-9.95112414 0.04000000 -0.05048449 0.09048449
-9.96089932 0.04000000 -0.05128105 0.09128105
-9.97067449 0.04000000 -0.05207115 0.09207115
-9.98044966 0.04000000 -0.05285474 0.09285474
-9.99022483 0.04000000 -0.05363174 0.09363174
-10.00000000 0.04000000 -0.05440211 0.09440211
+inputX outputFx trueFx diffFx
+0.000000000 nan nan nan
+0.009775171 0.840000000 0.999984074 0.159984074
+0.019550342 0.840000000 0.999936299 0.159936299
+0.029325513 0.840000000 0.999856675 0.159856675
+0.039100684 0.840000000 0.999745209 0.159745209
+0.048875855 0.840000000 0.999601906 0.159601906
+0.058651026 0.840000000 0.999426775 0.159426775
+0.068426197 0.840000000 0.999219825 0.159219825
+0.078201369 0.840000000 0.998981069 0.158981069
+0.087976540 0.840000000 0.998710521 0.158710521
+0.097751711 0.840000000 0.998408195 0.158408195
+0.107526882 0.840000000 0.998074109 0.158074109
+0.117302053 0.840000000 0.997708282 0.157708282
+0.127077224 0.840000000 0.997310736 0.157310736
+0.136852395 0.840000000 0.996881492 0.156881492
+0.146627566 0.840000000 0.996420576 0.156420576
+0.156402737 0.840000000 0.995928014 0.155928014
+0.166177908 0.840000000 0.995403835 0.155403835
+0.175953079 0.840000000 0.994848067 0.154848067
+0.185728250 0.840000000 0.994260744 0.154260744
+0.195503421 0.840000000 0.993641898 0.153641898
+0.205278592 0.840000000 0.992991566 0.152991566
+0.215053763 0.840000000 0.992309784 0.152309784
+0.224828935 0.840000000 0.991596592 0.151596592
+0.234604106 0.840000000 0.990852030 0.150852030
+0.244379277 0.840000000 0.990076141 0.150076141
+0.254154448 0.840000000 0.989268970 0.149268970
+0.263929619 0.840000000 0.988430562 0.148430562
+0.273704790 0.840000000 0.987560966 0.147560966
+0.283479961 0.840000000 0.986660231 0.146660231
+0.293255132 0.840000000 0.985728410 0.145728410
+0.303030303 0.840000000 0.984765555 0.144765555
+0.312805474 0.840000000 0.983771721 0.143771721
+0.322580645 0.840000000 0.982746966 0.142746966
+0.332355816 0.840000000 0.981691347 0.141691347
+0.342130987 0.840000000 0.980604926 0.140604926
+0.351906158 0.840000000 0.979487765 0.139487765
+0.361681329 0.840000000 0.978339927 0.138339927
+0.371456500 0.840000000 0.977161478 0.137161478
+0.381231672 0.840000000 0.975952486 0.135952486
+0.391006843 0.840000000 0.974713019 0.134713019
+0.400782014 0.840000000 0.973443149 0.133443149
+0.410557185 0.840000000 0.972142948 0.132142948
+0.420332356 0.840000000 0.970812490 0.130812490
+0.430107527 0.840000000 0.969451851 0.129451851
+0.439882698 0.840000000 0.968061110 0.128061110
+0.449657869 0.840000000 0.966640345 0.126640345
+0.459433040 0.840000000 0.965189638 0.125189638
+0.469208211 0.840000000 0.963709072 0.123709072
+0.478983382 0.840000000 0.962198730 0.122198730
+0.488758553 0.840000000 0.960658700 0.120658700
+0.498533724 0.840000000 0.959089069 0.119089069
+0.508308895 0.840000000 0.957489927 0.117489927
+0.518084066 0.840000000 0.955861365 0.115861365
+0.527859238 0.840000000 0.954203476 0.114203476
+0.537634409 0.840000000 0.952516354 0.112516354
+0.547409580 0.840000000 0.950800096 0.110800096
+0.557184751 0.840000000 0.949054799 0.109054799
+0.566959922 0.840000000 0.947280564 0.107280564
+0.576735093 0.840000000 0.945477490 0.105477490
+0.586510264 0.840000000 0.943645681 0.103645681
+0.596285435 0.840000000 0.941785241 0.101785241
+0.606060606 0.840000000 0.939896276 0.099896276
+0.615835777 0.840000000 0.937978894 0.097978894
+0.625610948 0.840000000 0.936033204 0.096033204
+0.635386119 0.840000000 0.934059316 0.094059316
+0.645161290 0.840000000 0.932057343 0.092057343
+0.654936461 0.840000000 0.930027398 0.090027398
+0.664711632 0.840000000 0.927969597 0.087969597
+0.674486804 0.840000000 0.925884058 0.085884058
+0.684261975 0.840000000 0.923770897 0.083770897
+0.694037146 0.840000000 0.921630237 0.081630237
+0.703812317 0.840000000 0.919462198 0.079462198
+0.713587488 0.840000000 0.917266903 0.077266903
+0.723362659 0.840000000 0.915044476 0.075044476
+0.733137830 0.840000000 0.912795045 0.072795045
+0.742913001 0.840000000 0.910518737 0.070518737
+0.752688172 0.840000000 0.908215680 0.068215680
+0.762463343 0.840000000 0.905886006 0.065886006
+0.772238514 0.840000000 0.903529847 0.063529847
+0.782013685 0.840000000 0.901147335 0.061147335
+0.791788856 0.840000000 0.898738606 0.058738606
+0.801564027 0.840000000 0.896303797 0.056303797
+0.811339198 0.840000000 0.893843045 0.053843045
+0.821114370 0.840000000 0.891356490 0.051356490
+0.830889541 0.840000000 0.888844272 0.048844272
+0.840664712 0.840000000 0.886306533 0.046306533
+0.850439883 0.840000000 0.883743417 0.043743417
+0.860215054 0.840000000 0.881155068 0.041155068
+0.869990225 0.840000000 0.878541634 0.038541634
+0.879765396 0.840000000 0.875903261 0.035903261
+0.889540567 0.840000000 0.873240099 0.033240099
+0.899315738 0.840000000 0.870552298 0.030552298
+0.909090909 0.840000000 0.867840009 0.027840009
+0.918866080 0.840000000 0.865103386 0.025103386
+0.928641251 0.840000000 0.862342583 0.022342583
+0.938416422 0.840000000 0.859557755 0.019557755
+0.948191593 0.840000000 0.856749059 0.016749059
+0.957966764 0.840000000 0.853916654 0.013916654
+0.967741935 0.840000000 0.851060700 0.011060700
+0.977517107 0.840000000 0.848181355 0.008181355
+0.987292278 0.840000000 0.845278784 0.005278784
+0.997067449 0.840000000 0.842353148 0.002353148
+1.006842620 0.837331378 0.839404613 0.002073235
+1.016617791 0.833519062 0.836433344 0.002914283
+1.026392962 0.829706745 0.833439508 0.003732763
+1.036168133 0.825894428 0.830423273 0.004528844
+1.045943304 0.822082111 0.827384807 0.005302696
+1.055718475 0.818269795 0.824324283 0.006054488
+1.065493646 0.814457478 0.821241871 0.006784393
+1.075268817 0.810645161 0.818137743 0.007492582
+1.085043988 0.806832845 0.815012075 0.008179230
+1.094819159 0.803020528 0.811865040 0.008844512
+1.104594330 0.799208211 0.808696816 0.009488604
+1.114369501 0.795395894 0.805507578 0.010111684
+1.124144673 0.791583578 0.802297506 0.010713928
+1.133919844 0.787771261 0.799066779 0.011295518
+1.143695015 0.783958944 0.795815577 0.011856632
+1.153470186 0.780146628 0.792544081 0.012397454
+1.163245357 0.776334311 0.789252476 0.012918165
+1.173020528 0.772521994 0.785940943 0.013418949
+1.182795699 0.768709677 0.782609668 0.013899990
+1.192570870 0.764897361 0.779258836 0.014361475
+1.202346041 0.761085044 0.775888633 0.014803589
+1.212121212 0.757272727 0.772499248 0.015226521
+1.221896383 0.753460411 0.769090869 0.015630459
+1.231671554 0.749648094 0.765663685 0.016015592
+1.241446725 0.745835777 0.762217888 0.016382110
+1.251221896 0.742023460 0.758753667 0.016730207
+1.260997067 0.738211144 0.755271216 0.017060072
+1.270772239 0.734398827 0.751770728 0.017371901
+1.280547410 0.730586510 0.748252396 0.017665886
+1.290322581 0.726774194 0.744716416 0.017942223
+1.300097752 0.722961877 0.741162984 0.018201107
+1.309872923 0.719149560 0.737592296 0.018442736
+1.319648094 0.715337243 0.734004550 0.018667307
+1.329423265 0.711524927 0.730399945 0.018875018
+1.339198436 0.707712610 0.726778678 0.019066068
+1.348973607 0.703900293 0.723140951 0.019240658
+1.358748778 0.700087977 0.719486964 0.019398987
+1.368523949 0.696275660 0.715816918 0.019541259
+1.378299120 0.692463343 0.712131017 0.019667674
+1.388074291 0.688651026 0.708429462 0.019778436
+1.397849462 0.684838710 0.704712458 0.019873748
+1.407624633 0.681026393 0.700980209 0.019953816
+1.417399804 0.677214076 0.697232921 0.020018845
+1.427174976 0.673401760 0.693470798 0.020069039
+1.436950147 0.669589443 0.689694049 0.020104606
+1.446725318 0.665777126 0.685902879 0.020125753
+1.456500489 0.661964809 0.682097497 0.020132688
+1.466275660 0.658152493 0.678278112 0.020125619
+1.476050831 0.654340176 0.674444932 0.020104756
+1.485826002 0.650527859 0.670598167 0.020070308
+1.495601173 0.646715543 0.666738028 0.020022485
+1.505376344 0.642903226 0.662864725 0.019961499
+1.515151515 0.639090909 0.658978470 0.019887561
+1.524926686 0.635278592 0.655079475 0.019800882
+1.534701857 0.631466276 0.651167952 0.019701676
+1.544477028 0.627653959 0.647244115 0.019590156
+1.554252199 0.623841642 0.643308177 0.019466535
+1.564027370 0.620029326 0.639360352 0.019331027
+1.573802542 0.616217009 0.635400856 0.019183847
+1.583577713 0.612404692 0.631429902 0.019025209
+1.593352884 0.608592375 0.627447706 0.018855331
+1.603128055 0.604780059 0.623454485 0.018674426
+1.612903226 0.600967742 0.619450454 0.018482712
+1.622678397 0.597155425 0.615435831 0.018280406
+1.632453568 0.593343109 0.611410832 0.018067724
+1.642228739 0.589530792 0.607375676 0.017844884
+1.652003910 0.585718475 0.603330579 0.017612104
+1.661779081 0.581906158 0.599275761 0.017369603
+1.671554252 0.578093842 0.595211440 0.017117598
+1.681329423 0.574281525 0.591137834 0.016856310
+1.691104594 0.570469208 0.587055164 0.016585956
+1.700879765 0.566656891 0.582963649 0.016306757
+1.710654936 0.562844575 0.578863507 0.016018933
+1.720430108 0.559032258 0.574754961 0.015722703
+1.730205279 0.555219941 0.570638229 0.015418287
+1.739980450 0.551407625 0.566513532 0.015105908
+1.749755621 0.547595308 0.562381092 0.014785784
+1.759530792 0.543782991 0.558241129 0.014458138
+1.769305963 0.539970674 0.554093865 0.014123190
+1.779081134 0.536158358 0.549939520 0.013781162
+1.788856305 0.532346041 0.545778317 0.013432276
+1.798631476 0.528533724 0.541610476 0.013076752
+1.808406647 0.524721408 0.537436221 0.012714813
+1.818181818 0.520909091 0.533255772 0.012346681
+1.827956989 0.517096774 0.529069352 0.011972578
+1.837732160 0.513284457 0.524877183 0.011592726
+1.847507331 0.509472141 0.520679488 0.011207347
+1.857282502 0.505659824 0.516476488 0.010816664
+1.867057674 0.501847507 0.512268406 0.010420898
+1.876832845 0.498035191 0.508055464 0.010020273
+1.886608016 0.494222874 0.503837884 0.009615010
+1.896383187 0.490410557 0.499615890 0.009205333
+1.906158358 0.486598240 0.495389703 0.008791463
+1.915933529 0.482785924 0.491159546 0.008373622
+1.925708700 0.478973607 0.486925641 0.007952034
+1.935483871 0.475161290 0.482688211 0.007526920
+1.945259042 0.471348974 0.478447477 0.007098503
+1.955034213 0.467536657 0.474203662 0.006667005
+1.964809384 0.463724340 0.469956987 0.006232647
+1.974584555 0.459912023 0.465707675 0.005795652
+1.984359726 0.456099707 0.461455948 0.005356241
+1.994134897 0.452287390 0.457202027 0.004914637
+2.003910068 0.448396872 0.452946134 0.004549262
+2.013685239 0.444389052 0.448688489 0.004299437
+2.023460411 0.440381232 0.444429315 0.004048083
+2.033235582 0.436373412 0.440168832 0.003795420
+2.043010753 0.432365591 0.435907260 0.003541669
+2.052785924 0.428357771 0.431644821 0.003287050
+2.062561095 0.424349951 0.427381735 0.003031784
+2.072336266 0.420342131 0.423118222 0.002776091
+2.082111437 0.416334311 0.418854501 0.002520190
+2.091886608 0.412326491 0.414590792 0.002264301
+2.101661779 0.408318671 0.410327314 0.002008643
+2.111436950 0.404310850 0.406064286 0.001753436
+2.121212121 0.400303030 0.401801927 0.001498897
+2.130987292 0.396295210 0.397540455 0.001245245
+2.140762463 0.392287390 0.393280087 0.000992697
+2.150537634 0.388279570 0.389021042 0.000741472
+2.160312805 0.384271750 0.384763536 0.000491786
+2.170087977 0.380263930 0.380507786 0.000243857
+2.179863148 0.376256109 0.376254009 0.000002100
+2.189638319 0.372248289 0.372002420 0.000245869
+2.199413490 0.368240469 0.367753235 0.000487234
+2.209188661 0.364232649 0.363506669 0.000725980
+2.218963832 0.360224829 0.359262937 0.000961892
+2.228739003 0.356217009 0.355022251 0.001194757
+2.238514174 0.352209189 0.350784828 0.001424361
+2.248289345 0.348201369 0.346550878 0.001650491
+2.258064516 0.344193548 0.342320615 0.001872933
+2.267839687 0.340185728 0.338094251 0.002091477
+2.277614858 0.336177908 0.333871998 0.002305910
+2.287390029 0.332170088 0.329654066 0.002516022
+2.297165200 0.328162268 0.325440666 0.002721602
+2.306940371 0.324154448 0.321232007 0.002922440
+2.316715543 0.320146628 0.317028300 0.003118328
+2.326490714 0.316138807 0.312829752 0.003309056
+2.336265885 0.312130987 0.308636571 0.003494416
+2.346041056 0.308123167 0.304448965 0.003674202
+2.355816227 0.304115347 0.300267141 0.003848206
+2.365591398 0.300107527 0.296091304 0.004016222
+2.375366569 0.296099707 0.291921661 0.004178046
+2.385141740 0.292091887 0.287758415 0.004333472
+2.394916911 0.288084066 0.283601770 0.004482296
+2.404692082 0.284076246 0.279451931 0.004624315
+2.414467253 0.280068426 0.275309099 0.004759327
+2.424242424 0.276060606 0.271173477 0.004887129
+2.434017595 0.272052786 0.267045265 0.005007521
+2.443792766 0.268044966 0.262924663 0.005120302
+2.453567937 0.264037146 0.258811872 0.005225273
+2.463343109 0.260029326 0.254707090 0.005322235
+2.473118280 0.256021505 0.250610515 0.005410990
+2.482893451 0.252013685 0.246522344 0.005491341
+2.492668622 0.248005865 0.242442774 0.005563091
+2.502443793 0.243998045 0.238371999 0.005626046
+2.512218964 0.239990225 0.234310215 0.005680009
+2.521994135 0.235982405 0.230257616 0.005724789
+2.531769306 0.231974585 0.226214394 0.005760191
+2.541544477 0.227966764 0.222180741 0.005786024
+2.551319648 0.223958944 0.218156848 0.005802096
+2.561094819 0.219951124 0.214142907 0.005808217
+2.570869990 0.215943304 0.210139105 0.005804199
+2.580645161 0.211935484 0.206145632 0.005789852
+2.590420332 0.207927664 0.202162674 0.005764989
+2.600195503 0.203919844 0.198190419 0.005729424
+2.609970674 0.199912023 0.194229052 0.005682971
+2.619745846 0.195904203 0.190278758 0.005625446
+2.629521017 0.191896383 0.186339719 0.005556664
+2.639296188 0.187888563 0.182412119 0.005476444
+2.649071359 0.183880743 0.178496140 0.005384603
+2.658846530 0.179872923 0.174591961 0.005280962
+2.668621701 0.175865103 0.170699762 0.005165340
+2.678396872 0.171857283 0.166819723 0.005037560
+2.688172043 0.167849462 0.162952019 0.004897443
+2.697947214 0.163841642 0.159096828 0.004744814
+2.707722385 0.159833822 0.155254326 0.004579496
+2.717497556 0.155826002 0.151424685 0.004401317
+2.727272727 0.151818182 0.147608080 0.004210102
+2.737047898 0.147810362 0.143804682 0.004005680
+2.746823069 0.143802542 0.140014663 0.003787879
+2.756598240 0.139794721 0.136238191 0.003556530
+2.766373412 0.135786901 0.132475437 0.003311464
+2.776148583 0.131779081 0.128726567 0.003052514
+2.785923754 0.127771261 0.124991748 0.002779513
+2.795698925 0.123763441 0.121271145 0.002492296
+2.805474096 0.119755621 0.117564921 0.002190699
+2.815249267 0.115747801 0.113873241 0.001874559
+2.825024438 0.111739980 0.110196266 0.001543715
+2.834799609 0.107732160 0.106534155 0.001198005
+2.844574780 0.103724340 0.102887069 0.000837271
+2.854349951 0.099716520 0.099255166 0.000461354
+2.864125122 0.095708700 0.095638602 0.000070098
+2.873900293 0.091700880 0.092037533 0.000336653
+2.883675464 0.087693060 0.088452113 0.000759053
+2.893450635 0.083685239 0.084882496 0.001197256
+2.903225806 0.079677419 0.081328833 0.001651414
+2.913000978 0.075669599 0.077791275 0.002121676
+2.922776149 0.071661779 0.074269971 0.002608192
+2.932551320 0.067653959 0.070765070 0.003111111
+2.942326491 0.063646139 0.067276718 0.003630579
+2.952101662 0.059638319 0.063805060 0.004166741
+2.961876833 0.055630499 0.060350240 0.004719742
+2.971652004 0.051622678 0.056912402 0.005289724
+2.981427175 0.047614858 0.053491687 0.005876829
+2.991202346 0.043607038 0.050088235 0.006481197
+3.000977517 0.039784946 0.046702185 0.006917238
+3.010752688 0.037634409 0.043333674 0.005699265
+3.020527859 0.035483871 0.039982838 0.004498967
+3.030303030 0.033333333 0.036649813 0.003316479
+3.040078201 0.031182796 0.033334731 0.002151935
+3.049853372 0.029032258 0.030037724 0.001005466
+3.059628543 0.026881720 0.026758924 0.000122797
+3.069403715 0.024731183 0.023498459 0.001232724
+3.079178886 0.022580645 0.020256457 0.002324188
+3.088954057 0.020430108 0.017033044 0.003397063
+3.098729228 0.018279570 0.013828347 0.004451223
+3.108504399 0.016129032 0.010642487 0.005486545
+3.118279570 0.013978495 0.007475588 0.006502907
+3.128054741 0.011827957 0.004327769 0.007500188
+3.137829912 0.009677419 0.001199151 0.008478268
+3.147605083 0.007526882 -0.001910149 0.009437030
+3.157380254 0.005376344 -0.005000014 0.010376358
+3.167155425 0.003225806 -0.008070329 0.011296136
+3.176930596 0.001075269 -0.011120982 0.012196251
+3.186705767 -0.001075269 -0.014151860 0.013076591
+3.196480938 -0.003225806 -0.017162852 0.013937045
+3.206256109 -0.005376344 -0.020153849 0.014777505
+3.216031281 -0.007526882 -0.023124744 0.015597862
+3.225806452 -0.009677419 -0.026075431 0.016398012
+3.235581623 -0.011827957 -0.029005805 0.017177848
+3.245356794 -0.013978495 -0.031915762 0.017937268
+3.255131965 -0.016129032 -0.034805202 0.018676170
+3.264907136 -0.018279570 -0.037674024 0.019394454
+3.274682307 -0.020430108 -0.040522130 0.020092022
+3.284457478 -0.022580645 -0.043349422 0.020768777
+3.294232649 -0.024731183 -0.046155805 0.021424622
+3.304007820 -0.026881720 -0.048941185 0.022059465
+3.313782991 -0.029032258 -0.051705469 0.022673211
+3.323558162 -0.031182796 -0.054448567 0.023265771
+3.333333333 -0.033333333 -0.057170389 0.023837056
+3.343108504 -0.035483871 -0.059870847 0.024386976
+3.352883675 -0.037634409 -0.062549854 0.024915446
+3.362658847 -0.039784946 -0.065207327 0.025422380
+3.372434018 -0.041935484 -0.067843181 0.025907697
+3.382209189 -0.044086022 -0.070457335 0.026371313
+3.391984360 -0.046236559 -0.073049709 0.026813150
+3.401759531 -0.048387097 -0.075620224 0.027233127
+3.411534702 -0.050537634 -0.078168803 0.027631169
+3.421309873 -0.052688172 -0.080695371 0.028007199
+3.431085044 -0.054838710 -0.083199854 0.028361144
+3.440860215 -0.056989247 -0.085682179 0.028692932
+3.450635386 -0.059139785 -0.088142277 0.029002492
+3.460410557 -0.061290323 -0.090580077 0.029289754
+3.470185728 -0.063440860 -0.092995512 0.029554651
+3.479960899 -0.065591398 -0.095388516 0.029797118
+3.489736070 -0.067741935 -0.097759024 0.030017089
+3.499511241 -0.069892473 -0.100106975 0.030214502
+3.509286413 -0.072043011 -0.102432306 0.030389296
+3.519061584 -0.074193548 -0.104734958 0.030541410
+3.528836755 -0.076344086 -0.107014873 0.030670787
+3.538611926 -0.078494624 -0.109271995 0.030777371
+3.548387097 -0.080645161 -0.111506268 0.030861107
+3.558162268 -0.082795699 -0.113717639 0.030921940
+3.567937439 -0.084946237 -0.115906057 0.030959820
+3.577712610 -0.087096774 -0.118071471 0.030974697
+3.587487781 -0.089247312 -0.120213834 0.030966522
+3.597262952 -0.091397849 -0.122333097 0.030935248
+3.607038123 -0.093548387 -0.124429216 0.030880829
+3.616813294 -0.095698925 -0.126502148 0.030803223
+3.626588465 -0.097849462 -0.128551849 0.030702387
+3.636363636 -0.100000000 -0.130578280 0.030578280
+3.646138807 -0.102150538 -0.132581402 0.030430865
+3.655913978 -0.104301075 -0.134561177 0.030260102
+3.665689150 -0.106451613 -0.136517570 0.030065957
+3.675464321 -0.108602151 -0.138450547 0.029848396
+3.685239492 -0.110752688 -0.140360075 0.029607387
+3.695014663 -0.112903226 -0.142246123 0.029342897
+3.704789834 -0.115053763 -0.144108662 0.029054898
+3.714565005 -0.117204301 -0.145947664 0.028743363
+3.724340176 -0.119354839 -0.147763104 0.028408265
+3.734115347 -0.121505376 -0.149554957 0.028049580
+3.743890518 -0.123655914 -0.151323199 0.027667285
+3.753665689 -0.125806452 -0.153067810 0.027261359
+3.763440860 -0.127956989 -0.154788770 0.026831781
+3.773216031 -0.130107527 -0.156486061 0.026378534
+3.782991202 -0.132258065 -0.158159667 0.025901602
+3.792766373 -0.134408602 -0.159809571 0.025400969
+3.802541544 -0.136559140 -0.161435762 0.024876622
+3.812316716 -0.138709677 -0.163038227 0.024328550
+3.822091887 -0.140860215 -0.164616957 0.023756742
+3.831867058 -0.143010753 -0.166171942 0.023161190
+3.841642229 -0.145161290 -0.167703176 0.022541886
+3.851417400 -0.147311828 -0.169210654 0.021898826
+3.861192571 -0.149462366 -0.170694370 0.021232005
+3.870967742 -0.151612903 -0.172154324 0.020541421
+3.880742913 -0.153763441 -0.173590515 0.019827074
+3.890518084 -0.155913978 -0.175002943 0.019088965
+3.900293255 -0.158064516 -0.176391612 0.018327095
+3.910068426 -0.160215054 -0.177756524 0.017541470
+3.919843597 -0.162365591 -0.179097686 0.016732094
+3.929618768 -0.164516129 -0.180415104 0.015898975
+3.939393939 -0.166666667 -0.181708788 0.015042122
+3.949169110 -0.168817204 -0.182978748 0.014161544
+3.958944282 -0.170967742 -0.184224995 0.013257253
+3.968719453 -0.173118280 -0.185447544 0.012329264
+3.978494624 -0.175268817 -0.186646408 0.011377591
+3.988269795 -0.177419355 -0.187821604 0.010402249
+3.998044966 -0.179569892 -0.188973151 0.009403258
+4.007820137 -0.180078201 -0.190101067 0.010022866
+4.017595308 -0.180175953 -0.191205374 0.011029421
+4.027370479 -0.180273705 -0.192286095 0.012012390
+4.037145650 -0.180371457 -0.193343253 0.012971796
+4.046920821 -0.180469208 -0.194376874 0.013907665
+4.056695992 -0.180566960 -0.195386985 0.014820025
+4.066471163 -0.180664712 -0.196373614 0.015708903
+4.076246334 -0.180762463 -0.197336793 0.016574330
+4.086021505 -0.180860215 -0.198276552 0.017416337
+4.095796676 -0.180957967 -0.199192925 0.018234958
+4.105571848 -0.181055718 -0.200085945 0.019030227
+4.115347019 -0.181153470 -0.200955650 0.019802180
+4.125122190 -0.181251222 -0.201802077 0.020550855
+4.134897361 -0.181348974 -0.202625264 0.021276290
+4.144672532 -0.181446725 -0.203425253 0.021978527
+4.154447703 -0.181544477 -0.204202084 0.022657607
+4.164222874 -0.181642229 -0.204955802 0.023313574
+4.173998045 -0.181739980 -0.205686452 0.023946472
+4.183773216 -0.181837732 -0.206394079 0.024556347
+4.193548387 -0.181935484 -0.207078732 0.025143248
+4.203323558 -0.182033236 -0.207740459 0.025707224
+4.213098729 -0.182130987 -0.208379312 0.026248324
+4.222873900 -0.182228739 -0.208995341 0.026766602
+4.232649071 -0.182326491 -0.209588601 0.027262110
+4.242424242 -0.182424242 -0.210159146 0.027734904
+4.252199413 -0.182521994 -0.210707033 0.028185039
+4.261974585 -0.182619746 -0.211232319 0.028612574
+4.271749756 -0.182717498 -0.211735064 0.029017566
+4.281524927 -0.182815249 -0.212215327 0.029400078
+4.291300098 -0.182913001 -0.212673170 0.029760169
+4.301075269 -0.183010753 -0.213108657 0.030097904
+4.310850440 -0.183108504 -0.213521852 0.030413347
+4.320625611 -0.183206256 -0.213912820 0.030706564
+4.330400782 -0.183304008 -0.214281630 0.030977622
+4.340175953 -0.183401760 -0.214628349 0.031226589
+4.349951124 -0.183499511 -0.214953047 0.031453536
+4.359726295 -0.183597263 -0.215255796 0.031658533
+4.369501466 -0.183695015 -0.215536668 0.031841654
+4.379276637 -0.183792766 -0.215795737 0.032002971
+4.389051808 -0.183890518 -0.216033078 0.032142560
+4.398826979 -0.183988270 -0.216248767 0.032260497
+4.408602151 -0.184086022 -0.216442883 0.032356861
+4.418377322 -0.184183773 -0.216615503 0.032431730
+4.428152493 -0.184281525 -0.216766708 0.032485183
+4.437927664 -0.184379277 -0.216896581 0.032517304
+4.447702835 -0.184477028 -0.217005203 0.032528174
+4.457478006 -0.184574780 -0.217092658 0.032517878
+4.467253177 -0.184672532 -0.217159032 0.032486500
+4.477028348 -0.184770283 -0.217204411 0.032434128
+4.486803519 -0.184868035 -0.217228884 0.032360849
+4.496578690 -0.184965787 -0.217232538 0.032266751
+4.506353861 -0.185063539 -0.217215464 0.032151925
+4.516129032 -0.185161290 -0.217177753 0.032016463
+4.525904203 -0.185259042 -0.217119498 0.031860456
+4.535679374 -0.185356794 -0.217040792 0.031683998
+4.545454545 -0.185454545 -0.216941730 0.031487185
+4.555229717 -0.185552297 -0.216822409 0.031270112
+4.565004888 -0.185650049 -0.216682925 0.031032876
+4.574780059 -0.185747801 -0.216523376 0.030775576
+4.584555230 -0.185845552 -0.216343863 0.030498310
+4.594330401 -0.185943304 -0.216144485 0.030201181
+4.604105572 -0.186041056 -0.215925344 0.029884288
+4.613880743 -0.186138807 -0.215686543 0.029547735
+4.623655914 -0.186236559 -0.215428185 0.029191626
+4.633431085 -0.186334311 -0.215150377 0.028816066
+4.643206256 -0.186432063 -0.214853223 0.028421161
+4.652981427 -0.186529814 -0.214536831 0.028007017
+4.662756598 -0.186627566 -0.214201309 0.027573743
+4.672531769 -0.186725318 -0.213846766 0.027121448
+4.682306940 -0.186823069 -0.213473312 0.026650242
+4.692082111 -0.186920821 -0.213081058 0.026160237
+4.701857283 -0.187018573 -0.212670118 0.025651545
+4.711632454 -0.187116325 -0.212240603 0.025124279
+4.721407625 -0.187214076 -0.211792629 0.024578553
+4.731182796 -0.187311828 -0.211326310 0.024014482
+4.740957967 -0.187409580 -0.210841763 0.023432183
+4.750733138 -0.187507331 -0.210339104 0.022831773
+4.760508309 -0.187605083 -0.209818453 0.022213370
+4.770283480 -0.187702835 -0.209279928 0.021577093
+4.780058651 -0.187800587 -0.208723648 0.020923062
+4.789833822 -0.187898338 -0.208149736 0.020251398
+4.799608993 -0.187996090 -0.207558313 0.019562223
+4.809384164 -0.188093842 -0.206949501 0.018855660
+4.819159335 -0.188191593 -0.206323425 0.018131831
+4.828934506 -0.188289345 -0.205680208 0.017390863
+4.838709677 -0.188387097 -0.205019977 0.016632880
+4.848484848 -0.188484848 -0.204342856 0.015858008
+4.858260020 -0.188582600 -0.203648975 0.015066375
+4.868035191 -0.188680352 -0.202938460 0.014258108
+4.877810362 -0.188778104 -0.202211440 0.013433336
+4.887585533 -0.188875855 -0.201468044 0.012592189
+4.897360704 -0.188973607 -0.200708404 0.011734797
+4.907135875 -0.189071359 -0.199932650 0.010861292
+4.916911046 -0.189169110 -0.199140915 0.009971804
+4.926686217 -0.189266862 -0.198333330 0.009066468
+4.936461388 -0.189364614 -0.197510031 0.008145417
+4.946236559 -0.189462366 -0.196671149 0.007208784
+4.956011730 -0.189560117 -0.195816822 0.006256704
+4.965786901 -0.189657869 -0.194947184 0.005289315
+4.975562072 -0.189755621 -0.194062371 0.004306751
+4.985337243 -0.189853372 -0.193162522 0.003309149
+4.995112414 -0.189951124 -0.192247773 0.002296649
+5.004887586 -0.189266862 -0.191318264 0.002051402
+5.014662757 -0.187800587 -0.190374133 0.002573546
+5.024437928 -0.186334311 -0.189415520 0.003081209
+5.034213099 -0.184868035 -0.188442566 0.003574530
+5.043988270 -0.183401760 -0.187455411 0.004053652
+5.053763441 -0.181935484 -0.186454198 0.004518714
+5.063538612 -0.180469208 -0.185439069 0.004969861
+5.073313783 -0.179002933 -0.184410166 0.005407234
+5.083088954 -0.177536657 -0.183367634 0.005830977
+5.092864125 -0.176070381 -0.182311616 0.006241235
+5.102639296 -0.174604106 -0.181242257 0.006638152
+5.112414467 -0.173137830 -0.180159702 0.007021872
+5.122189638 -0.171671554 -0.179064097 0.007392543
+5.131964809 -0.170205279 -0.177955589 0.007750310
+5.141739980 -0.168739003 -0.176834323 0.008095320
+5.151515152 -0.167272727 -0.175700447 0.008427720
+5.161290323 -0.165806452 -0.174554110 0.008747658
+5.171065494 -0.164340176 -0.173395458 0.009055283
+5.180840665 -0.162873900 -0.172224642 0.009350742
+5.190615836 -0.161407625 -0.171041810 0.009634186
+5.200391007 -0.159941349 -0.169847112 0.009905763
+5.210166178 -0.158475073 -0.168640698 0.010165625
+5.219941349 -0.157008798 -0.167422718 0.010413921
+5.229716520 -0.155542522 -0.166193324 0.010650802
+5.239491691 -0.154076246 -0.164952666 0.010876420
+5.249266862 -0.152609971 -0.163700897 0.011090926
+5.259042033 -0.151143695 -0.162438167 0.011294472
+5.268817204 -0.149677419 -0.161164631 0.011487212
+5.278592375 -0.148211144 -0.159880440 0.011669296
+5.288367546 -0.146744868 -0.158585748 0.011840880
+5.298142717 -0.145278592 -0.157280708 0.012002115
+5.307917889 -0.143812317 -0.155965473 0.012153157
+5.317693060 -0.142346041 -0.154640199 0.012294158
+5.327468231 -0.140879765 -0.153305038 0.012425273
+5.337243402 -0.139413490 -0.151960146 0.012546657
+5.347018573 -0.137947214 -0.150605678 0.012658464
+5.356793744 -0.136480938 -0.149241789 0.012760850
+5.366568915 -0.135014663 -0.147868633 0.012853971
+5.376344086 -0.133548387 -0.146486368 0.012937981
+5.386119257 -0.132082111 -0.145095148 0.013013036
+5.395894428 -0.130615836 -0.143695129 0.013079293
+5.405669599 -0.129149560 -0.142286468 0.013136908
+5.415444770 -0.127683284 -0.140869321 0.013186036
+5.425219941 -0.126217009 -0.139443844 0.013226835
+5.434995112 -0.124750733 -0.138010195 0.013259462
+5.444770283 -0.123284457 -0.136568530 0.013284072
+5.454545455 -0.121818182 -0.135119006 0.013300824
+5.464320626 -0.120351906 -0.133661780 0.013309874
+5.474095797 -0.118885630 -0.132197009 0.013311379
+5.483870968 -0.117419355 -0.130724852 0.013305497
+5.493646139 -0.115953079 -0.129245464 0.013292385
+5.503421310 -0.114486804 -0.127759003 0.013272200
+5.513196481 -0.113020528 -0.126265628 0.013245100
+5.522971652 -0.111554252 -0.124765495 0.013211243
+5.532746823 -0.110087977 -0.123258763 0.013170786
+5.542521994 -0.108621701 -0.121745588 0.013123887
+5.552297165 -0.107155425 -0.120226129 0.013070703
+5.562072336 -0.105689150 -0.118700542 0.013011393
+5.571847507 -0.104222874 -0.117168986 0.012946112
+5.581622678 -0.102756598 -0.115631619 0.012875020
+5.591397849 -0.101290323 -0.114088597 0.012798274
+5.601173021 -0.099824047 -0.112540078 0.012716031
+5.610948192 -0.098357771 -0.110986220 0.012628449
+5.620723363 -0.096891496 -0.109427180 0.012535685
+5.630498534 -0.095425220 -0.107863116 0.012437896
+5.640273705 -0.093958944 -0.106294184 0.012335240
+5.650048876 -0.092492669 -0.104720542 0.012227873
+5.659824047 -0.091026393 -0.103142346 0.012115953
+5.669599218 -0.089560117 -0.101559754 0.011999637
+5.679374389 -0.088093842 -0.099972922 0.011879080
+5.689149560 -0.086627566 -0.098382007 0.011754441
+5.698924731 -0.085161290 -0.096787164 0.011625874
+5.708699902 -0.083695015 -0.095188551 0.011493537
+5.718475073 -0.082228739 -0.093586324 0.011357585
+5.728250244 -0.080762463 -0.091980637 0.011218174
+5.738025415 -0.079296188 -0.090371648 0.011075460
+5.747800587 -0.077829912 -0.088759510 0.010929598
+5.757575758 -0.076363636 -0.087144380 0.010780744
+5.767350929 -0.074897361 -0.085526412 0.010629051
+5.777126100 -0.073431085 -0.083905761 0.010474676
+5.786901271 -0.071964809 -0.082282581 0.010317771
+5.796676442 -0.070498534 -0.080657026 0.010158492
+5.806451613 -0.069032258 -0.079029251 0.009996993
+5.816226784 -0.067565982 -0.077399408 0.009833426
+5.826001955 -0.066099707 -0.075767651 0.009667945
+5.835777126 -0.064633431 -0.074134133 0.009500702
+5.845552297 -0.063167155 -0.072499007 0.009331851
+5.855327468 -0.061700880 -0.070862424 0.009161544
+5.865102639 -0.060234604 -0.069224536 0.008989932
+5.874877810 -0.058768328 -0.067585496 0.008817167
+5.884652981 -0.057302053 -0.065945453 0.008643400
+5.894428152 -0.055835777 -0.064304559 0.008468782
+5.904203324 -0.054369501 -0.062662964 0.008293463
+5.913978495 -0.052903226 -0.061020818 0.008117593
+5.923753666 -0.051436950 -0.059378271 0.007941321
+5.933528837 -0.049970674 -0.057735471 0.007764797
+5.943304008 -0.048504399 -0.056092568 0.007588169
+5.953079179 -0.047038123 -0.054449709 0.007411586
+5.962854350 -0.045571848 -0.052807042 0.007235194
+5.972629521 -0.044105572 -0.051164714 0.007059142
+5.982404692 -0.042639296 -0.049522873 0.006883577
+5.992179863 -0.041173021 -0.047881664 0.006708643
+6.001955034 -0.039745846 -0.046241233 0.006495387
+6.011730205 -0.038475073 -0.044601725 0.006126652
+6.021505376 -0.037204301 -0.042963286 0.005758985
+6.031280547 -0.035933529 -0.041326059 0.005392530
+6.041055718 -0.034662757 -0.039690188 0.005027431
+6.050830890 -0.033391984 -0.038055816 0.004663832
+6.060606061 -0.032121212 -0.036423086 0.004301874
+6.070381232 -0.030850440 -0.034792139 0.003941699
+6.080156403 -0.029579668 -0.033163118 0.003583450
+6.089931574 -0.028308895 -0.031536162 0.003227267
+6.099706745 -0.027038123 -0.029911413 0.002873289
+6.109481916 -0.025767351 -0.028289009 0.002521658
+6.119257087 -0.024496579 -0.026669089 0.002172511
+6.129032258 -0.023225806 -0.025051793 0.001825986
+6.138807429 -0.021955034 -0.023437257 0.001482223
+6.148582600 -0.020684262 -0.021825619 0.001141357
+6.158357771 -0.019413490 -0.020217015 0.000803526
+6.168132942 -0.018142717 -0.018611581 0.000468864
+6.177908113 -0.016871945 -0.017009452 0.000137507
+6.187683284 -0.015601173 -0.015410762 0.000190411
+6.197458456 -0.014330401 -0.013815645 0.000514755
+6.207233627 -0.013059629 -0.012224234 0.000835394
+6.217008798 -0.011788856 -0.010636662 0.001152195
+6.226783969 -0.010518084 -0.009053059 0.001465025
+6.236559140 -0.009247312 -0.007473556 0.001773756
+6.246334311 -0.007976540 -0.005898284 0.002078255
+6.256109482 -0.006705767 -0.004327373 0.002378395
+6.265884653 -0.005434995 -0.002760950 0.002674046
+6.275659824 -0.004164223 -0.001199143 0.002965080
+6.285434995 -0.002893451 0.000357920 0.003251371
+6.295210166 -0.001622678 0.001910114 0.003532792
+6.304985337 -0.000351906 0.003457312 0.003809218
+6.314760508 0.000918866 0.004999391 0.004080525
+6.324535679 0.002189638 0.006536225 0.004346587
+6.334310850 0.003460411 0.008067693 0.004607282
+6.344086022 0.004731183 0.009593671 0.004862488
+6.353861193 0.006001955 0.011114039 0.005112084
+6.363636364 0.007272727 0.012628676 0.005355948
+6.373411535 0.008543500 0.014137461 0.005593962
+6.383186706 0.009814272 0.015640277 0.005826005
+6.392961877 0.011085044 0.017137005 0.006051961
+6.402737048 0.012355816 0.018627527 0.006271711
+6.412512219 0.013626588 0.020111728 0.006485140
+6.422287390 0.014897361 0.021589493 0.006692132
+6.432062561 0.016168133 0.023060705 0.006892572
+6.441837732 0.017438905 0.024525253 0.007086348
+6.451612903 0.018709677 0.025983022 0.007273345
+6.461388074 0.019980450 0.027433902 0.007453453
+6.471163245 0.021251222 0.028877781 0.007626559
+6.480938416 0.022521994 0.030314550 0.007792555
+6.490713587 0.023792766 0.031744098 0.007951331
+6.500488759 0.025063539 0.033166318 0.008102779
+6.510263930 0.026334311 0.034581103 0.008246792
+6.520039101 0.027605083 0.035988346 0.008383263
+6.529814272 0.028875855 0.037387943 0.008512087
+6.539589443 0.030146628 0.038779788 0.008633160
+6.549364614 0.031417400 0.040163778 0.008746378
+6.559139785 0.032688172 0.041539811 0.008851639
+6.568914956 0.033958944 0.042907785 0.008948841
+6.578690127 0.035229717 0.044267600 0.009037884
+6.588465298 0.036500489 0.045619157 0.009118668
+6.598240469 0.037771261 0.046962356 0.009191095
+6.608015640 0.039042033 0.048297101 0.009255067
+6.617790811 0.040312805 0.049623294 0.009310488
+6.627565982 0.041583578 0.050940840 0.009357263
+6.637341153 0.042854350 0.052249646 0.009395296
+6.647116325 0.044125122 0.053549616 0.009424494
+6.656891496 0.045395894 0.054840660 0.009444765
+6.666666667 0.046666667 0.056122685 0.009456018
+6.676441838 0.047937439 0.057395600 0.009458162
+6.686217009 0.049208211 0.058659318 0.009451107
+6.695992180 0.050478983 0.059913749 0.009434766
+6.705767351 0.051749756 0.061158806 0.009409051
+6.715542522 0.053020528 0.062394403 0.009373876
+6.725317693 0.054291300 0.063620455 0.009329155
+6.735092864 0.055562072 0.064836878 0.009274806
+6.744868035 0.056832845 0.066043589 0.009210744
+6.754643206 0.058103617 0.067240505 0.009136888
+6.764418377 0.059374389 0.068427546 0.009053157
+6.774193548 0.060645161 0.069604633 0.008959471
+6.783968719 0.061915934 0.070771685 0.008855752
+6.793743891 0.063186706 0.071928627 0.008741921
+6.803519062 0.064457478 0.073075381 0.008617903
+6.813294233 0.065728250 0.074211872 0.008483622
+6.823069404 0.066999022 0.075338026 0.008339003
+6.832844575 0.068269795 0.076453768 0.008183974
+6.842619746 0.069540567 0.077559028 0.008018461
+6.852394917 0.070811339 0.078653734 0.007842395
+6.862170088 0.072082111 0.079737817 0.007655705
+6.871945259 0.073352884 0.080811207 0.007458323
+6.881720430 0.074623656 0.081873836 0.007250181
+6.891495601 0.075894428 0.082925639 0.007031211
+6.901270772 0.077165200 0.083966550 0.006801350
+6.911045943 0.078435973 0.084996504 0.006560532
+6.920821114 0.079706745 0.086015439 0.006308694
+6.930596285 0.080977517 0.087023292 0.006045774
+6.940371457 0.082248289 0.088020002 0.005771712
+6.950146628 0.083519062 0.089005509 0.005486448
+6.959921799 0.084789834 0.089979756 0.005189922
+6.969696970 0.086060606 0.090942684 0.004882078
+6.979472141 0.087331378 0.091894237 0.004562859
+6.989247312 0.088602151 0.092834360 0.004232209
+6.999022483 0.089872923 0.093762998 0.003890075
+7.008797654 0.090263930 0.094680100 0.004416170
+7.018572825 0.090557185 0.095585612 0.005028427
+7.028347996 0.090850440 0.096479485 0.005629045
+7.038123167 0.091143695 0.097361668 0.006217973
+7.047898338 0.091436950 0.098232114 0.006795164
+7.057673509 0.091730205 0.099090776 0.007360571
+7.067448680 0.092023460 0.099937607 0.007914147
+7.077223851 0.092316716 0.100772562 0.008455847
+7.086999022 0.092609971 0.101595599 0.008985628
+7.096774194 0.092903226 0.102406673 0.009503447
+7.106549365 0.093196481 0.103205745 0.010009264
+7.116324536 0.093489736 0.103992773 0.010503037
+7.126099707 0.093782991 0.104767719 0.010984727
+7.135874878 0.094076246 0.105530544 0.011454298
+7.145650049 0.094369501 0.106281212 0.011911711
+7.155425220 0.094662757 0.107019688 0.012356931
+7.165200391 0.094956012 0.107745936 0.012789925
+7.174975562 0.095249267 0.108459925 0.013210658
+7.184750733 0.095542522 0.109161621 0.013619099
+7.194525904 0.095835777 0.109850993 0.014015216
+7.204301075 0.096129032 0.110528013 0.014398980
+7.214076246 0.096422287 0.111192650 0.014770363
+7.223851417 0.096715543 0.111844879 0.015129336
+7.233626588 0.097008798 0.112484672 0.015475874
+7.243401760 0.097302053 0.113112004 0.015809951
+7.253176931 0.097595308 0.113726852 0.016131544
+7.262952102 0.097888563 0.114329192 0.016440629
+7.272727273 0.098181818 0.114919004 0.016737185
+7.282502444 0.098475073 0.115496266 0.017021192
+7.292277615 0.098768328 0.116060959 0.017292630
+7.302052786 0.099061584 0.116613065 0.017551481
+7.311827957 0.099354839 0.117152566 0.017797728
+7.321603128 0.099648094 0.117679448 0.018031354
+7.331378299 0.099941349 0.118193696 0.018252347
+7.341153470 0.100234604 0.118695295 0.018460691
+7.350928641 0.100527859 0.119184233 0.018656374
+7.360703812 0.100821114 0.119660499 0.018839385
+7.370478983 0.101114370 0.120124084 0.019009714
+7.380254154 0.101407625 0.120574977 0.019167352
+7.390029326 0.101700880 0.121013171 0.019312291
+7.399804497 0.101994135 0.121438660 0.019444525
+7.409579668 0.102287390 0.121851437 0.019564047
+7.419354839 0.102580645 0.122251499 0.019670854
+7.429130010 0.102873900 0.122638842 0.019764942
+7.438905181 0.103167155 0.123013464 0.019846308
+7.448680352 0.103460411 0.123375363 0.019914953
+7.458455523 0.103753666 0.123724541 0.019970875
+7.468230694 0.104046921 0.124060997 0.020014077
+7.478005865 0.104340176 0.124384736 0.020044560
+7.487781036 0.104633431 0.124695758 0.020062327
+7.497556207 0.104926686 0.124994071 0.020067385
+7.507331378 0.105219941 0.125279678 0.020059737
+7.517106549 0.105513196 0.125552588 0.020039391
+7.526881720 0.105806452 0.125812807 0.020006355
+7.536656891 0.106099707 0.126060345 0.019960638
+7.546432063 0.106392962 0.126295212 0.019902250
+7.556207234 0.106686217 0.126517418 0.019831201
+7.565982405 0.106979472 0.126726978 0.019747505
+7.575757576 0.107272727 0.126923902 0.019651175
+7.585532747 0.107565982 0.127108207 0.019542225
+7.595307918 0.107859238 0.127279908 0.019420670
+7.605083089 0.108152493 0.127439020 0.019286528
+7.614858260 0.108445748 0.127585563 0.019139815
+7.624633431 0.108739003 0.127719554 0.018980551
+7.634408602 0.109032258 0.127841014 0.018808756
+7.644183773 0.109325513 0.127949963 0.018624450
+7.653958944 0.109618768 0.128046424 0.018427655
+7.663734115 0.109912023 0.128130418 0.018218395
+7.673509286 0.110205279 0.128201972 0.017996693
+7.683284457 0.110498534 0.128261108 0.017762574
+7.693059629 0.110791789 0.128307854 0.017516065
+7.702834800 0.111085044 0.128342237 0.017257193
+7.712609971 0.111378299 0.128364284 0.016985985
+7.722385142 0.111671554 0.128374026 0.016702472
+7.732160313 0.111964809 0.128371492 0.016406683
+7.741935484 0.112258065 0.128356713 0.016098649
+7.751710655 0.112551320 0.128329723 0.015778403
+7.761485826 0.112844575 0.128290553 0.015445979
+7.771260997 0.113137830 0.128239239 0.015101409
+7.781036168 0.113431085 0.128175816 0.014744731
+7.790811339 0.113724340 0.128100319 0.014375979
+7.800586510 0.114017595 0.128012787 0.013995192
+7.810361681 0.114310850 0.127913257 0.013602407
+7.820136852 0.114604106 0.127801769 0.013197663
+7.829912023 0.114897361 0.127678362 0.012781001
+7.839687195 0.115190616 0.127543078 0.012352462
+7.849462366 0.115483871 0.127395959 0.011912088
+7.859237537 0.115777126 0.127237049 0.011459922
+7.869012708 0.116070381 0.127066390 0.010996009
+7.878787879 0.116363636 0.126884028 0.010520392
+7.888563050 0.116656891 0.126690009 0.010033117
+7.898338221 0.116950147 0.126484379 0.009534233
+7.908113392 0.117243402 0.126267187 0.009023785
+7.917888563 0.117536657 0.126038481 0.008501824
+7.927663734 0.117829912 0.125798310 0.007968398
+7.937438905 0.118123167 0.125546725 0.007423558
+7.947214076 0.118416422 0.125283778 0.006867356
+7.956989247 0.118709677 0.125009520 0.006299842
+7.966764418 0.119002933 0.124724004 0.005721072
+7.976539589 0.119296188 0.124427286 0.005131098
+7.986314761 0.119589443 0.124119418 0.004529975
+7.996089932 0.119882698 0.123800458 0.003917760
+8.005865103 0.119530792 0.123470462 0.003939670
+8.015640274 0.118748778 0.123129487 0.004380709
+8.025415445 0.117966764 0.122777591 0.004810827
+8.035190616 0.117184751 0.122414835 0.005230084
+8.044965787 0.116402737 0.122041276 0.005638539
+8.054740958 0.115620723 0.121656978 0.006036254
+8.064516129 0.114838710 0.121262000 0.006423290
+8.074291300 0.114056696 0.120856406 0.006799710
+8.084066471 0.113274682 0.120440258 0.007165576
+8.093841642 0.112492669 0.120013621 0.007520952
+8.103616813 0.111710655 0.119576559 0.007865904
+8.113391984 0.110928641 0.119129139 0.008200497
+8.123167155 0.110146628 0.118671425 0.008524798
+8.132942326 0.109364614 0.118203486 0.008838873
+8.142717498 0.108582600 0.117725390 0.009142790
+8.152492669 0.107800587 0.117237204 0.009436618
+8.162267840 0.107018573 0.116738999 0.009720426
+8.172043011 0.106236559 0.116230844 0.009994285
+8.181818182 0.105454545 0.115712811 0.010258266
+8.191593353 0.104672532 0.115184970 0.010512439
+8.201368524 0.103890518 0.114647395 0.010756877
+8.211143695 0.103108504 0.114100157 0.010991653
+8.220918866 0.102326491 0.113543331 0.011216841
+8.230694037 0.101544477 0.112976992 0.011432515
+8.240469208 0.100762463 0.112401213 0.011638750
+8.250244379 0.099980450 0.111816071 0.011835622
+8.260019550 0.099198436 0.111221643 0.012023207
+8.269794721 0.098416422 0.110618004 0.012201582
+8.279569892 0.097634409 0.110005234 0.012370825
+8.289345064 0.096852395 0.109383410 0.012531015
+8.299120235 0.096070381 0.108752611 0.012682230
+8.308895406 0.095288368 0.108112917 0.012824549
+8.318670577 0.094506354 0.107464408 0.012958054
+8.328445748 0.093724340 0.106807165 0.013082824
+8.338220919 0.092942326 0.106141268 0.013198942
+8.347996090 0.092160313 0.105466802 0.013306489
+8.357771261 0.091378299 0.104783846 0.013405547
+8.367546432 0.090596285 0.104092486 0.013496201
+8.377321603 0.089814272 0.103392805 0.013578533
+8.387096774 0.089032258 0.102684886 0.013652628
+8.396871945 0.088250244 0.101968816 0.013718571
+8.406647116 0.087468231 0.101244678 0.013776447
+8.416422287 0.086686217 0.100512560 0.013826343
+8.426197458 0.085904203 0.099772547 0.013868343
+8.435972630 0.085122190 0.099024726 0.013902537
+8.445747801 0.084340176 0.098269186 0.013929010
+8.455522972 0.083558162 0.097506013 0.013947850
+8.465298143 0.082776149 0.096735296 0.013959148
+8.475073314 0.081994135 0.095957125 0.013962990
+8.484848485 0.081212121 0.095171588 0.013959467
+8.494623656 0.080430108 0.094378776 0.013948668
+8.504398827 0.079648094 0.093578778 0.013930684
+8.514173998 0.078866080 0.092771686 0.013905606
+8.523949169 0.078084066 0.091957590 0.013873524
+8.533724340 0.077302053 0.091136583 0.013834530
+8.543499511 0.076520039 0.090308756 0.013788717
+8.553274682 0.075738025 0.089474202 0.013736177
+8.563049853 0.074956012 0.088633013 0.013677002
+8.572825024 0.074173998 0.087785284 0.013611286
+8.582600196 0.073391984 0.086931106 0.013539122
+8.592375367 0.072609971 0.086070575 0.013460605
+8.602150538 0.071827957 0.085203785 0.013375828
+8.611925709 0.071045943 0.084330831 0.013284887
+8.621700880 0.070263930 0.083451807 0.013187877
+8.631476051 0.069481916 0.082566808 0.013084893
+8.641251222 0.068699902 0.081675932 0.012976030
+8.651026393 0.067917889 0.080779273 0.012861385
+8.660801564 0.067135875 0.079876928 0.012741054
+8.670576735 0.066353861 0.078968994 0.012615133
+8.680351906 0.065571848 0.078055568 0.012483720
+8.690127077 0.064789834 0.077136747 0.012346913
+8.699902248 0.064007820 0.076212627 0.012204807
+8.709677419 0.063225806 0.075283308 0.012057502
+8.719452590 0.062443793 0.074348888 0.011905095
+8.729227761 0.061661779 0.073409463 0.011747684
+8.739002933 0.060879765 0.072465134 0.011585369
+8.748778104 0.060097752 0.071515998 0.011418247
+8.758553275 0.059315738 0.070562155 0.011246417
+8.768328446 0.058533724 0.069603704 0.011069980
+8.778103617 0.057751711 0.068640744 0.010889033
+8.787878788 0.056969697 0.067673375 0.010703678
+8.797653959 0.056187683 0.066701696 0.010514013
+8.807429130 0.055405670 0.065725808 0.010320138
+8.817204301 0.054623656 0.064745810 0.010122154
+8.826979472 0.053841642 0.063761802 0.009920160
+8.836754643 0.053059629 0.062773886 0.009714258
+8.846529814 0.052277615 0.061782162 0.009504547
+8.856304985 0.051495601 0.060786730 0.009291128
+8.866080156 0.050713587 0.059787690 0.009074103
+8.875855327 0.049931574 0.058785145 0.008853571
+8.885630499 0.049149560 0.057779195 0.008629635
+8.895405670 0.048367546 0.056769940 0.008402394
+8.905180841 0.047585533 0.055757483 0.008171950
+8.914956012 0.046803519 0.054741924 0.007938405
+8.924731183 0.046021505 0.053723365 0.007701859
+8.934506354 0.045239492 0.052701907 0.007462415
+8.944281525 0.044457478 0.051677651 0.007220173
+8.954056696 0.043675464 0.050650698 0.006975234
+8.963831867 0.042893451 0.049621151 0.006727701
+8.973607038 0.042111437 0.048589111 0.006477674
+8.983382209 0.041329423 0.047554679 0.006225256
+8.993157380 0.040547410 0.046517957 0.005970547
+9.002932551 0.040000000 0.045479046 0.005479046
+9.012707722 0.040000000 0.044438047 0.004438047
+9.022482893 0.040000000 0.043395063 0.003395063
+9.032258065 0.040000000 0.042350194 0.002350194
+9.042033236 0.040000000 0.041303542 0.001303542
+9.051808407 0.040000000 0.040255208 0.000255208
+9.061583578 0.040000000 0.039205294 0.000794706
+9.071358749 0.040000000 0.038153900 0.001846100
+9.081133920 0.040000000 0.037101127 0.002898873
+9.090909091 0.040000000 0.036047078 0.003952922
+9.100684262 0.040000000 0.034991852 0.005008148
+9.110459433 0.040000000 0.033935551 0.006064449
+9.120234604 0.040000000 0.032878274 0.007121726
+9.130009775 0.040000000 0.031820124 0.008179876
+9.139784946 0.040000000 0.030761199 0.009238801
+9.149560117 0.040000000 0.029701602 0.010298398
+9.159335288 0.040000000 0.028641430 0.011358570
+9.169110459 0.040000000 0.027580786 0.012419214
+9.178885630 0.040000000 0.026519767 0.013480233
+9.188660802 0.040000000 0.025458475 0.014541525
+9.198435973 0.040000000 0.024397009 0.015602991
+9.208211144 0.040000000 0.023335467 0.016664533
+9.217986315 0.040000000 0.022273950 0.017726050
+9.227761486 0.040000000 0.021212555 0.018787445
+9.237536657 0.040000000 0.020151382 0.019848618
+9.247311828 0.040000000 0.019090529 0.020909471
+9.257086999 0.040000000 0.018030094 0.021969906
+9.266862170 0.040000000 0.016970175 0.023029825
+9.276637341 0.040000000 0.015910870 0.024089130
+9.286412512 0.040000000 0.014852277 0.025147723
+9.296187683 0.040000000 0.013794492 0.026205508
+9.305962854 0.040000000 0.012737613 0.027262387
+9.315738025 0.040000000 0.011681736 0.028318264
+9.325513196 0.040000000 0.010626957 0.029373043
+9.335288368 0.040000000 0.009573373 0.030426627
+9.345063539 0.040000000 0.008521079 0.031478921
+9.354838710 0.040000000 0.007470171 0.032529829
+9.364613881 0.040000000 0.006420744 0.033579256
+9.374389052 0.040000000 0.005372893 0.034627107
+9.384164223 0.040000000 0.004326712 0.035673288
+9.393939394 0.040000000 0.003282295 0.036717705
+9.403714565 0.040000000 0.002239736 0.037760264
+9.413489736 0.040000000 0.001199129 0.038800871
+9.423264907 0.040000000 0.000160566 0.039839434
+9.433040078 0.040000000 -0.000875860 0.040875860
+9.442815249 0.040000000 -0.001910056 0.041910056
+9.452590420 0.040000000 -0.002941932 0.042941932
+9.462365591 0.040000000 -0.003971394 0.043971394
+9.472140762 0.040000000 -0.004998352 0.044998352
+9.481915934 0.040000000 -0.006022716 0.046022716
+9.491691105 0.040000000 -0.007044395 0.047044395
+9.501466276 0.040000000 -0.008063300 0.048063300
+9.511241447 0.040000000 -0.009079340 0.049079340
+9.521016618 0.040000000 -0.010092427 0.050092427
+9.530791789 0.040000000 -0.011102473 0.051102473
+9.540566960 0.040000000 -0.012109389 0.052109389
+9.550342131 0.040000000 -0.013113089 0.053113089
+9.560117302 0.040000000 -0.014113483 0.054113483
+9.569892473 0.040000000 -0.015110487 0.055110487
+9.579667644 0.040000000 -0.016104014 0.056104014
+9.589442815 0.040000000 -0.017093978 0.057093978
+9.599217986 0.040000000 -0.018080295 0.058080295
+9.608993157 0.040000000 -0.019062878 0.059062878
+9.618768328 0.040000000 -0.020041645 0.060041645
+9.628543500 0.040000000 -0.021016511 0.061016511
+9.638318671 0.040000000 -0.021987394 0.061987394
+9.648093842 0.040000000 -0.022954211 0.062954211
+9.657869013 0.040000000 -0.023916879 0.063916879
+9.667644184 0.040000000 -0.024875317 0.064875317
+9.677419355 0.040000000 -0.025829445 0.065829445
+9.687194526 0.040000000 -0.026779182 0.066779182
+9.696969697 0.040000000 -0.027724447 0.067724447
+9.706744868 0.040000000 -0.028665163 0.068665163
+9.716520039 0.040000000 -0.029601249 0.069601249
+9.726295210 0.040000000 -0.030532628 0.070532628
+9.736070381 0.040000000 -0.031459222 0.071459222
+9.745845552 0.040000000 -0.032380954 0.072380954
+9.755620723 0.040000000 -0.033297748 0.073297748
+9.765395894 0.040000000 -0.034209528 0.074209528
+9.775171065 0.040000000 -0.035116220 0.075116220
+9.784946237 0.040000000 -0.036017747 0.076017747
+9.794721408 0.040000000 -0.036914037 0.076914037
+9.804496579 0.040000000 -0.037805016 0.077805016
+9.814271750 0.040000000 -0.038690611 0.078690611
+9.824046921 0.040000000 -0.039570750 0.079570750
+9.833822092 0.040000000 -0.040445362 0.080445362
+9.843597263 0.040000000 -0.041314377 0.081314377
+9.853372434 0.040000000 -0.042177723 0.082177723
+9.863147605 0.040000000 -0.043035332 0.083035332
+9.872922776 0.040000000 -0.043887135 0.083887135
+9.882697947 0.040000000 -0.044733063 0.084733063
+9.892473118 0.040000000 -0.045573049 0.085573049
+9.902248289 0.040000000 -0.046407026 0.086407026
+9.912023460 0.040000000 -0.047234929 0.087234929
+9.921798631 0.040000000 -0.048056691 0.088056691
+9.931573803 0.040000000 -0.048872248 0.088872248
+9.941348974 0.040000000 -0.049681535 0.089681535
+9.951124145 0.040000000 -0.050484491 0.090484491
+9.960899316 0.040000000 -0.051281051 0.091281051
+9.970674487 0.040000000 -0.052071154 0.092071154
+9.980449658 0.040000000 -0.052854739 0.092854739
+9.990224829 0.040000000 -0.053631744 0.093631744
+10.000000000 0.040000000 -0.054402111 0.094402111
diff --git a/examples/takagi-sugeno/approximation.fll b/examples/takagi-sugeno/approximation.fll
index 1d166c9..4461299 100644
--- a/examples/takagi-sugeno/approximation.fll
+++ b/examples/takagi-sugeno/approximation.fll
@@ -1,7 +1,8 @@
-Engine: approximation of sin(x)/x
+Engine: approximation
InputVariable: inputX
enabled: true
range: 0.000 10.000
+ lock-range: false
term: NEAR_1 Triangle 0.000 1.000 2.000
term: NEAR_2 Triangle 1.000 2.000 3.000
term: NEAR_3 Triangle 2.000 3.000 4.000
@@ -14,11 +15,11 @@ InputVariable: inputX
OutputVariable: outputFx
enabled: true
range: -1.000 1.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: true
- lock-range: false
term: f1 Constant 0.840
term: f2 Constant 0.450
term: f3 Constant 0.040
@@ -31,26 +32,27 @@ OutputVariable: outputFx
OutputVariable: trueFx
enabled: true
range: -1.000 1.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage Automatic
default: nan
lock-previous: true
- lock-range: false
term: fx Function sin(inputX)/inputX
OutputVariable: diffFx
enabled: true
range: -1.000 1.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage Automatic
default: nan
lock-previous: false
- lock-range: false
term: diff Function fabs(outputFx-trueFx)
RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if inputX is NEAR_1 then outputFx is f1
rule: if inputX is NEAR_2 then outputFx is f2
rule: if inputX is NEAR_3 then outputFx is f3
diff --git a/examples/takagi-sugeno/approximation.java b/examples/takagi-sugeno/approximation.java
index c3d98e1..c2f9d00 100644
--- a/examples/takagi-sugeno/approximation.java
+++ b/examples/takagi-sugeno/approximation.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,74 +13,84 @@ import com.fuzzylite.variable.*;
public class approximation{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("approximation of sin(x)/x");
+engine.setName("approximation");
+engine.setDescription("");
-InputVariable inputVariable = new InputVariable();
-inputVariable.setEnabled(true);
-inputVariable.setName("inputX");
-inputVariable.setRange(0.000, 10.000);
-inputVariable.addTerm(new Triangle("NEAR_1", 0.000, 1.000, 2.000));
-inputVariable.addTerm(new Triangle("NEAR_2", 1.000, 2.000, 3.000));
-inputVariable.addTerm(new Triangle("NEAR_3", 2.000, 3.000, 4.000));
-inputVariable.addTerm(new Triangle("NEAR_4", 3.000, 4.000, 5.000));
-inputVariable.addTerm(new Triangle("NEAR_5", 4.000, 5.000, 6.000));
-inputVariable.addTerm(new Triangle("NEAR_6", 5.000, 6.000, 7.000));
-inputVariable.addTerm(new Triangle("NEAR_7", 6.000, 7.000, 8.000));
-inputVariable.addTerm(new Triangle("NEAR_8", 7.000, 8.000, 9.000));
-inputVariable.addTerm(new Triangle("NEAR_9", 8.000, 9.000, 10.000));
-engine.addInputVariable(inputVariable);
+InputVariable inputX = new InputVariable();
+inputX.setName("inputX");
+inputX.setDescription("");
+inputX.setEnabled(true);
+inputX.setRange(0.000, 10.000);
+inputX.setLockValueInRange(false);
+inputX.addTerm(new Triangle("NEAR_1", 0.000, 1.000, 2.000));
+inputX.addTerm(new Triangle("NEAR_2", 1.000, 2.000, 3.000));
+inputX.addTerm(new Triangle("NEAR_3", 2.000, 3.000, 4.000));
+inputX.addTerm(new Triangle("NEAR_4", 3.000, 4.000, 5.000));
+inputX.addTerm(new Triangle("NEAR_5", 4.000, 5.000, 6.000));
+inputX.addTerm(new Triangle("NEAR_6", 5.000, 6.000, 7.000));
+inputX.addTerm(new Triangle("NEAR_7", 6.000, 7.000, 8.000));
+inputX.addTerm(new Triangle("NEAR_8", 7.000, 8.000, 9.000));
+inputX.addTerm(new Triangle("NEAR_9", 8.000, 9.000, 10.000));
+engine.addInputVariable(inputX);
-OutputVariable outputVariable1 = new OutputVariable();
-outputVariable1.setEnabled(true);
-outputVariable1.setName("outputFx");
-outputVariable1.setRange(-1.000, 1.000);
-outputVariable1.fuzzyOutput().setAccumulation(null);
-outputVariable1.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable1.setDefaultValue(Double.NaN);
-outputVariable1.setLockPreviousOutputValue(true);
-outputVariable1.setLockOutputValueInRange(false);
-outputVariable1.addTerm(new Constant("f1", 0.840));
-outputVariable1.addTerm(new Constant("f2", 0.450));
-outputVariable1.addTerm(new Constant("f3", 0.040));
-outputVariable1.addTerm(new Constant("f4", -0.180));
-outputVariable1.addTerm(new Constant("f5", -0.190));
-outputVariable1.addTerm(new Constant("f6", -0.040));
-outputVariable1.addTerm(new Constant("f7", 0.090));
-outputVariable1.addTerm(new Constant("f8", 0.120));
-outputVariable1.addTerm(new Constant("f9", 0.040));
-engine.addOutputVariable(outputVariable1);
+OutputVariable outputFx = new OutputVariable();
+outputFx.setName("outputFx");
+outputFx.setDescription("");
+outputFx.setEnabled(true);
+outputFx.setRange(-1.000, 1.000);
+outputFx.setLockValueInRange(false);
+outputFx.setAggregation(null);
+outputFx.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+outputFx.setDefaultValue(Double.NaN);
+outputFx.setLockPreviousValue(true);
+outputFx.addTerm(new Constant("f1", 0.840));
+outputFx.addTerm(new Constant("f2", 0.450));
+outputFx.addTerm(new Constant("f3", 0.040));
+outputFx.addTerm(new Constant("f4", -0.180));
+outputFx.addTerm(new Constant("f5", -0.190));
+outputFx.addTerm(new Constant("f6", -0.040));
+outputFx.addTerm(new Constant("f7", 0.090));
+outputFx.addTerm(new Constant("f8", 0.120));
+outputFx.addTerm(new Constant("f9", 0.040));
+engine.addOutputVariable(outputFx);
-OutputVariable outputVariable2 = new OutputVariable();
-outputVariable2.setEnabled(true);
-outputVariable2.setName("trueFx");
-outputVariable2.setRange(-1.000, 1.000);
-outputVariable2.fuzzyOutput().setAccumulation(null);
-outputVariable2.setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable2.setDefaultValue(Double.NaN);
-outputVariable2.setLockPreviousOutputValue(true);
-outputVariable2.setLockOutputValueInRange(false);
-outputVariable2.addTerm(Function.create("fx", "sin(inputX)/inputX", engine));
-engine.addOutputVariable(outputVariable2);
+OutputVariable trueFx = new OutputVariable();
+trueFx.setName("trueFx");
+trueFx.setDescription("");
+trueFx.setEnabled(true);
+trueFx.setRange(-1.000, 1.000);
+trueFx.setLockValueInRange(false);
+trueFx.setAggregation(null);
+trueFx.setDefuzzifier(new WeightedAverage("Automatic"));
+trueFx.setDefaultValue(Double.NaN);
+trueFx.setLockPreviousValue(true);
+trueFx.addTerm(Function.create("fx", "sin(inputX)/inputX", engine));
+engine.addOutputVariable(trueFx);
-OutputVariable outputVariable3 = new OutputVariable();
-outputVariable3.setEnabled(true);
-outputVariable3.setName("diffFx");
-outputVariable3.setRange(-1.000, 1.000);
-outputVariable3.fuzzyOutput().setAccumulation(null);
-outputVariable3.setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable3.setDefaultValue(Double.NaN);
-outputVariable3.setLockPreviousOutputValue(false);
-outputVariable3.setLockOutputValueInRange(false);
-outputVariable3.addTerm(Function.create("diff", "fabs(outputFx-trueFx)", engine));
-engine.addOutputVariable(outputVariable3);
+OutputVariable diffFx = new OutputVariable();
+diffFx.setName("diffFx");
+diffFx.setDescription("");
+diffFx.setEnabled(true);
+diffFx.setRange(-1.000, 1.000);
+diffFx.setLockValueInRange(false);
+diffFx.setAggregation(null);
+diffFx.setDefuzzifier(new WeightedAverage("Automatic"));
+diffFx.setDefaultValue(Double.NaN);
+diffFx.setLockPreviousValue(false);
+diffFx.addTerm(Function.create("diff", "fabs(outputFx-trueFx)", engine));
+engine.addOutputVariable(diffFx);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(null);
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(null);
+ruleBlock.setImplication(null);
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if inputX is NEAR_1 then outputFx is f1", engine));
ruleBlock.addRule(Rule.parse("if inputX is NEAR_2 then outputFx is f2", engine));
ruleBlock.addRule(Rule.parse("if inputX is NEAR_3 then outputFx is f3", engine));
diff --git a/examples/takagi-sugeno/approximation.pdf b/examples/takagi-sugeno/approximation.pdf
new file mode 100644
index 0000000..6af8fef
--- /dev/null
+++ b/examples/takagi-sugeno/approximation.pdf
Binary files differ
diff --git a/examples/takagi-sugeno/octave/cubic_approximator.R b/examples/takagi-sugeno/octave/cubic_approximator.R
new file mode 100644
index 0000000..d3d3fbf
--- /dev/null
+++ b/examples/takagi-sugeno/octave/cubic_approximator.R
@@ -0,0 +1,84 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "cubic_approximator"
+engine.fll = "Engine: cubic_approximator
+InputVariable: X
+ enabled: true
+ range: -5.000 5.000
+ lock-range: false
+ term: AboutNegFive Triangle -6.000 -5.000 -4.000
+ term: AboutNegFour Triangle -5.000 -4.000 -3.000
+ term: AboutNegThree Triangle -4.000 -3.000 -2.000
+ term: AboutNegTwo Triangle -3.000 -2.000 -1.000
+ term: AboutNegOne Triangle -2.000 -1.000 0.000
+ term: AboutZero Triangle -1.000 0.000 1.000
+ term: AboutOne Triangle 0.000 1.000 2.000
+ term: AboutTwo Triangle 1.000 2.000 3.000
+ term: AboutThree Triangle 2.000 3.000 4.000
+ term: AboutFour Triangle 3.000 4.000 5.000
+ term: AboutFive Triangle 4.000 5.000 6.000
+OutputVariable: ApproxXCubed
+ enabled: true
+ range: -5.000 5.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: TangentatNegFive Linear 75.000 250.000
+ term: TangentatNegFour Linear 48.000 128.000
+ term: TangentatNegThree Linear 27.000 54.000
+ term: TangentatNegTwo Linear 12.000 16.000
+ term: TangentatNegOne Linear 3.000 2.000
+ term: TangentatZero Linear 0.000 0.000
+ term: TangentatOne Linear 3.000 -2.000
+ term: TangentatTwo Linear 12.000 -16.000
+ term: TangentatThree Linear 27.000 -54.000
+ term: TangentatFour Linear 48.000 -128.000
+ term: TangentatFive Linear 75.000 -250.000
+RuleBlock:
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if X is AboutNegFive then ApproxXCubed is TangentatNegFive
+ rule: if X is AboutNegFour then ApproxXCubed is TangentatNegFour
+ rule: if X is AboutNegThree then ApproxXCubed is TangentatNegThree
+ rule: if X is AboutNegTwo then ApproxXCubed is TangentatNegTwo
+ rule: if X is AboutNegOne then ApproxXCubed is TangentatNegOne
+ rule: if X is AboutZero then ApproxXCubed is TangentatZero
+ rule: if X is AboutOne then ApproxXCubed is TangentatOne
+ rule: if X is AboutTwo then ApproxXCubed is TangentatTwo
+ rule: if X is AboutThree then ApproxXCubed is TangentatThree
+ rule: if X is AboutFour then ApproxXCubed is TangentatFour
+ rule: if X is AboutFive then ApproxXCubed is TangentatFive"
+
+engine.fldFile = "cubic_approximator.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(X, ApproxXCubed)) +
+ geom_line(aes(color=ApproxXCubed), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("X vs ApproxXCubed")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(X, ApproxXCubed)) +
+ geom_line(aes(color=ApproxXCubed), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("ApproxXCubed vs X")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/takagi-sugeno/octave/cubic_approximator.cpp b/examples/takagi-sugeno/octave/cubic_approximator.cpp
index 6941fa5..2b9df3f 100644
--- a/examples/takagi-sugeno/octave/cubic_approximator.cpp
+++ b/examples/takagi-sugeno/octave/cubic_approximator.cpp
@@ -1,67 +1,75 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("Cubic-Approximator");
+engine->setName("cubic_approximator");
+engine->setDescription("");
-InputVariable* inputVariable = new InputVariable;
-inputVariable->setEnabled(true);
-inputVariable->setName("X");
-inputVariable->setRange(-5.000, 5.000);
-inputVariable->addTerm(new Triangle("AboutNegFive", -6.000, -5.000, -4.000));
-inputVariable->addTerm(new Triangle("AboutNegFour", -5.000, -4.000, -3.000));
-inputVariable->addTerm(new Triangle("AboutNegThree", -4.000, -3.000, -2.000));
-inputVariable->addTerm(new Triangle("AboutNegTwo", -3.000, -2.000, -1.000));
-inputVariable->addTerm(new Triangle("AboutNegOne", -2.000, -1.000, 0.000));
-inputVariable->addTerm(new Triangle("AboutZero", -1.000, 0.000, 1.000));
-inputVariable->addTerm(new Triangle("AboutOne", 0.000, 1.000, 2.000));
-inputVariable->addTerm(new Triangle("AboutTwo", 1.000, 2.000, 3.000));
-inputVariable->addTerm(new Triangle("AboutThree", 2.000, 3.000, 4.000));
-inputVariable->addTerm(new Triangle("AboutFour", 3.000, 4.000, 5.000));
-inputVariable->addTerm(new Triangle("AboutFive", 4.000, 5.000, 6.000));
-engine->addInputVariable(inputVariable);
+InputVariable* X = new InputVariable;
+X->setName("X");
+X->setDescription("");
+X->setEnabled(true);
+X->setRange(-5.000, 5.000);
+X->setLockValueInRange(false);
+X->addTerm(new Triangle("AboutNegFive", -6.000, -5.000, -4.000));
+X->addTerm(new Triangle("AboutNegFour", -5.000, -4.000, -3.000));
+X->addTerm(new Triangle("AboutNegThree", -4.000, -3.000, -2.000));
+X->addTerm(new Triangle("AboutNegTwo", -3.000, -2.000, -1.000));
+X->addTerm(new Triangle("AboutNegOne", -2.000, -1.000, 0.000));
+X->addTerm(new Triangle("AboutZero", -1.000, 0.000, 1.000));
+X->addTerm(new Triangle("AboutOne", 0.000, 1.000, 2.000));
+X->addTerm(new Triangle("AboutTwo", 1.000, 2.000, 3.000));
+X->addTerm(new Triangle("AboutThree", 2.000, 3.000, 4.000));
+X->addTerm(new Triangle("AboutFour", 3.000, 4.000, 5.000));
+X->addTerm(new Triangle("AboutFive", 4.000, 5.000, 6.000));
+engine->addInputVariable(X);
-OutputVariable* outputVariable = new OutputVariable;
-outputVariable->setEnabled(true);
-outputVariable->setName("ApproxXCubed");
-outputVariable->setRange(-5.000, 5.000);
-outputVariable->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable->setDefaultValue(fl::nan);
-outputVariable->setLockPreviousOutputValue(false);
-outputVariable->setLockOutputValueInRange(false);
-outputVariable->addTerm(Linear::create("TangentatNegFive", engine, 75.000, 250.000));
-outputVariable->addTerm(Linear::create("TangentatNegFour", engine, 48.000, 128.000));
-outputVariable->addTerm(Linear::create("TangentatNegThree", engine, 27.000, 54.000));
-outputVariable->addTerm(Linear::create("TangentatNegTwo", engine, 12.000, 16.000));
-outputVariable->addTerm(Linear::create("TangentatNegOne", engine, 3.000, 2.000));
-outputVariable->addTerm(Linear::create("TangentatZero", engine, 0.000, 0.000));
-outputVariable->addTerm(Linear::create("TangentatOne", engine, 3.000, -2.000));
-outputVariable->addTerm(Linear::create("TangentatTwo", engine, 12.000, -16.000));
-outputVariable->addTerm(Linear::create("TangentatThree", engine, 27.000, -54.000));
-outputVariable->addTerm(Linear::create("TangentatFour", engine, 48.000, -128.000));
-outputVariable->addTerm(Linear::create("TangentatFive", engine, 75.000, -250.000));
-engine->addOutputVariable(outputVariable);
+OutputVariable* ApproxXCubed = new OutputVariable;
+ApproxXCubed->setName("ApproxXCubed");
+ApproxXCubed->setDescription("");
+ApproxXCubed->setEnabled(true);
+ApproxXCubed->setRange(-5.000, 5.000);
+ApproxXCubed->setLockValueInRange(false);
+ApproxXCubed->setAggregation(fl::null);
+ApproxXCubed->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+ApproxXCubed->setDefaultValue(fl::nan);
+ApproxXCubed->setLockPreviousValue(false);
+ApproxXCubed->addTerm(Linear::create("TangentatNegFive", engine, 75.000, 250.000));
+ApproxXCubed->addTerm(Linear::create("TangentatNegFour", engine, 48.000, 128.000));
+ApproxXCubed->addTerm(Linear::create("TangentatNegThree", engine, 27.000, 54.000));
+ApproxXCubed->addTerm(Linear::create("TangentatNegTwo", engine, 12.000, 16.000));
+ApproxXCubed->addTerm(Linear::create("TangentatNegOne", engine, 3.000, 2.000));
+ApproxXCubed->addTerm(Linear::create("TangentatZero", engine, 0.000, 0.000));
+ApproxXCubed->addTerm(Linear::create("TangentatOne", engine, 3.000, -2.000));
+ApproxXCubed->addTerm(Linear::create("TangentatTwo", engine, 12.000, -16.000));
+ApproxXCubed->addTerm(Linear::create("TangentatThree", engine, 27.000, -54.000));
+ApproxXCubed->addTerm(Linear::create("TangentatFour", engine, 48.000, -128.000));
+ApproxXCubed->addTerm(Linear::create("TangentatFive", engine, 75.000, -250.000));
+engine->addOutputVariable(ApproxXCubed);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(fl::null);
ruleBlock->setDisjunction(fl::null);
-ruleBlock->setActivation(fl::null);
-ruleBlock->addRule(fl::Rule::parse("if X is AboutNegFive then ApproxXCubed is TangentatNegFive", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutNegFour then ApproxXCubed is TangentatNegFour", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutNegThree then ApproxXCubed is TangentatNegThree", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutNegTwo then ApproxXCubed is TangentatNegTwo", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutNegOne then ApproxXCubed is TangentatNegOne", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutZero then ApproxXCubed is TangentatZero", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutOne then ApproxXCubed is TangentatOne", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutTwo then ApproxXCubed is TangentatTwo", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutThree then ApproxXCubed is TangentatThree", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutFour then ApproxXCubed is TangentatFour", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is AboutFive then ApproxXCubed is TangentatFive", engine));
+ruleBlock->setImplication(fl::null);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if X is AboutNegFive then ApproxXCubed is TangentatNegFive", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutNegFour then ApproxXCubed is TangentatNegFour", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutNegThree then ApproxXCubed is TangentatNegThree", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutNegTwo then ApproxXCubed is TangentatNegTwo", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutNegOne then ApproxXCubed is TangentatNegOne", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutZero then ApproxXCubed is TangentatZero", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutOne then ApproxXCubed is TangentatOne", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutTwo then ApproxXCubed is TangentatTwo", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutThree then ApproxXCubed is TangentatThree", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutFour then ApproxXCubed is TangentatFour", engine));
+ruleBlock->addRule(Rule::parse("if X is AboutFive then ApproxXCubed is TangentatFive", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/takagi-sugeno/octave/cubic_approximator.fcl b/examples/takagi-sugeno/octave/cubic_approximator.fcl
index db88e44..df4e8be 100644
--- a/examples/takagi-sugeno/octave/cubic_approximator.fcl
+++ b/examples/takagi-sugeno/octave/cubic_approximator.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK Cubic-Approximator
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK cubic_approximator
VAR_INPUT
X: REAL;
diff --git a/examples/takagi-sugeno/octave/cubic_approximator.fis b/examples/takagi-sugeno/octave/cubic_approximator.fis
index b69675b..e0af36f 100644
--- a/examples/takagi-sugeno/octave/cubic_approximator.fis
+++ b/examples/takagi-sugeno/octave/cubic_approximator.fis
@@ -1,13 +1,16 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='Cubic-Approximator'
+Name='cubic_approximator'
Type='sugeno'
+Version=6.0
NumInputs=1
NumOutputs=1
NumRules=11
-AndMethod=''
-OrMethod=''
-ImpMethod=''
-AggMethod=''
+AndMethod='min'
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
DefuzzMethod='wtaver'
[Input1]
diff --git a/examples/takagi-sugeno/octave/cubic_approximator.fld b/examples/takagi-sugeno/octave/cubic_approximator.fld
index e13c169..4f6ddeb 100644
--- a/examples/takagi-sugeno/octave/cubic_approximator.fld
+++ b/examples/takagi-sugeno/octave/cubic_approximator.fld
@@ -1,1026 +1,1025 @@
-#@Engine: Cubic-Approximator;
-#@InputVariable: X; @OutputVariable: ApproxXCubed;
--5.00000000 -125.00000000
--4.99022483 -124.14236490
--4.98044966 -123.28988972
--4.97067449 -122.44257445
--4.96089932 -121.60041910
--4.95112414 -120.76342366
--4.94134897 -119.93158814
--4.93157380 -119.10491253
--4.92179863 -118.28339683
--4.91202346 -117.46704105
--4.90224829 -116.65584518
--4.89247312 -115.84980923
--4.88269795 -115.04893319
--4.87292278 -114.25321706
--4.86314761 -113.46266085
--4.85337243 -112.67726456
--4.84359726 -111.89702818
--4.83382209 -111.12195171
--4.82404692 -110.35203516
--4.81427175 -109.58727852
--4.80449658 -108.82768179
--4.79472141 -108.07324498
--4.78494624 -107.32396809
--4.77517107 -106.57985111
--4.76539589 -105.84089404
--4.75562072 -105.10709689
--4.74584555 -104.37845965
--4.73607038 -103.65498233
--4.72629521 -102.93666492
--4.71652004 -102.22350742
--4.70674487 -101.51550984
--4.69696970 -100.81267218
--4.68719453 -100.11499442
--4.67741935 -99.42247659
--4.66764418 -98.73511866
--4.65786901 -98.05292065
--4.64809384 -97.37588256
--4.63831867 -96.70400438
--4.62854350 -96.03728611
--4.61876833 -95.37572776
--4.60899316 -94.71932933
--4.59921799 -94.06809080
--4.58944282 -93.42201219
--4.57966764 -92.78109350
--4.56989247 -92.14533472
--4.56011730 -91.51473586
--4.55034213 -90.88929690
--4.54056696 -90.26901787
--4.53079179 -89.65389875
--4.52101662 -89.04393954
--4.51124145 -88.43914024
--4.50146628 -87.83950086
--4.49169110 -87.24502140
--4.48191593 -86.65570185
--4.47214076 -86.07154221
--4.46236559 -85.49254249
--4.45259042 -84.91870268
--4.44281525 -84.35002279
--4.43304008 -83.78650281
--4.42326491 -83.22814275
--4.41348974 -82.67494260
--4.40371457 -82.12690236
--4.39393939 -81.58402204
--4.38416422 -81.04630163
--4.37438905 -80.51374114
--4.36461388 -79.98634056
--4.35483871 -79.46409990
--4.34506354 -78.94701915
--4.33528837 -78.43509831
--4.32551320 -77.92833739
--4.31573803 -77.42673638
--4.30596285 -76.93029529
--4.29618768 -76.43901411
--4.28641251 -75.95289285
--4.27663734 -75.47193150
--4.26686217 -74.99613006
--4.25708700 -74.52548854
--4.24731183 -74.06000694
--4.23753666 -73.59968525
--4.22776149 -73.14452347
--4.21798631 -72.69452160
--4.20821114 -72.24967966
--4.19843597 -71.80999762
--4.18866080 -71.37547550
--4.17888563 -70.94611329
--4.16911046 -70.52191100
--4.15933529 -70.10286863
--4.14956012 -69.68898616
--4.13978495 -69.28026361
--4.13000978 -68.87670098
--4.12023460 -68.47829826
--4.11045943 -68.08505545
--4.10068426 -67.69697256
--4.09090909 -67.31404959
--4.08113392 -66.93628652
--4.07135875 -66.56368338
--4.06158358 -66.19624014
--4.05180841 -65.83395682
--4.04203324 -65.47683342
--4.03225806 -65.12486993
--4.02248289 -64.77806635
--4.01270772 -64.43642269
--4.00293255 -64.09993894
--3.99315738 -63.60411131
--3.98338221 -63.04196730
--3.97360704 -62.48383657
--3.96383187 -61.92971910
--3.95405670 -61.37961490
--3.94428152 -60.83352396
--3.93450635 -60.29144630
--3.92473118 -59.75338189
--3.91495601 -59.21933076
--3.90518084 -58.68929289
--3.89540567 -58.16326829
--3.88563050 -57.64125696
--3.87585533 -57.12325889
--3.86608016 -56.60927409
--3.85630499 -56.09930255
--3.84652981 -55.59334428
--3.83675464 -55.09139928
--3.82697947 -54.59346755
--3.81720430 -54.09954908
--3.80742913 -53.60964388
--3.79765396 -53.12375195
--3.78787879 -52.64187328
--3.77810362 -52.16400788
--3.76832845 -51.69015574
--3.75855327 -51.22031688
--3.74877810 -50.75449128
--3.73900293 -50.29267894
--3.72922776 -49.83487987
--3.71945259 -49.38109407
--3.70967742 -48.93132154
--3.69990225 -48.48556227
--3.69012708 -48.04381627
--3.68035191 -47.60608354
--3.67057674 -47.17236407
--3.66080156 -46.74265787
--3.65102639 -46.31696494
--3.64125122 -45.89528527
--3.63147605 -45.47761887
--3.62170088 -45.06396574
--3.61192571 -44.65432587
--3.60215054 -44.24869927
--3.59237537 -43.84708594
--3.58260020 -43.44948587
--3.57282502 -43.05589907
--3.56304985 -42.66632554
--3.55327468 -42.28076527
--3.54349951 -41.89921827
--3.53372434 -41.52168454
--3.52394917 -41.14816407
--3.51417400 -40.77865687
--3.50439883 -40.41316294
--3.49462366 -40.05168228
--3.48484848 -39.69421488
--3.47507331 -39.34076074
--3.46529814 -38.99131988
--3.45552297 -38.64589228
--3.44574780 -38.30447795
--3.43597263 -37.96707688
--3.42619746 -37.63368908
--3.41642229 -37.30431455
--3.40664712 -36.97895328
--3.39687195 -36.65760528
--3.38709677 -36.34027055
--3.37732160 -36.02694909
--3.36754643 -35.71764089
--3.35777126 -35.41234596
--3.34799609 -35.11106429
--3.33822092 -34.81379589
--3.32844575 -34.52054076
--3.31867058 -34.23129889
--3.30889541 -33.94607030
--3.29912023 -33.66485496
--3.28934506 -33.38765290
--3.27956989 -33.11446410
--3.26979472 -32.84528857
--3.26001955 -32.58012630
--3.25024438 -32.31897730
--3.24046921 -32.06184157
--3.23069404 -31.80871911
--3.22091887 -31.55960991
--3.21114370 -31.31451398
--3.20136852 -31.07343131
--3.19159335 -30.83636192
--3.18181818 -30.60330579
--3.17204301 -30.37426292
--3.16226784 -30.14923332
--3.15249267 -29.92821699
--3.14271750 -29.71121393
--3.13294233 -29.49822413
--3.12316716 -29.28924760
--3.11339198 -29.08428433
--3.10361681 -28.88333434
--3.09384164 -28.68639761
--3.08406647 -28.49347414
--3.07429130 -28.30456394
--3.06451613 -28.11966701
--3.05474096 -27.93878335
--3.04496579 -27.76191295
--3.03519062 -27.58905582
--3.02541544 -27.42021196
--3.01564027 -27.25538136
--3.00586510 -27.09456403
--2.99608993 -26.86728700
--2.98631476 -26.53751114
--2.97653959 -26.21060190
--2.96676442 -25.88655928
--2.95698925 -25.56538328
--2.94721408 -25.24707390
--2.93743891 -24.93163113
--2.92766373 -24.61905499
--2.91788856 -24.30934546
--2.90811339 -24.00250256
--2.89833822 -23.69852627
--2.88856305 -23.39741660
--2.87878788 -23.09917355
--2.86901271 -22.80379712
--2.85923754 -22.51128731
--2.84946237 -22.22164412
--2.83968719 -21.93486755
--2.82991202 -21.65095759
--2.82013685 -21.36991426
--2.81036168 -21.09173754
--2.80058651 -20.81642745
--2.79081134 -20.54398397
--2.78103617 -20.27440711
--2.77126100 -20.00769687
--2.76148583 -19.74385325
--2.75171065 -19.48287625
--2.74193548 -19.22476587
--2.73216031 -18.96952211
--2.72238514 -18.71714496
--2.71260997 -18.46763444
--2.70283480 -18.22099053
--2.69305963 -17.97721324
--2.68328446 -17.73630258
--2.67350929 -17.49825853
--2.66373412 -17.26308110
--2.65395894 -17.03077029
--2.64418377 -16.80132610
--2.63440860 -16.57474853
--2.62463343 -16.35103757
--2.61485826 -16.13019324
--2.60508309 -15.91221552
--2.59530792 -15.69710443
--2.58553275 -15.48485995
--2.57575758 -15.27548209
--2.56598240 -15.06897086
--2.55620723 -14.86532624
--2.54643206 -14.66454824
--2.53665689 -14.46663685
--2.52688172 -14.27159209
--2.51710655 -14.07941395
--2.50733138 -13.89010242
--2.49755621 -13.70365752
--2.48778104 -13.52007923
--2.47800587 -13.33936757
--2.46823069 -13.16152252
--2.45845552 -12.98654409
--2.44868035 -12.81443228
--2.43890518 -12.64518709
--2.42913001 -12.47880852
--2.41935484 -12.31529657
--2.40957967 -12.15465123
--2.39980450 -11.99687252
--2.39002933 -11.84196042
--2.38025415 -11.68991495
--2.37047898 -11.54073609
--2.36070381 -11.39442385
--2.35092864 -11.25097823
--2.34115347 -11.11039923
--2.33137830 -10.97268685
--2.32160313 -10.83784109
--2.31182796 -10.70586195
--2.30205279 -10.57674943
--2.29227761 -10.45050352
--2.28250244 -10.32712424
--2.27272727 -10.20661157
--2.26295210 -10.08896552
--2.25317693 -9.97418610
--2.24340176 -9.86227329
--2.23362659 -9.75322710
--2.22385142 -9.64704753
--2.21407625 -9.54373457
--2.20430108 -9.44328824
--2.19452590 -9.34570853
--2.18475073 -9.25099543
--2.17497556 -9.15914896
--2.16520039 -9.07016910
--2.15542522 -8.98405586
--2.14565005 -8.90080925
--2.13587488 -8.82042925
--2.12609971 -8.74291587
--2.11632454 -8.66826911
--2.10654936 -8.59648896
--2.09677419 -8.52757544
--2.08699902 -8.46152854
--2.07722385 -8.39834825
--2.06744868 -8.33803459
--2.05767351 -8.28058754
--2.04789834 -8.22600711
--2.03812317 -8.17429331
--2.02834800 -8.12544612
--2.01857283 -8.07946555
--2.00879765 -8.03635160
--1.99902248 -7.98436833
--1.98924731 -7.82899757
--1.97947214 -7.67534679
--1.96969697 -7.52341598
--1.95992180 -7.37320514
--1.95014663 -7.22471427
--1.94037146 -7.07794337
--1.93059629 -6.93289245
--1.92082111 -6.78956149
--1.91104594 -6.64795051
--1.90127077 -6.50805950
--1.89149560 -6.36988846
--1.88172043 -6.23343739
--1.87194526 -6.09870629
--1.86217009 -5.96569517
--1.85239492 -5.83440402
--1.84261975 -5.70483283
--1.83284457 -5.57698162
--1.82306940 -5.45085038
--1.81329423 -5.32643911
--1.80351906 -5.20374782
--1.79374389 -5.08277649
--1.78396872 -4.96352514
--1.77419355 -4.84599376
--1.76441838 -4.73018235
--1.75464321 -4.61609091
--1.74486804 -4.50371944
--1.73509286 -4.39306794
--1.72531769 -4.28413642
--1.71554252 -4.17692486
--1.70576735 -4.07143328
--1.69599218 -3.96766167
--1.68621701 -3.86561003
--1.67644184 -3.76527836
--1.66666667 -3.66666667
--1.65689150 -3.56977494
--1.64711632 -3.47460319
--1.63734115 -3.38115141
--1.62756598 -3.28941960
--1.61779081 -3.19940776
--1.60801564 -3.11111589
--1.59824047 -3.02454399
--1.58846530 -2.93969207
--1.57869013 -2.85656011
--1.56891496 -2.77514813
--1.55913978 -2.69545612
--1.54936461 -2.61748408
--1.53958944 -2.54123202
--1.52981427 -2.46669992
--1.52003910 -2.39388779
--1.51026393 -2.32279564
--1.50048876 -2.25342346
--1.49071359 -2.18577125
--1.48093842 -2.11983901
--1.47116325 -2.05562674
--1.46138807 -1.99313445
--1.45161290 -1.93236212
--1.44183773 -1.87330977
--1.43206256 -1.81597739
--1.42228739 -1.76036498
--1.41251222 -1.70647254
--1.40273705 -1.65430007
--1.39296188 -1.60384758
--1.38318671 -1.55511505
--1.37341153 -1.50810250
--1.36363636 -1.46280992
--1.35386119 -1.41923731
--1.34408602 -1.37738467
--1.33431085 -1.33725200
--1.32453568 -1.29883931
--1.31476051 -1.26214658
--1.30498534 -1.22717383
--1.29521017 -1.19392105
--1.28543500 -1.16238824
--1.27565982 -1.13257540
--1.26588465 -1.10448253
--1.25610948 -1.07810964
--1.24633431 -1.05345671
--1.23655914 -1.03052376
--1.22678397 -1.00931078
--1.21700880 -0.98981777
--1.20723363 -0.97204473
--1.19745846 -0.95599166
--1.18768328 -0.94165857
--1.17790811 -0.92904544
--1.16813294 -0.91815229
--1.15835777 -0.90897911
--1.14858260 -0.90152590
--1.13880743 -0.89579266
--1.12903226 -0.89177940
--1.11925709 -0.88948610
--1.10948192 -0.88891278
--1.09970674 -0.89005943
--1.08993157 -0.89292604
--1.08015640 -0.89751263
--1.07038123 -0.90381920
--1.06060606 -0.91184573
--1.05083089 -0.92159223
--1.04105572 -0.93305871
--1.03128055 -0.94624516
--1.02150538 -0.96115158
--1.01173021 -0.97777797
--1.00195503 -0.99612433
--0.99217986 -0.96890292
--0.98240469 -0.93054755
--0.97262952 -0.89276551
--0.96285435 -0.85555680
--0.95307918 -0.81892141
--0.94330401 -0.78285934
--0.93352884 -0.74737059
--0.92375367 -0.71245517
--0.91397849 -0.67811308
--0.90420332 -0.64434430
--0.89442815 -0.61114885
--0.88465298 -0.57852673
--0.87487781 -0.54647793
--0.86510264 -0.51500245
--0.85532747 -0.48410030
--0.84555230 -0.45377147
--0.83577713 -0.42401596
--0.82600196 -0.39483378
--0.81622678 -0.36622492
--0.80645161 -0.33818939
--0.79667644 -0.31072718
--0.78690127 -0.28383829
--0.77712610 -0.25752273
--0.76735093 -0.23178049
--0.75757576 -0.20661157
--0.74780059 -0.18201598
--0.73802542 -0.15799371
--0.72825024 -0.13454477
--0.71847507 -0.11166915
--0.70869990 -0.08936685
--0.69892473 -0.06763788
--0.68914956 -0.04648223
--0.67937439 -0.02589990
--0.66959922 -0.00589090
--0.65982405 0.01354478
--0.65004888 0.03240713
--0.64027370 0.05069616
--0.63049853 0.06841186
--0.62072336 0.08555425
--0.61094819 0.10212330
--0.60117302 0.11811904
--0.59139785 0.13354145
--0.58162268 0.14839054
--0.57184751 0.16266630
--0.56207234 0.17636874
--0.55229717 0.18949785
--0.54252199 0.20205365
--0.53274682 0.21403611
--0.52297165 0.22544526
--0.51319648 0.23628108
--0.50342131 0.24654357
--0.49364614 0.25623275
--0.48387097 0.26534860
--0.47409580 0.27389112
--0.46432063 0.28186032
--0.45454545 0.28925620
--0.44477028 0.29607875
--0.43499511 0.30232798
--0.42521994 0.30800389
--0.41544477 0.31310647
--0.40566960 0.31763573
--0.39589443 0.32159166
--0.38611926 0.32497427
--0.37634409 0.32778356
--0.36656891 0.33001952
--0.35679374 0.33168216
--0.34701857 0.33277148
--0.33724340 0.33328747
--0.32746823 0.33323014
--0.31769306 0.33259948
--0.30791789 0.33139550
--0.29814272 0.32961820
--0.28836755 0.32726757
--0.27859238 0.32434362
--0.26881720 0.32084634
--0.25904203 0.31677574
--0.24926686 0.31213182
--0.23949169 0.30691457
--0.22971652 0.30112400
--0.21994135 0.29476011
--0.21016618 0.28782289
--0.20039101 0.28031235
--0.19061584 0.27222848
--0.18084066 0.26357129
--0.17106549 0.25434078
--0.16129032 0.24453694
--0.15151515 0.23415978
--0.14173998 0.22320929
--0.13196481 0.21168549
--0.12218964 0.19958835
--0.11241447 0.18691790
--0.10263930 0.17367412
--0.09286413 0.15985701
--0.08308895 0.14546659
--0.07331378 0.13050283
--0.06353861 0.11496576
--0.05376344 0.09885536
--0.04398827 0.08217164
--0.03421310 0.06491459
--0.02443793 0.04708422
--0.01466276 0.02868052
--0.00488759 0.00970351
-0.00488759 -0.00970351
-0.01466276 -0.02868052
-0.02443793 -0.04708422
-0.03421310 -0.06491459
-0.04398827 -0.08217164
-0.05376344 -0.09885536
-0.06353861 -0.11496576
-0.07331378 -0.13050283
-0.08308895 -0.14546659
-0.09286413 -0.15985701
-0.10263930 -0.17367412
-0.11241447 -0.18691790
-0.12218964 -0.19958835
-0.13196481 -0.21168549
-0.14173998 -0.22320929
-0.15151515 -0.23415978
-0.16129032 -0.24453694
-0.17106549 -0.25434078
-0.18084066 -0.26357129
-0.19061584 -0.27222848
-0.20039101 -0.28031235
-0.21016618 -0.28782289
-0.21994135 -0.29476011
-0.22971652 -0.30112400
-0.23949169 -0.30691457
-0.24926686 -0.31213182
-0.25904203 -0.31677574
-0.26881720 -0.32084634
-0.27859238 -0.32434362
-0.28836755 -0.32726757
-0.29814272 -0.32961820
-0.30791789 -0.33139550
-0.31769306 -0.33259948
-0.32746823 -0.33323014
-0.33724340 -0.33328747
-0.34701857 -0.33277148
-0.35679374 -0.33168216
-0.36656891 -0.33001952
-0.37634409 -0.32778356
-0.38611926 -0.32497427
-0.39589443 -0.32159166
-0.40566960 -0.31763573
-0.41544477 -0.31310647
-0.42521994 -0.30800389
-0.43499511 -0.30232798
-0.44477028 -0.29607875
-0.45454545 -0.28925620
-0.46432063 -0.28186032
-0.47409580 -0.27389112
-0.48387097 -0.26534860
-0.49364614 -0.25623275
-0.50342131 -0.24654357
-0.51319648 -0.23628108
-0.52297165 -0.22544526
-0.53274682 -0.21403611
-0.54252199 -0.20205365
-0.55229717 -0.18949785
-0.56207234 -0.17636874
-0.57184751 -0.16266630
-0.58162268 -0.14839054
-0.59139785 -0.13354145
-0.60117302 -0.11811904
-0.61094819 -0.10212330
-0.62072336 -0.08555425
-0.63049853 -0.06841186
-0.64027370 -0.05069616
-0.65004888 -0.03240713
-0.65982405 -0.01354478
-0.66959922 0.00589090
-0.67937439 0.02589990
-0.68914956 0.04648223
-0.69892473 0.06763788
-0.70869990 0.08936685
-0.71847507 0.11166915
-0.72825024 0.13454477
-0.73802542 0.15799371
-0.74780059 0.18201598
-0.75757576 0.20661157
-0.76735093 0.23178049
-0.77712610 0.25752273
-0.78690127 0.28383829
-0.79667644 0.31072718
-0.80645161 0.33818939
-0.81622678 0.36622492
-0.82600196 0.39483378
-0.83577713 0.42401596
-0.84555230 0.45377147
-0.85532747 0.48410030
-0.86510264 0.51500245
-0.87487781 0.54647793
-0.88465298 0.57852673
-0.89442815 0.61114885
-0.90420332 0.64434430
-0.91397849 0.67811308
-0.92375367 0.71245517
-0.93352884 0.74737059
-0.94330401 0.78285934
-0.95307918 0.81892141
-0.96285435 0.85555680
-0.97262952 0.89276551
-0.98240469 0.93054755
-0.99217986 0.96890292
-1.00195503 0.99612433
-1.01173021 0.97777797
-1.02150538 0.96115158
-1.03128055 0.94624516
-1.04105572 0.93305871
-1.05083089 0.92159223
-1.06060606 0.91184573
-1.07038123 0.90381920
-1.08015640 0.89751263
-1.08993157 0.89292604
-1.09970674 0.89005943
-1.10948192 0.88891278
-1.11925709 0.88948610
-1.12903226 0.89177940
-1.13880743 0.89579266
-1.14858260 0.90152590
-1.15835777 0.90897911
-1.16813294 0.91815229
-1.17790811 0.92904544
-1.18768328 0.94165857
-1.19745846 0.95599166
-1.20723363 0.97204473
-1.21700880 0.98981777
-1.22678397 1.00931078
-1.23655914 1.03052376
-1.24633431 1.05345671
-1.25610948 1.07810964
-1.26588465 1.10448253
-1.27565982 1.13257540
-1.28543500 1.16238824
-1.29521017 1.19392105
-1.30498534 1.22717383
-1.31476051 1.26214658
-1.32453568 1.29883931
-1.33431085 1.33725200
-1.34408602 1.37738467
-1.35386119 1.41923731
-1.36363636 1.46280992
-1.37341153 1.50810250
-1.38318671 1.55511505
-1.39296188 1.60384758
-1.40273705 1.65430007
-1.41251222 1.70647254
-1.42228739 1.76036498
-1.43206256 1.81597739
-1.44183773 1.87330977
-1.45161290 1.93236212
-1.46138807 1.99313445
-1.47116325 2.05562674
-1.48093842 2.11983901
-1.49071359 2.18577125
-1.50048876 2.25342346
-1.51026393 2.32279564
-1.52003910 2.39388779
-1.52981427 2.46669992
-1.53958944 2.54123202
-1.54936461 2.61748408
-1.55913978 2.69545612
-1.56891496 2.77514813
-1.57869013 2.85656011
-1.58846530 2.93969207
-1.59824047 3.02454399
-1.60801564 3.11111589
-1.61779081 3.19940776
-1.62756598 3.28941960
-1.63734115 3.38115141
-1.64711632 3.47460319
-1.65689150 3.56977494
-1.66666667 3.66666667
-1.67644184 3.76527836
-1.68621701 3.86561003
-1.69599218 3.96766167
-1.70576735 4.07143328
-1.71554252 4.17692486
-1.72531769 4.28413642
-1.73509286 4.39306794
-1.74486804 4.50371944
-1.75464321 4.61609091
-1.76441838 4.73018235
-1.77419355 4.84599376
-1.78396872 4.96352514
-1.79374389 5.08277649
-1.80351906 5.20374782
-1.81329423 5.32643911
-1.82306940 5.45085038
-1.83284457 5.57698162
-1.84261975 5.70483283
-1.85239492 5.83440402
-1.86217009 5.96569517
-1.87194526 6.09870629
-1.88172043 6.23343739
-1.89149560 6.36988846
-1.90127077 6.50805950
-1.91104594 6.64795051
-1.92082111 6.78956149
-1.93059629 6.93289245
-1.94037146 7.07794337
-1.95014663 7.22471427
-1.95992180 7.37320514
-1.96969697 7.52341598
-1.97947214 7.67534679
-1.98924731 7.82899757
-1.99902248 7.98436833
-2.00879765 8.03635160
-2.01857283 8.07946555
-2.02834800 8.12544612
-2.03812317 8.17429331
-2.04789834 8.22600711
-2.05767351 8.28058754
-2.06744868 8.33803459
-2.07722385 8.39834825
-2.08699902 8.46152854
-2.09677419 8.52757544
-2.10654936 8.59648896
-2.11632454 8.66826911
-2.12609971 8.74291587
-2.13587488 8.82042925
-2.14565005 8.90080925
-2.15542522 8.98405586
-2.16520039 9.07016910
-2.17497556 9.15914896
-2.18475073 9.25099543
-2.19452590 9.34570853
-2.20430108 9.44328824
-2.21407625 9.54373457
-2.22385142 9.64704753
-2.23362659 9.75322710
-2.24340176 9.86227329
-2.25317693 9.97418610
-2.26295210 10.08896552
-2.27272727 10.20661157
-2.28250244 10.32712424
-2.29227761 10.45050352
-2.30205279 10.57674943
-2.31182796 10.70586195
-2.32160313 10.83784109
-2.33137830 10.97268685
-2.34115347 11.11039923
-2.35092864 11.25097823
-2.36070381 11.39442385
-2.37047898 11.54073609
-2.38025415 11.68991495
-2.39002933 11.84196042
-2.39980450 11.99687252
-2.40957967 12.15465123
-2.41935484 12.31529657
-2.42913001 12.47880852
-2.43890518 12.64518709
-2.44868035 12.81443228
-2.45845552 12.98654409
-2.46823069 13.16152252
-2.47800587 13.33936757
-2.48778104 13.52007923
-2.49755621 13.70365752
-2.50733138 13.89010242
-2.51710655 14.07941395
-2.52688172 14.27159209
-2.53665689 14.46663685
-2.54643206 14.66454824
-2.55620723 14.86532624
-2.56598240 15.06897086
-2.57575758 15.27548209
-2.58553275 15.48485995
-2.59530792 15.69710443
-2.60508309 15.91221552
-2.61485826 16.13019324
-2.62463343 16.35103757
-2.63440860 16.57474853
-2.64418377 16.80132610
-2.65395894 17.03077029
-2.66373412 17.26308110
-2.67350929 17.49825853
-2.68328446 17.73630258
-2.69305963 17.97721324
-2.70283480 18.22099053
-2.71260997 18.46763444
-2.72238514 18.71714496
-2.73216031 18.96952211
-2.74193548 19.22476587
-2.75171065 19.48287625
-2.76148583 19.74385325
-2.77126100 20.00769687
-2.78103617 20.27440711
-2.79081134 20.54398397
-2.80058651 20.81642745
-2.81036168 21.09173754
-2.82013685 21.36991426
-2.82991202 21.65095759
-2.83968719 21.93486755
-2.84946237 22.22164412
-2.85923754 22.51128731
-2.86901271 22.80379712
-2.87878788 23.09917355
-2.88856305 23.39741660
-2.89833822 23.69852627
-2.90811339 24.00250256
-2.91788856 24.30934546
-2.92766373 24.61905499
-2.93743891 24.93163113
-2.94721408 25.24707390
-2.95698925 25.56538328
-2.96676442 25.88655928
-2.97653959 26.21060190
-2.98631476 26.53751114
-2.99608993 26.86728700
-3.00586510 27.09456403
-3.01564027 27.25538136
-3.02541544 27.42021196
-3.03519062 27.58905582
-3.04496579 27.76191295
-3.05474096 27.93878335
-3.06451613 28.11966701
-3.07429130 28.30456394
-3.08406647 28.49347414
-3.09384164 28.68639761
-3.10361681 28.88333434
-3.11339198 29.08428433
-3.12316716 29.28924760
-3.13294233 29.49822413
-3.14271750 29.71121393
-3.15249267 29.92821699
-3.16226784 30.14923332
-3.17204301 30.37426292
-3.18181818 30.60330579
-3.19159335 30.83636192
-3.20136852 31.07343131
-3.21114370 31.31451398
-3.22091887 31.55960991
-3.23069404 31.80871911
-3.24046921 32.06184157
-3.25024438 32.31897730
-3.26001955 32.58012630
-3.26979472 32.84528857
-3.27956989 33.11446410
-3.28934506 33.38765290
-3.29912023 33.66485496
-3.30889541 33.94607030
-3.31867058 34.23129889
-3.32844575 34.52054076
-3.33822092 34.81379589
-3.34799609 35.11106429
-3.35777126 35.41234596
-3.36754643 35.71764089
-3.37732160 36.02694909
-3.38709677 36.34027055
-3.39687195 36.65760528
-3.40664712 36.97895328
-3.41642229 37.30431455
-3.42619746 37.63368908
-3.43597263 37.96707688
-3.44574780 38.30447795
-3.45552297 38.64589228
-3.46529814 38.99131988
-3.47507331 39.34076074
-3.48484848 39.69421488
-3.49462366 40.05168228
-3.50439883 40.41316294
-3.51417400 40.77865687
-3.52394917 41.14816407
-3.53372434 41.52168454
-3.54349951 41.89921827
-3.55327468 42.28076527
-3.56304985 42.66632554
-3.57282502 43.05589907
-3.58260020 43.44948587
-3.59237537 43.84708594
-3.60215054 44.24869927
-3.61192571 44.65432587
-3.62170088 45.06396574
-3.63147605 45.47761887
-3.64125122 45.89528527
-3.65102639 46.31696494
-3.66080156 46.74265787
-3.67057674 47.17236407
-3.68035191 47.60608354
-3.69012708 48.04381627
-3.69990225 48.48556227
-3.70967742 48.93132154
-3.71945259 49.38109407
-3.72922776 49.83487987
-3.73900293 50.29267894
-3.74877810 50.75449128
-3.75855327 51.22031688
-3.76832845 51.69015574
-3.77810362 52.16400788
-3.78787879 52.64187328
-3.79765396 53.12375195
-3.80742913 53.60964388
-3.81720430 54.09954908
-3.82697947 54.59346755
-3.83675464 55.09139928
-3.84652981 55.59334428
-3.85630499 56.09930255
-3.86608016 56.60927409
-3.87585533 57.12325889
-3.88563050 57.64125696
-3.89540567 58.16326829
-3.90518084 58.68929289
-3.91495601 59.21933076
-3.92473118 59.75338189
-3.93450635 60.29144630
-3.94428152 60.83352396
-3.95405670 61.37961490
-3.96383187 61.92971910
-3.97360704 62.48383657
-3.98338221 63.04196730
-3.99315738 63.60411131
-4.00293255 64.09993894
-4.01270772 64.43642269
-4.02248289 64.77806635
-4.03225806 65.12486993
-4.04203324 65.47683342
-4.05180841 65.83395682
-4.06158358 66.19624014
-4.07135875 66.56368338
-4.08113392 66.93628652
-4.09090909 67.31404959
-4.10068426 67.69697256
-4.11045943 68.08505545
-4.12023460 68.47829826
-4.13000978 68.87670098
-4.13978495 69.28026361
-4.14956012 69.68898616
-4.15933529 70.10286863
-4.16911046 70.52191100
-4.17888563 70.94611329
-4.18866080 71.37547550
-4.19843597 71.80999762
-4.20821114 72.24967966
-4.21798631 72.69452160
-4.22776149 73.14452347
-4.23753666 73.59968525
-4.24731183 74.06000694
-4.25708700 74.52548854
-4.26686217 74.99613006
-4.27663734 75.47193150
-4.28641251 75.95289285
-4.29618768 76.43901411
-4.30596285 76.93029529
-4.31573803 77.42673638
-4.32551320 77.92833739
-4.33528837 78.43509831
-4.34506354 78.94701915
-4.35483871 79.46409990
-4.36461388 79.98634056
-4.37438905 80.51374114
-4.38416422 81.04630163
-4.39393939 81.58402204
-4.40371457 82.12690236
-4.41348974 82.67494260
-4.42326491 83.22814275
-4.43304008 83.78650281
-4.44281525 84.35002279
-4.45259042 84.91870268
-4.46236559 85.49254249
-4.47214076 86.07154221
-4.48191593 86.65570185
-4.49169110 87.24502140
-4.50146628 87.83950086
-4.51124145 88.43914024
-4.52101662 89.04393954
-4.53079179 89.65389875
-4.54056696 90.26901787
-4.55034213 90.88929690
-4.56011730 91.51473586
-4.56989247 92.14533472
-4.57966764 92.78109350
-4.58944282 93.42201219
-4.59921799 94.06809080
-4.60899316 94.71932933
-4.61876833 95.37572776
-4.62854350 96.03728611
-4.63831867 96.70400438
-4.64809384 97.37588256
-4.65786901 98.05292065
-4.66764418 98.73511866
-4.67741935 99.42247659
-4.68719453 100.11499442
-4.69696970 100.81267218
-4.70674487 101.51550984
-4.71652004 102.22350742
-4.72629521 102.93666492
-4.73607038 103.65498233
-4.74584555 104.37845965
-4.75562072 105.10709689
-4.76539589 105.84089404
-4.77517107 106.57985111
-4.78494624 107.32396809
-4.79472141 108.07324498
-4.80449658 108.82768179
-4.81427175 109.58727852
-4.82404692 110.35203516
-4.83382209 111.12195171
-4.84359726 111.89702818
-4.85337243 112.67726456
-4.86314761 113.46266085
-4.87292278 114.25321706
-4.88269795 115.04893319
-4.89247312 115.84980923
-4.90224829 116.65584518
-4.91202346 117.46704105
-4.92179863 118.28339683
-4.93157380 119.10491253
-4.94134897 119.93158814
-4.95112414 120.76342366
-4.96089932 121.60041910
-4.97067449 122.44257445
-4.98044966 123.28988972
-4.99022483 124.14236490
-5.00000000 125.00000000
+X ApproxXCubed
+-5.000000000 -125.000000000
+-4.990224829 -124.142364903
+-4.980449658 -123.289889721
+-4.970674487 -122.442574453
+-4.960899316 -121.600419100
+-4.951124145 -120.763423661
+-4.941348974 -119.931588136
+-4.931573803 -119.104912525
+-4.921798631 -118.283396829
+-4.912023460 -117.467041047
+-4.902248289 -116.655845180
+-4.892473118 -115.849809227
+-4.882697947 -115.048933188
+-4.872922776 -114.253217063
+-4.863147605 -113.462660853
+-4.853372434 -112.677264557
+-4.843597263 -111.897028176
+-4.833822092 -111.121951709
+-4.824046921 -110.352035156
+-4.814271750 -109.587278518
+-4.804496579 -108.827681794
+-4.794721408 -108.073244984
+-4.784946237 -107.323968089
+-4.775171065 -106.579851108
+-4.765395894 -105.840894041
+-4.755620723 -105.107096889
+-4.745845552 -104.378459651
+-4.736070381 -103.654982327
+-4.726295210 -102.936664918
+-4.716520039 -102.223507423
+-4.706744868 -101.515509843
+-4.696969697 -100.812672176
+-4.687194526 -100.114994424
+-4.677419355 -99.422476587
+-4.667644184 -98.735118664
+-4.657869013 -98.052920655
+-4.648093842 -97.375882560
+-4.638318671 -96.704004380
+-4.628543500 -96.037286114
+-4.618768328 -95.375727763
+-4.608993157 -94.719329326
+-4.599217986 -94.068090803
+-4.589442815 -93.422012195
+-4.579667644 -92.781093501
+-4.569892473 -92.145334721
+-4.560117302 -91.514735855
+-4.550342131 -90.889296904
+-4.540566960 -90.269017868
+-4.530791789 -89.653898745
+-4.521016618 -89.043939537
+-4.511241447 -88.439140244
+-4.501466276 -87.839500864
+-4.491691105 -87.245021399
+-4.481915934 -86.655701849
+-4.472140762 -86.071542212
+-4.462365591 -85.492542490
+-4.452590420 -84.918702683
+-4.442815249 -84.350022790
+-4.433040078 -83.786502811
+-4.423264907 -83.228142746
+-4.413489736 -82.674942596
+-4.403714565 -82.126902360
+-4.393939394 -81.584022039
+-4.384164223 -81.046301631
+-4.374389052 -80.513741139
+-4.364613881 -79.986340560
+-4.354838710 -79.464099896
+-4.345063539 -78.947019146
+-4.335288368 -78.435098311
+-4.325513196 -77.928337390
+-4.315738025 -77.426736383
+-4.305962854 -76.930295290
+-4.296187683 -76.439014112
+-4.286412512 -75.952892849
+-4.276637341 -75.471931499
+-4.266862170 -74.996130064
+-4.257086999 -74.525488544
+-4.247311828 -74.060006937
+-4.237536657 -73.599685245
+-4.227761486 -73.144523468
+-4.217986315 -72.694521604
+-4.208211144 -72.249679655
+-4.198435973 -71.809997621
+-4.188660802 -71.375475500
+-4.178885630 -70.946113295
+-4.169110459 -70.521911003
+-4.159335288 -70.102868626
+-4.149560117 -69.688986163
+-4.139784946 -69.280263614
+-4.130009775 -68.876700980
+-4.120234604 -68.478298260
+-4.110459433 -68.085055455
+-4.100684262 -67.696972564
+-4.090909091 -67.314049587
+-4.081133920 -66.936286524
+-4.071358749 -66.563683376
+-4.061583578 -66.196240142
+-4.051808407 -65.833956823
+-4.042033236 -65.476833418
+-4.032258065 -65.124869927
+-4.022482893 -64.778066351
+-4.012707722 -64.436422689
+-4.002932551 -64.099938941
+-3.993157380 -63.604111305
+-3.983382209 -63.041967303
+-3.973607038 -62.483836568
+-3.963831867 -61.929719100
+-3.954056696 -61.379614898
+-3.944281525 -60.833523964
+-3.934506354 -60.291446295
+-3.924731183 -59.753381894
+-3.914956012 -59.219330759
+-3.905180841 -58.689292891
+-3.895405670 -58.163268290
+-3.885630499 -57.641256955
+-3.875855327 -57.123258887
+-3.866080156 -56.609274086
+-3.856304985 -56.099302552
+-3.846529814 -55.593344284
+-3.836754643 -55.091399283
+-3.826979472 -54.593467548
+-3.817204301 -54.099549081
+-3.807429130 -53.609643880
+-3.797653959 -53.123751946
+-3.787878788 -52.641873278
+-3.778103617 -52.164007877
+-3.768328446 -51.690155743
+-3.758553275 -51.220316876
+-3.748778104 -50.754491275
+-3.739002933 -50.292678942
+-3.729227761 -49.834879874
+-3.719452590 -49.381094074
+-3.709677419 -48.931321540
+-3.699902248 -48.485562273
+-3.690127077 -48.043816273
+-3.680351906 -47.606083539
+-3.670576735 -47.172364072
+-3.660801564 -46.742657872
+-3.651026393 -46.316964938
+-3.641251222 -45.895285272
+-3.631476051 -45.477618872
+-3.621700880 -45.063965738
+-3.611925709 -44.654325872
+-3.602150538 -44.248699272
+-3.592375367 -43.847085938
+-3.582600196 -43.449485872
+-3.572825024 -43.055899072
+-3.563049853 -42.666325539
+-3.553274682 -42.280765273
+-3.543499511 -41.899218273
+-3.533724340 -41.521684540
+-3.523949169 -41.148164074
+-3.514173998 -40.778656874
+-3.504398827 -40.413162941
+-3.494623656 -40.051682275
+-3.484848485 -39.694214876
+-3.475073314 -39.340760743
+-3.465298143 -38.991319877
+-3.455522972 -38.645892278
+-3.445747801 -38.304477946
+-3.435972630 -37.967076880
+-3.426197458 -37.633689081
+-3.416422287 -37.304314548
+-3.406647116 -36.978953283
+-3.396871945 -36.657605284
+-3.387096774 -36.340270552
+-3.377321603 -36.026949086
+-3.367546432 -35.717640887
+-3.357771261 -35.412345955
+-3.347996090 -35.111064290
+-3.338220919 -34.813795891
+-3.328445748 -34.520540759
+-3.318670577 -34.231298894
+-3.308895406 -33.946070295
+-3.299120235 -33.664854963
+-3.289345064 -33.387652898
+-3.279569892 -33.114464100
+-3.269794721 -32.845288568
+-3.260019550 -32.580126303
+-3.250244379 -32.318977305
+-3.240469208 -32.061841573
+-3.230694037 -31.808719109
+-3.220918866 -31.559609910
+-3.211143695 -31.314513979
+-3.201368524 -31.073431314
+-3.191593353 -30.836361916
+-3.181818182 -30.603305785
+-3.172043011 -30.374262921
+-3.162267840 -30.149233323
+-3.152492669 -29.928216992
+-3.142717498 -29.711213927
+-3.132942326 -29.498224129
+-3.123167155 -29.289247598
+-3.113391984 -29.084284334
+-3.103616813 -28.883334337
+-3.093841642 -28.686397606
+-3.084066471 -28.493474142
+-3.074291300 -28.304563944
+-3.064516129 -28.119667014
+-3.054740958 -27.938783350
+-3.044965787 -27.761912952
+-3.035190616 -27.589055822
+-3.025415445 -27.420211958
+-3.015640274 -27.255381361
+-3.005865103 -27.094564030
+-2.996089932 -26.867287003
+-2.986314761 -26.537511144
+-2.976539589 -26.210601904
+-2.966764418 -25.886559283
+-2.956989247 -25.565383281
+-2.947214076 -25.247073899
+-2.937438905 -24.931631135
+-2.927663734 -24.619054990
+-2.917888563 -24.309345465
+-2.908113392 -24.002502558
+-2.898338221 -23.698526271
+-2.888563050 -23.397416603
+-2.878787879 -23.099173554
+-2.869012708 -22.803797124
+-2.859237537 -22.511287313
+-2.849462366 -22.221644121
+-2.839687195 -21.934867548
+-2.829912023 -21.650957594
+-2.820136852 -21.369914259
+-2.810361681 -21.091737544
+-2.800586510 -20.816427447
+-2.790811339 -20.543983970
+-2.781036168 -20.274407112
+-2.771260997 -20.007696872
+-2.761485826 -19.743853252
+-2.751710655 -19.482876251
+-2.741935484 -19.224765869
+-2.732160313 -18.969522106
+-2.722385142 -18.717144962
+-2.712609971 -18.467634437
+-2.702834800 -18.220990532
+-2.693059629 -17.977213245
+-2.683284457 -17.736302577
+-2.673509286 -17.498258529
+-2.663734115 -17.263081100
+-2.653958944 -17.030770289
+-2.644183773 -16.801326098
+-2.634408602 -16.574748526
+-2.624633431 -16.351037573
+-2.614858260 -16.130193239
+-2.605083089 -15.912215524
+-2.595307918 -15.697104428
+-2.585532747 -15.484859951
+-2.575757576 -15.275482094
+-2.565982405 -15.068970855
+-2.556207234 -14.865326236
+-2.546432063 -14.664548235
+-2.536656891 -14.466636854
+-2.526881720 -14.271592092
+-2.517106549 -14.079413948
+-2.507331378 -13.890102424
+-2.497556207 -13.703657519
+-2.487781036 -13.520079233
+-2.478005865 -13.339367566
+-2.468230694 -13.161522519
+-2.458455523 -12.986544090
+-2.448680352 -12.814432280
+-2.438905181 -12.645187090
+-2.429130010 -12.478808518
+-2.419354839 -12.315296566
+-2.409579668 -12.154651233
+-2.399804497 -11.996872519
+-2.390029326 -11.841960423
+-2.380254154 -11.689914947
+-2.370478983 -11.540736090
+-2.360703812 -11.394423853
+-2.350928641 -11.250978234
+-2.341153470 -11.110399234
+-2.331378299 -10.972686853
+-2.321603128 -10.837841092
+-2.311827957 -10.705861949
+-2.302052786 -10.576749426
+-2.292277615 -10.450503522
+-2.282502444 -10.327124236
+-2.272727273 -10.206611570
+-2.262952102 -10.088965523
+-2.253176931 -9.974186095
+-2.243401760 -9.862273286
+-2.233626588 -9.753227096
+-2.223851417 -9.647047526
+-2.214076246 -9.543734574
+-2.204301075 -9.443288241
+-2.194525904 -9.345708528
+-2.184750733 -9.250995433
+-2.174975562 -9.159148958
+-2.165200391 -9.070169102
+-2.155425220 -8.984055865
+-2.145650049 -8.900809247
+-2.135874878 -8.820429248
+-2.126099707 -8.742915868
+-2.116324536 -8.668269107
+-2.106549365 -8.596488965
+-2.096774194 -8.527575442
+-2.086999022 -8.461528539
+-2.077223851 -8.398348254
+-2.067448680 -8.338034589
+-2.057673509 -8.280587542
+-2.047898338 -8.226007115
+-2.038123167 -8.174293307
+-2.028347996 -8.125446118
+-2.018572825 -8.079465548
+-2.008797654 -8.036351597
+-1.999022483 -7.984368326
+-1.989247312 -7.828997572
+-1.979472141 -7.675346789
+-1.969696970 -7.523415978
+-1.959921799 -7.373205138
+-1.950146628 -7.224714270
+-1.940371457 -7.077943373
+-1.930596285 -6.932892447
+-1.920821114 -6.789561493
+-1.911045943 -6.647950511
+-1.901270772 -6.508059500
+-1.891495601 -6.369888460
+-1.881720430 -6.233437392
+-1.871945259 -6.098706295
+-1.862170088 -5.965695169
+-1.852394917 -5.834404016
+-1.842619746 -5.704832833
+-1.832844575 -5.576981622
+-1.823069404 -5.450850383
+-1.813294233 -5.326439114
+-1.803519062 -5.203747818
+-1.793743891 -5.082776493
+-1.783968719 -4.963525139
+-1.774193548 -4.845993757
+-1.764418377 -4.730182346
+-1.754643206 -4.616090906
+-1.744868035 -4.503719438
+-1.735092864 -4.393067942
+-1.725317693 -4.284136417
+-1.715542522 -4.176924863
+-1.705767351 -4.071433281
+-1.695992180 -3.967661670
+-1.686217009 -3.865610031
+-1.676441838 -3.765278363
+-1.666666667 -3.666666667
+-1.656891496 -3.569774942
+-1.647116325 -3.474603188
+-1.637341153 -3.381151406
+-1.627565982 -3.289419596
+-1.617790811 -3.199407756
+-1.608015640 -3.111115889
+-1.598240469 -3.024543993
+-1.588465298 -2.939692068
+-1.578690127 -2.856560114
+-1.568914956 -2.775148133
+-1.559139785 -2.695456122
+-1.549364614 -2.617484083
+-1.539589443 -2.541232016
+-1.529814272 -2.466699919
+-1.520039101 -2.393887795
+-1.510263930 -2.322795642
+-1.500488759 -2.253423460
+-1.490713587 -2.185771250
+-1.480938416 -2.119839011
+-1.471163245 -2.055626743
+-1.461388074 -1.993134447
+-1.451612903 -1.932362123
+-1.441837732 -1.873309770
+-1.432062561 -1.815977388
+-1.422287390 -1.760364978
+-1.412512219 -1.706472539
+-1.402737048 -1.654300072
+-1.392961877 -1.603847576
+-1.383186706 -1.555115052
+-1.373411535 -1.508102499
+-1.363636364 -1.462809917
+-1.353861193 -1.419237307
+-1.344086022 -1.377384669
+-1.334310850 -1.337252002
+-1.324535679 -1.298839306
+-1.314760508 -1.262146582
+-1.304985337 -1.227173829
+-1.295210166 -1.193921048
+-1.285434995 -1.162388238
+-1.275659824 -1.132575399
+-1.265884653 -1.104482532
+-1.256109482 -1.078109637
+-1.246334311 -1.053456713
+-1.236559140 -1.030523760
+-1.226783969 -1.009310779
+-1.217008798 -0.989817769
+-1.207233627 -0.972044731
+-1.197458456 -0.955991664
+-1.187683284 -0.941658568
+-1.177908113 -0.929045445
+-1.168132942 -0.918152292
+-1.158357771 -0.908979111
+-1.148582600 -0.901525901
+-1.138807429 -0.895792663
+-1.129032258 -0.891779396
+-1.119257087 -0.889486101
+-1.109481916 -0.888912777
+-1.099706745 -0.890059425
+-1.089931574 -0.892926044
+-1.080156403 -0.897512635
+-1.070381232 -0.903819197
+-1.060606061 -0.911845730
+-1.050830890 -0.921592235
+-1.041055718 -0.933058711
+-1.031280547 -0.946245159
+-1.021505376 -0.961151578
+-1.011730205 -0.977777969
+-1.001955034 -0.996124331
+-0.992179863 -0.968902916
+-0.982404692 -0.930547553
+-0.972629521 -0.892765513
+-0.962854350 -0.855556798
+-0.953079179 -0.818921406
+-0.943304008 -0.782859338
+-0.933528837 -0.747370594
+-0.923753666 -0.712455173
+-0.913978495 -0.678113077
+-0.904203324 -0.644344304
+-0.894428152 -0.611148855
+-0.884652981 -0.578526730
+-0.874877810 -0.546477928
+-0.865102639 -0.515002451
+-0.855327468 -0.484100297
+-0.845552297 -0.453771467
+-0.835777126 -0.424015961
+-0.826001955 -0.394833779
+-0.816226784 -0.366224921
+-0.806451613 -0.338189386
+-0.796676442 -0.310727175
+-0.786901271 -0.283838288
+-0.777126100 -0.257522725
+-0.767350929 -0.231780486
+-0.757575758 -0.206611570
+-0.747800587 -0.182015979
+-0.738025415 -0.157993711
+-0.728250244 -0.134544767
+-0.718475073 -0.111669146
+-0.708699902 -0.089366850
+-0.698924731 -0.067637877
+-0.689149560 -0.046482228
+-0.679374389 -0.025899903
+-0.669599218 -0.005890902
+-0.659824047 0.013544775
+-0.650048876 0.032407129
+-0.640273705 0.050696158
+-0.630498534 0.068411864
+-0.620723363 0.085554246
+-0.610948192 0.102123305
+-0.601173021 0.118119039
+-0.591397849 0.133541450
+-0.581622678 0.148390537
+-0.571847507 0.162666300
+-0.562072336 0.176368739
+-0.552297165 0.189497854
+-0.542521994 0.202053646
+-0.532746823 0.214036114
+-0.522971652 0.225445258
+-0.513196481 0.236281078
+-0.503421310 0.246543574
+-0.493646139 0.256232747
+-0.483870968 0.265348595
+-0.474095797 0.273891120
+-0.464320626 0.281860321
+-0.454545455 0.289256198
+-0.444770283 0.296078752
+-0.434995112 0.302327981
+-0.425219941 0.308003887
+-0.415444770 0.313106469
+-0.405669599 0.317635727
+-0.395894428 0.321591662
+-0.386119257 0.324974272
+-0.376344086 0.327783559
+-0.366568915 0.330019522
+-0.356793744 0.331682161
+-0.347018573 0.332771476
+-0.337243402 0.333287467
+-0.327468231 0.333230135
+-0.317693060 0.332599479
+-0.307917889 0.331395499
+-0.298142717 0.329618195
+-0.288367546 0.327267567
+-0.278592375 0.324343616
+-0.268817204 0.320846341
+-0.259042033 0.316775742
+-0.249266862 0.312131819
+-0.239491691 0.306914572
+-0.229716520 0.301124001
+-0.219941349 0.294760107
+-0.210166178 0.287822889
+-0.200391007 0.280312347
+-0.190615836 0.272228481
+-0.180840665 0.263571291
+-0.171065494 0.254340778
+-0.161290323 0.244536941
+-0.151515152 0.234159780
+-0.141739980 0.223209295
+-0.131964809 0.211685486
+-0.122189638 0.199588353
+-0.112414467 0.186917897
+-0.102639296 0.173674117
+-0.092864125 0.159857013
+-0.083088954 0.145466585
+-0.073313783 0.130502834
+-0.063538612 0.114965758
+-0.053763441 0.098855359
+-0.043988270 0.082171636
+-0.034213099 0.064914589
+-0.024437928 0.047084218
+-0.014662757 0.028680524
+-0.004887586 0.009703506
+0.004887586 -0.009703506
+0.014662757 -0.028680524
+0.024437928 -0.047084218
+0.034213099 -0.064914589
+0.043988270 -0.082171636
+0.053763441 -0.098855359
+0.063538612 -0.114965758
+0.073313783 -0.130502834
+0.083088954 -0.145466585
+0.092864125 -0.159857013
+0.102639296 -0.173674117
+0.112414467 -0.186917897
+0.122189638 -0.199588353
+0.131964809 -0.211685486
+0.141739980 -0.223209295
+0.151515152 -0.234159780
+0.161290323 -0.244536941
+0.171065494 -0.254340778
+0.180840665 -0.263571291
+0.190615836 -0.272228481
+0.200391007 -0.280312347
+0.210166178 -0.287822889
+0.219941349 -0.294760107
+0.229716520 -0.301124001
+0.239491691 -0.306914572
+0.249266862 -0.312131819
+0.259042033 -0.316775742
+0.268817204 -0.320846341
+0.278592375 -0.324343616
+0.288367546 -0.327267567
+0.298142717 -0.329618195
+0.307917889 -0.331395499
+0.317693060 -0.332599479
+0.327468231 -0.333230135
+0.337243402 -0.333287467
+0.347018573 -0.332771476
+0.356793744 -0.331682161
+0.366568915 -0.330019522
+0.376344086 -0.327783559
+0.386119257 -0.324974272
+0.395894428 -0.321591662
+0.405669599 -0.317635727
+0.415444770 -0.313106469
+0.425219941 -0.308003887
+0.434995112 -0.302327981
+0.444770283 -0.296078752
+0.454545455 -0.289256198
+0.464320626 -0.281860321
+0.474095797 -0.273891120
+0.483870968 -0.265348595
+0.493646139 -0.256232747
+0.503421310 -0.246543574
+0.513196481 -0.236281078
+0.522971652 -0.225445258
+0.532746823 -0.214036114
+0.542521994 -0.202053646
+0.552297165 -0.189497854
+0.562072336 -0.176368739
+0.571847507 -0.162666300
+0.581622678 -0.148390537
+0.591397849 -0.133541450
+0.601173021 -0.118119039
+0.610948192 -0.102123305
+0.620723363 -0.085554246
+0.630498534 -0.068411864
+0.640273705 -0.050696158
+0.650048876 -0.032407129
+0.659824047 -0.013544775
+0.669599218 0.005890902
+0.679374389 0.025899903
+0.689149560 0.046482228
+0.698924731 0.067637877
+0.708699902 0.089366850
+0.718475073 0.111669146
+0.728250244 0.134544767
+0.738025415 0.157993711
+0.747800587 0.182015979
+0.757575758 0.206611570
+0.767350929 0.231780486
+0.777126100 0.257522725
+0.786901271 0.283838288
+0.796676442 0.310727175
+0.806451613 0.338189386
+0.816226784 0.366224921
+0.826001955 0.394833779
+0.835777126 0.424015961
+0.845552297 0.453771467
+0.855327468 0.484100297
+0.865102639 0.515002451
+0.874877810 0.546477928
+0.884652981 0.578526730
+0.894428152 0.611148855
+0.904203324 0.644344304
+0.913978495 0.678113077
+0.923753666 0.712455173
+0.933528837 0.747370594
+0.943304008 0.782859338
+0.953079179 0.818921406
+0.962854350 0.855556798
+0.972629521 0.892765513
+0.982404692 0.930547553
+0.992179863 0.968902916
+1.001955034 0.996124331
+1.011730205 0.977777969
+1.021505376 0.961151578
+1.031280547 0.946245159
+1.041055718 0.933058711
+1.050830890 0.921592235
+1.060606061 0.911845730
+1.070381232 0.903819197
+1.080156403 0.897512635
+1.089931574 0.892926044
+1.099706745 0.890059425
+1.109481916 0.888912777
+1.119257087 0.889486101
+1.129032258 0.891779396
+1.138807429 0.895792663
+1.148582600 0.901525901
+1.158357771 0.908979111
+1.168132942 0.918152292
+1.177908113 0.929045445
+1.187683284 0.941658568
+1.197458456 0.955991664
+1.207233627 0.972044731
+1.217008798 0.989817769
+1.226783969 1.009310779
+1.236559140 1.030523760
+1.246334311 1.053456713
+1.256109482 1.078109637
+1.265884653 1.104482532
+1.275659824 1.132575399
+1.285434995 1.162388238
+1.295210166 1.193921048
+1.304985337 1.227173829
+1.314760508 1.262146582
+1.324535679 1.298839306
+1.334310850 1.337252002
+1.344086022 1.377384669
+1.353861193 1.419237307
+1.363636364 1.462809917
+1.373411535 1.508102499
+1.383186706 1.555115052
+1.392961877 1.603847576
+1.402737048 1.654300072
+1.412512219 1.706472539
+1.422287390 1.760364978
+1.432062561 1.815977388
+1.441837732 1.873309770
+1.451612903 1.932362123
+1.461388074 1.993134447
+1.471163245 2.055626743
+1.480938416 2.119839011
+1.490713587 2.185771250
+1.500488759 2.253423460
+1.510263930 2.322795642
+1.520039101 2.393887795
+1.529814272 2.466699919
+1.539589443 2.541232016
+1.549364614 2.617484083
+1.559139785 2.695456122
+1.568914956 2.775148133
+1.578690127 2.856560114
+1.588465298 2.939692068
+1.598240469 3.024543993
+1.608015640 3.111115889
+1.617790811 3.199407756
+1.627565982 3.289419596
+1.637341153 3.381151406
+1.647116325 3.474603188
+1.656891496 3.569774942
+1.666666667 3.666666667
+1.676441838 3.765278363
+1.686217009 3.865610031
+1.695992180 3.967661670
+1.705767351 4.071433281
+1.715542522 4.176924863
+1.725317693 4.284136417
+1.735092864 4.393067942
+1.744868035 4.503719438
+1.754643206 4.616090906
+1.764418377 4.730182346
+1.774193548 4.845993757
+1.783968719 4.963525139
+1.793743891 5.082776493
+1.803519062 5.203747818
+1.813294233 5.326439114
+1.823069404 5.450850383
+1.832844575 5.576981622
+1.842619746 5.704832833
+1.852394917 5.834404016
+1.862170088 5.965695169
+1.871945259 6.098706295
+1.881720430 6.233437392
+1.891495601 6.369888460
+1.901270772 6.508059500
+1.911045943 6.647950511
+1.920821114 6.789561493
+1.930596285 6.932892447
+1.940371457 7.077943373
+1.950146628 7.224714270
+1.959921799 7.373205138
+1.969696970 7.523415978
+1.979472141 7.675346789
+1.989247312 7.828997572
+1.999022483 7.984368326
+2.008797654 8.036351597
+2.018572825 8.079465548
+2.028347996 8.125446118
+2.038123167 8.174293307
+2.047898338 8.226007115
+2.057673509 8.280587542
+2.067448680 8.338034589
+2.077223851 8.398348254
+2.086999022 8.461528539
+2.096774194 8.527575442
+2.106549365 8.596488965
+2.116324536 8.668269107
+2.126099707 8.742915868
+2.135874878 8.820429248
+2.145650049 8.900809247
+2.155425220 8.984055865
+2.165200391 9.070169102
+2.174975562 9.159148958
+2.184750733 9.250995433
+2.194525904 9.345708528
+2.204301075 9.443288241
+2.214076246 9.543734574
+2.223851417 9.647047526
+2.233626588 9.753227096
+2.243401760 9.862273286
+2.253176931 9.974186095
+2.262952102 10.088965523
+2.272727273 10.206611570
+2.282502444 10.327124236
+2.292277615 10.450503522
+2.302052786 10.576749426
+2.311827957 10.705861949
+2.321603128 10.837841092
+2.331378299 10.972686853
+2.341153470 11.110399234
+2.350928641 11.250978234
+2.360703812 11.394423853
+2.370478983 11.540736090
+2.380254154 11.689914947
+2.390029326 11.841960423
+2.399804497 11.996872519
+2.409579668 12.154651233
+2.419354839 12.315296566
+2.429130010 12.478808518
+2.438905181 12.645187090
+2.448680352 12.814432280
+2.458455523 12.986544090
+2.468230694 13.161522519
+2.478005865 13.339367566
+2.487781036 13.520079233
+2.497556207 13.703657519
+2.507331378 13.890102424
+2.517106549 14.079413948
+2.526881720 14.271592092
+2.536656891 14.466636854
+2.546432063 14.664548235
+2.556207234 14.865326236
+2.565982405 15.068970855
+2.575757576 15.275482094
+2.585532747 15.484859951
+2.595307918 15.697104428
+2.605083089 15.912215524
+2.614858260 16.130193239
+2.624633431 16.351037573
+2.634408602 16.574748526
+2.644183773 16.801326098
+2.653958944 17.030770289
+2.663734115 17.263081100
+2.673509286 17.498258529
+2.683284457 17.736302577
+2.693059629 17.977213245
+2.702834800 18.220990532
+2.712609971 18.467634437
+2.722385142 18.717144962
+2.732160313 18.969522106
+2.741935484 19.224765869
+2.751710655 19.482876251
+2.761485826 19.743853252
+2.771260997 20.007696872
+2.781036168 20.274407112
+2.790811339 20.543983970
+2.800586510 20.816427447
+2.810361681 21.091737544
+2.820136852 21.369914259
+2.829912023 21.650957594
+2.839687195 21.934867548
+2.849462366 22.221644121
+2.859237537 22.511287313
+2.869012708 22.803797124
+2.878787879 23.099173554
+2.888563050 23.397416603
+2.898338221 23.698526271
+2.908113392 24.002502558
+2.917888563 24.309345465
+2.927663734 24.619054990
+2.937438905 24.931631135
+2.947214076 25.247073899
+2.956989247 25.565383281
+2.966764418 25.886559283
+2.976539589 26.210601904
+2.986314761 26.537511144
+2.996089932 26.867287003
+3.005865103 27.094564030
+3.015640274 27.255381361
+3.025415445 27.420211958
+3.035190616 27.589055822
+3.044965787 27.761912952
+3.054740958 27.938783350
+3.064516129 28.119667014
+3.074291300 28.304563944
+3.084066471 28.493474142
+3.093841642 28.686397606
+3.103616813 28.883334337
+3.113391984 29.084284334
+3.123167155 29.289247598
+3.132942326 29.498224129
+3.142717498 29.711213927
+3.152492669 29.928216992
+3.162267840 30.149233323
+3.172043011 30.374262921
+3.181818182 30.603305785
+3.191593353 30.836361916
+3.201368524 31.073431314
+3.211143695 31.314513979
+3.220918866 31.559609910
+3.230694037 31.808719109
+3.240469208 32.061841573
+3.250244379 32.318977305
+3.260019550 32.580126303
+3.269794721 32.845288568
+3.279569892 33.114464100
+3.289345064 33.387652898
+3.299120235 33.664854963
+3.308895406 33.946070295
+3.318670577 34.231298894
+3.328445748 34.520540759
+3.338220919 34.813795891
+3.347996090 35.111064290
+3.357771261 35.412345955
+3.367546432 35.717640887
+3.377321603 36.026949086
+3.387096774 36.340270552
+3.396871945 36.657605284
+3.406647116 36.978953283
+3.416422287 37.304314548
+3.426197458 37.633689081
+3.435972630 37.967076880
+3.445747801 38.304477946
+3.455522972 38.645892278
+3.465298143 38.991319877
+3.475073314 39.340760743
+3.484848485 39.694214876
+3.494623656 40.051682275
+3.504398827 40.413162941
+3.514173998 40.778656874
+3.523949169 41.148164074
+3.533724340 41.521684540
+3.543499511 41.899218273
+3.553274682 42.280765273
+3.563049853 42.666325539
+3.572825024 43.055899072
+3.582600196 43.449485872
+3.592375367 43.847085938
+3.602150538 44.248699272
+3.611925709 44.654325872
+3.621700880 45.063965738
+3.631476051 45.477618872
+3.641251222 45.895285272
+3.651026393 46.316964938
+3.660801564 46.742657872
+3.670576735 47.172364072
+3.680351906 47.606083539
+3.690127077 48.043816273
+3.699902248 48.485562273
+3.709677419 48.931321540
+3.719452590 49.381094074
+3.729227761 49.834879874
+3.739002933 50.292678942
+3.748778104 50.754491275
+3.758553275 51.220316876
+3.768328446 51.690155743
+3.778103617 52.164007877
+3.787878788 52.641873278
+3.797653959 53.123751946
+3.807429130 53.609643880
+3.817204301 54.099549081
+3.826979472 54.593467548
+3.836754643 55.091399283
+3.846529814 55.593344284
+3.856304985 56.099302552
+3.866080156 56.609274086
+3.875855327 57.123258887
+3.885630499 57.641256955
+3.895405670 58.163268290
+3.905180841 58.689292891
+3.914956012 59.219330759
+3.924731183 59.753381894
+3.934506354 60.291446295
+3.944281525 60.833523964
+3.954056696 61.379614898
+3.963831867 61.929719100
+3.973607038 62.483836568
+3.983382209 63.041967303
+3.993157380 63.604111305
+4.002932551 64.099938941
+4.012707722 64.436422689
+4.022482893 64.778066351
+4.032258065 65.124869927
+4.042033236 65.476833418
+4.051808407 65.833956823
+4.061583578 66.196240142
+4.071358749 66.563683376
+4.081133920 66.936286524
+4.090909091 67.314049587
+4.100684262 67.696972564
+4.110459433 68.085055455
+4.120234604 68.478298260
+4.130009775 68.876700980
+4.139784946 69.280263614
+4.149560117 69.688986163
+4.159335288 70.102868626
+4.169110459 70.521911003
+4.178885630 70.946113295
+4.188660802 71.375475500
+4.198435973 71.809997621
+4.208211144 72.249679655
+4.217986315 72.694521604
+4.227761486 73.144523468
+4.237536657 73.599685245
+4.247311828 74.060006937
+4.257086999 74.525488544
+4.266862170 74.996130064
+4.276637341 75.471931499
+4.286412512 75.952892849
+4.296187683 76.439014112
+4.305962854 76.930295290
+4.315738025 77.426736383
+4.325513196 77.928337390
+4.335288368 78.435098311
+4.345063539 78.947019146
+4.354838710 79.464099896
+4.364613881 79.986340560
+4.374389052 80.513741139
+4.384164223 81.046301631
+4.393939394 81.584022039
+4.403714565 82.126902360
+4.413489736 82.674942596
+4.423264907 83.228142746
+4.433040078 83.786502811
+4.442815249 84.350022790
+4.452590420 84.918702683
+4.462365591 85.492542490
+4.472140762 86.071542212
+4.481915934 86.655701849
+4.491691105 87.245021399
+4.501466276 87.839500864
+4.511241447 88.439140244
+4.521016618 89.043939537
+4.530791789 89.653898745
+4.540566960 90.269017868
+4.550342131 90.889296904
+4.560117302 91.514735855
+4.569892473 92.145334721
+4.579667644 92.781093501
+4.589442815 93.422012195
+4.599217986 94.068090803
+4.608993157 94.719329326
+4.618768328 95.375727763
+4.628543500 96.037286114
+4.638318671 96.704004380
+4.648093842 97.375882560
+4.657869013 98.052920655
+4.667644184 98.735118664
+4.677419355 99.422476587
+4.687194526 100.114994424
+4.696969697 100.812672176
+4.706744868 101.515509843
+4.716520039 102.223507423
+4.726295210 102.936664918
+4.736070381 103.654982327
+4.745845552 104.378459651
+4.755620723 105.107096889
+4.765395894 105.840894041
+4.775171065 106.579851108
+4.784946237 107.323968089
+4.794721408 108.073244984
+4.804496579 108.827681794
+4.814271750 109.587278518
+4.824046921 110.352035156
+4.833822092 111.121951709
+4.843597263 111.897028176
+4.853372434 112.677264557
+4.863147605 113.462660853
+4.872922776 114.253217063
+4.882697947 115.048933188
+4.892473118 115.849809227
+4.902248289 116.655845180
+4.912023460 117.467041047
+4.921798631 118.283396829
+4.931573803 119.104912525
+4.941348974 119.931588136
+4.951124145 120.763423661
+4.960899316 121.600419100
+4.970674487 122.442574453
+4.980449658 123.289889721
+4.990224829 124.142364903
+5.000000000 125.000000000
diff --git a/examples/takagi-sugeno/octave/cubic_approximator.fll b/examples/takagi-sugeno/octave/cubic_approximator.fll
index 073e70e..22b8fa6 100644
--- a/examples/takagi-sugeno/octave/cubic_approximator.fll
+++ b/examples/takagi-sugeno/octave/cubic_approximator.fll
@@ -1,7 +1,8 @@
-Engine: Cubic-Approximator
+Engine: cubic_approximator
InputVariable: X
enabled: true
range: -5.000 5.000
+ lock-range: false
term: AboutNegFive Triangle -6.000 -5.000 -4.000
term: AboutNegFour Triangle -5.000 -4.000 -3.000
term: AboutNegThree Triangle -4.000 -3.000 -2.000
@@ -16,11 +17,11 @@ InputVariable: X
OutputVariable: ApproxXCubed
enabled: true
range: -5.000 5.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
- lock-range: false
term: TangentatNegFive Linear 75.000 250.000
term: TangentatNegFour Linear 48.000 128.000
term: TangentatNegThree Linear 27.000 54.000
@@ -36,7 +37,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if X is AboutNegFive then ApproxXCubed is TangentatNegFive
rule: if X is AboutNegFour then ApproxXCubed is TangentatNegFour
rule: if X is AboutNegThree then ApproxXCubed is TangentatNegThree
diff --git a/examples/takagi-sugeno/octave/cubic_approximator.java b/examples/takagi-sugeno/octave/cubic_approximator.java
index 1955a24..ed64870 100644
--- a/examples/takagi-sugeno/octave/cubic_approximator.java
+++ b/examples/takagi-sugeno/octave/cubic_approximator.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,54 +13,62 @@ import com.fuzzylite.variable.*;
public class cubic_approximator{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("Cubic-Approximator");
+engine.setName("cubic_approximator");
+engine.setDescription("");
-InputVariable inputVariable = new InputVariable();
-inputVariable.setEnabled(true);
-inputVariable.setName("X");
-inputVariable.setRange(-5.000, 5.000);
-inputVariable.addTerm(new Triangle("AboutNegFive", -6.000, -5.000, -4.000));
-inputVariable.addTerm(new Triangle("AboutNegFour", -5.000, -4.000, -3.000));
-inputVariable.addTerm(new Triangle("AboutNegThree", -4.000, -3.000, -2.000));
-inputVariable.addTerm(new Triangle("AboutNegTwo", -3.000, -2.000, -1.000));
-inputVariable.addTerm(new Triangle("AboutNegOne", -2.000, -1.000, 0.000));
-inputVariable.addTerm(new Triangle("AboutZero", -1.000, 0.000, 1.000));
-inputVariable.addTerm(new Triangle("AboutOne", 0.000, 1.000, 2.000));
-inputVariable.addTerm(new Triangle("AboutTwo", 1.000, 2.000, 3.000));
-inputVariable.addTerm(new Triangle("AboutThree", 2.000, 3.000, 4.000));
-inputVariable.addTerm(new Triangle("AboutFour", 3.000, 4.000, 5.000));
-inputVariable.addTerm(new Triangle("AboutFive", 4.000, 5.000, 6.000));
-engine.addInputVariable(inputVariable);
+InputVariable X = new InputVariable();
+X.setName("X");
+X.setDescription("");
+X.setEnabled(true);
+X.setRange(-5.000, 5.000);
+X.setLockValueInRange(false);
+X.addTerm(new Triangle("AboutNegFive", -6.000, -5.000, -4.000));
+X.addTerm(new Triangle("AboutNegFour", -5.000, -4.000, -3.000));
+X.addTerm(new Triangle("AboutNegThree", -4.000, -3.000, -2.000));
+X.addTerm(new Triangle("AboutNegTwo", -3.000, -2.000, -1.000));
+X.addTerm(new Triangle("AboutNegOne", -2.000, -1.000, 0.000));
+X.addTerm(new Triangle("AboutZero", -1.000, 0.000, 1.000));
+X.addTerm(new Triangle("AboutOne", 0.000, 1.000, 2.000));
+X.addTerm(new Triangle("AboutTwo", 1.000, 2.000, 3.000));
+X.addTerm(new Triangle("AboutThree", 2.000, 3.000, 4.000));
+X.addTerm(new Triangle("AboutFour", 3.000, 4.000, 5.000));
+X.addTerm(new Triangle("AboutFive", 4.000, 5.000, 6.000));
+engine.addInputVariable(X);
-OutputVariable outputVariable = new OutputVariable();
-outputVariable.setEnabled(true);
-outputVariable.setName("ApproxXCubed");
-outputVariable.setRange(-5.000, 5.000);
-outputVariable.fuzzyOutput().setAccumulation(null);
-outputVariable.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable.setDefaultValue(Double.NaN);
-outputVariable.setLockPreviousOutputValue(false);
-outputVariable.setLockOutputValueInRange(false);
-outputVariable.addTerm(Linear.create("TangentatNegFive", engine, 75.000, 250.000));
-outputVariable.addTerm(Linear.create("TangentatNegFour", engine, 48.000, 128.000));
-outputVariable.addTerm(Linear.create("TangentatNegThree", engine, 27.000, 54.000));
-outputVariable.addTerm(Linear.create("TangentatNegTwo", engine, 12.000, 16.000));
-outputVariable.addTerm(Linear.create("TangentatNegOne", engine, 3.000, 2.000));
-outputVariable.addTerm(Linear.create("TangentatZero", engine, 0.000, 0.000));
-outputVariable.addTerm(Linear.create("TangentatOne", engine, 3.000, -2.000));
-outputVariable.addTerm(Linear.create("TangentatTwo", engine, 12.000, -16.000));
-outputVariable.addTerm(Linear.create("TangentatThree", engine, 27.000, -54.000));
-outputVariable.addTerm(Linear.create("TangentatFour", engine, 48.000, -128.000));
-outputVariable.addTerm(Linear.create("TangentatFive", engine, 75.000, -250.000));
-engine.addOutputVariable(outputVariable);
+OutputVariable ApproxXCubed = new OutputVariable();
+ApproxXCubed.setName("ApproxXCubed");
+ApproxXCubed.setDescription("");
+ApproxXCubed.setEnabled(true);
+ApproxXCubed.setRange(-5.000, 5.000);
+ApproxXCubed.setLockValueInRange(false);
+ApproxXCubed.setAggregation(null);
+ApproxXCubed.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+ApproxXCubed.setDefaultValue(Double.NaN);
+ApproxXCubed.setLockPreviousValue(false);
+ApproxXCubed.addTerm(Linear.create("TangentatNegFive", engine, 75.000, 250.000));
+ApproxXCubed.addTerm(Linear.create("TangentatNegFour", engine, 48.000, 128.000));
+ApproxXCubed.addTerm(Linear.create("TangentatNegThree", engine, 27.000, 54.000));
+ApproxXCubed.addTerm(Linear.create("TangentatNegTwo", engine, 12.000, 16.000));
+ApproxXCubed.addTerm(Linear.create("TangentatNegOne", engine, 3.000, 2.000));
+ApproxXCubed.addTerm(Linear.create("TangentatZero", engine, 0.000, 0.000));
+ApproxXCubed.addTerm(Linear.create("TangentatOne", engine, 3.000, -2.000));
+ApproxXCubed.addTerm(Linear.create("TangentatTwo", engine, 12.000, -16.000));
+ApproxXCubed.addTerm(Linear.create("TangentatThree", engine, 27.000, -54.000));
+ApproxXCubed.addTerm(Linear.create("TangentatFour", engine, 48.000, -128.000));
+ApproxXCubed.addTerm(Linear.create("TangentatFive", engine, 75.000, -250.000));
+engine.addOutputVariable(ApproxXCubed);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(null);
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(null);
+ruleBlock.setImplication(null);
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if X is AboutNegFive then ApproxXCubed is TangentatNegFive", engine));
ruleBlock.addRule(Rule.parse("if X is AboutNegFour then ApproxXCubed is TangentatNegFour", engine));
ruleBlock.addRule(Rule.parse("if X is AboutNegThree then ApproxXCubed is TangentatNegThree", engine));
diff --git a/examples/takagi-sugeno/octave/cubic_approximator.pdf b/examples/takagi-sugeno/octave/cubic_approximator.pdf
new file mode 100644
index 0000000..62d12ee
--- /dev/null
+++ b/examples/takagi-sugeno/octave/cubic_approximator.pdf
Binary files differ
diff --git a/examples/takagi-sugeno/octave/heart_disease_risk.R b/examples/takagi-sugeno/octave/heart_disease_risk.R
new file mode 100644
index 0000000..6ea4240
--- /dev/null
+++ b/examples/takagi-sugeno/octave/heart_disease_risk.R
@@ -0,0 +1,84 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "heart_disease_risk"
+engine.fll = "Engine: heart_disease_risk
+InputVariable: LDLLevel
+ enabled: true
+ range: 0.000 300.000
+ lock-range: false
+ term: Low Trapezoid -1.000 0.000 90.000 110.000
+ term: LowBorderline Trapezoid 90.000 110.000 120.000 140.000
+ term: Borderline Trapezoid 120.000 140.000 150.000 170.000
+ term: HighBorderline Trapezoid 150.000 170.000 180.000 200.000
+ term: High Trapezoid 180.000 200.000 300.000 301.000
+InputVariable: HDLLevel
+ enabled: true
+ range: 0.000 100.000
+ lock-range: false
+ term: LowHDL Trapezoid -1.000 0.000 35.000 45.000
+ term: ModerateHDL Trapezoid 35.000 45.000 55.000 65.000
+ term: HighHDL Trapezoid 55.000 65.000 100.000 101.000
+OutputVariable: HeartDiseaseRisk
+ enabled: true
+ range: 0.000 10.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: NoRisk Constant 0.000
+ term: LowRisk Constant 2.500
+ term: MediumRisk Constant 5.000
+ term: HighRisk Constant 7.500
+ term: ExtremeRisk Constant 10.000
+RuleBlock:
+ enabled: true
+ conjunction: Minimum
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if LDLLevel is Low and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk
+ rule: if LDLLevel is Low and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk
+ rule: if LDLLevel is Low and HDLLevel is HighHDL then HeartDiseaseRisk is NoRisk
+ rule: if LDLLevel is LowBorderline and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk
+ rule: if LDLLevel is LowBorderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk
+ rule: if LDLLevel is LowBorderline and HDLLevel is HighHDL then HeartDiseaseRisk is LowRisk
+ rule: if LDLLevel is Borderline and HDLLevel is LowHDL then HeartDiseaseRisk is HighRisk
+ rule: if LDLLevel is Borderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is MediumRisk
+ rule: if LDLLevel is Borderline and HDLLevel is HighHDL then HeartDiseaseRisk is LowRisk
+ rule: if LDLLevel is HighBorderline and HDLLevel is LowHDL then HeartDiseaseRisk is HighRisk
+ rule: if LDLLevel is HighBorderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is HighRisk
+ rule: if LDLLevel is HighBorderline and HDLLevel is HighHDL then HeartDiseaseRisk is MediumRisk
+ rule: if LDLLevel is High and HDLLevel is LowHDL then HeartDiseaseRisk is ExtremeRisk
+ rule: if LDLLevel is High and HDLLevel is ModerateHDL then HeartDiseaseRisk is HighRisk
+ rule: if LDLLevel is High and HDLLevel is HighHDL then HeartDiseaseRisk is MediumRisk"
+
+engine.fldFile = "heart_disease_risk.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1i2_o1 = ggplot(engine.df, aes(LDLLevel, HDLLevel)) +
+ geom_tile(aes(fill=HeartDiseaseRisk)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=LDLLevel, y=HDLLevel, z=HeartDiseaseRisk), color="black") +
+ ggtitle("(LDLLevel, HDLLevel) = HeartDiseaseRisk")
+
+engine.plot.i2i1_o1 = ggplot(engine.df, aes(HDLLevel, LDLLevel)) +
+ geom_tile(aes(fill=HeartDiseaseRisk)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=HDLLevel, y=LDLLevel, z=HeartDiseaseRisk), color="black") +
+ ggtitle("(HDLLevel, LDLLevel) = HeartDiseaseRisk")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1i2_o1, engine.plot.i2i1_o1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/takagi-sugeno/octave/heart_disease_risk.cpp b/examples/takagi-sugeno/octave/heart_disease_risk.cpp
index 397b303..12e7f72 100644
--- a/examples/takagi-sugeno/octave/heart_disease_risk.cpp
+++ b/examples/takagi-sugeno/octave/heart_disease_risk.cpp
@@ -1,68 +1,78 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("Heart-Disease-Risk");
+engine->setName("heart_disease_risk");
+engine->setDescription("");
-InputVariable* inputVariable1 = new InputVariable;
-inputVariable1->setEnabled(true);
-inputVariable1->setName("LDLLevel");
-inputVariable1->setRange(0.000, 300.000);
-inputVariable1->addTerm(new Trapezoid("Low", -1.000, 0.000, 90.000, 110.000));
-inputVariable1->addTerm(new Trapezoid("LowBorderline", 90.000, 110.000, 120.000, 140.000));
-inputVariable1->addTerm(new Trapezoid("Borderline", 120.000, 140.000, 150.000, 170.000));
-inputVariable1->addTerm(new Trapezoid("HighBorderline", 150.000, 170.000, 180.000, 200.000));
-inputVariable1->addTerm(new Trapezoid("High", 180.000, 200.000, 300.000, 301.000));
-engine->addInputVariable(inputVariable1);
+InputVariable* LDLLevel = new InputVariable;
+LDLLevel->setName("LDLLevel");
+LDLLevel->setDescription("");
+LDLLevel->setEnabled(true);
+LDLLevel->setRange(0.000, 300.000);
+LDLLevel->setLockValueInRange(false);
+LDLLevel->addTerm(new Trapezoid("Low", -1.000, 0.000, 90.000, 110.000));
+LDLLevel->addTerm(new Trapezoid("LowBorderline", 90.000, 110.000, 120.000, 140.000));
+LDLLevel->addTerm(new Trapezoid("Borderline", 120.000, 140.000, 150.000, 170.000));
+LDLLevel->addTerm(new Trapezoid("HighBorderline", 150.000, 170.000, 180.000, 200.000));
+LDLLevel->addTerm(new Trapezoid("High", 180.000, 200.000, 300.000, 301.000));
+engine->addInputVariable(LDLLevel);
-InputVariable* inputVariable2 = new InputVariable;
-inputVariable2->setEnabled(true);
-inputVariable2->setName("HDLLevel");
-inputVariable2->setRange(0.000, 100.000);
-inputVariable2->addTerm(new Trapezoid("LowHDL", -1.000, 0.000, 35.000, 45.000));
-inputVariable2->addTerm(new Trapezoid("ModerateHDL", 35.000, 45.000, 55.000, 65.000));
-inputVariable2->addTerm(new Trapezoid("HighHDL", 55.000, 65.000, 100.000, 101.000));
-engine->addInputVariable(inputVariable2);
+InputVariable* HDLLevel = new InputVariable;
+HDLLevel->setName("HDLLevel");
+HDLLevel->setDescription("");
+HDLLevel->setEnabled(true);
+HDLLevel->setRange(0.000, 100.000);
+HDLLevel->setLockValueInRange(false);
+HDLLevel->addTerm(new Trapezoid("LowHDL", -1.000, 0.000, 35.000, 45.000));
+HDLLevel->addTerm(new Trapezoid("ModerateHDL", 35.000, 45.000, 55.000, 65.000));
+HDLLevel->addTerm(new Trapezoid("HighHDL", 55.000, 65.000, 100.000, 101.000));
+engine->addInputVariable(HDLLevel);
-OutputVariable* outputVariable = new OutputVariable;
-outputVariable->setEnabled(true);
-outputVariable->setName("HeartDiseaseRisk");
-outputVariable->setRange(0.000, 10.000);
-outputVariable->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable->setDefaultValue(fl::nan);
-outputVariable->setLockPreviousOutputValue(false);
-outputVariable->setLockOutputValueInRange(false);
-outputVariable->addTerm(new Constant("NoRisk", 0.000));
-outputVariable->addTerm(new Constant("LowRisk", 2.500));
-outputVariable->addTerm(new Constant("MediumRisk", 5.000));
-outputVariable->addTerm(new Constant("HighRisk", 7.500));
-outputVariable->addTerm(new Constant("ExtremeRisk", 10.000));
-engine->addOutputVariable(outputVariable);
+OutputVariable* HeartDiseaseRisk = new OutputVariable;
+HeartDiseaseRisk->setName("HeartDiseaseRisk");
+HeartDiseaseRisk->setDescription("");
+HeartDiseaseRisk->setEnabled(true);
+HeartDiseaseRisk->setRange(0.000, 10.000);
+HeartDiseaseRisk->setLockValueInRange(false);
+HeartDiseaseRisk->setAggregation(fl::null);
+HeartDiseaseRisk->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+HeartDiseaseRisk->setDefaultValue(fl::nan);
+HeartDiseaseRisk->setLockPreviousValue(false);
+HeartDiseaseRisk->addTerm(new Constant("NoRisk", 0.000));
+HeartDiseaseRisk->addTerm(new Constant("LowRisk", 2.500));
+HeartDiseaseRisk->addTerm(new Constant("MediumRisk", 5.000));
+HeartDiseaseRisk->addTerm(new Constant("HighRisk", 7.500));
+HeartDiseaseRisk->addTerm(new Constant("ExtremeRisk", 10.000));
+engine->addOutputVariable(HeartDiseaseRisk);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(new Minimum);
ruleBlock->setDisjunction(fl::null);
-ruleBlock->setActivation(fl::null);
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is Low and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is Low and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is Low and HDLLevel is HighHDL then HeartDiseaseRisk is NoRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is LowBorderline and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is LowBorderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is LowBorderline and HDLLevel is HighHDL then HeartDiseaseRisk is LowRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is Borderline and HDLLevel is LowHDL then HeartDiseaseRisk is HighRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is Borderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is MediumRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is Borderline and HDLLevel is HighHDL then HeartDiseaseRisk is LowRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is HighBorderline and HDLLevel is LowHDL then HeartDiseaseRisk is HighRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is HighBorderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is HighRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is HighBorderline and HDLLevel is HighHDL then HeartDiseaseRisk is MediumRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is High and HDLLevel is LowHDL then HeartDiseaseRisk is ExtremeRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is High and HDLLevel is ModerateHDL then HeartDiseaseRisk is HighRisk", engine));
-ruleBlock->addRule(fl::Rule::parse("if LDLLevel is High and HDLLevel is HighHDL then HeartDiseaseRisk is MediumRisk", engine));
+ruleBlock->setImplication(fl::null);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if LDLLevel is Low and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is Low and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is Low and HDLLevel is HighHDL then HeartDiseaseRisk is NoRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is LowBorderline and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is LowBorderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is LowBorderline and HDLLevel is HighHDL then HeartDiseaseRisk is LowRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is Borderline and HDLLevel is LowHDL then HeartDiseaseRisk is HighRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is Borderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is MediumRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is Borderline and HDLLevel is HighHDL then HeartDiseaseRisk is LowRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is HighBorderline and HDLLevel is LowHDL then HeartDiseaseRisk is HighRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is HighBorderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is HighRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is HighBorderline and HDLLevel is HighHDL then HeartDiseaseRisk is MediumRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is High and HDLLevel is LowHDL then HeartDiseaseRisk is ExtremeRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is High and HDLLevel is ModerateHDL then HeartDiseaseRisk is HighRisk", engine));
+ruleBlock->addRule(Rule::parse("if LDLLevel is High and HDLLevel is HighHDL then HeartDiseaseRisk is MediumRisk", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/takagi-sugeno/octave/heart_disease_risk.fcl b/examples/takagi-sugeno/octave/heart_disease_risk.fcl
index 9629a47..4e09d59 100644
--- a/examples/takagi-sugeno/octave/heart_disease_risk.fcl
+++ b/examples/takagi-sugeno/octave/heart_disease_risk.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK Heart-Disease-Risk
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK heart_disease_risk
VAR_INPUT
LDLLevel: REAL;
diff --git a/examples/takagi-sugeno/octave/heart_disease_risk.fis b/examples/takagi-sugeno/octave/heart_disease_risk.fis
index 11686f1..485d8d9 100644
--- a/examples/takagi-sugeno/octave/heart_disease_risk.fis
+++ b/examples/takagi-sugeno/octave/heart_disease_risk.fis
@@ -1,13 +1,16 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='Heart-Disease-Risk'
+Name='heart_disease_risk'
Type='sugeno'
+Version=6.0
NumInputs=2
NumOutputs=1
NumRules=15
AndMethod='min'
-OrMethod=''
-ImpMethod=''
-AggMethod=''
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
DefuzzMethod='wtaver'
[Input1]
diff --git a/examples/takagi-sugeno/octave/heart_disease_risk.fld b/examples/takagi-sugeno/octave/heart_disease_risk.fld
index afc1fe0..7b9a00e 100644
--- a/examples/takagi-sugeno/octave/heart_disease_risk.fld
+++ b/examples/takagi-sugeno/octave/heart_disease_risk.fld
@@ -1,1026 +1,1025 @@
-#@Engine: Heart-Disease-Risk;
-#@InputVariable: LDLLevel; @InputVariable: HDLLevel; @OutputVariable: HeartDiseaseRisk;
-0.00000000 0.00000000 5.00000000
-0.00000000 3.22580645 5.00000000
-0.00000000 6.45161290 5.00000000
-0.00000000 9.67741935 5.00000000
-0.00000000 12.90322581 5.00000000
-0.00000000 16.12903226 5.00000000
-0.00000000 19.35483871 5.00000000
-0.00000000 22.58064516 5.00000000
-0.00000000 25.80645161 5.00000000
-0.00000000 29.03225806 5.00000000
-0.00000000 32.25806452 5.00000000
-0.00000000 35.48387097 4.87903226
-0.00000000 38.70967742 4.07258065
-0.00000000 41.93548387 3.26612903
-0.00000000 45.16129032 2.50000000
-0.00000000 48.38709677 2.50000000
-0.00000000 51.61290323 2.50000000
-0.00000000 54.83870968 2.50000000
-0.00000000 58.06451613 1.73387097
-0.00000000 61.29032258 0.92741935
-0.00000000 64.51612903 0.12096774
-0.00000000 67.74193548 0.00000000
-0.00000000 70.96774194 0.00000000
-0.00000000 74.19354839 0.00000000
-0.00000000 77.41935484 0.00000000
-0.00000000 80.64516129 0.00000000
-0.00000000 83.87096774 0.00000000
-0.00000000 87.09677419 0.00000000
-0.00000000 90.32258065 0.00000000
-0.00000000 93.54838710 0.00000000
-0.00000000 96.77419355 0.00000000
-0.00000000 100.00000000 0.00000000
-9.67741935 0.00000000 5.00000000
-9.67741935 3.22580645 5.00000000
-9.67741935 6.45161290 5.00000000
-9.67741935 9.67741935 5.00000000
-9.67741935 12.90322581 5.00000000
-9.67741935 16.12903226 5.00000000
-9.67741935 19.35483871 5.00000000
-9.67741935 22.58064516 5.00000000
-9.67741935 25.80645161 5.00000000
-9.67741935 29.03225806 5.00000000
-9.67741935 32.25806452 5.00000000
-9.67741935 35.48387097 4.87903226
-9.67741935 38.70967742 4.07258065
-9.67741935 41.93548387 3.26612903
-9.67741935 45.16129032 2.50000000
-9.67741935 48.38709677 2.50000000
-9.67741935 51.61290323 2.50000000
-9.67741935 54.83870968 2.50000000
-9.67741935 58.06451613 1.73387097
-9.67741935 61.29032258 0.92741935
-9.67741935 64.51612903 0.12096774
-9.67741935 67.74193548 0.00000000
-9.67741935 70.96774194 0.00000000
-9.67741935 74.19354839 0.00000000
-9.67741935 77.41935484 0.00000000
-9.67741935 80.64516129 0.00000000
-9.67741935 83.87096774 0.00000000
-9.67741935 87.09677419 0.00000000
-9.67741935 90.32258065 0.00000000
-9.67741935 93.54838710 0.00000000
-9.67741935 96.77419355 0.00000000
-9.67741935 100.00000000 0.00000000
-19.35483871 0.00000000 5.00000000
-19.35483871 3.22580645 5.00000000
-19.35483871 6.45161290 5.00000000
-19.35483871 9.67741935 5.00000000
-19.35483871 12.90322581 5.00000000
-19.35483871 16.12903226 5.00000000
-19.35483871 19.35483871 5.00000000
-19.35483871 22.58064516 5.00000000
-19.35483871 25.80645161 5.00000000
-19.35483871 29.03225806 5.00000000
-19.35483871 32.25806452 5.00000000
-19.35483871 35.48387097 4.87903226
-19.35483871 38.70967742 4.07258065
-19.35483871 41.93548387 3.26612903
-19.35483871 45.16129032 2.50000000
-19.35483871 48.38709677 2.50000000
-19.35483871 51.61290323 2.50000000
-19.35483871 54.83870968 2.50000000
-19.35483871 58.06451613 1.73387097
-19.35483871 61.29032258 0.92741935
-19.35483871 64.51612903 0.12096774
-19.35483871 67.74193548 0.00000000
-19.35483871 70.96774194 0.00000000
-19.35483871 74.19354839 0.00000000
-19.35483871 77.41935484 0.00000000
-19.35483871 80.64516129 0.00000000
-19.35483871 83.87096774 0.00000000
-19.35483871 87.09677419 0.00000000
-19.35483871 90.32258065 0.00000000
-19.35483871 93.54838710 0.00000000
-19.35483871 96.77419355 0.00000000
-19.35483871 100.00000000 0.00000000
-29.03225806 0.00000000 5.00000000
-29.03225806 3.22580645 5.00000000
-29.03225806 6.45161290 5.00000000
-29.03225806 9.67741935 5.00000000
-29.03225806 12.90322581 5.00000000
-29.03225806 16.12903226 5.00000000
-29.03225806 19.35483871 5.00000000
-29.03225806 22.58064516 5.00000000
-29.03225806 25.80645161 5.00000000
-29.03225806 29.03225806 5.00000000
-29.03225806 32.25806452 5.00000000
-29.03225806 35.48387097 4.87903226
-29.03225806 38.70967742 4.07258065
-29.03225806 41.93548387 3.26612903
-29.03225806 45.16129032 2.50000000
-29.03225806 48.38709677 2.50000000
-29.03225806 51.61290323 2.50000000
-29.03225806 54.83870968 2.50000000
-29.03225806 58.06451613 1.73387097
-29.03225806 61.29032258 0.92741935
-29.03225806 64.51612903 0.12096774
-29.03225806 67.74193548 0.00000000
-29.03225806 70.96774194 0.00000000
-29.03225806 74.19354839 0.00000000
-29.03225806 77.41935484 0.00000000
-29.03225806 80.64516129 0.00000000
-29.03225806 83.87096774 0.00000000
-29.03225806 87.09677419 0.00000000
-29.03225806 90.32258065 0.00000000
-29.03225806 93.54838710 0.00000000
-29.03225806 96.77419355 0.00000000
-29.03225806 100.00000000 0.00000000
-38.70967742 0.00000000 5.00000000
-38.70967742 3.22580645 5.00000000
-38.70967742 6.45161290 5.00000000
-38.70967742 9.67741935 5.00000000
-38.70967742 12.90322581 5.00000000
-38.70967742 16.12903226 5.00000000
-38.70967742 19.35483871 5.00000000
-38.70967742 22.58064516 5.00000000
-38.70967742 25.80645161 5.00000000
-38.70967742 29.03225806 5.00000000
-38.70967742 32.25806452 5.00000000
-38.70967742 35.48387097 4.87903226
-38.70967742 38.70967742 4.07258065
-38.70967742 41.93548387 3.26612903
-38.70967742 45.16129032 2.50000000
-38.70967742 48.38709677 2.50000000
-38.70967742 51.61290323 2.50000000
-38.70967742 54.83870968 2.50000000
-38.70967742 58.06451613 1.73387097
-38.70967742 61.29032258 0.92741935
-38.70967742 64.51612903 0.12096774
-38.70967742 67.74193548 0.00000000
-38.70967742 70.96774194 0.00000000
-38.70967742 74.19354839 0.00000000
-38.70967742 77.41935484 0.00000000
-38.70967742 80.64516129 0.00000000
-38.70967742 83.87096774 0.00000000
-38.70967742 87.09677419 0.00000000
-38.70967742 90.32258065 0.00000000
-38.70967742 93.54838710 0.00000000
-38.70967742 96.77419355 0.00000000
-38.70967742 100.00000000 0.00000000
-48.38709677 0.00000000 5.00000000
-48.38709677 3.22580645 5.00000000
-48.38709677 6.45161290 5.00000000
-48.38709677 9.67741935 5.00000000
-48.38709677 12.90322581 5.00000000
-48.38709677 16.12903226 5.00000000
-48.38709677 19.35483871 5.00000000
-48.38709677 22.58064516 5.00000000
-48.38709677 25.80645161 5.00000000
-48.38709677 29.03225806 5.00000000
-48.38709677 32.25806452 5.00000000
-48.38709677 35.48387097 4.87903226
-48.38709677 38.70967742 4.07258065
-48.38709677 41.93548387 3.26612903
-48.38709677 45.16129032 2.50000000
-48.38709677 48.38709677 2.50000000
-48.38709677 51.61290323 2.50000000
-48.38709677 54.83870968 2.50000000
-48.38709677 58.06451613 1.73387097
-48.38709677 61.29032258 0.92741935
-48.38709677 64.51612903 0.12096774
-48.38709677 67.74193548 0.00000000
-48.38709677 70.96774194 0.00000000
-48.38709677 74.19354839 0.00000000
-48.38709677 77.41935484 0.00000000
-48.38709677 80.64516129 0.00000000
-48.38709677 83.87096774 0.00000000
-48.38709677 87.09677419 0.00000000
-48.38709677 90.32258065 0.00000000
-48.38709677 93.54838710 0.00000000
-48.38709677 96.77419355 0.00000000
-48.38709677 100.00000000 0.00000000
-58.06451613 0.00000000 5.00000000
-58.06451613 3.22580645 5.00000000
-58.06451613 6.45161290 5.00000000
-58.06451613 9.67741935 5.00000000
-58.06451613 12.90322581 5.00000000
-58.06451613 16.12903226 5.00000000
-58.06451613 19.35483871 5.00000000
-58.06451613 22.58064516 5.00000000
-58.06451613 25.80645161 5.00000000
-58.06451613 29.03225806 5.00000000
-58.06451613 32.25806452 5.00000000
-58.06451613 35.48387097 4.87903226
-58.06451613 38.70967742 4.07258065
-58.06451613 41.93548387 3.26612903
-58.06451613 45.16129032 2.50000000
-58.06451613 48.38709677 2.50000000
-58.06451613 51.61290323 2.50000000
-58.06451613 54.83870968 2.50000000
-58.06451613 58.06451613 1.73387097
-58.06451613 61.29032258 0.92741935
-58.06451613 64.51612903 0.12096774
-58.06451613 67.74193548 0.00000000
-58.06451613 70.96774194 0.00000000
-58.06451613 74.19354839 0.00000000
-58.06451613 77.41935484 0.00000000
-58.06451613 80.64516129 0.00000000
-58.06451613 83.87096774 0.00000000
-58.06451613 87.09677419 0.00000000
-58.06451613 90.32258065 0.00000000
-58.06451613 93.54838710 0.00000000
-58.06451613 96.77419355 0.00000000
-58.06451613 100.00000000 0.00000000
-67.74193548 0.00000000 5.00000000
-67.74193548 3.22580645 5.00000000
-67.74193548 6.45161290 5.00000000
-67.74193548 9.67741935 5.00000000
-67.74193548 12.90322581 5.00000000
-67.74193548 16.12903226 5.00000000
-67.74193548 19.35483871 5.00000000
-67.74193548 22.58064516 5.00000000
-67.74193548 25.80645161 5.00000000
-67.74193548 29.03225806 5.00000000
-67.74193548 32.25806452 5.00000000
-67.74193548 35.48387097 4.87903226
-67.74193548 38.70967742 4.07258065
-67.74193548 41.93548387 3.26612903
-67.74193548 45.16129032 2.50000000
-67.74193548 48.38709677 2.50000000
-67.74193548 51.61290323 2.50000000
-67.74193548 54.83870968 2.50000000
-67.74193548 58.06451613 1.73387097
-67.74193548 61.29032258 0.92741935
-67.74193548 64.51612903 0.12096774
-67.74193548 67.74193548 0.00000000
-67.74193548 70.96774194 0.00000000
-67.74193548 74.19354839 0.00000000
-67.74193548 77.41935484 0.00000000
-67.74193548 80.64516129 0.00000000
-67.74193548 83.87096774 0.00000000
-67.74193548 87.09677419 0.00000000
-67.74193548 90.32258065 0.00000000
-67.74193548 93.54838710 0.00000000
-67.74193548 96.77419355 0.00000000
-67.74193548 100.00000000 0.00000000
-77.41935484 0.00000000 5.00000000
-77.41935484 3.22580645 5.00000000
-77.41935484 6.45161290 5.00000000
-77.41935484 9.67741935 5.00000000
-77.41935484 12.90322581 5.00000000
-77.41935484 16.12903226 5.00000000
-77.41935484 19.35483871 5.00000000
-77.41935484 22.58064516 5.00000000
-77.41935484 25.80645161 5.00000000
-77.41935484 29.03225806 5.00000000
-77.41935484 32.25806452 5.00000000
-77.41935484 35.48387097 4.87903226
-77.41935484 38.70967742 4.07258065
-77.41935484 41.93548387 3.26612903
-77.41935484 45.16129032 2.50000000
-77.41935484 48.38709677 2.50000000
-77.41935484 51.61290323 2.50000000
-77.41935484 54.83870968 2.50000000
-77.41935484 58.06451613 1.73387097
-77.41935484 61.29032258 0.92741935
-77.41935484 64.51612903 0.12096774
-77.41935484 67.74193548 0.00000000
-77.41935484 70.96774194 0.00000000
-77.41935484 74.19354839 0.00000000
-77.41935484 77.41935484 0.00000000
-77.41935484 80.64516129 0.00000000
-77.41935484 83.87096774 0.00000000
-77.41935484 87.09677419 0.00000000
-77.41935484 90.32258065 0.00000000
-77.41935484 93.54838710 0.00000000
-77.41935484 96.77419355 0.00000000
-77.41935484 100.00000000 0.00000000
-87.09677419 0.00000000 5.00000000
-87.09677419 3.22580645 5.00000000
-87.09677419 6.45161290 5.00000000
-87.09677419 9.67741935 5.00000000
-87.09677419 12.90322581 5.00000000
-87.09677419 16.12903226 5.00000000
-87.09677419 19.35483871 5.00000000
-87.09677419 22.58064516 5.00000000
-87.09677419 25.80645161 5.00000000
-87.09677419 29.03225806 5.00000000
-87.09677419 32.25806452 5.00000000
-87.09677419 35.48387097 4.87903226
-87.09677419 38.70967742 4.07258065
-87.09677419 41.93548387 3.26612903
-87.09677419 45.16129032 2.50000000
-87.09677419 48.38709677 2.50000000
-87.09677419 51.61290323 2.50000000
-87.09677419 54.83870968 2.50000000
-87.09677419 58.06451613 1.73387097
-87.09677419 61.29032258 0.92741935
-87.09677419 64.51612903 0.12096774
-87.09677419 67.74193548 0.00000000
-87.09677419 70.96774194 0.00000000
-87.09677419 74.19354839 0.00000000
-87.09677419 77.41935484 0.00000000
-87.09677419 80.64516129 0.00000000
-87.09677419 83.87096774 0.00000000
-87.09677419 87.09677419 0.00000000
-87.09677419 90.32258065 0.00000000
-87.09677419 93.54838710 0.00000000
-87.09677419 96.77419355 0.00000000
-87.09677419 100.00000000 0.00000000
-96.77419355 0.00000000 5.00000000
-96.77419355 3.22580645 5.00000000
-96.77419355 6.45161290 5.00000000
-96.77419355 9.67741935 5.00000000
-96.77419355 12.90322581 5.00000000
-96.77419355 16.12903226 5.00000000
-96.77419355 19.35483871 5.00000000
-96.77419355 22.58064516 5.00000000
-96.77419355 25.80645161 5.00000000
-96.77419355 29.03225806 5.00000000
-96.77419355 32.25806452 5.00000000
-96.77419355 35.48387097 4.77941176
-96.77419355 38.70967742 3.94230769
-96.77419355 41.93548387 3.45000000
-96.77419355 45.16129032 2.50000000
-96.77419355 48.38709677 2.50000000
-96.77419355 51.61290323 2.50000000
-96.77419355 54.83870968 2.50000000
-96.77419355 58.06451613 2.02500000
-96.77419355 61.29032258 1.56250000
-96.77419355 64.51612903 0.99264706
-96.77419355 67.74193548 0.84677419
-96.77419355 70.96774194 0.84677419
-96.77419355 74.19354839 0.84677419
-96.77419355 77.41935484 0.84677419
-96.77419355 80.64516129 0.84677419
-96.77419355 83.87096774 0.84677419
-96.77419355 87.09677419 0.84677419
-96.77419355 90.32258065 0.84677419
-96.77419355 93.54838710 0.84677419
-96.77419355 96.77419355 0.84677419
-96.77419355 100.00000000 0.84677419
-106.45161290 0.00000000 5.00000000
-106.45161290 3.22580645 5.00000000
-106.45161290 6.45161290 5.00000000
-106.45161290 9.67741935 5.00000000
-106.45161290 12.90322581 5.00000000
-106.45161290 16.12903226 5.00000000
-106.45161290 19.35483871 5.00000000
-106.45161290 22.58064516 5.00000000
-106.45161290 25.80645161 5.00000000
-106.45161290 29.03225806 5.00000000
-106.45161290 32.25806452 5.00000000
-106.45161290 35.48387097 4.77941176
-106.45161290 38.70967742 3.98809524
-106.45161290 41.93548387 3.39285714
-106.45161290 45.16129032 2.50000000
-106.45161290 48.38709677 2.50000000
-106.45161290 51.61290323 2.50000000
-106.45161290 54.83870968 2.50000000
-106.45161290 58.06451613 2.17261905
-106.45161290 61.29032258 2.17261905
-106.45161290 64.51612903 2.09558824
-106.45161290 67.74193548 2.05645161
-106.45161290 70.96774194 2.05645161
-106.45161290 74.19354839 2.05645161
-106.45161290 77.41935484 2.05645161
-106.45161290 80.64516129 2.05645161
-106.45161290 83.87096774 2.05645161
-106.45161290 87.09677419 2.05645161
-106.45161290 90.32258065 2.05645161
-106.45161290 93.54838710 2.05645161
-106.45161290 96.77419355 2.05645161
-106.45161290 100.00000000 2.05645161
-116.12903226 0.00000000 5.00000000
-116.12903226 3.22580645 5.00000000
-116.12903226 6.45161290 5.00000000
-116.12903226 9.67741935 5.00000000
-116.12903226 12.90322581 5.00000000
-116.12903226 16.12903226 5.00000000
-116.12903226 19.35483871 5.00000000
-116.12903226 22.58064516 5.00000000
-116.12903226 25.80645161 5.00000000
-116.12903226 29.03225806 5.00000000
-116.12903226 32.25806452 5.00000000
-116.12903226 35.48387097 4.87903226
-116.12903226 38.70967742 4.07258065
-116.12903226 41.93548387 3.26612903
-116.12903226 45.16129032 2.50000000
-116.12903226 48.38709677 2.50000000
-116.12903226 51.61290323 2.50000000
-116.12903226 54.83870968 2.50000000
-116.12903226 58.06451613 2.50000000
-116.12903226 61.29032258 2.50000000
-116.12903226 64.51612903 2.50000000
-116.12903226 67.74193548 2.50000000
-116.12903226 70.96774194 2.50000000
-116.12903226 74.19354839 2.50000000
-116.12903226 77.41935484 2.50000000
-116.12903226 80.64516129 2.50000000
-116.12903226 83.87096774 2.50000000
-116.12903226 87.09677419 2.50000000
-116.12903226 90.32258065 2.50000000
-116.12903226 93.54838710 2.50000000
-116.12903226 96.77419355 2.50000000
-116.12903226 100.00000000 2.50000000
-125.80645161 0.00000000 5.72580645
-125.80645161 3.22580645 5.72580645
-125.80645161 6.45161290 5.72580645
-125.80645161 9.67741935 5.72580645
-125.80645161 12.90322581 5.72580645
-125.80645161 16.12903226 5.72580645
-125.80645161 19.35483871 5.72580645
-125.80645161 22.58064516 5.72580645
-125.80645161 25.80645161 5.72580645
-125.80645161 29.03225806 5.72580645
-125.80645161 32.25806452 5.72580645
-125.80645161 35.48387097 5.55147059
-125.80645161 38.70967742 4.87244898
-125.80645161 41.93548387 4.36224490
-125.80645161 45.16129032 3.22580645
-125.80645161 48.38709677 3.22580645
-125.80645161 51.61290323 3.22580645
-125.80645161 54.83870968 3.22580645
-125.80645161 58.06451613 2.95918367
-125.80645161 61.29032258 2.95918367
-125.80645161 64.51612903 2.61029412
-125.80645161 67.74193548 2.50000000
-125.80645161 70.96774194 2.50000000
-125.80645161 74.19354839 2.50000000
-125.80645161 77.41935484 2.50000000
-125.80645161 80.64516129 2.50000000
-125.80645161 83.87096774 2.50000000
-125.80645161 87.09677419 2.50000000
-125.80645161 90.32258065 2.50000000
-125.80645161 93.54838710 2.50000000
-125.80645161 96.77419355 2.50000000
-125.80645161 100.00000000 2.50000000
-135.48387097 0.00000000 6.93548387
-135.48387097 3.22580645 6.93548387
-135.48387097 6.45161290 6.93548387
-135.48387097 9.67741935 6.93548387
-135.48387097 12.90322581 6.93548387
-135.48387097 16.12903226 6.93548387
-135.48387097 19.35483871 6.93548387
-135.48387097 22.58064516 6.93548387
-135.48387097 25.80645161 6.93548387
-135.48387097 29.03225806 6.93548387
-135.48387097 32.25806452 6.93548387
-135.48387097 35.48387097 6.65441176
-135.48387097 38.70967742 5.69444444
-135.48387097 41.93548387 5.13888889
-135.48387097 45.16129032 4.43548387
-135.48387097 48.38709677 4.43548387
-135.48387097 51.61290323 4.43548387
-135.48387097 54.83870968 4.43548387
-135.48387097 58.06451613 3.69444444
-135.48387097 61.29032258 3.13888889
-135.48387097 64.51612903 2.61029412
-135.48387097 67.74193548 2.50000000
-135.48387097 70.96774194 2.50000000
-135.48387097 74.19354839 2.50000000
-135.48387097 77.41935484 2.50000000
-135.48387097 80.64516129 2.50000000
-135.48387097 83.87096774 2.50000000
-135.48387097 87.09677419 2.50000000
-135.48387097 90.32258065 2.50000000
-135.48387097 93.54838710 2.50000000
-135.48387097 96.77419355 2.50000000
-135.48387097 100.00000000 2.50000000
-145.16129032 0.00000000 7.50000000
-145.16129032 3.22580645 7.50000000
-145.16129032 6.45161290 7.50000000
-145.16129032 9.67741935 7.50000000
-145.16129032 12.90322581 7.50000000
-145.16129032 16.12903226 7.50000000
-145.16129032 19.35483871 7.50000000
-145.16129032 22.58064516 7.50000000
-145.16129032 25.80645161 7.50000000
-145.16129032 29.03225806 7.50000000
-145.16129032 32.25806452 7.50000000
-145.16129032 35.48387097 7.37903226
-145.16129032 38.70967742 6.57258065
-145.16129032 41.93548387 5.76612903
-145.16129032 45.16129032 5.00000000
-145.16129032 48.38709677 5.00000000
-145.16129032 51.61290323 5.00000000
-145.16129032 54.83870968 5.00000000
-145.16129032 58.06451613 4.23387097
-145.16129032 61.29032258 3.42741935
-145.16129032 64.51612903 2.62096774
-145.16129032 67.74193548 2.50000000
-145.16129032 70.96774194 2.50000000
-145.16129032 74.19354839 2.50000000
-145.16129032 77.41935484 2.50000000
-145.16129032 80.64516129 2.50000000
-145.16129032 83.87096774 2.50000000
-145.16129032 87.09677419 2.50000000
-145.16129032 90.32258065 2.50000000
-145.16129032 93.54838710 2.50000000
-145.16129032 96.77419355 2.50000000
-145.16129032 100.00000000 2.50000000
-154.83870968 0.00000000 7.50000000
-154.83870968 3.22580645 7.50000000
-154.83870968 6.45161290 7.50000000
-154.83870968 9.67741935 7.50000000
-154.83870968 12.90322581 7.50000000
-154.83870968 16.12903226 7.50000000
-154.83870968 19.35483871 7.50000000
-154.83870968 22.58064516 7.50000000
-154.83870968 25.80645161 7.50000000
-154.83870968 29.03225806 7.50000000
-154.83870968 32.25806452 7.50000000
-154.83870968 35.48387097 7.38970588
-154.83870968 38.70967742 6.87500000
-154.83870968 41.93548387 6.33152174
-154.83870968 45.16129032 5.60483871
-154.83870968 48.38709677 5.60483871
-154.83870968 51.61290323 5.60483871
-154.83870968 54.83870968 5.60483871
-154.83870968 58.06451613 4.89130435
-154.83870968 61.29032258 4.34782609
-154.83870968 64.51612903 3.38235294
-154.83870968 67.74193548 3.10483871
-154.83870968 70.96774194 3.10483871
-154.83870968 74.19354839 3.10483871
-154.83870968 77.41935484 3.10483871
-154.83870968 80.64516129 3.10483871
-154.83870968 83.87096774 3.10483871
-154.83870968 87.09677419 3.10483871
-154.83870968 90.32258065 3.10483871
-154.83870968 93.54838710 3.10483871
-154.83870968 96.77419355 3.10483871
-154.83870968 100.00000000 3.10483871
-164.51612903 0.00000000 7.50000000
-164.51612903 3.22580645 7.50000000
-164.51612903 6.45161290 7.50000000
-164.51612903 9.67741935 7.50000000
-164.51612903 12.90322581 7.50000000
-164.51612903 16.12903226 7.50000000
-164.51612903 19.35483871 7.50000000
-164.51612903 22.58064516 7.50000000
-164.51612903 25.80645161 7.50000000
-164.51612903 29.03225806 7.50000000
-164.51612903 32.25806452 7.50000000
-164.51612903 35.48387097 7.38970588
-164.51612903 38.70967742 7.05729167
-164.51612903 41.93548387 7.05729167
-164.51612903 45.16129032 6.81451613
-164.51612903 48.38709677 6.81451613
-164.51612903 51.61290323 6.81451613
-164.51612903 54.83870968 6.81451613
-164.51612903 58.06451613 5.67708333
-164.51612903 61.29032258 5.15625000
-164.51612903 64.51612903 4.48529412
-164.51612903 67.74193548 4.31451613
-164.51612903 70.96774194 4.31451613
-164.51612903 74.19354839 4.31451613
-164.51612903 77.41935484 4.31451613
-164.51612903 80.64516129 4.31451613
-164.51612903 83.87096774 4.31451613
-164.51612903 87.09677419 4.31451613
-164.51612903 90.32258065 4.31451613
-164.51612903 93.54838710 4.31451613
-164.51612903 96.77419355 4.31451613
-164.51612903 100.00000000 4.31451613
-174.19354839 0.00000000 7.50000000
-174.19354839 3.22580645 7.50000000
-174.19354839 6.45161290 7.50000000
-174.19354839 9.67741935 7.50000000
-174.19354839 12.90322581 7.50000000
-174.19354839 16.12903226 7.50000000
-174.19354839 19.35483871 7.50000000
-174.19354839 22.58064516 7.50000000
-174.19354839 25.80645161 7.50000000
-174.19354839 29.03225806 7.50000000
-174.19354839 32.25806452 7.50000000
-174.19354839 35.48387097 7.50000000
-174.19354839 38.70967742 7.50000000
-174.19354839 41.93548387 7.50000000
-174.19354839 45.16129032 7.50000000
-174.19354839 48.38709677 7.50000000
-174.19354839 51.61290323 7.50000000
-174.19354839 54.83870968 7.50000000
-174.19354839 58.06451613 6.73387097
-174.19354839 61.29032258 5.92741935
-174.19354839 64.51612903 5.12096774
-174.19354839 67.74193548 5.00000000
-174.19354839 70.96774194 5.00000000
-174.19354839 74.19354839 5.00000000
-174.19354839 77.41935484 5.00000000
-174.19354839 80.64516129 5.00000000
-174.19354839 83.87096774 5.00000000
-174.19354839 87.09677419 5.00000000
-174.19354839 90.32258065 5.00000000
-174.19354839 93.54838710 5.00000000
-174.19354839 96.77419355 5.00000000
-174.19354839 100.00000000 5.00000000
-183.87096774 0.00000000 7.98387097
-183.87096774 3.22580645 7.98387097
-183.87096774 6.45161290 7.98387097
-183.87096774 9.67741935 7.98387097
-183.87096774 12.90322581 7.98387097
-183.87096774 16.12903226 7.98387097
-183.87096774 19.35483871 7.98387097
-183.87096774 22.58064516 7.98387097
-183.87096774 25.80645161 7.98387097
-183.87096774 29.03225806 7.98387097
-183.87096774 32.25806452 7.98387097
-183.87096774 35.48387097 7.94117647
-183.87096774 38.70967742 7.84883721
-183.87096774 41.93548387 7.84883721
-183.87096774 45.16129032 7.50000000
-183.87096774 48.38709677 7.50000000
-183.87096774 51.61290323 7.50000000
-183.87096774 54.83870968 7.50000000
-183.87096774 58.06451613 6.59883721
-183.87096774 61.29032258 6.01744186
-183.87096774 64.51612903 5.22058824
-183.87096774 67.74193548 5.00000000
-183.87096774 70.96774194 5.00000000
-183.87096774 74.19354839 5.00000000
-183.87096774 77.41935484 5.00000000
-183.87096774 80.64516129 5.00000000
-183.87096774 83.87096774 5.00000000
-183.87096774 87.09677419 5.00000000
-183.87096774 90.32258065 5.00000000
-183.87096774 93.54838710 5.00000000
-183.87096774 96.77419355 5.00000000
-183.87096774 100.00000000 5.00000000
-193.54838710 0.00000000 9.19354839
-193.54838710 3.22580645 9.19354839
-193.54838710 6.45161290 9.19354839
-193.54838710 9.67741935 9.19354839
-193.54838710 12.90322581 9.19354839
-193.54838710 16.12903226 9.19354839
-193.54838710 19.35483871 9.19354839
-193.54838710 22.58064516 9.19354839
-193.54838710 25.80645161 9.19354839
-193.54838710 29.03225806 9.19354839
-193.54838710 32.25806452 9.19354839
-193.54838710 35.48387097 9.04411765
-193.54838710 38.70967742 8.45588235
-193.54838710 41.93548387 7.97500000
-193.54838710 45.16129032 7.50000000
-193.54838710 48.38709677 7.50000000
-193.54838710 51.61290323 7.50000000
-193.54838710 54.83870968 7.50000000
-193.54838710 58.06451613 6.55000000
-193.54838710 61.29032258 6.05392157
-193.54838710 64.51612903 5.22058824
-193.54838710 67.74193548 5.00000000
-193.54838710 70.96774194 5.00000000
-193.54838710 74.19354839 5.00000000
-193.54838710 77.41935484 5.00000000
-193.54838710 80.64516129 5.00000000
-193.54838710 83.87096774 5.00000000
-193.54838710 87.09677419 5.00000000
-193.54838710 90.32258065 5.00000000
-193.54838710 93.54838710 5.00000000
-193.54838710 96.77419355 5.00000000
-193.54838710 100.00000000 5.00000000
-203.22580645 0.00000000 10.00000000
-203.22580645 3.22580645 10.00000000
-203.22580645 6.45161290 10.00000000
-203.22580645 9.67741935 10.00000000
-203.22580645 12.90322581 10.00000000
-203.22580645 16.12903226 10.00000000
-203.22580645 19.35483871 10.00000000
-203.22580645 22.58064516 10.00000000
-203.22580645 25.80645161 10.00000000
-203.22580645 29.03225806 10.00000000
-203.22580645 32.25806452 10.00000000
-203.22580645 35.48387097 9.87903226
-203.22580645 38.70967742 9.07258065
-203.22580645 41.93548387 8.26612903
-203.22580645 45.16129032 7.50000000
-203.22580645 48.38709677 7.50000000
-203.22580645 51.61290323 7.50000000
-203.22580645 54.83870968 7.50000000
-203.22580645 58.06451613 6.73387097
-203.22580645 61.29032258 5.92741935
-203.22580645 64.51612903 5.12096774
-203.22580645 67.74193548 5.00000000
-203.22580645 70.96774194 5.00000000
-203.22580645 74.19354839 5.00000000
-203.22580645 77.41935484 5.00000000
-203.22580645 80.64516129 5.00000000
-203.22580645 83.87096774 5.00000000
-203.22580645 87.09677419 5.00000000
-203.22580645 90.32258065 5.00000000
-203.22580645 93.54838710 5.00000000
-203.22580645 96.77419355 5.00000000
-203.22580645 100.00000000 5.00000000
-212.90322581 0.00000000 10.00000000
-212.90322581 3.22580645 10.00000000
-212.90322581 6.45161290 10.00000000
-212.90322581 9.67741935 10.00000000
-212.90322581 12.90322581 10.00000000
-212.90322581 16.12903226 10.00000000
-212.90322581 19.35483871 10.00000000
-212.90322581 22.58064516 10.00000000
-212.90322581 25.80645161 10.00000000
-212.90322581 29.03225806 10.00000000
-212.90322581 32.25806452 10.00000000
-212.90322581 35.48387097 9.87903226
-212.90322581 38.70967742 9.07258065
-212.90322581 41.93548387 8.26612903
-212.90322581 45.16129032 7.50000000
-212.90322581 48.38709677 7.50000000
-212.90322581 51.61290323 7.50000000
-212.90322581 54.83870968 7.50000000
-212.90322581 58.06451613 6.73387097
-212.90322581 61.29032258 5.92741935
-212.90322581 64.51612903 5.12096774
-212.90322581 67.74193548 5.00000000
-212.90322581 70.96774194 5.00000000
-212.90322581 74.19354839 5.00000000
-212.90322581 77.41935484 5.00000000
-212.90322581 80.64516129 5.00000000
-212.90322581 83.87096774 5.00000000
-212.90322581 87.09677419 5.00000000
-212.90322581 90.32258065 5.00000000
-212.90322581 93.54838710 5.00000000
-212.90322581 96.77419355 5.00000000
-212.90322581 100.00000000 5.00000000
-222.58064516 0.00000000 10.00000000
-222.58064516 3.22580645 10.00000000
-222.58064516 6.45161290 10.00000000
-222.58064516 9.67741935 10.00000000
-222.58064516 12.90322581 10.00000000
-222.58064516 16.12903226 10.00000000
-222.58064516 19.35483871 10.00000000
-222.58064516 22.58064516 10.00000000
-222.58064516 25.80645161 10.00000000
-222.58064516 29.03225806 10.00000000
-222.58064516 32.25806452 10.00000000
-222.58064516 35.48387097 9.87903226
-222.58064516 38.70967742 9.07258065
-222.58064516 41.93548387 8.26612903
-222.58064516 45.16129032 7.50000000
-222.58064516 48.38709677 7.50000000
-222.58064516 51.61290323 7.50000000
-222.58064516 54.83870968 7.50000000
-222.58064516 58.06451613 6.73387097
-222.58064516 61.29032258 5.92741935
-222.58064516 64.51612903 5.12096774
-222.58064516 67.74193548 5.00000000
-222.58064516 70.96774194 5.00000000
-222.58064516 74.19354839 5.00000000
-222.58064516 77.41935484 5.00000000
-222.58064516 80.64516129 5.00000000
-222.58064516 83.87096774 5.00000000
-222.58064516 87.09677419 5.00000000
-222.58064516 90.32258065 5.00000000
-222.58064516 93.54838710 5.00000000
-222.58064516 96.77419355 5.00000000
-222.58064516 100.00000000 5.00000000
-232.25806452 0.00000000 10.00000000
-232.25806452 3.22580645 10.00000000
-232.25806452 6.45161290 10.00000000
-232.25806452 9.67741935 10.00000000
-232.25806452 12.90322581 10.00000000
-232.25806452 16.12903226 10.00000000
-232.25806452 19.35483871 10.00000000
-232.25806452 22.58064516 10.00000000
-232.25806452 25.80645161 10.00000000
-232.25806452 29.03225806 10.00000000
-232.25806452 32.25806452 10.00000000
-232.25806452 35.48387097 9.87903226
-232.25806452 38.70967742 9.07258065
-232.25806452 41.93548387 8.26612903
-232.25806452 45.16129032 7.50000000
-232.25806452 48.38709677 7.50000000
-232.25806452 51.61290323 7.50000000
-232.25806452 54.83870968 7.50000000
-232.25806452 58.06451613 6.73387097
-232.25806452 61.29032258 5.92741935
-232.25806452 64.51612903 5.12096774
-232.25806452 67.74193548 5.00000000
-232.25806452 70.96774194 5.00000000
-232.25806452 74.19354839 5.00000000
-232.25806452 77.41935484 5.00000000
-232.25806452 80.64516129 5.00000000
-232.25806452 83.87096774 5.00000000
-232.25806452 87.09677419 5.00000000
-232.25806452 90.32258065 5.00000000
-232.25806452 93.54838710 5.00000000
-232.25806452 96.77419355 5.00000000
-232.25806452 100.00000000 5.00000000
-241.93548387 0.00000000 10.00000000
-241.93548387 3.22580645 10.00000000
-241.93548387 6.45161290 10.00000000
-241.93548387 9.67741935 10.00000000
-241.93548387 12.90322581 10.00000000
-241.93548387 16.12903226 10.00000000
-241.93548387 19.35483871 10.00000000
-241.93548387 22.58064516 10.00000000
-241.93548387 25.80645161 10.00000000
-241.93548387 29.03225806 10.00000000
-241.93548387 32.25806452 10.00000000
-241.93548387 35.48387097 9.87903226
-241.93548387 38.70967742 9.07258065
-241.93548387 41.93548387 8.26612903
-241.93548387 45.16129032 7.50000000
-241.93548387 48.38709677 7.50000000
-241.93548387 51.61290323 7.50000000
-241.93548387 54.83870968 7.50000000
-241.93548387 58.06451613 6.73387097
-241.93548387 61.29032258 5.92741935
-241.93548387 64.51612903 5.12096774
-241.93548387 67.74193548 5.00000000
-241.93548387 70.96774194 5.00000000
-241.93548387 74.19354839 5.00000000
-241.93548387 77.41935484 5.00000000
-241.93548387 80.64516129 5.00000000
-241.93548387 83.87096774 5.00000000
-241.93548387 87.09677419 5.00000000
-241.93548387 90.32258065 5.00000000
-241.93548387 93.54838710 5.00000000
-241.93548387 96.77419355 5.00000000
-241.93548387 100.00000000 5.00000000
-251.61290323 0.00000000 10.00000000
-251.61290323 3.22580645 10.00000000
-251.61290323 6.45161290 10.00000000
-251.61290323 9.67741935 10.00000000
-251.61290323 12.90322581 10.00000000
-251.61290323 16.12903226 10.00000000
-251.61290323 19.35483871 10.00000000
-251.61290323 22.58064516 10.00000000
-251.61290323 25.80645161 10.00000000
-251.61290323 29.03225806 10.00000000
-251.61290323 32.25806452 10.00000000
-251.61290323 35.48387097 9.87903226
-251.61290323 38.70967742 9.07258065
-251.61290323 41.93548387 8.26612903
-251.61290323 45.16129032 7.50000000
-251.61290323 48.38709677 7.50000000
-251.61290323 51.61290323 7.50000000
-251.61290323 54.83870968 7.50000000
-251.61290323 58.06451613 6.73387097
-251.61290323 61.29032258 5.92741935
-251.61290323 64.51612903 5.12096774
-251.61290323 67.74193548 5.00000000
-251.61290323 70.96774194 5.00000000
-251.61290323 74.19354839 5.00000000
-251.61290323 77.41935484 5.00000000
-251.61290323 80.64516129 5.00000000
-251.61290323 83.87096774 5.00000000
-251.61290323 87.09677419 5.00000000
-251.61290323 90.32258065 5.00000000
-251.61290323 93.54838710 5.00000000
-251.61290323 96.77419355 5.00000000
-251.61290323 100.00000000 5.00000000
-261.29032258 0.00000000 10.00000000
-261.29032258 3.22580645 10.00000000
-261.29032258 6.45161290 10.00000000
-261.29032258 9.67741935 10.00000000
-261.29032258 12.90322581 10.00000000
-261.29032258 16.12903226 10.00000000
-261.29032258 19.35483871 10.00000000
-261.29032258 22.58064516 10.00000000
-261.29032258 25.80645161 10.00000000
-261.29032258 29.03225806 10.00000000
-261.29032258 32.25806452 10.00000000
-261.29032258 35.48387097 9.87903226
-261.29032258 38.70967742 9.07258065
-261.29032258 41.93548387 8.26612903
-261.29032258 45.16129032 7.50000000
-261.29032258 48.38709677 7.50000000
-261.29032258 51.61290323 7.50000000
-261.29032258 54.83870968 7.50000000
-261.29032258 58.06451613 6.73387097
-261.29032258 61.29032258 5.92741935
-261.29032258 64.51612903 5.12096774
-261.29032258 67.74193548 5.00000000
-261.29032258 70.96774194 5.00000000
-261.29032258 74.19354839 5.00000000
-261.29032258 77.41935484 5.00000000
-261.29032258 80.64516129 5.00000000
-261.29032258 83.87096774 5.00000000
-261.29032258 87.09677419 5.00000000
-261.29032258 90.32258065 5.00000000
-261.29032258 93.54838710 5.00000000
-261.29032258 96.77419355 5.00000000
-261.29032258 100.00000000 5.00000000
-270.96774194 0.00000000 10.00000000
-270.96774194 3.22580645 10.00000000
-270.96774194 6.45161290 10.00000000
-270.96774194 9.67741935 10.00000000
-270.96774194 12.90322581 10.00000000
-270.96774194 16.12903226 10.00000000
-270.96774194 19.35483871 10.00000000
-270.96774194 22.58064516 10.00000000
-270.96774194 25.80645161 10.00000000
-270.96774194 29.03225806 10.00000000
-270.96774194 32.25806452 10.00000000
-270.96774194 35.48387097 9.87903226
-270.96774194 38.70967742 9.07258065
-270.96774194 41.93548387 8.26612903
-270.96774194 45.16129032 7.50000000
-270.96774194 48.38709677 7.50000000
-270.96774194 51.61290323 7.50000000
-270.96774194 54.83870968 7.50000000
-270.96774194 58.06451613 6.73387097
-270.96774194 61.29032258 5.92741935
-270.96774194 64.51612903 5.12096774
-270.96774194 67.74193548 5.00000000
-270.96774194 70.96774194 5.00000000
-270.96774194 74.19354839 5.00000000
-270.96774194 77.41935484 5.00000000
-270.96774194 80.64516129 5.00000000
-270.96774194 83.87096774 5.00000000
-270.96774194 87.09677419 5.00000000
-270.96774194 90.32258065 5.00000000
-270.96774194 93.54838710 5.00000000
-270.96774194 96.77419355 5.00000000
-270.96774194 100.00000000 5.00000000
-280.64516129 0.00000000 10.00000000
-280.64516129 3.22580645 10.00000000
-280.64516129 6.45161290 10.00000000
-280.64516129 9.67741935 10.00000000
-280.64516129 12.90322581 10.00000000
-280.64516129 16.12903226 10.00000000
-280.64516129 19.35483871 10.00000000
-280.64516129 22.58064516 10.00000000
-280.64516129 25.80645161 10.00000000
-280.64516129 29.03225806 10.00000000
-280.64516129 32.25806452 10.00000000
-280.64516129 35.48387097 9.87903226
-280.64516129 38.70967742 9.07258065
-280.64516129 41.93548387 8.26612903
-280.64516129 45.16129032 7.50000000
-280.64516129 48.38709677 7.50000000
-280.64516129 51.61290323 7.50000000
-280.64516129 54.83870968 7.50000000
-280.64516129 58.06451613 6.73387097
-280.64516129 61.29032258 5.92741935
-280.64516129 64.51612903 5.12096774
-280.64516129 67.74193548 5.00000000
-280.64516129 70.96774194 5.00000000
-280.64516129 74.19354839 5.00000000
-280.64516129 77.41935484 5.00000000
-280.64516129 80.64516129 5.00000000
-280.64516129 83.87096774 5.00000000
-280.64516129 87.09677419 5.00000000
-280.64516129 90.32258065 5.00000000
-280.64516129 93.54838710 5.00000000
-280.64516129 96.77419355 5.00000000
-280.64516129 100.00000000 5.00000000
-290.32258065 0.00000000 10.00000000
-290.32258065 3.22580645 10.00000000
-290.32258065 6.45161290 10.00000000
-290.32258065 9.67741935 10.00000000
-290.32258065 12.90322581 10.00000000
-290.32258065 16.12903226 10.00000000
-290.32258065 19.35483871 10.00000000
-290.32258065 22.58064516 10.00000000
-290.32258065 25.80645161 10.00000000
-290.32258065 29.03225806 10.00000000
-290.32258065 32.25806452 10.00000000
-290.32258065 35.48387097 9.87903226
-290.32258065 38.70967742 9.07258065
-290.32258065 41.93548387 8.26612903
-290.32258065 45.16129032 7.50000000
-290.32258065 48.38709677 7.50000000
-290.32258065 51.61290323 7.50000000
-290.32258065 54.83870968 7.50000000
-290.32258065 58.06451613 6.73387097
-290.32258065 61.29032258 5.92741935
-290.32258065 64.51612903 5.12096774
-290.32258065 67.74193548 5.00000000
-290.32258065 70.96774194 5.00000000
-290.32258065 74.19354839 5.00000000
-290.32258065 77.41935484 5.00000000
-290.32258065 80.64516129 5.00000000
-290.32258065 83.87096774 5.00000000
-290.32258065 87.09677419 5.00000000
-290.32258065 90.32258065 5.00000000
-290.32258065 93.54838710 5.00000000
-290.32258065 96.77419355 5.00000000
-290.32258065 100.00000000 5.00000000
-300.00000000 0.00000000 10.00000000
-300.00000000 3.22580645 10.00000000
-300.00000000 6.45161290 10.00000000
-300.00000000 9.67741935 10.00000000
-300.00000000 12.90322581 10.00000000
-300.00000000 16.12903226 10.00000000
-300.00000000 19.35483871 10.00000000
-300.00000000 22.58064516 10.00000000
-300.00000000 25.80645161 10.00000000
-300.00000000 29.03225806 10.00000000
-300.00000000 32.25806452 10.00000000
-300.00000000 35.48387097 9.87903226
-300.00000000 38.70967742 9.07258065
-300.00000000 41.93548387 8.26612903
-300.00000000 45.16129032 7.50000000
-300.00000000 48.38709677 7.50000000
-300.00000000 51.61290323 7.50000000
-300.00000000 54.83870968 7.50000000
-300.00000000 58.06451613 6.73387097
-300.00000000 61.29032258 5.92741935
-300.00000000 64.51612903 5.12096774
-300.00000000 67.74193548 5.00000000
-300.00000000 70.96774194 5.00000000
-300.00000000 74.19354839 5.00000000
-300.00000000 77.41935484 5.00000000
-300.00000000 80.64516129 5.00000000
-300.00000000 83.87096774 5.00000000
-300.00000000 87.09677419 5.00000000
-300.00000000 90.32258065 5.00000000
-300.00000000 93.54838710 5.00000000
-300.00000000 96.77419355 5.00000000
-300.00000000 100.00000000 5.00000000
+LDLLevel HDLLevel HeartDiseaseRisk
+0.000000000 0.000000000 5.000000000
+0.000000000 3.225806452 5.000000000
+0.000000000 6.451612903 5.000000000
+0.000000000 9.677419355 5.000000000
+0.000000000 12.903225806 5.000000000
+0.000000000 16.129032258 5.000000000
+0.000000000 19.354838710 5.000000000
+0.000000000 22.580645161 5.000000000
+0.000000000 25.806451613 5.000000000
+0.000000000 29.032258065 5.000000000
+0.000000000 32.258064516 5.000000000
+0.000000000 35.483870968 4.879032258
+0.000000000 38.709677419 4.072580645
+0.000000000 41.935483871 3.266129032
+0.000000000 45.161290323 2.500000000
+0.000000000 48.387096774 2.500000000
+0.000000000 51.612903226 2.500000000
+0.000000000 54.838709677 2.500000000
+0.000000000 58.064516129 1.733870968
+0.000000000 61.290322581 0.927419355
+0.000000000 64.516129032 0.120967742
+0.000000000 67.741935484 0.000000000
+0.000000000 70.967741935 0.000000000
+0.000000000 74.193548387 0.000000000
+0.000000000 77.419354839 0.000000000
+0.000000000 80.645161290 0.000000000
+0.000000000 83.870967742 0.000000000
+0.000000000 87.096774194 0.000000000
+0.000000000 90.322580645 0.000000000
+0.000000000 93.548387097 0.000000000
+0.000000000 96.774193548 0.000000000
+0.000000000 100.000000000 0.000000000
+9.677419355 0.000000000 5.000000000
+9.677419355 3.225806452 5.000000000
+9.677419355 6.451612903 5.000000000
+9.677419355 9.677419355 5.000000000
+9.677419355 12.903225806 5.000000000
+9.677419355 16.129032258 5.000000000
+9.677419355 19.354838710 5.000000000
+9.677419355 22.580645161 5.000000000
+9.677419355 25.806451613 5.000000000
+9.677419355 29.032258065 5.000000000
+9.677419355 32.258064516 5.000000000
+9.677419355 35.483870968 4.879032258
+9.677419355 38.709677419 4.072580645
+9.677419355 41.935483871 3.266129032
+9.677419355 45.161290323 2.500000000
+9.677419355 48.387096774 2.500000000
+9.677419355 51.612903226 2.500000000
+9.677419355 54.838709677 2.500000000
+9.677419355 58.064516129 1.733870968
+9.677419355 61.290322581 0.927419355
+9.677419355 64.516129032 0.120967742
+9.677419355 67.741935484 0.000000000
+9.677419355 70.967741935 0.000000000
+9.677419355 74.193548387 0.000000000
+9.677419355 77.419354839 0.000000000
+9.677419355 80.645161290 0.000000000
+9.677419355 83.870967742 0.000000000
+9.677419355 87.096774194 0.000000000
+9.677419355 90.322580645 0.000000000
+9.677419355 93.548387097 0.000000000
+9.677419355 96.774193548 0.000000000
+9.677419355 100.000000000 0.000000000
+19.354838710 0.000000000 5.000000000
+19.354838710 3.225806452 5.000000000
+19.354838710 6.451612903 5.000000000
+19.354838710 9.677419355 5.000000000
+19.354838710 12.903225806 5.000000000
+19.354838710 16.129032258 5.000000000
+19.354838710 19.354838710 5.000000000
+19.354838710 22.580645161 5.000000000
+19.354838710 25.806451613 5.000000000
+19.354838710 29.032258065 5.000000000
+19.354838710 32.258064516 5.000000000
+19.354838710 35.483870968 4.879032258
+19.354838710 38.709677419 4.072580645
+19.354838710 41.935483871 3.266129032
+19.354838710 45.161290323 2.500000000
+19.354838710 48.387096774 2.500000000
+19.354838710 51.612903226 2.500000000
+19.354838710 54.838709677 2.500000000
+19.354838710 58.064516129 1.733870968
+19.354838710 61.290322581 0.927419355
+19.354838710 64.516129032 0.120967742
+19.354838710 67.741935484 0.000000000
+19.354838710 70.967741935 0.000000000
+19.354838710 74.193548387 0.000000000
+19.354838710 77.419354839 0.000000000
+19.354838710 80.645161290 0.000000000
+19.354838710 83.870967742 0.000000000
+19.354838710 87.096774194 0.000000000
+19.354838710 90.322580645 0.000000000
+19.354838710 93.548387097 0.000000000
+19.354838710 96.774193548 0.000000000
+19.354838710 100.000000000 0.000000000
+29.032258065 0.000000000 5.000000000
+29.032258065 3.225806452 5.000000000
+29.032258065 6.451612903 5.000000000
+29.032258065 9.677419355 5.000000000
+29.032258065 12.903225806 5.000000000
+29.032258065 16.129032258 5.000000000
+29.032258065 19.354838710 5.000000000
+29.032258065 22.580645161 5.000000000
+29.032258065 25.806451613 5.000000000
+29.032258065 29.032258065 5.000000000
+29.032258065 32.258064516 5.000000000
+29.032258065 35.483870968 4.879032258
+29.032258065 38.709677419 4.072580645
+29.032258065 41.935483871 3.266129032
+29.032258065 45.161290323 2.500000000
+29.032258065 48.387096774 2.500000000
+29.032258065 51.612903226 2.500000000
+29.032258065 54.838709677 2.500000000
+29.032258065 58.064516129 1.733870968
+29.032258065 61.290322581 0.927419355
+29.032258065 64.516129032 0.120967742
+29.032258065 67.741935484 0.000000000
+29.032258065 70.967741935 0.000000000
+29.032258065 74.193548387 0.000000000
+29.032258065 77.419354839 0.000000000
+29.032258065 80.645161290 0.000000000
+29.032258065 83.870967742 0.000000000
+29.032258065 87.096774194 0.000000000
+29.032258065 90.322580645 0.000000000
+29.032258065 93.548387097 0.000000000
+29.032258065 96.774193548 0.000000000
+29.032258065 100.000000000 0.000000000
+38.709677419 0.000000000 5.000000000
+38.709677419 3.225806452 5.000000000
+38.709677419 6.451612903 5.000000000
+38.709677419 9.677419355 5.000000000
+38.709677419 12.903225806 5.000000000
+38.709677419 16.129032258 5.000000000
+38.709677419 19.354838710 5.000000000
+38.709677419 22.580645161 5.000000000
+38.709677419 25.806451613 5.000000000
+38.709677419 29.032258065 5.000000000
+38.709677419 32.258064516 5.000000000
+38.709677419 35.483870968 4.879032258
+38.709677419 38.709677419 4.072580645
+38.709677419 41.935483871 3.266129032
+38.709677419 45.161290323 2.500000000
+38.709677419 48.387096774 2.500000000
+38.709677419 51.612903226 2.500000000
+38.709677419 54.838709677 2.500000000
+38.709677419 58.064516129 1.733870968
+38.709677419 61.290322581 0.927419355
+38.709677419 64.516129032 0.120967742
+38.709677419 67.741935484 0.000000000
+38.709677419 70.967741935 0.000000000
+38.709677419 74.193548387 0.000000000
+38.709677419 77.419354839 0.000000000
+38.709677419 80.645161290 0.000000000
+38.709677419 83.870967742 0.000000000
+38.709677419 87.096774194 0.000000000
+38.709677419 90.322580645 0.000000000
+38.709677419 93.548387097 0.000000000
+38.709677419 96.774193548 0.000000000
+38.709677419 100.000000000 0.000000000
+48.387096774 0.000000000 5.000000000
+48.387096774 3.225806452 5.000000000
+48.387096774 6.451612903 5.000000000
+48.387096774 9.677419355 5.000000000
+48.387096774 12.903225806 5.000000000
+48.387096774 16.129032258 5.000000000
+48.387096774 19.354838710 5.000000000
+48.387096774 22.580645161 5.000000000
+48.387096774 25.806451613 5.000000000
+48.387096774 29.032258065 5.000000000
+48.387096774 32.258064516 5.000000000
+48.387096774 35.483870968 4.879032258
+48.387096774 38.709677419 4.072580645
+48.387096774 41.935483871 3.266129032
+48.387096774 45.161290323 2.500000000
+48.387096774 48.387096774 2.500000000
+48.387096774 51.612903226 2.500000000
+48.387096774 54.838709677 2.500000000
+48.387096774 58.064516129 1.733870968
+48.387096774 61.290322581 0.927419355
+48.387096774 64.516129032 0.120967742
+48.387096774 67.741935484 0.000000000
+48.387096774 70.967741935 0.000000000
+48.387096774 74.193548387 0.000000000
+48.387096774 77.419354839 0.000000000
+48.387096774 80.645161290 0.000000000
+48.387096774 83.870967742 0.000000000
+48.387096774 87.096774194 0.000000000
+48.387096774 90.322580645 0.000000000
+48.387096774 93.548387097 0.000000000
+48.387096774 96.774193548 0.000000000
+48.387096774 100.000000000 0.000000000
+58.064516129 0.000000000 5.000000000
+58.064516129 3.225806452 5.000000000
+58.064516129 6.451612903 5.000000000
+58.064516129 9.677419355 5.000000000
+58.064516129 12.903225806 5.000000000
+58.064516129 16.129032258 5.000000000
+58.064516129 19.354838710 5.000000000
+58.064516129 22.580645161 5.000000000
+58.064516129 25.806451613 5.000000000
+58.064516129 29.032258065 5.000000000
+58.064516129 32.258064516 5.000000000
+58.064516129 35.483870968 4.879032258
+58.064516129 38.709677419 4.072580645
+58.064516129 41.935483871 3.266129032
+58.064516129 45.161290323 2.500000000
+58.064516129 48.387096774 2.500000000
+58.064516129 51.612903226 2.500000000
+58.064516129 54.838709677 2.500000000
+58.064516129 58.064516129 1.733870968
+58.064516129 61.290322581 0.927419355
+58.064516129 64.516129032 0.120967742
+58.064516129 67.741935484 0.000000000
+58.064516129 70.967741935 0.000000000
+58.064516129 74.193548387 0.000000000
+58.064516129 77.419354839 0.000000000
+58.064516129 80.645161290 0.000000000
+58.064516129 83.870967742 0.000000000
+58.064516129 87.096774194 0.000000000
+58.064516129 90.322580645 0.000000000
+58.064516129 93.548387097 0.000000000
+58.064516129 96.774193548 0.000000000
+58.064516129 100.000000000 0.000000000
+67.741935484 0.000000000 5.000000000
+67.741935484 3.225806452 5.000000000
+67.741935484 6.451612903 5.000000000
+67.741935484 9.677419355 5.000000000
+67.741935484 12.903225806 5.000000000
+67.741935484 16.129032258 5.000000000
+67.741935484 19.354838710 5.000000000
+67.741935484 22.580645161 5.000000000
+67.741935484 25.806451613 5.000000000
+67.741935484 29.032258065 5.000000000
+67.741935484 32.258064516 5.000000000
+67.741935484 35.483870968 4.879032258
+67.741935484 38.709677419 4.072580645
+67.741935484 41.935483871 3.266129032
+67.741935484 45.161290323 2.500000000
+67.741935484 48.387096774 2.500000000
+67.741935484 51.612903226 2.500000000
+67.741935484 54.838709677 2.500000000
+67.741935484 58.064516129 1.733870968
+67.741935484 61.290322581 0.927419355
+67.741935484 64.516129032 0.120967742
+67.741935484 67.741935484 0.000000000
+67.741935484 70.967741935 0.000000000
+67.741935484 74.193548387 0.000000000
+67.741935484 77.419354839 0.000000000
+67.741935484 80.645161290 0.000000000
+67.741935484 83.870967742 0.000000000
+67.741935484 87.096774194 0.000000000
+67.741935484 90.322580645 0.000000000
+67.741935484 93.548387097 0.000000000
+67.741935484 96.774193548 0.000000000
+67.741935484 100.000000000 0.000000000
+77.419354839 0.000000000 5.000000000
+77.419354839 3.225806452 5.000000000
+77.419354839 6.451612903 5.000000000
+77.419354839 9.677419355 5.000000000
+77.419354839 12.903225806 5.000000000
+77.419354839 16.129032258 5.000000000
+77.419354839 19.354838710 5.000000000
+77.419354839 22.580645161 5.000000000
+77.419354839 25.806451613 5.000000000
+77.419354839 29.032258065 5.000000000
+77.419354839 32.258064516 5.000000000
+77.419354839 35.483870968 4.879032258
+77.419354839 38.709677419 4.072580645
+77.419354839 41.935483871 3.266129032
+77.419354839 45.161290323 2.500000000
+77.419354839 48.387096774 2.500000000
+77.419354839 51.612903226 2.500000000
+77.419354839 54.838709677 2.500000000
+77.419354839 58.064516129 1.733870968
+77.419354839 61.290322581 0.927419355
+77.419354839 64.516129032 0.120967742
+77.419354839 67.741935484 0.000000000
+77.419354839 70.967741935 0.000000000
+77.419354839 74.193548387 0.000000000
+77.419354839 77.419354839 0.000000000
+77.419354839 80.645161290 0.000000000
+77.419354839 83.870967742 0.000000000
+77.419354839 87.096774194 0.000000000
+77.419354839 90.322580645 0.000000000
+77.419354839 93.548387097 0.000000000
+77.419354839 96.774193548 0.000000000
+77.419354839 100.000000000 0.000000000
+87.096774194 0.000000000 5.000000000
+87.096774194 3.225806452 5.000000000
+87.096774194 6.451612903 5.000000000
+87.096774194 9.677419355 5.000000000
+87.096774194 12.903225806 5.000000000
+87.096774194 16.129032258 5.000000000
+87.096774194 19.354838710 5.000000000
+87.096774194 22.580645161 5.000000000
+87.096774194 25.806451613 5.000000000
+87.096774194 29.032258065 5.000000000
+87.096774194 32.258064516 5.000000000
+87.096774194 35.483870968 4.879032258
+87.096774194 38.709677419 4.072580645
+87.096774194 41.935483871 3.266129032
+87.096774194 45.161290323 2.500000000
+87.096774194 48.387096774 2.500000000
+87.096774194 51.612903226 2.500000000
+87.096774194 54.838709677 2.500000000
+87.096774194 58.064516129 1.733870968
+87.096774194 61.290322581 0.927419355
+87.096774194 64.516129032 0.120967742
+87.096774194 67.741935484 0.000000000
+87.096774194 70.967741935 0.000000000
+87.096774194 74.193548387 0.000000000
+87.096774194 77.419354839 0.000000000
+87.096774194 80.645161290 0.000000000
+87.096774194 83.870967742 0.000000000
+87.096774194 87.096774194 0.000000000
+87.096774194 90.322580645 0.000000000
+87.096774194 93.548387097 0.000000000
+87.096774194 96.774193548 0.000000000
+87.096774194 100.000000000 0.000000000
+96.774193548 0.000000000 5.000000000
+96.774193548 3.225806452 5.000000000
+96.774193548 6.451612903 5.000000000
+96.774193548 9.677419355 5.000000000
+96.774193548 12.903225806 5.000000000
+96.774193548 16.129032258 5.000000000
+96.774193548 19.354838710 5.000000000
+96.774193548 22.580645161 5.000000000
+96.774193548 25.806451613 5.000000000
+96.774193548 29.032258065 5.000000000
+96.774193548 32.258064516 5.000000000
+96.774193548 35.483870968 4.779411765
+96.774193548 38.709677419 3.942307692
+96.774193548 41.935483871 3.450000000
+96.774193548 45.161290323 2.500000000
+96.774193548 48.387096774 2.500000000
+96.774193548 51.612903226 2.500000000
+96.774193548 54.838709677 2.500000000
+96.774193548 58.064516129 2.025000000
+96.774193548 61.290322581 1.562500000
+96.774193548 64.516129032 0.992647059
+96.774193548 67.741935484 0.846774194
+96.774193548 70.967741935 0.846774194
+96.774193548 74.193548387 0.846774194
+96.774193548 77.419354839 0.846774194
+96.774193548 80.645161290 0.846774194
+96.774193548 83.870967742 0.846774194
+96.774193548 87.096774194 0.846774194
+96.774193548 90.322580645 0.846774194
+96.774193548 93.548387097 0.846774194
+96.774193548 96.774193548 0.846774194
+96.774193548 100.000000000 0.846774194
+106.451612903 0.000000000 5.000000000
+106.451612903 3.225806452 5.000000000
+106.451612903 6.451612903 5.000000000
+106.451612903 9.677419355 5.000000000
+106.451612903 12.903225806 5.000000000
+106.451612903 16.129032258 5.000000000
+106.451612903 19.354838710 5.000000000
+106.451612903 22.580645161 5.000000000
+106.451612903 25.806451613 5.000000000
+106.451612903 29.032258065 5.000000000
+106.451612903 32.258064516 5.000000000
+106.451612903 35.483870968 4.779411765
+106.451612903 38.709677419 3.988095238
+106.451612903 41.935483871 3.392857143
+106.451612903 45.161290323 2.500000000
+106.451612903 48.387096774 2.500000000
+106.451612903 51.612903226 2.500000000
+106.451612903 54.838709677 2.500000000
+106.451612903 58.064516129 2.172619048
+106.451612903 61.290322581 2.172619048
+106.451612903 64.516129032 2.095588235
+106.451612903 67.741935484 2.056451613
+106.451612903 70.967741935 2.056451613
+106.451612903 74.193548387 2.056451613
+106.451612903 77.419354839 2.056451613
+106.451612903 80.645161290 2.056451613
+106.451612903 83.870967742 2.056451613
+106.451612903 87.096774194 2.056451613
+106.451612903 90.322580645 2.056451613
+106.451612903 93.548387097 2.056451613
+106.451612903 96.774193548 2.056451613
+106.451612903 100.000000000 2.056451613
+116.129032258 0.000000000 5.000000000
+116.129032258 3.225806452 5.000000000
+116.129032258 6.451612903 5.000000000
+116.129032258 9.677419355 5.000000000
+116.129032258 12.903225806 5.000000000
+116.129032258 16.129032258 5.000000000
+116.129032258 19.354838710 5.000000000
+116.129032258 22.580645161 5.000000000
+116.129032258 25.806451613 5.000000000
+116.129032258 29.032258065 5.000000000
+116.129032258 32.258064516 5.000000000
+116.129032258 35.483870968 4.879032258
+116.129032258 38.709677419 4.072580645
+116.129032258 41.935483871 3.266129032
+116.129032258 45.161290323 2.500000000
+116.129032258 48.387096774 2.500000000
+116.129032258 51.612903226 2.500000000
+116.129032258 54.838709677 2.500000000
+116.129032258 58.064516129 2.500000000
+116.129032258 61.290322581 2.500000000
+116.129032258 64.516129032 2.500000000
+116.129032258 67.741935484 2.500000000
+116.129032258 70.967741935 2.500000000
+116.129032258 74.193548387 2.500000000
+116.129032258 77.419354839 2.500000000
+116.129032258 80.645161290 2.500000000
+116.129032258 83.870967742 2.500000000
+116.129032258 87.096774194 2.500000000
+116.129032258 90.322580645 2.500000000
+116.129032258 93.548387097 2.500000000
+116.129032258 96.774193548 2.500000000
+116.129032258 100.000000000 2.500000000
+125.806451613 0.000000000 5.725806452
+125.806451613 3.225806452 5.725806452
+125.806451613 6.451612903 5.725806452
+125.806451613 9.677419355 5.725806452
+125.806451613 12.903225806 5.725806452
+125.806451613 16.129032258 5.725806452
+125.806451613 19.354838710 5.725806452
+125.806451613 22.580645161 5.725806452
+125.806451613 25.806451613 5.725806452
+125.806451613 29.032258065 5.725806452
+125.806451613 32.258064516 5.725806452
+125.806451613 35.483870968 5.551470588
+125.806451613 38.709677419 4.872448980
+125.806451613 41.935483871 4.362244898
+125.806451613 45.161290323 3.225806452
+125.806451613 48.387096774 3.225806452
+125.806451613 51.612903226 3.225806452
+125.806451613 54.838709677 3.225806452
+125.806451613 58.064516129 2.959183673
+125.806451613 61.290322581 2.959183673
+125.806451613 64.516129032 2.610294118
+125.806451613 67.741935484 2.500000000
+125.806451613 70.967741935 2.500000000
+125.806451613 74.193548387 2.500000000
+125.806451613 77.419354839 2.500000000
+125.806451613 80.645161290 2.500000000
+125.806451613 83.870967742 2.500000000
+125.806451613 87.096774194 2.500000000
+125.806451613 90.322580645 2.500000000
+125.806451613 93.548387097 2.500000000
+125.806451613 96.774193548 2.500000000
+125.806451613 100.000000000 2.500000000
+135.483870968 0.000000000 6.935483871
+135.483870968 3.225806452 6.935483871
+135.483870968 6.451612903 6.935483871
+135.483870968 9.677419355 6.935483871
+135.483870968 12.903225806 6.935483871
+135.483870968 16.129032258 6.935483871
+135.483870968 19.354838710 6.935483871
+135.483870968 22.580645161 6.935483871
+135.483870968 25.806451613 6.935483871
+135.483870968 29.032258065 6.935483871
+135.483870968 32.258064516 6.935483871
+135.483870968 35.483870968 6.654411765
+135.483870968 38.709677419 5.694444444
+135.483870968 41.935483871 5.138888889
+135.483870968 45.161290323 4.435483871
+135.483870968 48.387096774 4.435483871
+135.483870968 51.612903226 4.435483871
+135.483870968 54.838709677 4.435483871
+135.483870968 58.064516129 3.694444444
+135.483870968 61.290322581 3.138888889
+135.483870968 64.516129032 2.610294118
+135.483870968 67.741935484 2.500000000
+135.483870968 70.967741935 2.500000000
+135.483870968 74.193548387 2.500000000
+135.483870968 77.419354839 2.500000000
+135.483870968 80.645161290 2.500000000
+135.483870968 83.870967742 2.500000000
+135.483870968 87.096774194 2.500000000
+135.483870968 90.322580645 2.500000000
+135.483870968 93.548387097 2.500000000
+135.483870968 96.774193548 2.500000000
+135.483870968 100.000000000 2.500000000
+145.161290323 0.000000000 7.500000000
+145.161290323 3.225806452 7.500000000
+145.161290323 6.451612903 7.500000000
+145.161290323 9.677419355 7.500000000
+145.161290323 12.903225806 7.500000000
+145.161290323 16.129032258 7.500000000
+145.161290323 19.354838710 7.500000000
+145.161290323 22.580645161 7.500000000
+145.161290323 25.806451613 7.500000000
+145.161290323 29.032258065 7.500000000
+145.161290323 32.258064516 7.500000000
+145.161290323 35.483870968 7.379032258
+145.161290323 38.709677419 6.572580645
+145.161290323 41.935483871 5.766129032
+145.161290323 45.161290323 5.000000000
+145.161290323 48.387096774 5.000000000
+145.161290323 51.612903226 5.000000000
+145.161290323 54.838709677 5.000000000
+145.161290323 58.064516129 4.233870968
+145.161290323 61.290322581 3.427419355
+145.161290323 64.516129032 2.620967742
+145.161290323 67.741935484 2.500000000
+145.161290323 70.967741935 2.500000000
+145.161290323 74.193548387 2.500000000
+145.161290323 77.419354839 2.500000000
+145.161290323 80.645161290 2.500000000
+145.161290323 83.870967742 2.500000000
+145.161290323 87.096774194 2.500000000
+145.161290323 90.322580645 2.500000000
+145.161290323 93.548387097 2.500000000
+145.161290323 96.774193548 2.500000000
+145.161290323 100.000000000 2.500000000
+154.838709677 0.000000000 7.500000000
+154.838709677 3.225806452 7.500000000
+154.838709677 6.451612903 7.500000000
+154.838709677 9.677419355 7.500000000
+154.838709677 12.903225806 7.500000000
+154.838709677 16.129032258 7.500000000
+154.838709677 19.354838710 7.500000000
+154.838709677 22.580645161 7.500000000
+154.838709677 25.806451613 7.500000000
+154.838709677 29.032258065 7.500000000
+154.838709677 32.258064516 7.500000000
+154.838709677 35.483870968 7.389705882
+154.838709677 38.709677419 6.875000000
+154.838709677 41.935483871 6.331521739
+154.838709677 45.161290323 5.604838710
+154.838709677 48.387096774 5.604838710
+154.838709677 51.612903226 5.604838710
+154.838709677 54.838709677 5.604838710
+154.838709677 58.064516129 4.891304348
+154.838709677 61.290322581 4.347826087
+154.838709677 64.516129032 3.382352941
+154.838709677 67.741935484 3.104838710
+154.838709677 70.967741935 3.104838710
+154.838709677 74.193548387 3.104838710
+154.838709677 77.419354839 3.104838710
+154.838709677 80.645161290 3.104838710
+154.838709677 83.870967742 3.104838710
+154.838709677 87.096774194 3.104838710
+154.838709677 90.322580645 3.104838710
+154.838709677 93.548387097 3.104838710
+154.838709677 96.774193548 3.104838710
+154.838709677 100.000000000 3.104838710
+164.516129032 0.000000000 7.500000000
+164.516129032 3.225806452 7.500000000
+164.516129032 6.451612903 7.500000000
+164.516129032 9.677419355 7.500000000
+164.516129032 12.903225806 7.500000000
+164.516129032 16.129032258 7.500000000
+164.516129032 19.354838710 7.500000000
+164.516129032 22.580645161 7.500000000
+164.516129032 25.806451613 7.500000000
+164.516129032 29.032258065 7.500000000
+164.516129032 32.258064516 7.500000000
+164.516129032 35.483870968 7.389705882
+164.516129032 38.709677419 7.057291667
+164.516129032 41.935483871 7.057291667
+164.516129032 45.161290323 6.814516129
+164.516129032 48.387096774 6.814516129
+164.516129032 51.612903226 6.814516129
+164.516129032 54.838709677 6.814516129
+164.516129032 58.064516129 5.677083333
+164.516129032 61.290322581 5.156250000
+164.516129032 64.516129032 4.485294118
+164.516129032 67.741935484 4.314516129
+164.516129032 70.967741935 4.314516129
+164.516129032 74.193548387 4.314516129
+164.516129032 77.419354839 4.314516129
+164.516129032 80.645161290 4.314516129
+164.516129032 83.870967742 4.314516129
+164.516129032 87.096774194 4.314516129
+164.516129032 90.322580645 4.314516129
+164.516129032 93.548387097 4.314516129
+164.516129032 96.774193548 4.314516129
+164.516129032 100.000000000 4.314516129
+174.193548387 0.000000000 7.500000000
+174.193548387 3.225806452 7.500000000
+174.193548387 6.451612903 7.500000000
+174.193548387 9.677419355 7.500000000
+174.193548387 12.903225806 7.500000000
+174.193548387 16.129032258 7.500000000
+174.193548387 19.354838710 7.500000000
+174.193548387 22.580645161 7.500000000
+174.193548387 25.806451613 7.500000000
+174.193548387 29.032258065 7.500000000
+174.193548387 32.258064516 7.500000000
+174.193548387 35.483870968 7.500000000
+174.193548387 38.709677419 7.500000000
+174.193548387 41.935483871 7.500000000
+174.193548387 45.161290323 7.500000000
+174.193548387 48.387096774 7.500000000
+174.193548387 51.612903226 7.500000000
+174.193548387 54.838709677 7.500000000
+174.193548387 58.064516129 6.733870968
+174.193548387 61.290322581 5.927419355
+174.193548387 64.516129032 5.120967742
+174.193548387 67.741935484 5.000000000
+174.193548387 70.967741935 5.000000000
+174.193548387 74.193548387 5.000000000
+174.193548387 77.419354839 5.000000000
+174.193548387 80.645161290 5.000000000
+174.193548387 83.870967742 5.000000000
+174.193548387 87.096774194 5.000000000
+174.193548387 90.322580645 5.000000000
+174.193548387 93.548387097 5.000000000
+174.193548387 96.774193548 5.000000000
+174.193548387 100.000000000 5.000000000
+183.870967742 0.000000000 7.983870968
+183.870967742 3.225806452 7.983870968
+183.870967742 6.451612903 7.983870968
+183.870967742 9.677419355 7.983870968
+183.870967742 12.903225806 7.983870968
+183.870967742 16.129032258 7.983870968
+183.870967742 19.354838710 7.983870968
+183.870967742 22.580645161 7.983870968
+183.870967742 25.806451613 7.983870968
+183.870967742 29.032258065 7.983870968
+183.870967742 32.258064516 7.983870968
+183.870967742 35.483870968 7.941176471
+183.870967742 38.709677419 7.848837209
+183.870967742 41.935483871 7.848837209
+183.870967742 45.161290323 7.500000000
+183.870967742 48.387096774 7.500000000
+183.870967742 51.612903226 7.500000000
+183.870967742 54.838709677 7.500000000
+183.870967742 58.064516129 6.598837209
+183.870967742 61.290322581 6.017441860
+183.870967742 64.516129032 5.220588235
+183.870967742 67.741935484 5.000000000
+183.870967742 70.967741935 5.000000000
+183.870967742 74.193548387 5.000000000
+183.870967742 77.419354839 5.000000000
+183.870967742 80.645161290 5.000000000
+183.870967742 83.870967742 5.000000000
+183.870967742 87.096774194 5.000000000
+183.870967742 90.322580645 5.000000000
+183.870967742 93.548387097 5.000000000
+183.870967742 96.774193548 5.000000000
+183.870967742 100.000000000 5.000000000
+193.548387097 0.000000000 9.193548387
+193.548387097 3.225806452 9.193548387
+193.548387097 6.451612903 9.193548387
+193.548387097 9.677419355 9.193548387
+193.548387097 12.903225806 9.193548387
+193.548387097 16.129032258 9.193548387
+193.548387097 19.354838710 9.193548387
+193.548387097 22.580645161 9.193548387
+193.548387097 25.806451613 9.193548387
+193.548387097 29.032258065 9.193548387
+193.548387097 32.258064516 9.193548387
+193.548387097 35.483870968 9.044117647
+193.548387097 38.709677419 8.455882353
+193.548387097 41.935483871 7.975000000
+193.548387097 45.161290323 7.500000000
+193.548387097 48.387096774 7.500000000
+193.548387097 51.612903226 7.500000000
+193.548387097 54.838709677 7.500000000
+193.548387097 58.064516129 6.550000000
+193.548387097 61.290322581 6.053921569
+193.548387097 64.516129032 5.220588235
+193.548387097 67.741935484 5.000000000
+193.548387097 70.967741935 5.000000000
+193.548387097 74.193548387 5.000000000
+193.548387097 77.419354839 5.000000000
+193.548387097 80.645161290 5.000000000
+193.548387097 83.870967742 5.000000000
+193.548387097 87.096774194 5.000000000
+193.548387097 90.322580645 5.000000000
+193.548387097 93.548387097 5.000000000
+193.548387097 96.774193548 5.000000000
+193.548387097 100.000000000 5.000000000
+203.225806452 0.000000000 10.000000000
+203.225806452 3.225806452 10.000000000
+203.225806452 6.451612903 10.000000000
+203.225806452 9.677419355 10.000000000
+203.225806452 12.903225806 10.000000000
+203.225806452 16.129032258 10.000000000
+203.225806452 19.354838710 10.000000000
+203.225806452 22.580645161 10.000000000
+203.225806452 25.806451613 10.000000000
+203.225806452 29.032258065 10.000000000
+203.225806452 32.258064516 10.000000000
+203.225806452 35.483870968 9.879032258
+203.225806452 38.709677419 9.072580645
+203.225806452 41.935483871 8.266129032
+203.225806452 45.161290323 7.500000000
+203.225806452 48.387096774 7.500000000
+203.225806452 51.612903226 7.500000000
+203.225806452 54.838709677 7.500000000
+203.225806452 58.064516129 6.733870968
+203.225806452 61.290322581 5.927419355
+203.225806452 64.516129032 5.120967742
+203.225806452 67.741935484 5.000000000
+203.225806452 70.967741935 5.000000000
+203.225806452 74.193548387 5.000000000
+203.225806452 77.419354839 5.000000000
+203.225806452 80.645161290 5.000000000
+203.225806452 83.870967742 5.000000000
+203.225806452 87.096774194 5.000000000
+203.225806452 90.322580645 5.000000000
+203.225806452 93.548387097 5.000000000
+203.225806452 96.774193548 5.000000000
+203.225806452 100.000000000 5.000000000
+212.903225806 0.000000000 10.000000000
+212.903225806 3.225806452 10.000000000
+212.903225806 6.451612903 10.000000000
+212.903225806 9.677419355 10.000000000
+212.903225806 12.903225806 10.000000000
+212.903225806 16.129032258 10.000000000
+212.903225806 19.354838710 10.000000000
+212.903225806 22.580645161 10.000000000
+212.903225806 25.806451613 10.000000000
+212.903225806 29.032258065 10.000000000
+212.903225806 32.258064516 10.000000000
+212.903225806 35.483870968 9.879032258
+212.903225806 38.709677419 9.072580645
+212.903225806 41.935483871 8.266129032
+212.903225806 45.161290323 7.500000000
+212.903225806 48.387096774 7.500000000
+212.903225806 51.612903226 7.500000000
+212.903225806 54.838709677 7.500000000
+212.903225806 58.064516129 6.733870968
+212.903225806 61.290322581 5.927419355
+212.903225806 64.516129032 5.120967742
+212.903225806 67.741935484 5.000000000
+212.903225806 70.967741935 5.000000000
+212.903225806 74.193548387 5.000000000
+212.903225806 77.419354839 5.000000000
+212.903225806 80.645161290 5.000000000
+212.903225806 83.870967742 5.000000000
+212.903225806 87.096774194 5.000000000
+212.903225806 90.322580645 5.000000000
+212.903225806 93.548387097 5.000000000
+212.903225806 96.774193548 5.000000000
+212.903225806 100.000000000 5.000000000
+222.580645161 0.000000000 10.000000000
+222.580645161 3.225806452 10.000000000
+222.580645161 6.451612903 10.000000000
+222.580645161 9.677419355 10.000000000
+222.580645161 12.903225806 10.000000000
+222.580645161 16.129032258 10.000000000
+222.580645161 19.354838710 10.000000000
+222.580645161 22.580645161 10.000000000
+222.580645161 25.806451613 10.000000000
+222.580645161 29.032258065 10.000000000
+222.580645161 32.258064516 10.000000000
+222.580645161 35.483870968 9.879032258
+222.580645161 38.709677419 9.072580645
+222.580645161 41.935483871 8.266129032
+222.580645161 45.161290323 7.500000000
+222.580645161 48.387096774 7.500000000
+222.580645161 51.612903226 7.500000000
+222.580645161 54.838709677 7.500000000
+222.580645161 58.064516129 6.733870968
+222.580645161 61.290322581 5.927419355
+222.580645161 64.516129032 5.120967742
+222.580645161 67.741935484 5.000000000
+222.580645161 70.967741935 5.000000000
+222.580645161 74.193548387 5.000000000
+222.580645161 77.419354839 5.000000000
+222.580645161 80.645161290 5.000000000
+222.580645161 83.870967742 5.000000000
+222.580645161 87.096774194 5.000000000
+222.580645161 90.322580645 5.000000000
+222.580645161 93.548387097 5.000000000
+222.580645161 96.774193548 5.000000000
+222.580645161 100.000000000 5.000000000
+232.258064516 0.000000000 10.000000000
+232.258064516 3.225806452 10.000000000
+232.258064516 6.451612903 10.000000000
+232.258064516 9.677419355 10.000000000
+232.258064516 12.903225806 10.000000000
+232.258064516 16.129032258 10.000000000
+232.258064516 19.354838710 10.000000000
+232.258064516 22.580645161 10.000000000
+232.258064516 25.806451613 10.000000000
+232.258064516 29.032258065 10.000000000
+232.258064516 32.258064516 10.000000000
+232.258064516 35.483870968 9.879032258
+232.258064516 38.709677419 9.072580645
+232.258064516 41.935483871 8.266129032
+232.258064516 45.161290323 7.500000000
+232.258064516 48.387096774 7.500000000
+232.258064516 51.612903226 7.500000000
+232.258064516 54.838709677 7.500000000
+232.258064516 58.064516129 6.733870968
+232.258064516 61.290322581 5.927419355
+232.258064516 64.516129032 5.120967742
+232.258064516 67.741935484 5.000000000
+232.258064516 70.967741935 5.000000000
+232.258064516 74.193548387 5.000000000
+232.258064516 77.419354839 5.000000000
+232.258064516 80.645161290 5.000000000
+232.258064516 83.870967742 5.000000000
+232.258064516 87.096774194 5.000000000
+232.258064516 90.322580645 5.000000000
+232.258064516 93.548387097 5.000000000
+232.258064516 96.774193548 5.000000000
+232.258064516 100.000000000 5.000000000
+241.935483871 0.000000000 10.000000000
+241.935483871 3.225806452 10.000000000
+241.935483871 6.451612903 10.000000000
+241.935483871 9.677419355 10.000000000
+241.935483871 12.903225806 10.000000000
+241.935483871 16.129032258 10.000000000
+241.935483871 19.354838710 10.000000000
+241.935483871 22.580645161 10.000000000
+241.935483871 25.806451613 10.000000000
+241.935483871 29.032258065 10.000000000
+241.935483871 32.258064516 10.000000000
+241.935483871 35.483870968 9.879032258
+241.935483871 38.709677419 9.072580645
+241.935483871 41.935483871 8.266129032
+241.935483871 45.161290323 7.500000000
+241.935483871 48.387096774 7.500000000
+241.935483871 51.612903226 7.500000000
+241.935483871 54.838709677 7.500000000
+241.935483871 58.064516129 6.733870968
+241.935483871 61.290322581 5.927419355
+241.935483871 64.516129032 5.120967742
+241.935483871 67.741935484 5.000000000
+241.935483871 70.967741935 5.000000000
+241.935483871 74.193548387 5.000000000
+241.935483871 77.419354839 5.000000000
+241.935483871 80.645161290 5.000000000
+241.935483871 83.870967742 5.000000000
+241.935483871 87.096774194 5.000000000
+241.935483871 90.322580645 5.000000000
+241.935483871 93.548387097 5.000000000
+241.935483871 96.774193548 5.000000000
+241.935483871 100.000000000 5.000000000
+251.612903226 0.000000000 10.000000000
+251.612903226 3.225806452 10.000000000
+251.612903226 6.451612903 10.000000000
+251.612903226 9.677419355 10.000000000
+251.612903226 12.903225806 10.000000000
+251.612903226 16.129032258 10.000000000
+251.612903226 19.354838710 10.000000000
+251.612903226 22.580645161 10.000000000
+251.612903226 25.806451613 10.000000000
+251.612903226 29.032258065 10.000000000
+251.612903226 32.258064516 10.000000000
+251.612903226 35.483870968 9.879032258
+251.612903226 38.709677419 9.072580645
+251.612903226 41.935483871 8.266129032
+251.612903226 45.161290323 7.500000000
+251.612903226 48.387096774 7.500000000
+251.612903226 51.612903226 7.500000000
+251.612903226 54.838709677 7.500000000
+251.612903226 58.064516129 6.733870968
+251.612903226 61.290322581 5.927419355
+251.612903226 64.516129032 5.120967742
+251.612903226 67.741935484 5.000000000
+251.612903226 70.967741935 5.000000000
+251.612903226 74.193548387 5.000000000
+251.612903226 77.419354839 5.000000000
+251.612903226 80.645161290 5.000000000
+251.612903226 83.870967742 5.000000000
+251.612903226 87.096774194 5.000000000
+251.612903226 90.322580645 5.000000000
+251.612903226 93.548387097 5.000000000
+251.612903226 96.774193548 5.000000000
+251.612903226 100.000000000 5.000000000
+261.290322581 0.000000000 10.000000000
+261.290322581 3.225806452 10.000000000
+261.290322581 6.451612903 10.000000000
+261.290322581 9.677419355 10.000000000
+261.290322581 12.903225806 10.000000000
+261.290322581 16.129032258 10.000000000
+261.290322581 19.354838710 10.000000000
+261.290322581 22.580645161 10.000000000
+261.290322581 25.806451613 10.000000000
+261.290322581 29.032258065 10.000000000
+261.290322581 32.258064516 10.000000000
+261.290322581 35.483870968 9.879032258
+261.290322581 38.709677419 9.072580645
+261.290322581 41.935483871 8.266129032
+261.290322581 45.161290323 7.500000000
+261.290322581 48.387096774 7.500000000
+261.290322581 51.612903226 7.500000000
+261.290322581 54.838709677 7.500000000
+261.290322581 58.064516129 6.733870968
+261.290322581 61.290322581 5.927419355
+261.290322581 64.516129032 5.120967742
+261.290322581 67.741935484 5.000000000
+261.290322581 70.967741935 5.000000000
+261.290322581 74.193548387 5.000000000
+261.290322581 77.419354839 5.000000000
+261.290322581 80.645161290 5.000000000
+261.290322581 83.870967742 5.000000000
+261.290322581 87.096774194 5.000000000
+261.290322581 90.322580645 5.000000000
+261.290322581 93.548387097 5.000000000
+261.290322581 96.774193548 5.000000000
+261.290322581 100.000000000 5.000000000
+270.967741935 0.000000000 10.000000000
+270.967741935 3.225806452 10.000000000
+270.967741935 6.451612903 10.000000000
+270.967741935 9.677419355 10.000000000
+270.967741935 12.903225806 10.000000000
+270.967741935 16.129032258 10.000000000
+270.967741935 19.354838710 10.000000000
+270.967741935 22.580645161 10.000000000
+270.967741935 25.806451613 10.000000000
+270.967741935 29.032258065 10.000000000
+270.967741935 32.258064516 10.000000000
+270.967741935 35.483870968 9.879032258
+270.967741935 38.709677419 9.072580645
+270.967741935 41.935483871 8.266129032
+270.967741935 45.161290323 7.500000000
+270.967741935 48.387096774 7.500000000
+270.967741935 51.612903226 7.500000000
+270.967741935 54.838709677 7.500000000
+270.967741935 58.064516129 6.733870968
+270.967741935 61.290322581 5.927419355
+270.967741935 64.516129032 5.120967742
+270.967741935 67.741935484 5.000000000
+270.967741935 70.967741935 5.000000000
+270.967741935 74.193548387 5.000000000
+270.967741935 77.419354839 5.000000000
+270.967741935 80.645161290 5.000000000
+270.967741935 83.870967742 5.000000000
+270.967741935 87.096774194 5.000000000
+270.967741935 90.322580645 5.000000000
+270.967741935 93.548387097 5.000000000
+270.967741935 96.774193548 5.000000000
+270.967741935 100.000000000 5.000000000
+280.645161290 0.000000000 10.000000000
+280.645161290 3.225806452 10.000000000
+280.645161290 6.451612903 10.000000000
+280.645161290 9.677419355 10.000000000
+280.645161290 12.903225806 10.000000000
+280.645161290 16.129032258 10.000000000
+280.645161290 19.354838710 10.000000000
+280.645161290 22.580645161 10.000000000
+280.645161290 25.806451613 10.000000000
+280.645161290 29.032258065 10.000000000
+280.645161290 32.258064516 10.000000000
+280.645161290 35.483870968 9.879032258
+280.645161290 38.709677419 9.072580645
+280.645161290 41.935483871 8.266129032
+280.645161290 45.161290323 7.500000000
+280.645161290 48.387096774 7.500000000
+280.645161290 51.612903226 7.500000000
+280.645161290 54.838709677 7.500000000
+280.645161290 58.064516129 6.733870968
+280.645161290 61.290322581 5.927419355
+280.645161290 64.516129032 5.120967742
+280.645161290 67.741935484 5.000000000
+280.645161290 70.967741935 5.000000000
+280.645161290 74.193548387 5.000000000
+280.645161290 77.419354839 5.000000000
+280.645161290 80.645161290 5.000000000
+280.645161290 83.870967742 5.000000000
+280.645161290 87.096774194 5.000000000
+280.645161290 90.322580645 5.000000000
+280.645161290 93.548387097 5.000000000
+280.645161290 96.774193548 5.000000000
+280.645161290 100.000000000 5.000000000
+290.322580645 0.000000000 10.000000000
+290.322580645 3.225806452 10.000000000
+290.322580645 6.451612903 10.000000000
+290.322580645 9.677419355 10.000000000
+290.322580645 12.903225806 10.000000000
+290.322580645 16.129032258 10.000000000
+290.322580645 19.354838710 10.000000000
+290.322580645 22.580645161 10.000000000
+290.322580645 25.806451613 10.000000000
+290.322580645 29.032258065 10.000000000
+290.322580645 32.258064516 10.000000000
+290.322580645 35.483870968 9.879032258
+290.322580645 38.709677419 9.072580645
+290.322580645 41.935483871 8.266129032
+290.322580645 45.161290323 7.500000000
+290.322580645 48.387096774 7.500000000
+290.322580645 51.612903226 7.500000000
+290.322580645 54.838709677 7.500000000
+290.322580645 58.064516129 6.733870968
+290.322580645 61.290322581 5.927419355
+290.322580645 64.516129032 5.120967742
+290.322580645 67.741935484 5.000000000
+290.322580645 70.967741935 5.000000000
+290.322580645 74.193548387 5.000000000
+290.322580645 77.419354839 5.000000000
+290.322580645 80.645161290 5.000000000
+290.322580645 83.870967742 5.000000000
+290.322580645 87.096774194 5.000000000
+290.322580645 90.322580645 5.000000000
+290.322580645 93.548387097 5.000000000
+290.322580645 96.774193548 5.000000000
+290.322580645 100.000000000 5.000000000
+300.000000000 0.000000000 10.000000000
+300.000000000 3.225806452 10.000000000
+300.000000000 6.451612903 10.000000000
+300.000000000 9.677419355 10.000000000
+300.000000000 12.903225806 10.000000000
+300.000000000 16.129032258 10.000000000
+300.000000000 19.354838710 10.000000000
+300.000000000 22.580645161 10.000000000
+300.000000000 25.806451613 10.000000000
+300.000000000 29.032258065 10.000000000
+300.000000000 32.258064516 10.000000000
+300.000000000 35.483870968 9.879032258
+300.000000000 38.709677419 9.072580645
+300.000000000 41.935483871 8.266129032
+300.000000000 45.161290323 7.500000000
+300.000000000 48.387096774 7.500000000
+300.000000000 51.612903226 7.500000000
+300.000000000 54.838709677 7.500000000
+300.000000000 58.064516129 6.733870968
+300.000000000 61.290322581 5.927419355
+300.000000000 64.516129032 5.120967742
+300.000000000 67.741935484 5.000000000
+300.000000000 70.967741935 5.000000000
+300.000000000 74.193548387 5.000000000
+300.000000000 77.419354839 5.000000000
+300.000000000 80.645161290 5.000000000
+300.000000000 83.870967742 5.000000000
+300.000000000 87.096774194 5.000000000
+300.000000000 90.322580645 5.000000000
+300.000000000 93.548387097 5.000000000
+300.000000000 96.774193548 5.000000000
+300.000000000 100.000000000 5.000000000
diff --git a/examples/takagi-sugeno/octave/heart_disease_risk.fll b/examples/takagi-sugeno/octave/heart_disease_risk.fll
index 5bc3207..4ab822f 100644
--- a/examples/takagi-sugeno/octave/heart_disease_risk.fll
+++ b/examples/takagi-sugeno/octave/heart_disease_risk.fll
@@ -1,7 +1,8 @@
-Engine: Heart-Disease-Risk
+Engine: heart_disease_risk
InputVariable: LDLLevel
enabled: true
range: 0.000 300.000
+ lock-range: false
term: Low Trapezoid -1.000 0.000 90.000 110.000
term: LowBorderline Trapezoid 90.000 110.000 120.000 140.000
term: Borderline Trapezoid 120.000 140.000 150.000 170.000
@@ -10,17 +11,18 @@ InputVariable: LDLLevel
InputVariable: HDLLevel
enabled: true
range: 0.000 100.000
+ lock-range: false
term: LowHDL Trapezoid -1.000 0.000 35.000 45.000
term: ModerateHDL Trapezoid 35.000 45.000 55.000 65.000
term: HighHDL Trapezoid 55.000 65.000 100.000 101.000
OutputVariable: HeartDiseaseRisk
enabled: true
range: 0.000 10.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
- lock-range: false
term: NoRisk Constant 0.000
term: LowRisk Constant 2.500
term: MediumRisk Constant 5.000
@@ -30,7 +32,8 @@ RuleBlock:
enabled: true
conjunction: Minimum
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if LDLLevel is Low and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk
rule: if LDLLevel is Low and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk
rule: if LDLLevel is Low and HDLLevel is HighHDL then HeartDiseaseRisk is NoRisk
diff --git a/examples/takagi-sugeno/octave/heart_disease_risk.java b/examples/takagi-sugeno/octave/heart_disease_risk.java
index fcd67c9..febd1c7 100644
--- a/examples/takagi-sugeno/octave/heart_disease_risk.java
+++ b/examples/takagi-sugeno/octave/heart_disease_risk.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,51 +13,61 @@ import com.fuzzylite.variable.*;
public class heart_disease_risk{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("Heart-Disease-Risk");
+engine.setName("heart_disease_risk");
+engine.setDescription("");
-InputVariable inputVariable1 = new InputVariable();
-inputVariable1.setEnabled(true);
-inputVariable1.setName("LDLLevel");
-inputVariable1.setRange(0.000, 300.000);
-inputVariable1.addTerm(new Trapezoid("Low", -1.000, 0.000, 90.000, 110.000));
-inputVariable1.addTerm(new Trapezoid("LowBorderline", 90.000, 110.000, 120.000, 140.000));
-inputVariable1.addTerm(new Trapezoid("Borderline", 120.000, 140.000, 150.000, 170.000));
-inputVariable1.addTerm(new Trapezoid("HighBorderline", 150.000, 170.000, 180.000, 200.000));
-inputVariable1.addTerm(new Trapezoid("High", 180.000, 200.000, 300.000, 301.000));
-engine.addInputVariable(inputVariable1);
+InputVariable LDLLevel = new InputVariable();
+LDLLevel.setName("LDLLevel");
+LDLLevel.setDescription("");
+LDLLevel.setEnabled(true);
+LDLLevel.setRange(0.000, 300.000);
+LDLLevel.setLockValueInRange(false);
+LDLLevel.addTerm(new Trapezoid("Low", -1.000, 0.000, 90.000, 110.000));
+LDLLevel.addTerm(new Trapezoid("LowBorderline", 90.000, 110.000, 120.000, 140.000));
+LDLLevel.addTerm(new Trapezoid("Borderline", 120.000, 140.000, 150.000, 170.000));
+LDLLevel.addTerm(new Trapezoid("HighBorderline", 150.000, 170.000, 180.000, 200.000));
+LDLLevel.addTerm(new Trapezoid("High", 180.000, 200.000, 300.000, 301.000));
+engine.addInputVariable(LDLLevel);
-InputVariable inputVariable2 = new InputVariable();
-inputVariable2.setEnabled(true);
-inputVariable2.setName("HDLLevel");
-inputVariable2.setRange(0.000, 100.000);
-inputVariable2.addTerm(new Trapezoid("LowHDL", -1.000, 0.000, 35.000, 45.000));
-inputVariable2.addTerm(new Trapezoid("ModerateHDL", 35.000, 45.000, 55.000, 65.000));
-inputVariable2.addTerm(new Trapezoid("HighHDL", 55.000, 65.000, 100.000, 101.000));
-engine.addInputVariable(inputVariable2);
+InputVariable HDLLevel = new InputVariable();
+HDLLevel.setName("HDLLevel");
+HDLLevel.setDescription("");
+HDLLevel.setEnabled(true);
+HDLLevel.setRange(0.000, 100.000);
+HDLLevel.setLockValueInRange(false);
+HDLLevel.addTerm(new Trapezoid("LowHDL", -1.000, 0.000, 35.000, 45.000));
+HDLLevel.addTerm(new Trapezoid("ModerateHDL", 35.000, 45.000, 55.000, 65.000));
+HDLLevel.addTerm(new Trapezoid("HighHDL", 55.000, 65.000, 100.000, 101.000));
+engine.addInputVariable(HDLLevel);
-OutputVariable outputVariable = new OutputVariable();
-outputVariable.setEnabled(true);
-outputVariable.setName("HeartDiseaseRisk");
-outputVariable.setRange(0.000, 10.000);
-outputVariable.fuzzyOutput().setAccumulation(null);
-outputVariable.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable.setDefaultValue(Double.NaN);
-outputVariable.setLockPreviousOutputValue(false);
-outputVariable.setLockOutputValueInRange(false);
-outputVariable.addTerm(new Constant("NoRisk", 0.000));
-outputVariable.addTerm(new Constant("LowRisk", 2.500));
-outputVariable.addTerm(new Constant("MediumRisk", 5.000));
-outputVariable.addTerm(new Constant("HighRisk", 7.500));
-outputVariable.addTerm(new Constant("ExtremeRisk", 10.000));
-engine.addOutputVariable(outputVariable);
+OutputVariable HeartDiseaseRisk = new OutputVariable();
+HeartDiseaseRisk.setName("HeartDiseaseRisk");
+HeartDiseaseRisk.setDescription("");
+HeartDiseaseRisk.setEnabled(true);
+HeartDiseaseRisk.setRange(0.000, 10.000);
+HeartDiseaseRisk.setLockValueInRange(false);
+HeartDiseaseRisk.setAggregation(null);
+HeartDiseaseRisk.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+HeartDiseaseRisk.setDefaultValue(Double.NaN);
+HeartDiseaseRisk.setLockPreviousValue(false);
+HeartDiseaseRisk.addTerm(new Constant("NoRisk", 0.000));
+HeartDiseaseRisk.addTerm(new Constant("LowRisk", 2.500));
+HeartDiseaseRisk.addTerm(new Constant("MediumRisk", 5.000));
+HeartDiseaseRisk.addTerm(new Constant("HighRisk", 7.500));
+HeartDiseaseRisk.addTerm(new Constant("ExtremeRisk", 10.000));
+engine.addOutputVariable(HeartDiseaseRisk);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(new Minimum());
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(null);
+ruleBlock.setImplication(null);
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if LDLLevel is Low and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk", engine));
ruleBlock.addRule(Rule.parse("if LDLLevel is Low and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk", engine));
ruleBlock.addRule(Rule.parse("if LDLLevel is Low and HDLLevel is HighHDL then HeartDiseaseRisk is NoRisk", engine));
diff --git a/examples/takagi-sugeno/octave/heart_disease_risk.pdf b/examples/takagi-sugeno/octave/heart_disease_risk.pdf
new file mode 100644
index 0000000..e712d54
--- /dev/null
+++ b/examples/takagi-sugeno/octave/heart_disease_risk.pdf
Binary files differ
diff --git a/examples/takagi-sugeno/octave/linear_tip_calculator.R b/examples/takagi-sugeno/octave/linear_tip_calculator.R
new file mode 100644
index 0000000..e6a7058
--- /dev/null
+++ b/examples/takagi-sugeno/octave/linear_tip_calculator.R
@@ -0,0 +1,67 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "linear_tip_calculator"
+engine.fll = "Engine: linear_tip_calculator
+InputVariable: FoodQuality
+ enabled: true
+ range: 1.000 10.000
+ lock-range: false
+ term: Bad Trapezoid 0.000 1.000 3.000 7.000
+ term: Good Trapezoid 3.000 7.000 10.000 11.000
+InputVariable: Service
+ enabled: true
+ range: 1.000 10.000
+ lock-range: false
+ term: Bad Trapezoid 0.000 1.000 3.000 7.000
+ term: Good Trapezoid 3.000 7.000 10.000 11.000
+OutputVariable: Tip
+ enabled: true
+ range: 10.000 20.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: TenPercent Linear 0.000 0.000 10.000
+ term: FifteenPercent Linear 0.000 0.000 15.000
+ term: TwentyPercent Linear 0.000 0.000 20.000
+RuleBlock:
+ enabled: true
+ conjunction: Minimum
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if FoodQuality is Bad and Service is Bad then Tip is TenPercent
+ rule: if FoodQuality is Bad and Service is Good then Tip is FifteenPercent
+ rule: if FoodQuality is Good and Service is Bad then Tip is FifteenPercent
+ rule: if FoodQuality is Good and Service is Good then Tip is TwentyPercent"
+
+engine.fldFile = "linear_tip_calculator.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1i2_o1 = ggplot(engine.df, aes(FoodQuality, Service)) +
+ geom_tile(aes(fill=Tip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=FoodQuality, y=Service, z=Tip), color="black") +
+ ggtitle("(FoodQuality, Service) = Tip")
+
+engine.plot.i2i1_o1 = ggplot(engine.df, aes(Service, FoodQuality)) +
+ geom_tile(aes(fill=Tip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Service, y=FoodQuality, z=Tip), color="black") +
+ ggtitle("(Service, FoodQuality) = Tip")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1i2_o1, engine.plot.i2i1_o1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/takagi-sugeno/octave/linear_tip_calculator.cpp b/examples/takagi-sugeno/octave/linear_tip_calculator.cpp
index 6982766..f0d4a43 100644
--- a/examples/takagi-sugeno/octave/linear_tip_calculator.cpp
+++ b/examples/takagi-sugeno/octave/linear_tip_calculator.cpp
@@ -1,51 +1,61 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("Linear-Tip-Calculator");
-
-InputVariable* inputVariable1 = new InputVariable;
-inputVariable1->setEnabled(true);
-inputVariable1->setName("FoodQuality");
-inputVariable1->setRange(1.000, 10.000);
-inputVariable1->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable1->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine->addInputVariable(inputVariable1);
-
-InputVariable* inputVariable2 = new InputVariable;
-inputVariable2->setEnabled(true);
-inputVariable2->setName("Service");
-inputVariable2->setRange(1.000, 10.000);
-inputVariable2->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable2->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine->addInputVariable(inputVariable2);
-
-OutputVariable* outputVariable = new OutputVariable;
-outputVariable->setEnabled(true);
-outputVariable->setName("Tip");
-outputVariable->setRange(10.000, 20.000);
-outputVariable->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable->setDefaultValue(fl::nan);
-outputVariable->setLockPreviousOutputValue(false);
-outputVariable->setLockOutputValueInRange(false);
-outputVariable->addTerm(Linear::create("TenPercent", engine, 0.000, 0.000, 10.000));
-outputVariable->addTerm(Linear::create("FifteenPercent", engine, 0.000, 0.000, 15.000));
-outputVariable->addTerm(Linear::create("TwentyPercent", engine, 0.000, 0.000, 20.000));
-engine->addOutputVariable(outputVariable);
+engine->setName("linear_tip_calculator");
+engine->setDescription("");
+
+InputVariable* FoodQuality = new InputVariable;
+FoodQuality->setName("FoodQuality");
+FoodQuality->setDescription("");
+FoodQuality->setEnabled(true);
+FoodQuality->setRange(1.000, 10.000);
+FoodQuality->setLockValueInRange(false);
+FoodQuality->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+FoodQuality->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine->addInputVariable(FoodQuality);
+
+InputVariable* Service = new InputVariable;
+Service->setName("Service");
+Service->setDescription("");
+Service->setEnabled(true);
+Service->setRange(1.000, 10.000);
+Service->setLockValueInRange(false);
+Service->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+Service->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine->addInputVariable(Service);
+
+OutputVariable* Tip = new OutputVariable;
+Tip->setName("Tip");
+Tip->setDescription("");
+Tip->setEnabled(true);
+Tip->setRange(10.000, 20.000);
+Tip->setLockValueInRange(false);
+Tip->setAggregation(fl::null);
+Tip->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+Tip->setDefaultValue(fl::nan);
+Tip->setLockPreviousValue(false);
+Tip->addTerm(Linear::create("TenPercent", engine, 0.000, 0.000, 10.000));
+Tip->addTerm(Linear::create("FifteenPercent", engine, 0.000, 0.000, 15.000));
+Tip->addTerm(Linear::create("TwentyPercent", engine, 0.000, 0.000, 20.000));
+engine->addOutputVariable(Tip);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(new Minimum);
ruleBlock->setDisjunction(fl::null);
-ruleBlock->setActivation(fl::null);
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Bad and Service is Bad then Tip is TenPercent", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Bad and Service is Good then Tip is FifteenPercent", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Good and Service is Bad then Tip is FifteenPercent", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Good and Service is Good then Tip is TwentyPercent", engine));
+ruleBlock->setImplication(fl::null);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if FoodQuality is Bad and Service is Bad then Tip is TenPercent", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Bad and Service is Good then Tip is FifteenPercent", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Good and Service is Bad then Tip is FifteenPercent", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Good and Service is Good then Tip is TwentyPercent", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/takagi-sugeno/octave/linear_tip_calculator.fcl b/examples/takagi-sugeno/octave/linear_tip_calculator.fcl
index d326b2e..9b28c0e 100644
--- a/examples/takagi-sugeno/octave/linear_tip_calculator.fcl
+++ b/examples/takagi-sugeno/octave/linear_tip_calculator.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK Linear-Tip-Calculator
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK linear_tip_calculator
VAR_INPUT
FoodQuality: REAL;
diff --git a/examples/takagi-sugeno/octave/linear_tip_calculator.fis b/examples/takagi-sugeno/octave/linear_tip_calculator.fis
index 8df5a02..58b4016 100644
--- a/examples/takagi-sugeno/octave/linear_tip_calculator.fis
+++ b/examples/takagi-sugeno/octave/linear_tip_calculator.fis
@@ -1,13 +1,16 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='Linear-Tip-Calculator'
+Name='linear_tip_calculator'
Type='sugeno'
+Version=6.0
NumInputs=2
NumOutputs=1
NumRules=4
AndMethod='min'
-OrMethod=''
-ImpMethod=''
-AggMethod=''
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
DefuzzMethod='wtaver'
[Input1]
diff --git a/examples/takagi-sugeno/octave/linear_tip_calculator.fld b/examples/takagi-sugeno/octave/linear_tip_calculator.fld
index 27f51b4..60f4542 100644
--- a/examples/takagi-sugeno/octave/linear_tip_calculator.fld
+++ b/examples/takagi-sugeno/octave/linear_tip_calculator.fld
@@ -1,1026 +1,1025 @@
-#@Engine: Linear-Tip-Calculator;
-#@InputVariable: FoodQuality; @InputVariable: Service; @OutputVariable: Tip;
-1.00000000 1.00000000 10.00000000
-1.00000000 1.29032258 10.00000000
-1.00000000 1.58064516 10.00000000
-1.00000000 1.87096774 10.00000000
-1.00000000 2.16129032 10.00000000
-1.00000000 2.45161290 10.00000000
-1.00000000 2.74193548 10.00000000
-1.00000000 3.03225806 10.04032258
-1.00000000 3.32258065 10.40322581
-1.00000000 3.61290323 10.76612903
-1.00000000 3.90322581 11.12903226
-1.00000000 4.19354839 11.49193548
-1.00000000 4.48387097 11.85483871
-1.00000000 4.77419355 12.21774194
-1.00000000 5.06451613 12.58064516
-1.00000000 5.35483871 12.94354839
-1.00000000 5.64516129 13.30645161
-1.00000000 5.93548387 13.66935484
-1.00000000 6.22580645 14.03225806
-1.00000000 6.51612903 14.39516129
-1.00000000 6.80645161 14.75806452
-1.00000000 7.09677419 15.00000000
-1.00000000 7.38709677 15.00000000
-1.00000000 7.67741935 15.00000000
-1.00000000 7.96774194 15.00000000
-1.00000000 8.25806452 15.00000000
-1.00000000 8.54838710 15.00000000
-1.00000000 8.83870968 15.00000000
-1.00000000 9.12903226 15.00000000
-1.00000000 9.41935484 15.00000000
-1.00000000 9.70967742 15.00000000
-1.00000000 10.00000000 15.00000000
-1.29032258 1.00000000 10.00000000
-1.29032258 1.29032258 10.00000000
-1.29032258 1.58064516 10.00000000
-1.29032258 1.87096774 10.00000000
-1.29032258 2.16129032 10.00000000
-1.29032258 2.45161290 10.00000000
-1.29032258 2.74193548 10.00000000
-1.29032258 3.03225806 10.04032258
-1.29032258 3.32258065 10.40322581
-1.29032258 3.61290323 10.76612903
-1.29032258 3.90322581 11.12903226
-1.29032258 4.19354839 11.49193548
-1.29032258 4.48387097 11.85483871
-1.29032258 4.77419355 12.21774194
-1.29032258 5.06451613 12.58064516
-1.29032258 5.35483871 12.94354839
-1.29032258 5.64516129 13.30645161
-1.29032258 5.93548387 13.66935484
-1.29032258 6.22580645 14.03225806
-1.29032258 6.51612903 14.39516129
-1.29032258 6.80645161 14.75806452
-1.29032258 7.09677419 15.00000000
-1.29032258 7.38709677 15.00000000
-1.29032258 7.67741935 15.00000000
-1.29032258 7.96774194 15.00000000
-1.29032258 8.25806452 15.00000000
-1.29032258 8.54838710 15.00000000
-1.29032258 8.83870968 15.00000000
-1.29032258 9.12903226 15.00000000
-1.29032258 9.41935484 15.00000000
-1.29032258 9.70967742 15.00000000
-1.29032258 10.00000000 15.00000000
-1.58064516 1.00000000 10.00000000
-1.58064516 1.29032258 10.00000000
-1.58064516 1.58064516 10.00000000
-1.58064516 1.87096774 10.00000000
-1.58064516 2.16129032 10.00000000
-1.58064516 2.45161290 10.00000000
-1.58064516 2.74193548 10.00000000
-1.58064516 3.03225806 10.04032258
-1.58064516 3.32258065 10.40322581
-1.58064516 3.61290323 10.76612903
-1.58064516 3.90322581 11.12903226
-1.58064516 4.19354839 11.49193548
-1.58064516 4.48387097 11.85483871
-1.58064516 4.77419355 12.21774194
-1.58064516 5.06451613 12.58064516
-1.58064516 5.35483871 12.94354839
-1.58064516 5.64516129 13.30645161
-1.58064516 5.93548387 13.66935484
-1.58064516 6.22580645 14.03225806
-1.58064516 6.51612903 14.39516129
-1.58064516 6.80645161 14.75806452
-1.58064516 7.09677419 15.00000000
-1.58064516 7.38709677 15.00000000
-1.58064516 7.67741935 15.00000000
-1.58064516 7.96774194 15.00000000
-1.58064516 8.25806452 15.00000000
-1.58064516 8.54838710 15.00000000
-1.58064516 8.83870968 15.00000000
-1.58064516 9.12903226 15.00000000
-1.58064516 9.41935484 15.00000000
-1.58064516 9.70967742 15.00000000
-1.58064516 10.00000000 15.00000000
-1.87096774 1.00000000 10.00000000
-1.87096774 1.29032258 10.00000000
-1.87096774 1.58064516 10.00000000
-1.87096774 1.87096774 10.00000000
-1.87096774 2.16129032 10.00000000
-1.87096774 2.45161290 10.00000000
-1.87096774 2.74193548 10.00000000
-1.87096774 3.03225806 10.04032258
-1.87096774 3.32258065 10.40322581
-1.87096774 3.61290323 10.76612903
-1.87096774 3.90322581 11.12903226
-1.87096774 4.19354839 11.49193548
-1.87096774 4.48387097 11.85483871
-1.87096774 4.77419355 12.21774194
-1.87096774 5.06451613 12.58064516
-1.87096774 5.35483871 12.94354839
-1.87096774 5.64516129 13.30645161
-1.87096774 5.93548387 13.66935484
-1.87096774 6.22580645 14.03225806
-1.87096774 6.51612903 14.39516129
-1.87096774 6.80645161 14.75806452
-1.87096774 7.09677419 15.00000000
-1.87096774 7.38709677 15.00000000
-1.87096774 7.67741935 15.00000000
-1.87096774 7.96774194 15.00000000
-1.87096774 8.25806452 15.00000000
-1.87096774 8.54838710 15.00000000
-1.87096774 8.83870968 15.00000000
-1.87096774 9.12903226 15.00000000
-1.87096774 9.41935484 15.00000000
-1.87096774 9.70967742 15.00000000
-1.87096774 10.00000000 15.00000000
-2.16129032 1.00000000 10.00000000
-2.16129032 1.29032258 10.00000000
-2.16129032 1.58064516 10.00000000
-2.16129032 1.87096774 10.00000000
-2.16129032 2.16129032 10.00000000
-2.16129032 2.45161290 10.00000000
-2.16129032 2.74193548 10.00000000
-2.16129032 3.03225806 10.04032258
-2.16129032 3.32258065 10.40322581
-2.16129032 3.61290323 10.76612903
-2.16129032 3.90322581 11.12903226
-2.16129032 4.19354839 11.49193548
-2.16129032 4.48387097 11.85483871
-2.16129032 4.77419355 12.21774194
-2.16129032 5.06451613 12.58064516
-2.16129032 5.35483871 12.94354839
-2.16129032 5.64516129 13.30645161
-2.16129032 5.93548387 13.66935484
-2.16129032 6.22580645 14.03225806
-2.16129032 6.51612903 14.39516129
-2.16129032 6.80645161 14.75806452
-2.16129032 7.09677419 15.00000000
-2.16129032 7.38709677 15.00000000
-2.16129032 7.67741935 15.00000000
-2.16129032 7.96774194 15.00000000
-2.16129032 8.25806452 15.00000000
-2.16129032 8.54838710 15.00000000
-2.16129032 8.83870968 15.00000000
-2.16129032 9.12903226 15.00000000
-2.16129032 9.41935484 15.00000000
-2.16129032 9.70967742 15.00000000
-2.16129032 10.00000000 15.00000000
-2.45161290 1.00000000 10.00000000
-2.45161290 1.29032258 10.00000000
-2.45161290 1.58064516 10.00000000
-2.45161290 1.87096774 10.00000000
-2.45161290 2.16129032 10.00000000
-2.45161290 2.45161290 10.00000000
-2.45161290 2.74193548 10.00000000
-2.45161290 3.03225806 10.04032258
-2.45161290 3.32258065 10.40322581
-2.45161290 3.61290323 10.76612903
-2.45161290 3.90322581 11.12903226
-2.45161290 4.19354839 11.49193548
-2.45161290 4.48387097 11.85483871
-2.45161290 4.77419355 12.21774194
-2.45161290 5.06451613 12.58064516
-2.45161290 5.35483871 12.94354839
-2.45161290 5.64516129 13.30645161
-2.45161290 5.93548387 13.66935484
-2.45161290 6.22580645 14.03225806
-2.45161290 6.51612903 14.39516129
-2.45161290 6.80645161 14.75806452
-2.45161290 7.09677419 15.00000000
-2.45161290 7.38709677 15.00000000
-2.45161290 7.67741935 15.00000000
-2.45161290 7.96774194 15.00000000
-2.45161290 8.25806452 15.00000000
-2.45161290 8.54838710 15.00000000
-2.45161290 8.83870968 15.00000000
-2.45161290 9.12903226 15.00000000
-2.45161290 9.41935484 15.00000000
-2.45161290 9.70967742 15.00000000
-2.45161290 10.00000000 15.00000000
-2.74193548 1.00000000 10.00000000
-2.74193548 1.29032258 10.00000000
-2.74193548 1.58064516 10.00000000
-2.74193548 1.87096774 10.00000000
-2.74193548 2.16129032 10.00000000
-2.74193548 2.45161290 10.00000000
-2.74193548 2.74193548 10.00000000
-2.74193548 3.03225806 10.04032258
-2.74193548 3.32258065 10.40322581
-2.74193548 3.61290323 10.76612903
-2.74193548 3.90322581 11.12903226
-2.74193548 4.19354839 11.49193548
-2.74193548 4.48387097 11.85483871
-2.74193548 4.77419355 12.21774194
-2.74193548 5.06451613 12.58064516
-2.74193548 5.35483871 12.94354839
-2.74193548 5.64516129 13.30645161
-2.74193548 5.93548387 13.66935484
-2.74193548 6.22580645 14.03225806
-2.74193548 6.51612903 14.39516129
-2.74193548 6.80645161 14.75806452
-2.74193548 7.09677419 15.00000000
-2.74193548 7.38709677 15.00000000
-2.74193548 7.67741935 15.00000000
-2.74193548 7.96774194 15.00000000
-2.74193548 8.25806452 15.00000000
-2.74193548 8.54838710 15.00000000
-2.74193548 8.83870968 15.00000000
-2.74193548 9.12903226 15.00000000
-2.74193548 9.41935484 15.00000000
-2.74193548 9.70967742 15.00000000
-2.74193548 10.00000000 15.00000000
-3.03225806 1.00000000 10.04032258
-3.03225806 1.29032258 10.04032258
-3.03225806 1.58064516 10.04032258
-3.03225806 1.87096774 10.04032258
-3.03225806 2.16129032 10.04032258
-3.03225806 2.45161290 10.04032258
-3.03225806 2.74193548 10.04032258
-3.03225806 3.03225806 10.15873016
-3.03225806 3.32258065 10.51587302
-3.03225806 3.61290323 10.87301587
-3.03225806 3.90322581 11.23015873
-3.03225806 4.19354839 11.58730159
-3.03225806 4.48387097 11.94444444
-3.03225806 4.77419355 12.30158730
-3.03225806 5.06451613 12.65873016
-3.03225806 5.35483871 13.01587302
-3.03225806 5.64516129 13.37301587
-3.03225806 5.93548387 13.73015873
-3.03225806 6.22580645 14.08730159
-3.03225806 6.51612903 14.44444444
-3.03225806 6.80645161 14.80158730
-3.03225806 7.09677419 15.04032258
-3.03225806 7.38709677 15.04032258
-3.03225806 7.67741935 15.04032258
-3.03225806 7.96774194 15.04032258
-3.03225806 8.25806452 15.04032258
-3.03225806 8.54838710 15.04032258
-3.03225806 8.83870968 15.04032258
-3.03225806 9.12903226 15.04032258
-3.03225806 9.41935484 15.04032258
-3.03225806 9.70967742 15.04032258
-3.03225806 10.00000000 15.04032258
-3.32258065 1.00000000 10.40322581
-3.32258065 1.29032258 10.40322581
-3.32258065 1.58064516 10.40322581
-3.32258065 1.87096774 10.40322581
-3.32258065 2.16129032 10.40322581
-3.32258065 2.45161290 10.40322581
-3.32258065 2.74193548 10.40322581
-3.32258065 3.03225806 10.51587302
-3.32258065 3.32258065 11.38888889
-3.32258065 3.61290323 11.70138889
-3.32258065 3.90322581 12.01388889
-3.32258065 4.19354839 12.32638889
-3.32258065 4.48387097 12.63888889
-3.32258065 4.77419355 12.95138889
-3.32258065 5.06451613 13.26388889
-3.32258065 5.35483871 13.57638889
-3.32258065 5.64516129 13.88888889
-3.32258065 5.93548387 14.20138889
-3.32258065 6.22580645 14.51388889
-3.32258065 6.51612903 14.82638889
-3.32258065 6.80645161 15.14705882
-3.32258065 7.09677419 15.40322581
-3.32258065 7.38709677 15.40322581
-3.32258065 7.67741935 15.40322581
-3.32258065 7.96774194 15.40322581
-3.32258065 8.25806452 15.40322581
-3.32258065 8.54838710 15.40322581
-3.32258065 8.83870968 15.40322581
-3.32258065 9.12903226 15.40322581
-3.32258065 9.41935484 15.40322581
-3.32258065 9.70967742 15.40322581
-3.32258065 10.00000000 15.40322581
-3.61290323 1.00000000 10.76612903
-3.61290323 1.29032258 10.76612903
-3.61290323 1.58064516 10.76612903
-3.61290323 1.87096774 10.76612903
-3.61290323 2.16129032 10.76612903
-3.61290323 2.45161290 10.76612903
-3.61290323 2.74193548 10.76612903
-3.61290323 3.03225806 10.87301587
-3.61290323 3.32258065 11.70138889
-3.61290323 3.61290323 12.34567901
-3.61290323 3.90322581 12.62345679
-3.61290323 4.19354839 12.90123457
-3.61290323 4.48387097 13.17901235
-3.61290323 4.77419355 13.45679012
-3.61290323 5.06451613 13.73456790
-3.61290323 5.35483871 14.01234568
-3.61290323 5.64516129 14.29012346
-3.61290323 5.93548387 14.56790123
-3.61290323 6.22580645 14.84567901
-3.61290323 6.51612903 15.12987013
-3.61290323 6.80645161 15.47794118
-3.61290323 7.09677419 15.76612903
-3.61290323 7.38709677 15.76612903
-3.61290323 7.67741935 15.76612903
-3.61290323 7.96774194 15.76612903
-3.61290323 8.25806452 15.76612903
-3.61290323 8.54838710 15.76612903
-3.61290323 8.83870968 15.76612903
-3.61290323 9.12903226 15.76612903
-3.61290323 9.41935484 15.76612903
-3.61290323 9.70967742 15.76612903
-3.61290323 10.00000000 15.76612903
-3.90322581 1.00000000 11.12903226
-3.90322581 1.29032258 11.12903226
-3.90322581 1.58064516 11.12903226
-3.90322581 1.87096774 11.12903226
-3.90322581 2.16129032 11.12903226
-3.90322581 2.45161290 11.12903226
-3.90322581 2.74193548 11.12903226
-3.90322581 3.03225806 11.23015873
-3.90322581 3.32258065 12.01388889
-3.90322581 3.61290323 12.62345679
-3.90322581 3.90322581 13.11111111
-3.90322581 4.19354839 13.36111111
-3.90322581 4.48387097 13.61111111
-3.90322581 4.77419355 13.86111111
-3.90322581 5.06451613 14.11111111
-3.90322581 5.35483871 14.36111111
-3.90322581 5.64516129 14.61111111
-3.90322581 5.93548387 14.86111111
-3.90322581 6.22580645 15.11627907
-3.90322581 6.51612903 15.42207792
-3.90322581 6.80645161 15.80882353
-3.90322581 7.09677419 16.12903226
-3.90322581 7.38709677 16.12903226
-3.90322581 7.67741935 16.12903226
-3.90322581 7.96774194 16.12903226
-3.90322581 8.25806452 16.12903226
-3.90322581 8.54838710 16.12903226
-3.90322581 8.83870968 16.12903226
-3.90322581 9.12903226 16.12903226
-3.90322581 9.41935484 16.12903226
-3.90322581 9.70967742 16.12903226
-3.90322581 10.00000000 16.12903226
-4.19354839 1.00000000 11.49193548
-4.19354839 1.29032258 11.49193548
-4.19354839 1.58064516 11.49193548
-4.19354839 1.87096774 11.49193548
-4.19354839 2.16129032 11.49193548
-4.19354839 2.45161290 11.49193548
-4.19354839 2.74193548 11.49193548
-4.19354839 3.03225806 11.58730159
-4.19354839 3.32258065 12.32638889
-4.19354839 3.61290323 12.90123457
-4.19354839 3.90322581 13.36111111
-4.19354839 4.19354839 13.73737374
-4.19354839 4.48387097 13.96464646
-4.19354839 4.77419355 14.19191919
-4.19354839 5.06451613 14.41919192
-4.19354839 5.35483871 14.64646465
-4.19354839 5.64516129 14.87373737
-4.19354839 5.93548387 15.10526316
-4.19354839 6.22580645 15.37790698
-4.19354839 6.51612903 15.71428571
-4.19354839 6.80645161 16.13970588
-4.19354839 7.09677419 16.49193548
-4.19354839 7.38709677 16.49193548
-4.19354839 7.67741935 16.49193548
-4.19354839 7.96774194 16.49193548
-4.19354839 8.25806452 16.49193548
-4.19354839 8.54838710 16.49193548
-4.19354839 8.83870968 16.49193548
-4.19354839 9.12903226 16.49193548
-4.19354839 9.41935484 16.49193548
-4.19354839 9.70967742 16.49193548
-4.19354839 10.00000000 16.49193548
-4.48387097 1.00000000 11.85483871
-4.48387097 1.29032258 11.85483871
-4.48387097 1.58064516 11.85483871
-4.48387097 1.87096774 11.85483871
-4.48387097 2.16129032 11.85483871
-4.48387097 2.45161290 11.85483871
-4.48387097 2.74193548 11.85483871
-4.48387097 3.03225806 11.94444444
-4.48387097 3.32258065 12.63888889
-4.48387097 3.61290323 13.17901235
-4.48387097 3.90322581 13.61111111
-4.48387097 4.19354839 13.96464646
-4.48387097 4.48387097 14.25925926
-4.48387097 4.77419355 14.46759259
-4.48387097 5.06451613 14.67592593
-4.48387097 5.35483871 14.88425926
-4.48387097 5.64516129 15.09615385
-4.48387097 5.93548387 15.34210526
-4.48387097 6.22580645 15.63953488
-4.48387097 6.51612903 16.00649351
-4.48387097 6.80645161 16.47058824
-4.48387097 7.09677419 16.85483871
-4.48387097 7.38709677 16.85483871
-4.48387097 7.67741935 16.85483871
-4.48387097 7.96774194 16.85483871
-4.48387097 8.25806452 16.85483871
-4.48387097 8.54838710 16.85483871
-4.48387097 8.83870968 16.85483871
-4.48387097 9.12903226 16.85483871
-4.48387097 9.41935484 16.85483871
-4.48387097 9.70967742 16.85483871
-4.48387097 10.00000000 16.85483871
-4.77419355 1.00000000 12.21774194
-4.77419355 1.29032258 12.21774194
-4.77419355 1.58064516 12.21774194
-4.77419355 1.87096774 12.21774194
-4.77419355 2.16129032 12.21774194
-4.77419355 2.45161290 12.21774194
-4.77419355 2.74193548 12.21774194
-4.77419355 3.03225806 12.30158730
-4.77419355 3.32258065 12.95138889
-4.77419355 3.61290323 13.45679012
-4.77419355 3.90322581 13.86111111
-4.77419355 4.19354839 14.19191919
-4.77419355 4.48387097 14.46759259
-4.77419355 4.77419355 14.70085470
-4.77419355 5.06451613 14.89316239
-4.77419355 5.35483871 15.08849558
-4.77419355 5.64516129 15.31250000
-4.77419355 5.93548387 15.57894737
-4.77419355 6.22580645 15.90116279
-4.77419355 6.51612903 16.29870130
-4.77419355 6.80645161 16.80147059
-4.77419355 7.09677419 17.21774194
-4.77419355 7.38709677 17.21774194
-4.77419355 7.67741935 17.21774194
-4.77419355 7.96774194 17.21774194
-4.77419355 8.25806452 17.21774194
-4.77419355 8.54838710 17.21774194
-4.77419355 8.83870968 17.21774194
-4.77419355 9.12903226 17.21774194
-4.77419355 9.41935484 17.21774194
-4.77419355 9.70967742 17.21774194
-4.77419355 10.00000000 17.21774194
-5.06451613 1.00000000 12.58064516
-5.06451613 1.29032258 12.58064516
-5.06451613 1.58064516 12.58064516
-5.06451613 1.87096774 12.58064516
-5.06451613 2.16129032 12.58064516
-5.06451613 2.45161290 12.58064516
-5.06451613 2.74193548 12.58064516
-5.06451613 3.03225806 12.65873016
-5.06451613 3.32258065 13.26388889
-5.06451613 3.61290323 13.73456790
-5.06451613 3.90322581 14.11111111
-5.06451613 4.19354839 14.41919192
-5.06451613 4.48387097 14.67592593
-5.06451613 4.77419355 14.89316239
-5.06451613 5.06451613 15.08196721
-5.06451613 5.35483871 15.28761062
-5.06451613 5.64516129 15.52884615
-5.06451613 5.93548387 15.81578947
-5.06451613 6.22580645 16.16279070
-5.06451613 6.51612903 16.59090909
-5.06451613 6.80645161 17.13235294
-5.06451613 7.09677419 17.58064516
-5.06451613 7.38709677 17.58064516
-5.06451613 7.67741935 17.58064516
-5.06451613 7.96774194 17.58064516
-5.06451613 8.25806452 17.58064516
-5.06451613 8.54838710 17.58064516
-5.06451613 8.83870968 17.58064516
-5.06451613 9.12903226 17.58064516
-5.06451613 9.41935484 17.58064516
-5.06451613 9.70967742 17.58064516
-5.06451613 10.00000000 17.58064516
-5.35483871 1.00000000 12.94354839
-5.35483871 1.29032258 12.94354839
-5.35483871 1.58064516 12.94354839
-5.35483871 1.87096774 12.94354839
-5.35483871 2.16129032 12.94354839
-5.35483871 2.45161290 12.94354839
-5.35483871 2.74193548 12.94354839
-5.35483871 3.03225806 13.01587302
-5.35483871 3.32258065 13.57638889
-5.35483871 3.61290323 14.01234568
-5.35483871 3.90322581 14.36111111
-5.35483871 4.19354839 14.64646465
-5.35483871 4.48387097 14.88425926
-5.35483871 4.77419355 15.08849558
-5.35483871 5.06451613 15.28761062
-5.35483871 5.35483871 15.48672566
-5.35483871 5.64516129 15.74519231
-5.35483871 5.93548387 16.05263158
-5.35483871 6.22580645 16.42441860
-5.35483871 6.51612903 16.88311688
-5.35483871 6.80645161 17.46323529
-5.35483871 7.09677419 17.94354839
-5.35483871 7.38709677 17.94354839
-5.35483871 7.67741935 17.94354839
-5.35483871 7.96774194 17.94354839
-5.35483871 8.25806452 17.94354839
-5.35483871 8.54838710 17.94354839
-5.35483871 8.83870968 17.94354839
-5.35483871 9.12903226 17.94354839
-5.35483871 9.41935484 17.94354839
-5.35483871 9.70967742 17.94354839
-5.35483871 10.00000000 17.94354839
-5.64516129 1.00000000 13.30645161
-5.64516129 1.29032258 13.30645161
-5.64516129 1.58064516 13.30645161
-5.64516129 1.87096774 13.30645161
-5.64516129 2.16129032 13.30645161
-5.64516129 2.45161290 13.30645161
-5.64516129 2.74193548 13.30645161
-5.64516129 3.03225806 13.37301587
-5.64516129 3.32258065 13.88888889
-5.64516129 3.61290323 14.29012346
-5.64516129 3.90322581 14.61111111
-5.64516129 4.19354839 14.87373737
-5.64516129 4.48387097 15.09615385
-5.64516129 4.77419355 15.31250000
-5.64516129 5.06451613 15.52884615
-5.64516129 5.35483871 15.74519231
-5.64516129 5.64516129 15.96153846
-5.64516129 5.93548387 16.28947368
-5.64516129 6.22580645 16.68604651
-5.64516129 6.51612903 17.17532468
-5.64516129 6.80645161 17.79411765
-5.64516129 7.09677419 18.30645161
-5.64516129 7.38709677 18.30645161
-5.64516129 7.67741935 18.30645161
-5.64516129 7.96774194 18.30645161
-5.64516129 8.25806452 18.30645161
-5.64516129 8.54838710 18.30645161
-5.64516129 8.83870968 18.30645161
-5.64516129 9.12903226 18.30645161
-5.64516129 9.41935484 18.30645161
-5.64516129 9.70967742 18.30645161
-5.64516129 10.00000000 18.30645161
-5.93548387 1.00000000 13.66935484
-5.93548387 1.29032258 13.66935484
-5.93548387 1.58064516 13.66935484
-5.93548387 1.87096774 13.66935484
-5.93548387 2.16129032 13.66935484
-5.93548387 2.45161290 13.66935484
-5.93548387 2.74193548 13.66935484
-5.93548387 3.03225806 13.73015873
-5.93548387 3.32258065 14.20138889
-5.93548387 3.61290323 14.56790123
-5.93548387 3.90322581 14.86111111
-5.93548387 4.19354839 15.10526316
-5.93548387 4.48387097 15.34210526
-5.93548387 4.77419355 15.57894737
-5.93548387 5.06451613 15.81578947
-5.93548387 5.35483871 16.05263158
-5.93548387 5.64516129 16.28947368
-5.93548387 5.93548387 16.52631579
-5.93548387 6.22580645 16.94767442
-5.93548387 6.51612903 17.46753247
-5.93548387 6.80645161 18.12500000
-5.93548387 7.09677419 18.66935484
-5.93548387 7.38709677 18.66935484
-5.93548387 7.67741935 18.66935484
-5.93548387 7.96774194 18.66935484
-5.93548387 8.25806452 18.66935484
-5.93548387 8.54838710 18.66935484
-5.93548387 8.83870968 18.66935484
-5.93548387 9.12903226 18.66935484
-5.93548387 9.41935484 18.66935484
-5.93548387 9.70967742 18.66935484
-5.93548387 10.00000000 18.66935484
-6.22580645 1.00000000 14.03225806
-6.22580645 1.29032258 14.03225806
-6.22580645 1.58064516 14.03225806
-6.22580645 1.87096774 14.03225806
-6.22580645 2.16129032 14.03225806
-6.22580645 2.45161290 14.03225806
-6.22580645 2.74193548 14.03225806
-6.22580645 3.03225806 14.08730159
-6.22580645 3.32258065 14.51388889
-6.22580645 3.61290323 14.84567901
-6.22580645 3.90322581 15.11627907
-6.22580645 4.19354839 15.37790698
-6.22580645 4.48387097 15.63953488
-6.22580645 4.77419355 15.90116279
-6.22580645 5.06451613 16.16279070
-6.22580645 5.35483871 16.42441860
-6.22580645 5.64516129 16.68604651
-6.22580645 5.93548387 16.94767442
-6.22580645 6.22580645 17.20930233
-6.22580645 6.51612903 17.75974026
-6.22580645 6.80645161 18.45588235
-6.22580645 7.09677419 19.03225806
-6.22580645 7.38709677 19.03225806
-6.22580645 7.67741935 19.03225806
-6.22580645 7.96774194 19.03225806
-6.22580645 8.25806452 19.03225806
-6.22580645 8.54838710 19.03225806
-6.22580645 8.83870968 19.03225806
-6.22580645 9.12903226 19.03225806
-6.22580645 9.41935484 19.03225806
-6.22580645 9.70967742 19.03225806
-6.22580645 10.00000000 19.03225806
-6.51612903 1.00000000 14.39516129
-6.51612903 1.29032258 14.39516129
-6.51612903 1.58064516 14.39516129
-6.51612903 1.87096774 14.39516129
-6.51612903 2.16129032 14.39516129
-6.51612903 2.45161290 14.39516129
-6.51612903 2.74193548 14.39516129
-6.51612903 3.03225806 14.44444444
-6.51612903 3.32258065 14.82638889
-6.51612903 3.61290323 15.12987013
-6.51612903 3.90322581 15.42207792
-6.51612903 4.19354839 15.71428571
-6.51612903 4.48387097 16.00649351
-6.51612903 4.77419355 16.29870130
-6.51612903 5.06451613 16.59090909
-6.51612903 5.35483871 16.88311688
-6.51612903 5.64516129 17.17532468
-6.51612903 5.93548387 17.46753247
-6.51612903 6.22580645 17.75974026
-6.51612903 6.51612903 18.05194805
-6.51612903 6.80645161 18.78676471
-6.51612903 7.09677419 19.39516129
-6.51612903 7.38709677 19.39516129
-6.51612903 7.67741935 19.39516129
-6.51612903 7.96774194 19.39516129
-6.51612903 8.25806452 19.39516129
-6.51612903 8.54838710 19.39516129
-6.51612903 8.83870968 19.39516129
-6.51612903 9.12903226 19.39516129
-6.51612903 9.41935484 19.39516129
-6.51612903 9.70967742 19.39516129
-6.51612903 10.00000000 19.39516129
-6.80645161 1.00000000 14.75806452
-6.80645161 1.29032258 14.75806452
-6.80645161 1.58064516 14.75806452
-6.80645161 1.87096774 14.75806452
-6.80645161 2.16129032 14.75806452
-6.80645161 2.45161290 14.75806452
-6.80645161 2.74193548 14.75806452
-6.80645161 3.03225806 14.80158730
-6.80645161 3.32258065 15.14705882
-6.80645161 3.61290323 15.47794118
-6.80645161 3.90322581 15.80882353
-6.80645161 4.19354839 16.13970588
-6.80645161 4.48387097 16.47058824
-6.80645161 4.77419355 16.80147059
-6.80645161 5.06451613 17.13235294
-6.80645161 5.35483871 17.46323529
-6.80645161 5.64516129 17.79411765
-6.80645161 5.93548387 18.12500000
-6.80645161 6.22580645 18.45588235
-6.80645161 6.51612903 18.78676471
-6.80645161 6.80645161 19.11764706
-6.80645161 7.09677419 19.75806452
-6.80645161 7.38709677 19.75806452
-6.80645161 7.67741935 19.75806452
-6.80645161 7.96774194 19.75806452
-6.80645161 8.25806452 19.75806452
-6.80645161 8.54838710 19.75806452
-6.80645161 8.83870968 19.75806452
-6.80645161 9.12903226 19.75806452
-6.80645161 9.41935484 19.75806452
-6.80645161 9.70967742 19.75806452
-6.80645161 10.00000000 19.75806452
-7.09677419 1.00000000 15.00000000
-7.09677419 1.29032258 15.00000000
-7.09677419 1.58064516 15.00000000
-7.09677419 1.87096774 15.00000000
-7.09677419 2.16129032 15.00000000
-7.09677419 2.45161290 15.00000000
-7.09677419 2.74193548 15.00000000
-7.09677419 3.03225806 15.04032258
-7.09677419 3.32258065 15.40322581
-7.09677419 3.61290323 15.76612903
-7.09677419 3.90322581 16.12903226
-7.09677419 4.19354839 16.49193548
-7.09677419 4.48387097 16.85483871
-7.09677419 4.77419355 17.21774194
-7.09677419 5.06451613 17.58064516
-7.09677419 5.35483871 17.94354839
-7.09677419 5.64516129 18.30645161
-7.09677419 5.93548387 18.66935484
-7.09677419 6.22580645 19.03225806
-7.09677419 6.51612903 19.39516129
-7.09677419 6.80645161 19.75806452
-7.09677419 7.09677419 20.00000000
-7.09677419 7.38709677 20.00000000
-7.09677419 7.67741935 20.00000000
-7.09677419 7.96774194 20.00000000
-7.09677419 8.25806452 20.00000000
-7.09677419 8.54838710 20.00000000
-7.09677419 8.83870968 20.00000000
-7.09677419 9.12903226 20.00000000
-7.09677419 9.41935484 20.00000000
-7.09677419 9.70967742 20.00000000
-7.09677419 10.00000000 20.00000000
-7.38709677 1.00000000 15.00000000
-7.38709677 1.29032258 15.00000000
-7.38709677 1.58064516 15.00000000
-7.38709677 1.87096774 15.00000000
-7.38709677 2.16129032 15.00000000
-7.38709677 2.45161290 15.00000000
-7.38709677 2.74193548 15.00000000
-7.38709677 3.03225806 15.04032258
-7.38709677 3.32258065 15.40322581
-7.38709677 3.61290323 15.76612903
-7.38709677 3.90322581 16.12903226
-7.38709677 4.19354839 16.49193548
-7.38709677 4.48387097 16.85483871
-7.38709677 4.77419355 17.21774194
-7.38709677 5.06451613 17.58064516
-7.38709677 5.35483871 17.94354839
-7.38709677 5.64516129 18.30645161
-7.38709677 5.93548387 18.66935484
-7.38709677 6.22580645 19.03225806
-7.38709677 6.51612903 19.39516129
-7.38709677 6.80645161 19.75806452
-7.38709677 7.09677419 20.00000000
-7.38709677 7.38709677 20.00000000
-7.38709677 7.67741935 20.00000000
-7.38709677 7.96774194 20.00000000
-7.38709677 8.25806452 20.00000000
-7.38709677 8.54838710 20.00000000
-7.38709677 8.83870968 20.00000000
-7.38709677 9.12903226 20.00000000
-7.38709677 9.41935484 20.00000000
-7.38709677 9.70967742 20.00000000
-7.38709677 10.00000000 20.00000000
-7.67741935 1.00000000 15.00000000
-7.67741935 1.29032258 15.00000000
-7.67741935 1.58064516 15.00000000
-7.67741935 1.87096774 15.00000000
-7.67741935 2.16129032 15.00000000
-7.67741935 2.45161290 15.00000000
-7.67741935 2.74193548 15.00000000
-7.67741935 3.03225806 15.04032258
-7.67741935 3.32258065 15.40322581
-7.67741935 3.61290323 15.76612903
-7.67741935 3.90322581 16.12903226
-7.67741935 4.19354839 16.49193548
-7.67741935 4.48387097 16.85483871
-7.67741935 4.77419355 17.21774194
-7.67741935 5.06451613 17.58064516
-7.67741935 5.35483871 17.94354839
-7.67741935 5.64516129 18.30645161
-7.67741935 5.93548387 18.66935484
-7.67741935 6.22580645 19.03225806
-7.67741935 6.51612903 19.39516129
-7.67741935 6.80645161 19.75806452
-7.67741935 7.09677419 20.00000000
-7.67741935 7.38709677 20.00000000
-7.67741935 7.67741935 20.00000000
-7.67741935 7.96774194 20.00000000
-7.67741935 8.25806452 20.00000000
-7.67741935 8.54838710 20.00000000
-7.67741935 8.83870968 20.00000000
-7.67741935 9.12903226 20.00000000
-7.67741935 9.41935484 20.00000000
-7.67741935 9.70967742 20.00000000
-7.67741935 10.00000000 20.00000000
-7.96774194 1.00000000 15.00000000
-7.96774194 1.29032258 15.00000000
-7.96774194 1.58064516 15.00000000
-7.96774194 1.87096774 15.00000000
-7.96774194 2.16129032 15.00000000
-7.96774194 2.45161290 15.00000000
-7.96774194 2.74193548 15.00000000
-7.96774194 3.03225806 15.04032258
-7.96774194 3.32258065 15.40322581
-7.96774194 3.61290323 15.76612903
-7.96774194 3.90322581 16.12903226
-7.96774194 4.19354839 16.49193548
-7.96774194 4.48387097 16.85483871
-7.96774194 4.77419355 17.21774194
-7.96774194 5.06451613 17.58064516
-7.96774194 5.35483871 17.94354839
-7.96774194 5.64516129 18.30645161
-7.96774194 5.93548387 18.66935484
-7.96774194 6.22580645 19.03225806
-7.96774194 6.51612903 19.39516129
-7.96774194 6.80645161 19.75806452
-7.96774194 7.09677419 20.00000000
-7.96774194 7.38709677 20.00000000
-7.96774194 7.67741935 20.00000000
-7.96774194 7.96774194 20.00000000
-7.96774194 8.25806452 20.00000000
-7.96774194 8.54838710 20.00000000
-7.96774194 8.83870968 20.00000000
-7.96774194 9.12903226 20.00000000
-7.96774194 9.41935484 20.00000000
-7.96774194 9.70967742 20.00000000
-7.96774194 10.00000000 20.00000000
-8.25806452 1.00000000 15.00000000
-8.25806452 1.29032258 15.00000000
-8.25806452 1.58064516 15.00000000
-8.25806452 1.87096774 15.00000000
-8.25806452 2.16129032 15.00000000
-8.25806452 2.45161290 15.00000000
-8.25806452 2.74193548 15.00000000
-8.25806452 3.03225806 15.04032258
-8.25806452 3.32258065 15.40322581
-8.25806452 3.61290323 15.76612903
-8.25806452 3.90322581 16.12903226
-8.25806452 4.19354839 16.49193548
-8.25806452 4.48387097 16.85483871
-8.25806452 4.77419355 17.21774194
-8.25806452 5.06451613 17.58064516
-8.25806452 5.35483871 17.94354839
-8.25806452 5.64516129 18.30645161
-8.25806452 5.93548387 18.66935484
-8.25806452 6.22580645 19.03225806
-8.25806452 6.51612903 19.39516129
-8.25806452 6.80645161 19.75806452
-8.25806452 7.09677419 20.00000000
-8.25806452 7.38709677 20.00000000
-8.25806452 7.67741935 20.00000000
-8.25806452 7.96774194 20.00000000
-8.25806452 8.25806452 20.00000000
-8.25806452 8.54838710 20.00000000
-8.25806452 8.83870968 20.00000000
-8.25806452 9.12903226 20.00000000
-8.25806452 9.41935484 20.00000000
-8.25806452 9.70967742 20.00000000
-8.25806452 10.00000000 20.00000000
-8.54838710 1.00000000 15.00000000
-8.54838710 1.29032258 15.00000000
-8.54838710 1.58064516 15.00000000
-8.54838710 1.87096774 15.00000000
-8.54838710 2.16129032 15.00000000
-8.54838710 2.45161290 15.00000000
-8.54838710 2.74193548 15.00000000
-8.54838710 3.03225806 15.04032258
-8.54838710 3.32258065 15.40322581
-8.54838710 3.61290323 15.76612903
-8.54838710 3.90322581 16.12903226
-8.54838710 4.19354839 16.49193548
-8.54838710 4.48387097 16.85483871
-8.54838710 4.77419355 17.21774194
-8.54838710 5.06451613 17.58064516
-8.54838710 5.35483871 17.94354839
-8.54838710 5.64516129 18.30645161
-8.54838710 5.93548387 18.66935484
-8.54838710 6.22580645 19.03225806
-8.54838710 6.51612903 19.39516129
-8.54838710 6.80645161 19.75806452
-8.54838710 7.09677419 20.00000000
-8.54838710 7.38709677 20.00000000
-8.54838710 7.67741935 20.00000000
-8.54838710 7.96774194 20.00000000
-8.54838710 8.25806452 20.00000000
-8.54838710 8.54838710 20.00000000
-8.54838710 8.83870968 20.00000000
-8.54838710 9.12903226 20.00000000
-8.54838710 9.41935484 20.00000000
-8.54838710 9.70967742 20.00000000
-8.54838710 10.00000000 20.00000000
-8.83870968 1.00000000 15.00000000
-8.83870968 1.29032258 15.00000000
-8.83870968 1.58064516 15.00000000
-8.83870968 1.87096774 15.00000000
-8.83870968 2.16129032 15.00000000
-8.83870968 2.45161290 15.00000000
-8.83870968 2.74193548 15.00000000
-8.83870968 3.03225806 15.04032258
-8.83870968 3.32258065 15.40322581
-8.83870968 3.61290323 15.76612903
-8.83870968 3.90322581 16.12903226
-8.83870968 4.19354839 16.49193548
-8.83870968 4.48387097 16.85483871
-8.83870968 4.77419355 17.21774194
-8.83870968 5.06451613 17.58064516
-8.83870968 5.35483871 17.94354839
-8.83870968 5.64516129 18.30645161
-8.83870968 5.93548387 18.66935484
-8.83870968 6.22580645 19.03225806
-8.83870968 6.51612903 19.39516129
-8.83870968 6.80645161 19.75806452
-8.83870968 7.09677419 20.00000000
-8.83870968 7.38709677 20.00000000
-8.83870968 7.67741935 20.00000000
-8.83870968 7.96774194 20.00000000
-8.83870968 8.25806452 20.00000000
-8.83870968 8.54838710 20.00000000
-8.83870968 8.83870968 20.00000000
-8.83870968 9.12903226 20.00000000
-8.83870968 9.41935484 20.00000000
-8.83870968 9.70967742 20.00000000
-8.83870968 10.00000000 20.00000000
-9.12903226 1.00000000 15.00000000
-9.12903226 1.29032258 15.00000000
-9.12903226 1.58064516 15.00000000
-9.12903226 1.87096774 15.00000000
-9.12903226 2.16129032 15.00000000
-9.12903226 2.45161290 15.00000000
-9.12903226 2.74193548 15.00000000
-9.12903226 3.03225806 15.04032258
-9.12903226 3.32258065 15.40322581
-9.12903226 3.61290323 15.76612903
-9.12903226 3.90322581 16.12903226
-9.12903226 4.19354839 16.49193548
-9.12903226 4.48387097 16.85483871
-9.12903226 4.77419355 17.21774194
-9.12903226 5.06451613 17.58064516
-9.12903226 5.35483871 17.94354839
-9.12903226 5.64516129 18.30645161
-9.12903226 5.93548387 18.66935484
-9.12903226 6.22580645 19.03225806
-9.12903226 6.51612903 19.39516129
-9.12903226 6.80645161 19.75806452
-9.12903226 7.09677419 20.00000000
-9.12903226 7.38709677 20.00000000
-9.12903226 7.67741935 20.00000000
-9.12903226 7.96774194 20.00000000
-9.12903226 8.25806452 20.00000000
-9.12903226 8.54838710 20.00000000
-9.12903226 8.83870968 20.00000000
-9.12903226 9.12903226 20.00000000
-9.12903226 9.41935484 20.00000000
-9.12903226 9.70967742 20.00000000
-9.12903226 10.00000000 20.00000000
-9.41935484 1.00000000 15.00000000
-9.41935484 1.29032258 15.00000000
-9.41935484 1.58064516 15.00000000
-9.41935484 1.87096774 15.00000000
-9.41935484 2.16129032 15.00000000
-9.41935484 2.45161290 15.00000000
-9.41935484 2.74193548 15.00000000
-9.41935484 3.03225806 15.04032258
-9.41935484 3.32258065 15.40322581
-9.41935484 3.61290323 15.76612903
-9.41935484 3.90322581 16.12903226
-9.41935484 4.19354839 16.49193548
-9.41935484 4.48387097 16.85483871
-9.41935484 4.77419355 17.21774194
-9.41935484 5.06451613 17.58064516
-9.41935484 5.35483871 17.94354839
-9.41935484 5.64516129 18.30645161
-9.41935484 5.93548387 18.66935484
-9.41935484 6.22580645 19.03225806
-9.41935484 6.51612903 19.39516129
-9.41935484 6.80645161 19.75806452
-9.41935484 7.09677419 20.00000000
-9.41935484 7.38709677 20.00000000
-9.41935484 7.67741935 20.00000000
-9.41935484 7.96774194 20.00000000
-9.41935484 8.25806452 20.00000000
-9.41935484 8.54838710 20.00000000
-9.41935484 8.83870968 20.00000000
-9.41935484 9.12903226 20.00000000
-9.41935484 9.41935484 20.00000000
-9.41935484 9.70967742 20.00000000
-9.41935484 10.00000000 20.00000000
-9.70967742 1.00000000 15.00000000
-9.70967742 1.29032258 15.00000000
-9.70967742 1.58064516 15.00000000
-9.70967742 1.87096774 15.00000000
-9.70967742 2.16129032 15.00000000
-9.70967742 2.45161290 15.00000000
-9.70967742 2.74193548 15.00000000
-9.70967742 3.03225806 15.04032258
-9.70967742 3.32258065 15.40322581
-9.70967742 3.61290323 15.76612903
-9.70967742 3.90322581 16.12903226
-9.70967742 4.19354839 16.49193548
-9.70967742 4.48387097 16.85483871
-9.70967742 4.77419355 17.21774194
-9.70967742 5.06451613 17.58064516
-9.70967742 5.35483871 17.94354839
-9.70967742 5.64516129 18.30645161
-9.70967742 5.93548387 18.66935484
-9.70967742 6.22580645 19.03225806
-9.70967742 6.51612903 19.39516129
-9.70967742 6.80645161 19.75806452
-9.70967742 7.09677419 20.00000000
-9.70967742 7.38709677 20.00000000
-9.70967742 7.67741935 20.00000000
-9.70967742 7.96774194 20.00000000
-9.70967742 8.25806452 20.00000000
-9.70967742 8.54838710 20.00000000
-9.70967742 8.83870968 20.00000000
-9.70967742 9.12903226 20.00000000
-9.70967742 9.41935484 20.00000000
-9.70967742 9.70967742 20.00000000
-9.70967742 10.00000000 20.00000000
-10.00000000 1.00000000 15.00000000
-10.00000000 1.29032258 15.00000000
-10.00000000 1.58064516 15.00000000
-10.00000000 1.87096774 15.00000000
-10.00000000 2.16129032 15.00000000
-10.00000000 2.45161290 15.00000000
-10.00000000 2.74193548 15.00000000
-10.00000000 3.03225806 15.04032258
-10.00000000 3.32258065 15.40322581
-10.00000000 3.61290323 15.76612903
-10.00000000 3.90322581 16.12903226
-10.00000000 4.19354839 16.49193548
-10.00000000 4.48387097 16.85483871
-10.00000000 4.77419355 17.21774194
-10.00000000 5.06451613 17.58064516
-10.00000000 5.35483871 17.94354839
-10.00000000 5.64516129 18.30645161
-10.00000000 5.93548387 18.66935484
-10.00000000 6.22580645 19.03225806
-10.00000000 6.51612903 19.39516129
-10.00000000 6.80645161 19.75806452
-10.00000000 7.09677419 20.00000000
-10.00000000 7.38709677 20.00000000
-10.00000000 7.67741935 20.00000000
-10.00000000 7.96774194 20.00000000
-10.00000000 8.25806452 20.00000000
-10.00000000 8.54838710 20.00000000
-10.00000000 8.83870968 20.00000000
-10.00000000 9.12903226 20.00000000
-10.00000000 9.41935484 20.00000000
-10.00000000 9.70967742 20.00000000
-10.00000000 10.00000000 20.00000000
+FoodQuality Service Tip
+1.000000000 1.000000000 10.000000000
+1.000000000 1.290322581 10.000000000
+1.000000000 1.580645161 10.000000000
+1.000000000 1.870967742 10.000000000
+1.000000000 2.161290323 10.000000000
+1.000000000 2.451612903 10.000000000
+1.000000000 2.741935484 10.000000000
+1.000000000 3.032258065 10.040322581
+1.000000000 3.322580645 10.403225806
+1.000000000 3.612903226 10.766129032
+1.000000000 3.903225806 11.129032258
+1.000000000 4.193548387 11.491935484
+1.000000000 4.483870968 11.854838710
+1.000000000 4.774193548 12.217741935
+1.000000000 5.064516129 12.580645161
+1.000000000 5.354838710 12.943548387
+1.000000000 5.645161290 13.306451613
+1.000000000 5.935483871 13.669354839
+1.000000000 6.225806452 14.032258065
+1.000000000 6.516129032 14.395161290
+1.000000000 6.806451613 14.758064516
+1.000000000 7.096774194 15.000000000
+1.000000000 7.387096774 15.000000000
+1.000000000 7.677419355 15.000000000
+1.000000000 7.967741935 15.000000000
+1.000000000 8.258064516 15.000000000
+1.000000000 8.548387097 15.000000000
+1.000000000 8.838709677 15.000000000
+1.000000000 9.129032258 15.000000000
+1.000000000 9.419354839 15.000000000
+1.000000000 9.709677419 15.000000000
+1.000000000 10.000000000 15.000000000
+1.290322581 1.000000000 10.000000000
+1.290322581 1.290322581 10.000000000
+1.290322581 1.580645161 10.000000000
+1.290322581 1.870967742 10.000000000
+1.290322581 2.161290323 10.000000000
+1.290322581 2.451612903 10.000000000
+1.290322581 2.741935484 10.000000000
+1.290322581 3.032258065 10.040322581
+1.290322581 3.322580645 10.403225806
+1.290322581 3.612903226 10.766129032
+1.290322581 3.903225806 11.129032258
+1.290322581 4.193548387 11.491935484
+1.290322581 4.483870968 11.854838710
+1.290322581 4.774193548 12.217741935
+1.290322581 5.064516129 12.580645161
+1.290322581 5.354838710 12.943548387
+1.290322581 5.645161290 13.306451613
+1.290322581 5.935483871 13.669354839
+1.290322581 6.225806452 14.032258065
+1.290322581 6.516129032 14.395161290
+1.290322581 6.806451613 14.758064516
+1.290322581 7.096774194 15.000000000
+1.290322581 7.387096774 15.000000000
+1.290322581 7.677419355 15.000000000
+1.290322581 7.967741935 15.000000000
+1.290322581 8.258064516 15.000000000
+1.290322581 8.548387097 15.000000000
+1.290322581 8.838709677 15.000000000
+1.290322581 9.129032258 15.000000000
+1.290322581 9.419354839 15.000000000
+1.290322581 9.709677419 15.000000000
+1.290322581 10.000000000 15.000000000
+1.580645161 1.000000000 10.000000000
+1.580645161 1.290322581 10.000000000
+1.580645161 1.580645161 10.000000000
+1.580645161 1.870967742 10.000000000
+1.580645161 2.161290323 10.000000000
+1.580645161 2.451612903 10.000000000
+1.580645161 2.741935484 10.000000000
+1.580645161 3.032258065 10.040322581
+1.580645161 3.322580645 10.403225806
+1.580645161 3.612903226 10.766129032
+1.580645161 3.903225806 11.129032258
+1.580645161 4.193548387 11.491935484
+1.580645161 4.483870968 11.854838710
+1.580645161 4.774193548 12.217741935
+1.580645161 5.064516129 12.580645161
+1.580645161 5.354838710 12.943548387
+1.580645161 5.645161290 13.306451613
+1.580645161 5.935483871 13.669354839
+1.580645161 6.225806452 14.032258065
+1.580645161 6.516129032 14.395161290
+1.580645161 6.806451613 14.758064516
+1.580645161 7.096774194 15.000000000
+1.580645161 7.387096774 15.000000000
+1.580645161 7.677419355 15.000000000
+1.580645161 7.967741935 15.000000000
+1.580645161 8.258064516 15.000000000
+1.580645161 8.548387097 15.000000000
+1.580645161 8.838709677 15.000000000
+1.580645161 9.129032258 15.000000000
+1.580645161 9.419354839 15.000000000
+1.580645161 9.709677419 15.000000000
+1.580645161 10.000000000 15.000000000
+1.870967742 1.000000000 10.000000000
+1.870967742 1.290322581 10.000000000
+1.870967742 1.580645161 10.000000000
+1.870967742 1.870967742 10.000000000
+1.870967742 2.161290323 10.000000000
+1.870967742 2.451612903 10.000000000
+1.870967742 2.741935484 10.000000000
+1.870967742 3.032258065 10.040322581
+1.870967742 3.322580645 10.403225806
+1.870967742 3.612903226 10.766129032
+1.870967742 3.903225806 11.129032258
+1.870967742 4.193548387 11.491935484
+1.870967742 4.483870968 11.854838710
+1.870967742 4.774193548 12.217741935
+1.870967742 5.064516129 12.580645161
+1.870967742 5.354838710 12.943548387
+1.870967742 5.645161290 13.306451613
+1.870967742 5.935483871 13.669354839
+1.870967742 6.225806452 14.032258065
+1.870967742 6.516129032 14.395161290
+1.870967742 6.806451613 14.758064516
+1.870967742 7.096774194 15.000000000
+1.870967742 7.387096774 15.000000000
+1.870967742 7.677419355 15.000000000
+1.870967742 7.967741935 15.000000000
+1.870967742 8.258064516 15.000000000
+1.870967742 8.548387097 15.000000000
+1.870967742 8.838709677 15.000000000
+1.870967742 9.129032258 15.000000000
+1.870967742 9.419354839 15.000000000
+1.870967742 9.709677419 15.000000000
+1.870967742 10.000000000 15.000000000
+2.161290323 1.000000000 10.000000000
+2.161290323 1.290322581 10.000000000
+2.161290323 1.580645161 10.000000000
+2.161290323 1.870967742 10.000000000
+2.161290323 2.161290323 10.000000000
+2.161290323 2.451612903 10.000000000
+2.161290323 2.741935484 10.000000000
+2.161290323 3.032258065 10.040322581
+2.161290323 3.322580645 10.403225806
+2.161290323 3.612903226 10.766129032
+2.161290323 3.903225806 11.129032258
+2.161290323 4.193548387 11.491935484
+2.161290323 4.483870968 11.854838710
+2.161290323 4.774193548 12.217741935
+2.161290323 5.064516129 12.580645161
+2.161290323 5.354838710 12.943548387
+2.161290323 5.645161290 13.306451613
+2.161290323 5.935483871 13.669354839
+2.161290323 6.225806452 14.032258065
+2.161290323 6.516129032 14.395161290
+2.161290323 6.806451613 14.758064516
+2.161290323 7.096774194 15.000000000
+2.161290323 7.387096774 15.000000000
+2.161290323 7.677419355 15.000000000
+2.161290323 7.967741935 15.000000000
+2.161290323 8.258064516 15.000000000
+2.161290323 8.548387097 15.000000000
+2.161290323 8.838709677 15.000000000
+2.161290323 9.129032258 15.000000000
+2.161290323 9.419354839 15.000000000
+2.161290323 9.709677419 15.000000000
+2.161290323 10.000000000 15.000000000
+2.451612903 1.000000000 10.000000000
+2.451612903 1.290322581 10.000000000
+2.451612903 1.580645161 10.000000000
+2.451612903 1.870967742 10.000000000
+2.451612903 2.161290323 10.000000000
+2.451612903 2.451612903 10.000000000
+2.451612903 2.741935484 10.000000000
+2.451612903 3.032258065 10.040322581
+2.451612903 3.322580645 10.403225806
+2.451612903 3.612903226 10.766129032
+2.451612903 3.903225806 11.129032258
+2.451612903 4.193548387 11.491935484
+2.451612903 4.483870968 11.854838710
+2.451612903 4.774193548 12.217741935
+2.451612903 5.064516129 12.580645161
+2.451612903 5.354838710 12.943548387
+2.451612903 5.645161290 13.306451613
+2.451612903 5.935483871 13.669354839
+2.451612903 6.225806452 14.032258065
+2.451612903 6.516129032 14.395161290
+2.451612903 6.806451613 14.758064516
+2.451612903 7.096774194 15.000000000
+2.451612903 7.387096774 15.000000000
+2.451612903 7.677419355 15.000000000
+2.451612903 7.967741935 15.000000000
+2.451612903 8.258064516 15.000000000
+2.451612903 8.548387097 15.000000000
+2.451612903 8.838709677 15.000000000
+2.451612903 9.129032258 15.000000000
+2.451612903 9.419354839 15.000000000
+2.451612903 9.709677419 15.000000000
+2.451612903 10.000000000 15.000000000
+2.741935484 1.000000000 10.000000000
+2.741935484 1.290322581 10.000000000
+2.741935484 1.580645161 10.000000000
+2.741935484 1.870967742 10.000000000
+2.741935484 2.161290323 10.000000000
+2.741935484 2.451612903 10.000000000
+2.741935484 2.741935484 10.000000000
+2.741935484 3.032258065 10.040322581
+2.741935484 3.322580645 10.403225806
+2.741935484 3.612903226 10.766129032
+2.741935484 3.903225806 11.129032258
+2.741935484 4.193548387 11.491935484
+2.741935484 4.483870968 11.854838710
+2.741935484 4.774193548 12.217741935
+2.741935484 5.064516129 12.580645161
+2.741935484 5.354838710 12.943548387
+2.741935484 5.645161290 13.306451613
+2.741935484 5.935483871 13.669354839
+2.741935484 6.225806452 14.032258065
+2.741935484 6.516129032 14.395161290
+2.741935484 6.806451613 14.758064516
+2.741935484 7.096774194 15.000000000
+2.741935484 7.387096774 15.000000000
+2.741935484 7.677419355 15.000000000
+2.741935484 7.967741935 15.000000000
+2.741935484 8.258064516 15.000000000
+2.741935484 8.548387097 15.000000000
+2.741935484 8.838709677 15.000000000
+2.741935484 9.129032258 15.000000000
+2.741935484 9.419354839 15.000000000
+2.741935484 9.709677419 15.000000000
+2.741935484 10.000000000 15.000000000
+3.032258065 1.000000000 10.040322581
+3.032258065 1.290322581 10.040322581
+3.032258065 1.580645161 10.040322581
+3.032258065 1.870967742 10.040322581
+3.032258065 2.161290323 10.040322581
+3.032258065 2.451612903 10.040322581
+3.032258065 2.741935484 10.040322581
+3.032258065 3.032258065 10.158730159
+3.032258065 3.322580645 10.515873016
+3.032258065 3.612903226 10.873015873
+3.032258065 3.903225806 11.230158730
+3.032258065 4.193548387 11.587301587
+3.032258065 4.483870968 11.944444444
+3.032258065 4.774193548 12.301587302
+3.032258065 5.064516129 12.658730159
+3.032258065 5.354838710 13.015873016
+3.032258065 5.645161290 13.373015873
+3.032258065 5.935483871 13.730158730
+3.032258065 6.225806452 14.087301587
+3.032258065 6.516129032 14.444444444
+3.032258065 6.806451613 14.801587302
+3.032258065 7.096774194 15.040322581
+3.032258065 7.387096774 15.040322581
+3.032258065 7.677419355 15.040322581
+3.032258065 7.967741935 15.040322581
+3.032258065 8.258064516 15.040322581
+3.032258065 8.548387097 15.040322581
+3.032258065 8.838709677 15.040322581
+3.032258065 9.129032258 15.040322581
+3.032258065 9.419354839 15.040322581
+3.032258065 9.709677419 15.040322581
+3.032258065 10.000000000 15.040322581
+3.322580645 1.000000000 10.403225806
+3.322580645 1.290322581 10.403225806
+3.322580645 1.580645161 10.403225806
+3.322580645 1.870967742 10.403225806
+3.322580645 2.161290323 10.403225806
+3.322580645 2.451612903 10.403225806
+3.322580645 2.741935484 10.403225806
+3.322580645 3.032258065 10.515873016
+3.322580645 3.322580645 11.388888889
+3.322580645 3.612903226 11.701388889
+3.322580645 3.903225806 12.013888889
+3.322580645 4.193548387 12.326388889
+3.322580645 4.483870968 12.638888889
+3.322580645 4.774193548 12.951388889
+3.322580645 5.064516129 13.263888889
+3.322580645 5.354838710 13.576388889
+3.322580645 5.645161290 13.888888889
+3.322580645 5.935483871 14.201388889
+3.322580645 6.225806452 14.513888889
+3.322580645 6.516129032 14.826388889
+3.322580645 6.806451613 15.147058824
+3.322580645 7.096774194 15.403225806
+3.322580645 7.387096774 15.403225806
+3.322580645 7.677419355 15.403225806
+3.322580645 7.967741935 15.403225806
+3.322580645 8.258064516 15.403225806
+3.322580645 8.548387097 15.403225806
+3.322580645 8.838709677 15.403225806
+3.322580645 9.129032258 15.403225806
+3.322580645 9.419354839 15.403225806
+3.322580645 9.709677419 15.403225806
+3.322580645 10.000000000 15.403225806
+3.612903226 1.000000000 10.766129032
+3.612903226 1.290322581 10.766129032
+3.612903226 1.580645161 10.766129032
+3.612903226 1.870967742 10.766129032
+3.612903226 2.161290323 10.766129032
+3.612903226 2.451612903 10.766129032
+3.612903226 2.741935484 10.766129032
+3.612903226 3.032258065 10.873015873
+3.612903226 3.322580645 11.701388889
+3.612903226 3.612903226 12.345679012
+3.612903226 3.903225806 12.623456790
+3.612903226 4.193548387 12.901234568
+3.612903226 4.483870968 13.179012346
+3.612903226 4.774193548 13.456790123
+3.612903226 5.064516129 13.734567901
+3.612903226 5.354838710 14.012345679
+3.612903226 5.645161290 14.290123457
+3.612903226 5.935483871 14.567901235
+3.612903226 6.225806452 14.845679012
+3.612903226 6.516129032 15.129870130
+3.612903226 6.806451613 15.477941176
+3.612903226 7.096774194 15.766129032
+3.612903226 7.387096774 15.766129032
+3.612903226 7.677419355 15.766129032
+3.612903226 7.967741935 15.766129032
+3.612903226 8.258064516 15.766129032
+3.612903226 8.548387097 15.766129032
+3.612903226 8.838709677 15.766129032
+3.612903226 9.129032258 15.766129032
+3.612903226 9.419354839 15.766129032
+3.612903226 9.709677419 15.766129032
+3.612903226 10.000000000 15.766129032
+3.903225806 1.000000000 11.129032258
+3.903225806 1.290322581 11.129032258
+3.903225806 1.580645161 11.129032258
+3.903225806 1.870967742 11.129032258
+3.903225806 2.161290323 11.129032258
+3.903225806 2.451612903 11.129032258
+3.903225806 2.741935484 11.129032258
+3.903225806 3.032258065 11.230158730
+3.903225806 3.322580645 12.013888889
+3.903225806 3.612903226 12.623456790
+3.903225806 3.903225806 13.111111111
+3.903225806 4.193548387 13.361111111
+3.903225806 4.483870968 13.611111111
+3.903225806 4.774193548 13.861111111
+3.903225806 5.064516129 14.111111111
+3.903225806 5.354838710 14.361111111
+3.903225806 5.645161290 14.611111111
+3.903225806 5.935483871 14.861111111
+3.903225806 6.225806452 15.116279070
+3.903225806 6.516129032 15.422077922
+3.903225806 6.806451613 15.808823529
+3.903225806 7.096774194 16.129032258
+3.903225806 7.387096774 16.129032258
+3.903225806 7.677419355 16.129032258
+3.903225806 7.967741935 16.129032258
+3.903225806 8.258064516 16.129032258
+3.903225806 8.548387097 16.129032258
+3.903225806 8.838709677 16.129032258
+3.903225806 9.129032258 16.129032258
+3.903225806 9.419354839 16.129032258
+3.903225806 9.709677419 16.129032258
+3.903225806 10.000000000 16.129032258
+4.193548387 1.000000000 11.491935484
+4.193548387 1.290322581 11.491935484
+4.193548387 1.580645161 11.491935484
+4.193548387 1.870967742 11.491935484
+4.193548387 2.161290323 11.491935484
+4.193548387 2.451612903 11.491935484
+4.193548387 2.741935484 11.491935484
+4.193548387 3.032258065 11.587301587
+4.193548387 3.322580645 12.326388889
+4.193548387 3.612903226 12.901234568
+4.193548387 3.903225806 13.361111111
+4.193548387 4.193548387 13.737373737
+4.193548387 4.483870968 13.964646465
+4.193548387 4.774193548 14.191919192
+4.193548387 5.064516129 14.419191919
+4.193548387 5.354838710 14.646464646
+4.193548387 5.645161290 14.873737374
+4.193548387 5.935483871 15.105263158
+4.193548387 6.225806452 15.377906977
+4.193548387 6.516129032 15.714285714
+4.193548387 6.806451613 16.139705882
+4.193548387 7.096774194 16.491935484
+4.193548387 7.387096774 16.491935484
+4.193548387 7.677419355 16.491935484
+4.193548387 7.967741935 16.491935484
+4.193548387 8.258064516 16.491935484
+4.193548387 8.548387097 16.491935484
+4.193548387 8.838709677 16.491935484
+4.193548387 9.129032258 16.491935484
+4.193548387 9.419354839 16.491935484
+4.193548387 9.709677419 16.491935484
+4.193548387 10.000000000 16.491935484
+4.483870968 1.000000000 11.854838710
+4.483870968 1.290322581 11.854838710
+4.483870968 1.580645161 11.854838710
+4.483870968 1.870967742 11.854838710
+4.483870968 2.161290323 11.854838710
+4.483870968 2.451612903 11.854838710
+4.483870968 2.741935484 11.854838710
+4.483870968 3.032258065 11.944444444
+4.483870968 3.322580645 12.638888889
+4.483870968 3.612903226 13.179012346
+4.483870968 3.903225806 13.611111111
+4.483870968 4.193548387 13.964646465
+4.483870968 4.483870968 14.259259259
+4.483870968 4.774193548 14.467592593
+4.483870968 5.064516129 14.675925926
+4.483870968 5.354838710 14.884259259
+4.483870968 5.645161290 15.096153846
+4.483870968 5.935483871 15.342105263
+4.483870968 6.225806452 15.639534884
+4.483870968 6.516129032 16.006493506
+4.483870968 6.806451613 16.470588235
+4.483870968 7.096774194 16.854838710
+4.483870968 7.387096774 16.854838710
+4.483870968 7.677419355 16.854838710
+4.483870968 7.967741935 16.854838710
+4.483870968 8.258064516 16.854838710
+4.483870968 8.548387097 16.854838710
+4.483870968 8.838709677 16.854838710
+4.483870968 9.129032258 16.854838710
+4.483870968 9.419354839 16.854838710
+4.483870968 9.709677419 16.854838710
+4.483870968 10.000000000 16.854838710
+4.774193548 1.000000000 12.217741935
+4.774193548 1.290322581 12.217741935
+4.774193548 1.580645161 12.217741935
+4.774193548 1.870967742 12.217741935
+4.774193548 2.161290323 12.217741935
+4.774193548 2.451612903 12.217741935
+4.774193548 2.741935484 12.217741935
+4.774193548 3.032258065 12.301587302
+4.774193548 3.322580645 12.951388889
+4.774193548 3.612903226 13.456790123
+4.774193548 3.903225806 13.861111111
+4.774193548 4.193548387 14.191919192
+4.774193548 4.483870968 14.467592593
+4.774193548 4.774193548 14.700854701
+4.774193548 5.064516129 14.893162393
+4.774193548 5.354838710 15.088495575
+4.774193548 5.645161290 15.312500000
+4.774193548 5.935483871 15.578947368
+4.774193548 6.225806452 15.901162791
+4.774193548 6.516129032 16.298701299
+4.774193548 6.806451613 16.801470588
+4.774193548 7.096774194 17.217741935
+4.774193548 7.387096774 17.217741935
+4.774193548 7.677419355 17.217741935
+4.774193548 7.967741935 17.217741935
+4.774193548 8.258064516 17.217741935
+4.774193548 8.548387097 17.217741935
+4.774193548 8.838709677 17.217741935
+4.774193548 9.129032258 17.217741935
+4.774193548 9.419354839 17.217741935
+4.774193548 9.709677419 17.217741935
+4.774193548 10.000000000 17.217741935
+5.064516129 1.000000000 12.580645161
+5.064516129 1.290322581 12.580645161
+5.064516129 1.580645161 12.580645161
+5.064516129 1.870967742 12.580645161
+5.064516129 2.161290323 12.580645161
+5.064516129 2.451612903 12.580645161
+5.064516129 2.741935484 12.580645161
+5.064516129 3.032258065 12.658730159
+5.064516129 3.322580645 13.263888889
+5.064516129 3.612903226 13.734567901
+5.064516129 3.903225806 14.111111111
+5.064516129 4.193548387 14.419191919
+5.064516129 4.483870968 14.675925926
+5.064516129 4.774193548 14.893162393
+5.064516129 5.064516129 15.081967213
+5.064516129 5.354838710 15.287610619
+5.064516129 5.645161290 15.528846154
+5.064516129 5.935483871 15.815789474
+5.064516129 6.225806452 16.162790698
+5.064516129 6.516129032 16.590909091
+5.064516129 6.806451613 17.132352941
+5.064516129 7.096774194 17.580645161
+5.064516129 7.387096774 17.580645161
+5.064516129 7.677419355 17.580645161
+5.064516129 7.967741935 17.580645161
+5.064516129 8.258064516 17.580645161
+5.064516129 8.548387097 17.580645161
+5.064516129 8.838709677 17.580645161
+5.064516129 9.129032258 17.580645161
+5.064516129 9.419354839 17.580645161
+5.064516129 9.709677419 17.580645161
+5.064516129 10.000000000 17.580645161
+5.354838710 1.000000000 12.943548387
+5.354838710 1.290322581 12.943548387
+5.354838710 1.580645161 12.943548387
+5.354838710 1.870967742 12.943548387
+5.354838710 2.161290323 12.943548387
+5.354838710 2.451612903 12.943548387
+5.354838710 2.741935484 12.943548387
+5.354838710 3.032258065 13.015873016
+5.354838710 3.322580645 13.576388889
+5.354838710 3.612903226 14.012345679
+5.354838710 3.903225806 14.361111111
+5.354838710 4.193548387 14.646464646
+5.354838710 4.483870968 14.884259259
+5.354838710 4.774193548 15.088495575
+5.354838710 5.064516129 15.287610619
+5.354838710 5.354838710 15.486725664
+5.354838710 5.645161290 15.745192308
+5.354838710 5.935483871 16.052631579
+5.354838710 6.225806452 16.424418605
+5.354838710 6.516129032 16.883116883
+5.354838710 6.806451613 17.463235294
+5.354838710 7.096774194 17.943548387
+5.354838710 7.387096774 17.943548387
+5.354838710 7.677419355 17.943548387
+5.354838710 7.967741935 17.943548387
+5.354838710 8.258064516 17.943548387
+5.354838710 8.548387097 17.943548387
+5.354838710 8.838709677 17.943548387
+5.354838710 9.129032258 17.943548387
+5.354838710 9.419354839 17.943548387
+5.354838710 9.709677419 17.943548387
+5.354838710 10.000000000 17.943548387
+5.645161290 1.000000000 13.306451613
+5.645161290 1.290322581 13.306451613
+5.645161290 1.580645161 13.306451613
+5.645161290 1.870967742 13.306451613
+5.645161290 2.161290323 13.306451613
+5.645161290 2.451612903 13.306451613
+5.645161290 2.741935484 13.306451613
+5.645161290 3.032258065 13.373015873
+5.645161290 3.322580645 13.888888889
+5.645161290 3.612903226 14.290123457
+5.645161290 3.903225806 14.611111111
+5.645161290 4.193548387 14.873737374
+5.645161290 4.483870968 15.096153846
+5.645161290 4.774193548 15.312500000
+5.645161290 5.064516129 15.528846154
+5.645161290 5.354838710 15.745192308
+5.645161290 5.645161290 15.961538462
+5.645161290 5.935483871 16.289473684
+5.645161290 6.225806452 16.686046512
+5.645161290 6.516129032 17.175324675
+5.645161290 6.806451613 17.794117647
+5.645161290 7.096774194 18.306451613
+5.645161290 7.387096774 18.306451613
+5.645161290 7.677419355 18.306451613
+5.645161290 7.967741935 18.306451613
+5.645161290 8.258064516 18.306451613
+5.645161290 8.548387097 18.306451613
+5.645161290 8.838709677 18.306451613
+5.645161290 9.129032258 18.306451613
+5.645161290 9.419354839 18.306451613
+5.645161290 9.709677419 18.306451613
+5.645161290 10.000000000 18.306451613
+5.935483871 1.000000000 13.669354839
+5.935483871 1.290322581 13.669354839
+5.935483871 1.580645161 13.669354839
+5.935483871 1.870967742 13.669354839
+5.935483871 2.161290323 13.669354839
+5.935483871 2.451612903 13.669354839
+5.935483871 2.741935484 13.669354839
+5.935483871 3.032258065 13.730158730
+5.935483871 3.322580645 14.201388889
+5.935483871 3.612903226 14.567901235
+5.935483871 3.903225806 14.861111111
+5.935483871 4.193548387 15.105263158
+5.935483871 4.483870968 15.342105263
+5.935483871 4.774193548 15.578947368
+5.935483871 5.064516129 15.815789474
+5.935483871 5.354838710 16.052631579
+5.935483871 5.645161290 16.289473684
+5.935483871 5.935483871 16.526315789
+5.935483871 6.225806452 16.947674419
+5.935483871 6.516129032 17.467532468
+5.935483871 6.806451613 18.125000000
+5.935483871 7.096774194 18.669354839
+5.935483871 7.387096774 18.669354839
+5.935483871 7.677419355 18.669354839
+5.935483871 7.967741935 18.669354839
+5.935483871 8.258064516 18.669354839
+5.935483871 8.548387097 18.669354839
+5.935483871 8.838709677 18.669354839
+5.935483871 9.129032258 18.669354839
+5.935483871 9.419354839 18.669354839
+5.935483871 9.709677419 18.669354839
+5.935483871 10.000000000 18.669354839
+6.225806452 1.000000000 14.032258065
+6.225806452 1.290322581 14.032258065
+6.225806452 1.580645161 14.032258065
+6.225806452 1.870967742 14.032258065
+6.225806452 2.161290323 14.032258065
+6.225806452 2.451612903 14.032258065
+6.225806452 2.741935484 14.032258065
+6.225806452 3.032258065 14.087301587
+6.225806452 3.322580645 14.513888889
+6.225806452 3.612903226 14.845679012
+6.225806452 3.903225806 15.116279070
+6.225806452 4.193548387 15.377906977
+6.225806452 4.483870968 15.639534884
+6.225806452 4.774193548 15.901162791
+6.225806452 5.064516129 16.162790698
+6.225806452 5.354838710 16.424418605
+6.225806452 5.645161290 16.686046512
+6.225806452 5.935483871 16.947674419
+6.225806452 6.225806452 17.209302326
+6.225806452 6.516129032 17.759740260
+6.225806452 6.806451613 18.455882353
+6.225806452 7.096774194 19.032258065
+6.225806452 7.387096774 19.032258065
+6.225806452 7.677419355 19.032258065
+6.225806452 7.967741935 19.032258065
+6.225806452 8.258064516 19.032258065
+6.225806452 8.548387097 19.032258065
+6.225806452 8.838709677 19.032258065
+6.225806452 9.129032258 19.032258065
+6.225806452 9.419354839 19.032258065
+6.225806452 9.709677419 19.032258065
+6.225806452 10.000000000 19.032258065
+6.516129032 1.000000000 14.395161290
+6.516129032 1.290322581 14.395161290
+6.516129032 1.580645161 14.395161290
+6.516129032 1.870967742 14.395161290
+6.516129032 2.161290323 14.395161290
+6.516129032 2.451612903 14.395161290
+6.516129032 2.741935484 14.395161290
+6.516129032 3.032258065 14.444444444
+6.516129032 3.322580645 14.826388889
+6.516129032 3.612903226 15.129870130
+6.516129032 3.903225806 15.422077922
+6.516129032 4.193548387 15.714285714
+6.516129032 4.483870968 16.006493506
+6.516129032 4.774193548 16.298701299
+6.516129032 5.064516129 16.590909091
+6.516129032 5.354838710 16.883116883
+6.516129032 5.645161290 17.175324675
+6.516129032 5.935483871 17.467532468
+6.516129032 6.225806452 17.759740260
+6.516129032 6.516129032 18.051948052
+6.516129032 6.806451613 18.786764706
+6.516129032 7.096774194 19.395161290
+6.516129032 7.387096774 19.395161290
+6.516129032 7.677419355 19.395161290
+6.516129032 7.967741935 19.395161290
+6.516129032 8.258064516 19.395161290
+6.516129032 8.548387097 19.395161290
+6.516129032 8.838709677 19.395161290
+6.516129032 9.129032258 19.395161290
+6.516129032 9.419354839 19.395161290
+6.516129032 9.709677419 19.395161290
+6.516129032 10.000000000 19.395161290
+6.806451613 1.000000000 14.758064516
+6.806451613 1.290322581 14.758064516
+6.806451613 1.580645161 14.758064516
+6.806451613 1.870967742 14.758064516
+6.806451613 2.161290323 14.758064516
+6.806451613 2.451612903 14.758064516
+6.806451613 2.741935484 14.758064516
+6.806451613 3.032258065 14.801587302
+6.806451613 3.322580645 15.147058824
+6.806451613 3.612903226 15.477941176
+6.806451613 3.903225806 15.808823529
+6.806451613 4.193548387 16.139705882
+6.806451613 4.483870968 16.470588235
+6.806451613 4.774193548 16.801470588
+6.806451613 5.064516129 17.132352941
+6.806451613 5.354838710 17.463235294
+6.806451613 5.645161290 17.794117647
+6.806451613 5.935483871 18.125000000
+6.806451613 6.225806452 18.455882353
+6.806451613 6.516129032 18.786764706
+6.806451613 6.806451613 19.117647059
+6.806451613 7.096774194 19.758064516
+6.806451613 7.387096774 19.758064516
+6.806451613 7.677419355 19.758064516
+6.806451613 7.967741935 19.758064516
+6.806451613 8.258064516 19.758064516
+6.806451613 8.548387097 19.758064516
+6.806451613 8.838709677 19.758064516
+6.806451613 9.129032258 19.758064516
+6.806451613 9.419354839 19.758064516
+6.806451613 9.709677419 19.758064516
+6.806451613 10.000000000 19.758064516
+7.096774194 1.000000000 15.000000000
+7.096774194 1.290322581 15.000000000
+7.096774194 1.580645161 15.000000000
+7.096774194 1.870967742 15.000000000
+7.096774194 2.161290323 15.000000000
+7.096774194 2.451612903 15.000000000
+7.096774194 2.741935484 15.000000000
+7.096774194 3.032258065 15.040322581
+7.096774194 3.322580645 15.403225806
+7.096774194 3.612903226 15.766129032
+7.096774194 3.903225806 16.129032258
+7.096774194 4.193548387 16.491935484
+7.096774194 4.483870968 16.854838710
+7.096774194 4.774193548 17.217741935
+7.096774194 5.064516129 17.580645161
+7.096774194 5.354838710 17.943548387
+7.096774194 5.645161290 18.306451613
+7.096774194 5.935483871 18.669354839
+7.096774194 6.225806452 19.032258065
+7.096774194 6.516129032 19.395161290
+7.096774194 6.806451613 19.758064516
+7.096774194 7.096774194 20.000000000
+7.096774194 7.387096774 20.000000000
+7.096774194 7.677419355 20.000000000
+7.096774194 7.967741935 20.000000000
+7.096774194 8.258064516 20.000000000
+7.096774194 8.548387097 20.000000000
+7.096774194 8.838709677 20.000000000
+7.096774194 9.129032258 20.000000000
+7.096774194 9.419354839 20.000000000
+7.096774194 9.709677419 20.000000000
+7.096774194 10.000000000 20.000000000
+7.387096774 1.000000000 15.000000000
+7.387096774 1.290322581 15.000000000
+7.387096774 1.580645161 15.000000000
+7.387096774 1.870967742 15.000000000
+7.387096774 2.161290323 15.000000000
+7.387096774 2.451612903 15.000000000
+7.387096774 2.741935484 15.000000000
+7.387096774 3.032258065 15.040322581
+7.387096774 3.322580645 15.403225806
+7.387096774 3.612903226 15.766129032
+7.387096774 3.903225806 16.129032258
+7.387096774 4.193548387 16.491935484
+7.387096774 4.483870968 16.854838710
+7.387096774 4.774193548 17.217741935
+7.387096774 5.064516129 17.580645161
+7.387096774 5.354838710 17.943548387
+7.387096774 5.645161290 18.306451613
+7.387096774 5.935483871 18.669354839
+7.387096774 6.225806452 19.032258065
+7.387096774 6.516129032 19.395161290
+7.387096774 6.806451613 19.758064516
+7.387096774 7.096774194 20.000000000
+7.387096774 7.387096774 20.000000000
+7.387096774 7.677419355 20.000000000
+7.387096774 7.967741935 20.000000000
+7.387096774 8.258064516 20.000000000
+7.387096774 8.548387097 20.000000000
+7.387096774 8.838709677 20.000000000
+7.387096774 9.129032258 20.000000000
+7.387096774 9.419354839 20.000000000
+7.387096774 9.709677419 20.000000000
+7.387096774 10.000000000 20.000000000
+7.677419355 1.000000000 15.000000000
+7.677419355 1.290322581 15.000000000
+7.677419355 1.580645161 15.000000000
+7.677419355 1.870967742 15.000000000
+7.677419355 2.161290323 15.000000000
+7.677419355 2.451612903 15.000000000
+7.677419355 2.741935484 15.000000000
+7.677419355 3.032258065 15.040322581
+7.677419355 3.322580645 15.403225806
+7.677419355 3.612903226 15.766129032
+7.677419355 3.903225806 16.129032258
+7.677419355 4.193548387 16.491935484
+7.677419355 4.483870968 16.854838710
+7.677419355 4.774193548 17.217741935
+7.677419355 5.064516129 17.580645161
+7.677419355 5.354838710 17.943548387
+7.677419355 5.645161290 18.306451613
+7.677419355 5.935483871 18.669354839
+7.677419355 6.225806452 19.032258065
+7.677419355 6.516129032 19.395161290
+7.677419355 6.806451613 19.758064516
+7.677419355 7.096774194 20.000000000
+7.677419355 7.387096774 20.000000000
+7.677419355 7.677419355 20.000000000
+7.677419355 7.967741935 20.000000000
+7.677419355 8.258064516 20.000000000
+7.677419355 8.548387097 20.000000000
+7.677419355 8.838709677 20.000000000
+7.677419355 9.129032258 20.000000000
+7.677419355 9.419354839 20.000000000
+7.677419355 9.709677419 20.000000000
+7.677419355 10.000000000 20.000000000
+7.967741935 1.000000000 15.000000000
+7.967741935 1.290322581 15.000000000
+7.967741935 1.580645161 15.000000000
+7.967741935 1.870967742 15.000000000
+7.967741935 2.161290323 15.000000000
+7.967741935 2.451612903 15.000000000
+7.967741935 2.741935484 15.000000000
+7.967741935 3.032258065 15.040322581
+7.967741935 3.322580645 15.403225806
+7.967741935 3.612903226 15.766129032
+7.967741935 3.903225806 16.129032258
+7.967741935 4.193548387 16.491935484
+7.967741935 4.483870968 16.854838710
+7.967741935 4.774193548 17.217741935
+7.967741935 5.064516129 17.580645161
+7.967741935 5.354838710 17.943548387
+7.967741935 5.645161290 18.306451613
+7.967741935 5.935483871 18.669354839
+7.967741935 6.225806452 19.032258065
+7.967741935 6.516129032 19.395161290
+7.967741935 6.806451613 19.758064516
+7.967741935 7.096774194 20.000000000
+7.967741935 7.387096774 20.000000000
+7.967741935 7.677419355 20.000000000
+7.967741935 7.967741935 20.000000000
+7.967741935 8.258064516 20.000000000
+7.967741935 8.548387097 20.000000000
+7.967741935 8.838709677 20.000000000
+7.967741935 9.129032258 20.000000000
+7.967741935 9.419354839 20.000000000
+7.967741935 9.709677419 20.000000000
+7.967741935 10.000000000 20.000000000
+8.258064516 1.000000000 15.000000000
+8.258064516 1.290322581 15.000000000
+8.258064516 1.580645161 15.000000000
+8.258064516 1.870967742 15.000000000
+8.258064516 2.161290323 15.000000000
+8.258064516 2.451612903 15.000000000
+8.258064516 2.741935484 15.000000000
+8.258064516 3.032258065 15.040322581
+8.258064516 3.322580645 15.403225806
+8.258064516 3.612903226 15.766129032
+8.258064516 3.903225806 16.129032258
+8.258064516 4.193548387 16.491935484
+8.258064516 4.483870968 16.854838710
+8.258064516 4.774193548 17.217741935
+8.258064516 5.064516129 17.580645161
+8.258064516 5.354838710 17.943548387
+8.258064516 5.645161290 18.306451613
+8.258064516 5.935483871 18.669354839
+8.258064516 6.225806452 19.032258065
+8.258064516 6.516129032 19.395161290
+8.258064516 6.806451613 19.758064516
+8.258064516 7.096774194 20.000000000
+8.258064516 7.387096774 20.000000000
+8.258064516 7.677419355 20.000000000
+8.258064516 7.967741935 20.000000000
+8.258064516 8.258064516 20.000000000
+8.258064516 8.548387097 20.000000000
+8.258064516 8.838709677 20.000000000
+8.258064516 9.129032258 20.000000000
+8.258064516 9.419354839 20.000000000
+8.258064516 9.709677419 20.000000000
+8.258064516 10.000000000 20.000000000
+8.548387097 1.000000000 15.000000000
+8.548387097 1.290322581 15.000000000
+8.548387097 1.580645161 15.000000000
+8.548387097 1.870967742 15.000000000
+8.548387097 2.161290323 15.000000000
+8.548387097 2.451612903 15.000000000
+8.548387097 2.741935484 15.000000000
+8.548387097 3.032258065 15.040322581
+8.548387097 3.322580645 15.403225806
+8.548387097 3.612903226 15.766129032
+8.548387097 3.903225806 16.129032258
+8.548387097 4.193548387 16.491935484
+8.548387097 4.483870968 16.854838710
+8.548387097 4.774193548 17.217741935
+8.548387097 5.064516129 17.580645161
+8.548387097 5.354838710 17.943548387
+8.548387097 5.645161290 18.306451613
+8.548387097 5.935483871 18.669354839
+8.548387097 6.225806452 19.032258065
+8.548387097 6.516129032 19.395161290
+8.548387097 6.806451613 19.758064516
+8.548387097 7.096774194 20.000000000
+8.548387097 7.387096774 20.000000000
+8.548387097 7.677419355 20.000000000
+8.548387097 7.967741935 20.000000000
+8.548387097 8.258064516 20.000000000
+8.548387097 8.548387097 20.000000000
+8.548387097 8.838709677 20.000000000
+8.548387097 9.129032258 20.000000000
+8.548387097 9.419354839 20.000000000
+8.548387097 9.709677419 20.000000000
+8.548387097 10.000000000 20.000000000
+8.838709677 1.000000000 15.000000000
+8.838709677 1.290322581 15.000000000
+8.838709677 1.580645161 15.000000000
+8.838709677 1.870967742 15.000000000
+8.838709677 2.161290323 15.000000000
+8.838709677 2.451612903 15.000000000
+8.838709677 2.741935484 15.000000000
+8.838709677 3.032258065 15.040322581
+8.838709677 3.322580645 15.403225806
+8.838709677 3.612903226 15.766129032
+8.838709677 3.903225806 16.129032258
+8.838709677 4.193548387 16.491935484
+8.838709677 4.483870968 16.854838710
+8.838709677 4.774193548 17.217741935
+8.838709677 5.064516129 17.580645161
+8.838709677 5.354838710 17.943548387
+8.838709677 5.645161290 18.306451613
+8.838709677 5.935483871 18.669354839
+8.838709677 6.225806452 19.032258065
+8.838709677 6.516129032 19.395161290
+8.838709677 6.806451613 19.758064516
+8.838709677 7.096774194 20.000000000
+8.838709677 7.387096774 20.000000000
+8.838709677 7.677419355 20.000000000
+8.838709677 7.967741935 20.000000000
+8.838709677 8.258064516 20.000000000
+8.838709677 8.548387097 20.000000000
+8.838709677 8.838709677 20.000000000
+8.838709677 9.129032258 20.000000000
+8.838709677 9.419354839 20.000000000
+8.838709677 9.709677419 20.000000000
+8.838709677 10.000000000 20.000000000
+9.129032258 1.000000000 15.000000000
+9.129032258 1.290322581 15.000000000
+9.129032258 1.580645161 15.000000000
+9.129032258 1.870967742 15.000000000
+9.129032258 2.161290323 15.000000000
+9.129032258 2.451612903 15.000000000
+9.129032258 2.741935484 15.000000000
+9.129032258 3.032258065 15.040322581
+9.129032258 3.322580645 15.403225806
+9.129032258 3.612903226 15.766129032
+9.129032258 3.903225806 16.129032258
+9.129032258 4.193548387 16.491935484
+9.129032258 4.483870968 16.854838710
+9.129032258 4.774193548 17.217741935
+9.129032258 5.064516129 17.580645161
+9.129032258 5.354838710 17.943548387
+9.129032258 5.645161290 18.306451613
+9.129032258 5.935483871 18.669354839
+9.129032258 6.225806452 19.032258065
+9.129032258 6.516129032 19.395161290
+9.129032258 6.806451613 19.758064516
+9.129032258 7.096774194 20.000000000
+9.129032258 7.387096774 20.000000000
+9.129032258 7.677419355 20.000000000
+9.129032258 7.967741935 20.000000000
+9.129032258 8.258064516 20.000000000
+9.129032258 8.548387097 20.000000000
+9.129032258 8.838709677 20.000000000
+9.129032258 9.129032258 20.000000000
+9.129032258 9.419354839 20.000000000
+9.129032258 9.709677419 20.000000000
+9.129032258 10.000000000 20.000000000
+9.419354839 1.000000000 15.000000000
+9.419354839 1.290322581 15.000000000
+9.419354839 1.580645161 15.000000000
+9.419354839 1.870967742 15.000000000
+9.419354839 2.161290323 15.000000000
+9.419354839 2.451612903 15.000000000
+9.419354839 2.741935484 15.000000000
+9.419354839 3.032258065 15.040322581
+9.419354839 3.322580645 15.403225806
+9.419354839 3.612903226 15.766129032
+9.419354839 3.903225806 16.129032258
+9.419354839 4.193548387 16.491935484
+9.419354839 4.483870968 16.854838710
+9.419354839 4.774193548 17.217741935
+9.419354839 5.064516129 17.580645161
+9.419354839 5.354838710 17.943548387
+9.419354839 5.645161290 18.306451613
+9.419354839 5.935483871 18.669354839
+9.419354839 6.225806452 19.032258065
+9.419354839 6.516129032 19.395161290
+9.419354839 6.806451613 19.758064516
+9.419354839 7.096774194 20.000000000
+9.419354839 7.387096774 20.000000000
+9.419354839 7.677419355 20.000000000
+9.419354839 7.967741935 20.000000000
+9.419354839 8.258064516 20.000000000
+9.419354839 8.548387097 20.000000000
+9.419354839 8.838709677 20.000000000
+9.419354839 9.129032258 20.000000000
+9.419354839 9.419354839 20.000000000
+9.419354839 9.709677419 20.000000000
+9.419354839 10.000000000 20.000000000
+9.709677419 1.000000000 15.000000000
+9.709677419 1.290322581 15.000000000
+9.709677419 1.580645161 15.000000000
+9.709677419 1.870967742 15.000000000
+9.709677419 2.161290323 15.000000000
+9.709677419 2.451612903 15.000000000
+9.709677419 2.741935484 15.000000000
+9.709677419 3.032258065 15.040322581
+9.709677419 3.322580645 15.403225806
+9.709677419 3.612903226 15.766129032
+9.709677419 3.903225806 16.129032258
+9.709677419 4.193548387 16.491935484
+9.709677419 4.483870968 16.854838710
+9.709677419 4.774193548 17.217741935
+9.709677419 5.064516129 17.580645161
+9.709677419 5.354838710 17.943548387
+9.709677419 5.645161290 18.306451613
+9.709677419 5.935483871 18.669354839
+9.709677419 6.225806452 19.032258065
+9.709677419 6.516129032 19.395161290
+9.709677419 6.806451613 19.758064516
+9.709677419 7.096774194 20.000000000
+9.709677419 7.387096774 20.000000000
+9.709677419 7.677419355 20.000000000
+9.709677419 7.967741935 20.000000000
+9.709677419 8.258064516 20.000000000
+9.709677419 8.548387097 20.000000000
+9.709677419 8.838709677 20.000000000
+9.709677419 9.129032258 20.000000000
+9.709677419 9.419354839 20.000000000
+9.709677419 9.709677419 20.000000000
+9.709677419 10.000000000 20.000000000
+10.000000000 1.000000000 15.000000000
+10.000000000 1.290322581 15.000000000
+10.000000000 1.580645161 15.000000000
+10.000000000 1.870967742 15.000000000
+10.000000000 2.161290323 15.000000000
+10.000000000 2.451612903 15.000000000
+10.000000000 2.741935484 15.000000000
+10.000000000 3.032258065 15.040322581
+10.000000000 3.322580645 15.403225806
+10.000000000 3.612903226 15.766129032
+10.000000000 3.903225806 16.129032258
+10.000000000 4.193548387 16.491935484
+10.000000000 4.483870968 16.854838710
+10.000000000 4.774193548 17.217741935
+10.000000000 5.064516129 17.580645161
+10.000000000 5.354838710 17.943548387
+10.000000000 5.645161290 18.306451613
+10.000000000 5.935483871 18.669354839
+10.000000000 6.225806452 19.032258065
+10.000000000 6.516129032 19.395161290
+10.000000000 6.806451613 19.758064516
+10.000000000 7.096774194 20.000000000
+10.000000000 7.387096774 20.000000000
+10.000000000 7.677419355 20.000000000
+10.000000000 7.967741935 20.000000000
+10.000000000 8.258064516 20.000000000
+10.000000000 8.548387097 20.000000000
+10.000000000 8.838709677 20.000000000
+10.000000000 9.129032258 20.000000000
+10.000000000 9.419354839 20.000000000
+10.000000000 9.709677419 20.000000000
+10.000000000 10.000000000 20.000000000
diff --git a/examples/takagi-sugeno/octave/linear_tip_calculator.fll b/examples/takagi-sugeno/octave/linear_tip_calculator.fll
index 8c1f597..510d8a4 100644
--- a/examples/takagi-sugeno/octave/linear_tip_calculator.fll
+++ b/examples/takagi-sugeno/octave/linear_tip_calculator.fll
@@ -1,22 +1,24 @@
-Engine: Linear-Tip-Calculator
+Engine: linear_tip_calculator
InputVariable: FoodQuality
enabled: true
range: 1.000 10.000
+ lock-range: false
term: Bad Trapezoid 0.000 1.000 3.000 7.000
term: Good Trapezoid 3.000 7.000 10.000 11.000
InputVariable: Service
enabled: true
range: 1.000 10.000
+ lock-range: false
term: Bad Trapezoid 0.000 1.000 3.000 7.000
term: Good Trapezoid 3.000 7.000 10.000 11.000
OutputVariable: Tip
enabled: true
range: 10.000 20.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
- lock-range: false
term: TenPercent Linear 0.000 0.000 10.000
term: FifteenPercent Linear 0.000 0.000 15.000
term: TwentyPercent Linear 0.000 0.000 20.000
@@ -24,7 +26,8 @@ RuleBlock:
enabled: true
conjunction: Minimum
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if FoodQuality is Bad and Service is Bad then Tip is TenPercent
rule: if FoodQuality is Bad and Service is Good then Tip is FifteenPercent
rule: if FoodQuality is Good and Service is Bad then Tip is FifteenPercent
diff --git a/examples/takagi-sugeno/octave/linear_tip_calculator.java b/examples/takagi-sugeno/octave/linear_tip_calculator.java
index 0600638..7046734 100644
--- a/examples/takagi-sugeno/octave/linear_tip_calculator.java
+++ b/examples/takagi-sugeno/octave/linear_tip_calculator.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,45 +13,55 @@ import com.fuzzylite.variable.*;
public class linear_tip_calculator{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("Linear-Tip-Calculator");
-
-InputVariable inputVariable1 = new InputVariable();
-inputVariable1.setEnabled(true);
-inputVariable1.setName("FoodQuality");
-inputVariable1.setRange(1.000, 10.000);
-inputVariable1.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable1.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine.addInputVariable(inputVariable1);
-
-InputVariable inputVariable2 = new InputVariable();
-inputVariable2.setEnabled(true);
-inputVariable2.setName("Service");
-inputVariable2.setRange(1.000, 10.000);
-inputVariable2.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable2.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine.addInputVariable(inputVariable2);
-
-OutputVariable outputVariable = new OutputVariable();
-outputVariable.setEnabled(true);
-outputVariable.setName("Tip");
-outputVariable.setRange(10.000, 20.000);
-outputVariable.fuzzyOutput().setAccumulation(null);
-outputVariable.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable.setDefaultValue(Double.NaN);
-outputVariable.setLockPreviousOutputValue(false);
-outputVariable.setLockOutputValueInRange(false);
-outputVariable.addTerm(Linear.create("TenPercent", engine, 0.000, 0.000, 10.000));
-outputVariable.addTerm(Linear.create("FifteenPercent", engine, 0.000, 0.000, 15.000));
-outputVariable.addTerm(Linear.create("TwentyPercent", engine, 0.000, 0.000, 20.000));
-engine.addOutputVariable(outputVariable);
+engine.setName("linear_tip_calculator");
+engine.setDescription("");
+
+InputVariable FoodQuality = new InputVariable();
+FoodQuality.setName("FoodQuality");
+FoodQuality.setDescription("");
+FoodQuality.setEnabled(true);
+FoodQuality.setRange(1.000, 10.000);
+FoodQuality.setLockValueInRange(false);
+FoodQuality.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+FoodQuality.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine.addInputVariable(FoodQuality);
+
+InputVariable Service = new InputVariable();
+Service.setName("Service");
+Service.setDescription("");
+Service.setEnabled(true);
+Service.setRange(1.000, 10.000);
+Service.setLockValueInRange(false);
+Service.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+Service.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine.addInputVariable(Service);
+
+OutputVariable Tip = new OutputVariable();
+Tip.setName("Tip");
+Tip.setDescription("");
+Tip.setEnabled(true);
+Tip.setRange(10.000, 20.000);
+Tip.setLockValueInRange(false);
+Tip.setAggregation(null);
+Tip.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+Tip.setDefaultValue(Double.NaN);
+Tip.setLockPreviousValue(false);
+Tip.addTerm(Linear.create("TenPercent", engine, 0.000, 0.000, 10.000));
+Tip.addTerm(Linear.create("FifteenPercent", engine, 0.000, 0.000, 15.000));
+Tip.addTerm(Linear.create("TwentyPercent", engine, 0.000, 0.000, 20.000));
+engine.addOutputVariable(Tip);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(new Minimum());
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(null);
+ruleBlock.setImplication(null);
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if FoodQuality is Bad and Service is Bad then Tip is TenPercent", engine));
ruleBlock.addRule(Rule.parse("if FoodQuality is Bad and Service is Good then Tip is FifteenPercent", engine));
ruleBlock.addRule(Rule.parse("if FoodQuality is Good and Service is Bad then Tip is FifteenPercent", engine));
diff --git a/examples/takagi-sugeno/octave/linear_tip_calculator.pdf b/examples/takagi-sugeno/octave/linear_tip_calculator.pdf
new file mode 100644
index 0000000..357f529
--- /dev/null
+++ b/examples/takagi-sugeno/octave/linear_tip_calculator.pdf
Binary files differ
diff --git a/examples/takagi-sugeno/octave/sugeno_tip_calculator.R b/examples/takagi-sugeno/octave/sugeno_tip_calculator.R
new file mode 100644
index 0000000..1491a96
--- /dev/null
+++ b/examples/takagi-sugeno/octave/sugeno_tip_calculator.R
@@ -0,0 +1,119 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "sugeno_tip_calculator"
+engine.fll = "Engine: sugeno_tip_calculator
+InputVariable: FoodQuality
+ enabled: true
+ range: 1.000 10.000
+ lock-range: false
+ term: Bad Trapezoid 0.000 1.000 3.000 7.000
+ term: Good Trapezoid 3.000 7.000 10.000 11.000
+InputVariable: Service
+ enabled: true
+ range: 1.000 10.000
+ lock-range: false
+ term: Bad Trapezoid 0.000 1.000 3.000 7.000
+ term: Good Trapezoid 3.000 7.000 10.000 11.000
+OutputVariable: CheapTip
+ enabled: true
+ range: 5.000 25.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: Low Constant 10.000
+ term: Medium Constant 15.000
+ term: High Constant 20.000
+OutputVariable: AverageTip
+ enabled: true
+ range: 5.000 25.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: Low Constant 10.000
+ term: Medium Constant 15.000
+ term: High Constant 20.000
+OutputVariable: GenerousTip
+ enabled: true
+ range: 5.000 25.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: Low Constant 10.000
+ term: Medium Constant 15.000
+ term: High Constant 20.000
+RuleBlock:
+ enabled: true
+ conjunction: EinsteinProduct
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if FoodQuality is extremely Bad and Service is extremely Bad then CheapTip is extremely Low and AverageTip is very Low and GenerousTip is Low
+ rule: if FoodQuality is Good and Service is extremely Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium
+ rule: if FoodQuality is very Good and Service is very Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High
+ rule: if FoodQuality is Bad and Service is Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium
+ rule: if FoodQuality is Good and Service is Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High
+ rule: if FoodQuality is extremely Good and Service is Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is very High
+ rule: if FoodQuality is Bad and Service is Good then CheapTip is Low and AverageTip is Medium and GenerousTip is High
+ rule: if FoodQuality is Good and Service is Good then CheapTip is Medium and AverageTip is Medium and GenerousTip is very High
+ rule: if FoodQuality is very Bad and Service is very Good then CheapTip is Low and AverageTip is Medium and GenerousTip is High
+ rule: if FoodQuality is very very Good and Service is very very Good then CheapTip is High and AverageTip is very High and GenerousTip is extremely High"
+
+engine.fldFile = "sugeno_tip_calculator.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1i2_o1 = ggplot(engine.df, aes(FoodQuality, Service)) +
+ geom_tile(aes(fill=CheapTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=FoodQuality, y=Service, z=CheapTip), color="black") +
+ ggtitle("(FoodQuality, Service) = CheapTip")
+
+engine.plot.i2i1_o1 = ggplot(engine.df, aes(Service, FoodQuality)) +
+ geom_tile(aes(fill=CheapTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Service, y=FoodQuality, z=CheapTip), color="black") +
+ ggtitle("(Service, FoodQuality) = CheapTip")
+
+engine.plot.i1i2_o2 = ggplot(engine.df, aes(FoodQuality, Service)) +
+ geom_tile(aes(fill=AverageTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=FoodQuality, y=Service, z=AverageTip), color="black") +
+ ggtitle("(FoodQuality, Service) = AverageTip")
+
+engine.plot.i2i1_o2 = ggplot(engine.df, aes(Service, FoodQuality)) +
+ geom_tile(aes(fill=AverageTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Service, y=FoodQuality, z=AverageTip), color="black") +
+ ggtitle("(Service, FoodQuality) = AverageTip")
+
+engine.plot.i1i2_o3 = ggplot(engine.df, aes(FoodQuality, Service)) +
+ geom_tile(aes(fill=GenerousTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=FoodQuality, y=Service, z=GenerousTip), color="black") +
+ ggtitle("(FoodQuality, Service) = GenerousTip")
+
+engine.plot.i2i1_o3 = ggplot(engine.df, aes(Service, FoodQuality)) +
+ geom_tile(aes(fill=GenerousTip)) +
+ scale_fill_gradient(low="yellow", high="red") +
+ stat_contour(aes(x=Service, y=FoodQuality, z=GenerousTip), color="black") +
+ ggtitle("(Service, FoodQuality) = GenerousTip")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1i2_o1, engine.plot.i2i1_o1, engine.plot.i1i2_o2, engine.plot.i2i1_o2, engine.plot.i1i2_o3, engine.plot.i2i1_o3, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/takagi-sugeno/octave/sugeno_tip_calculator.cpp b/examples/takagi-sugeno/octave/sugeno_tip_calculator.cpp
index d92de0a..96536fa 100644
--- a/examples/takagi-sugeno/octave/sugeno_tip_calculator.cpp
+++ b/examples/takagi-sugeno/octave/sugeno_tip_calculator.cpp
@@ -1,85 +1,97 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("Sugeno-Tip-Calculator");
+engine->setName("sugeno_tip_calculator");
+engine->setDescription("");
-InputVariable* inputVariable1 = new InputVariable;
-inputVariable1->setEnabled(true);
-inputVariable1->setName("FoodQuality");
-inputVariable1->setRange(1.000, 10.000);
-inputVariable1->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable1->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine->addInputVariable(inputVariable1);
+InputVariable* FoodQuality = new InputVariable;
+FoodQuality->setName("FoodQuality");
+FoodQuality->setDescription("");
+FoodQuality->setEnabled(true);
+FoodQuality->setRange(1.000, 10.000);
+FoodQuality->setLockValueInRange(false);
+FoodQuality->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+FoodQuality->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine->addInputVariable(FoodQuality);
-InputVariable* inputVariable2 = new InputVariable;
-inputVariable2->setEnabled(true);
-inputVariable2->setName("Service");
-inputVariable2->setRange(1.000, 10.000);
-inputVariable2->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable2->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine->addInputVariable(inputVariable2);
+InputVariable* Service = new InputVariable;
+Service->setName("Service");
+Service->setDescription("");
+Service->setEnabled(true);
+Service->setRange(1.000, 10.000);
+Service->setLockValueInRange(false);
+Service->addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+Service->addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine->addInputVariable(Service);
-OutputVariable* outputVariable1 = new OutputVariable;
-outputVariable1->setEnabled(true);
-outputVariable1->setName("CheapTip");
-outputVariable1->setRange(5.000, 25.000);
-outputVariable1->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable1->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable1->setDefaultValue(fl::nan);
-outputVariable1->setLockPreviousOutputValue(false);
-outputVariable1->setLockOutputValueInRange(false);
-outputVariable1->addTerm(new Constant("Low", 10.000));
-outputVariable1->addTerm(new Constant("Medium", 15.000));
-outputVariable1->addTerm(new Constant("High", 20.000));
-engine->addOutputVariable(outputVariable1);
+OutputVariable* CheapTip = new OutputVariable;
+CheapTip->setName("CheapTip");
+CheapTip->setDescription("");
+CheapTip->setEnabled(true);
+CheapTip->setRange(5.000, 25.000);
+CheapTip->setLockValueInRange(false);
+CheapTip->setAggregation(fl::null);
+CheapTip->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+CheapTip->setDefaultValue(fl::nan);
+CheapTip->setLockPreviousValue(false);
+CheapTip->addTerm(new Constant("Low", 10.000));
+CheapTip->addTerm(new Constant("Medium", 15.000));
+CheapTip->addTerm(new Constant("High", 20.000));
+engine->addOutputVariable(CheapTip);
-OutputVariable* outputVariable2 = new OutputVariable;
-outputVariable2->setEnabled(true);
-outputVariable2->setName("AverageTip");
-outputVariable2->setRange(5.000, 25.000);
-outputVariable2->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable2->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable2->setDefaultValue(fl::nan);
-outputVariable2->setLockPreviousOutputValue(false);
-outputVariable2->setLockOutputValueInRange(false);
-outputVariable2->addTerm(new Constant("Low", 10.000));
-outputVariable2->addTerm(new Constant("Medium", 15.000));
-outputVariable2->addTerm(new Constant("High", 20.000));
-engine->addOutputVariable(outputVariable2);
+OutputVariable* AverageTip = new OutputVariable;
+AverageTip->setName("AverageTip");
+AverageTip->setDescription("");
+AverageTip->setEnabled(true);
+AverageTip->setRange(5.000, 25.000);
+AverageTip->setLockValueInRange(false);
+AverageTip->setAggregation(fl::null);
+AverageTip->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+AverageTip->setDefaultValue(fl::nan);
+AverageTip->setLockPreviousValue(false);
+AverageTip->addTerm(new Constant("Low", 10.000));
+AverageTip->addTerm(new Constant("Medium", 15.000));
+AverageTip->addTerm(new Constant("High", 20.000));
+engine->addOutputVariable(AverageTip);
-OutputVariable* outputVariable3 = new OutputVariable;
-outputVariable3->setEnabled(true);
-outputVariable3->setName("GenerousTip");
-outputVariable3->setRange(5.000, 25.000);
-outputVariable3->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable3->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable3->setDefaultValue(fl::nan);
-outputVariable3->setLockPreviousOutputValue(false);
-outputVariable3->setLockOutputValueInRange(false);
-outputVariable3->addTerm(new Constant("Low", 10.000));
-outputVariable3->addTerm(new Constant("Medium", 15.000));
-outputVariable3->addTerm(new Constant("High", 20.000));
-engine->addOutputVariable(outputVariable3);
+OutputVariable* GenerousTip = new OutputVariable;
+GenerousTip->setName("GenerousTip");
+GenerousTip->setDescription("");
+GenerousTip->setEnabled(true);
+GenerousTip->setRange(5.000, 25.000);
+GenerousTip->setLockValueInRange(false);
+GenerousTip->setAggregation(fl::null);
+GenerousTip->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+GenerousTip->setDefaultValue(fl::nan);
+GenerousTip->setLockPreviousValue(false);
+GenerousTip->addTerm(new Constant("Low", 10.000));
+GenerousTip->addTerm(new Constant("Medium", 15.000));
+GenerousTip->addTerm(new Constant("High", 20.000));
+engine->addOutputVariable(GenerousTip);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(new EinsteinProduct);
ruleBlock->setDisjunction(fl::null);
-ruleBlock->setActivation(fl::null);
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is extremely Bad and Service is extremely Bad then CheapTip is extremely Low and AverageTip is very Low and GenerousTip is Low", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Good and Service is extremely Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is very Good and Service is very Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Bad and Service is Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Good and Service is Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is extremely Good and Service is Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is very High", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Bad and Service is Good then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is Good and Service is Good then CheapTip is Medium and AverageTip is Medium and GenerousTip is very High", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is very Bad and Service is very Good then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
-ruleBlock->addRule(fl::Rule::parse("if FoodQuality is very very Good and Service is very very Good then CheapTip is High and AverageTip is very High and GenerousTip is extremely High", engine));
+ruleBlock->setImplication(fl::null);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if FoodQuality is extremely Bad and Service is extremely Bad then CheapTip is extremely Low and AverageTip is very Low and GenerousTip is Low", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Good and Service is extremely Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is very Good and Service is very Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Bad and Service is Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Good and Service is Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is extremely Good and Service is Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is very High", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Bad and Service is Good then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is Good and Service is Good then CheapTip is Medium and AverageTip is Medium and GenerousTip is very High", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is very Bad and Service is very Good then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
+ruleBlock->addRule(Rule::parse("if FoodQuality is very very Good and Service is very very Good then CheapTip is High and AverageTip is very High and GenerousTip is extremely High", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/takagi-sugeno/octave/sugeno_tip_calculator.fcl b/examples/takagi-sugeno/octave/sugeno_tip_calculator.fcl
index ad98f68..fcb857c 100644
--- a/examples/takagi-sugeno/octave/sugeno_tip_calculator.fcl
+++ b/examples/takagi-sugeno/octave/sugeno_tip_calculator.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK Sugeno-Tip-Calculator
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK sugeno_tip_calculator
VAR_INPUT
FoodQuality: REAL;
diff --git a/examples/takagi-sugeno/octave/sugeno_tip_calculator.fis b/examples/takagi-sugeno/octave/sugeno_tip_calculator.fis
index 4349913..3d28f10 100644
--- a/examples/takagi-sugeno/octave/sugeno_tip_calculator.fis
+++ b/examples/takagi-sugeno/octave/sugeno_tip_calculator.fis
@@ -1,13 +1,16 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name='Sugeno-Tip-Calculator'
+Name='sugeno_tip_calculator'
Type='sugeno'
+Version=6.0
NumInputs=2
NumOutputs=3
NumRules=10
AndMethod='einstein_product'
-OrMethod=''
-ImpMethod=''
-AggMethod=''
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
DefuzzMethod='wtaver'
[Input1]
diff --git a/examples/takagi-sugeno/octave/sugeno_tip_calculator.fld b/examples/takagi-sugeno/octave/sugeno_tip_calculator.fld
index 6816af5..ce942fd 100644
--- a/examples/takagi-sugeno/octave/sugeno_tip_calculator.fld
+++ b/examples/takagi-sugeno/octave/sugeno_tip_calculator.fld
@@ -1,1026 +1,1025 @@
-#@Engine: Sugeno-Tip-Calculator;
-#@InputVariable: FoodQuality; @InputVariable: Service; @OutputVariable: CheapTip; @OutputVariable: AverageTip; @OutputVariable: GenerousTip;
-1.00000000 1.00000000 10.00000000 10.00000000 12.50000000
-1.00000000 1.29032258 10.00000000 10.00000000 12.50000000
-1.00000000 1.58064516 10.00000000 10.00000000 12.50000000
-1.00000000 1.87096774 10.00000000 10.00000000 12.50000000
-1.00000000 2.16129032 10.00000000 10.00000000 12.50000000
-1.00000000 2.45161290 10.00000000 10.00000000 12.50000000
-1.00000000 2.74193548 10.00000000 10.00000000 12.50000000
-1.00000000 3.03225806 10.00000000 10.02032322 12.52040460
-1.00000000 3.32258065 10.00000000 10.21723908 12.72618837
-1.00000000 3.61290323 10.00000000 10.43854143 12.97859532
-1.00000000 3.90322581 10.00000000 10.68860515 13.30323372
-1.00000000 4.19354839 10.00000000 10.98519415 13.75455390
-1.00000000 4.48387097 10.00000000 11.36896201 14.43109544
-1.00000000 4.77419355 10.00000000 11.91319586 15.48909397
-1.00000000 5.06451613 10.00000000 12.68223479 17.02303230
-1.00000000 5.35483871 10.00000000 13.34274407 18.15544945
-1.00000000 5.64516129 10.00000000 13.79246624 18.75419392
-1.00000000 5.93548387 10.00000000 14.13081618 19.12558840
-1.00000000 6.22580645 10.00000000 14.41328213 19.41290031
-1.00000000 6.51612903 10.00000000 14.65879553 19.65878725
-1.00000000 6.80645161 10.00000000 14.87303754 19.87303753
-1.00000000 7.09677419 10.00000000 15.00000000 20.00000000
-1.00000000 7.38709677 10.00000000 15.00000000 20.00000000
-1.00000000 7.67741935 10.00000000 15.00000000 20.00000000
-1.00000000 7.96774194 10.00000000 15.00000000 20.00000000
-1.00000000 8.25806452 10.00000000 15.00000000 20.00000000
-1.00000000 8.54838710 10.00000000 15.00000000 20.00000000
-1.00000000 8.83870968 10.00000000 15.00000000 20.00000000
-1.00000000 9.12903226 10.00000000 15.00000000 20.00000000
-1.00000000 9.41935484 10.00000000 15.00000000 20.00000000
-1.00000000 9.70967742 10.00000000 15.00000000 20.00000000
-1.00000000 10.00000000 10.00000000 15.00000000 20.00000000
-1.29032258 1.00000000 10.00000000 10.00000000 12.50000000
-1.29032258 1.29032258 10.00000000 10.00000000 12.50000000
-1.29032258 1.58064516 10.00000000 10.00000000 12.50000000
-1.29032258 1.87096774 10.00000000 10.00000000 12.50000000
-1.29032258 2.16129032 10.00000000 10.00000000 12.50000000
-1.29032258 2.45161290 10.00000000 10.00000000 12.50000000
-1.29032258 2.74193548 10.00000000 10.00000000 12.50000000
-1.29032258 3.03225806 10.00000000 10.02032322 12.52040460
-1.29032258 3.32258065 10.00000000 10.21723908 12.72618837
-1.29032258 3.61290323 10.00000000 10.43854143 12.97859532
-1.29032258 3.90322581 10.00000000 10.68860515 13.30323372
-1.29032258 4.19354839 10.00000000 10.98519415 13.75455390
-1.29032258 4.48387097 10.00000000 11.36896201 14.43109544
-1.29032258 4.77419355 10.00000000 11.91319586 15.48909397
-1.29032258 5.06451613 10.00000000 12.68223479 17.02303230
-1.29032258 5.35483871 10.00000000 13.34274407 18.15544945
-1.29032258 5.64516129 10.00000000 13.79246624 18.75419392
-1.29032258 5.93548387 10.00000000 14.13081618 19.12558840
-1.29032258 6.22580645 10.00000000 14.41328213 19.41290031
-1.29032258 6.51612903 10.00000000 14.65879553 19.65878725
-1.29032258 6.80645161 10.00000000 14.87303754 19.87303753
-1.29032258 7.09677419 10.00000000 15.00000000 20.00000000
-1.29032258 7.38709677 10.00000000 15.00000000 20.00000000
-1.29032258 7.67741935 10.00000000 15.00000000 20.00000000
-1.29032258 7.96774194 10.00000000 15.00000000 20.00000000
-1.29032258 8.25806452 10.00000000 15.00000000 20.00000000
-1.29032258 8.54838710 10.00000000 15.00000000 20.00000000
-1.29032258 8.83870968 10.00000000 15.00000000 20.00000000
-1.29032258 9.12903226 10.00000000 15.00000000 20.00000000
-1.29032258 9.41935484 10.00000000 15.00000000 20.00000000
-1.29032258 9.70967742 10.00000000 15.00000000 20.00000000
-1.29032258 10.00000000 10.00000000 15.00000000 20.00000000
-1.58064516 1.00000000 10.00000000 10.00000000 12.50000000
-1.58064516 1.29032258 10.00000000 10.00000000 12.50000000
-1.58064516 1.58064516 10.00000000 10.00000000 12.50000000
-1.58064516 1.87096774 10.00000000 10.00000000 12.50000000
-1.58064516 2.16129032 10.00000000 10.00000000 12.50000000
-1.58064516 2.45161290 10.00000000 10.00000000 12.50000000
-1.58064516 2.74193548 10.00000000 10.00000000 12.50000000
-1.58064516 3.03225806 10.00000000 10.02032322 12.52040460
-1.58064516 3.32258065 10.00000000 10.21723908 12.72618837
-1.58064516 3.61290323 10.00000000 10.43854143 12.97859532
-1.58064516 3.90322581 10.00000000 10.68860515 13.30323372
-1.58064516 4.19354839 10.00000000 10.98519415 13.75455390
-1.58064516 4.48387097 10.00000000 11.36896201 14.43109544
-1.58064516 4.77419355 10.00000000 11.91319586 15.48909397
-1.58064516 5.06451613 10.00000000 12.68223479 17.02303230
-1.58064516 5.35483871 10.00000000 13.34274407 18.15544945
-1.58064516 5.64516129 10.00000000 13.79246624 18.75419392
-1.58064516 5.93548387 10.00000000 14.13081618 19.12558840
-1.58064516 6.22580645 10.00000000 14.41328213 19.41290031
-1.58064516 6.51612903 10.00000000 14.65879553 19.65878725
-1.58064516 6.80645161 10.00000000 14.87303754 19.87303753
-1.58064516 7.09677419 10.00000000 15.00000000 20.00000000
-1.58064516 7.38709677 10.00000000 15.00000000 20.00000000
-1.58064516 7.67741935 10.00000000 15.00000000 20.00000000
-1.58064516 7.96774194 10.00000000 15.00000000 20.00000000
-1.58064516 8.25806452 10.00000000 15.00000000 20.00000000
-1.58064516 8.54838710 10.00000000 15.00000000 20.00000000
-1.58064516 8.83870968 10.00000000 15.00000000 20.00000000
-1.58064516 9.12903226 10.00000000 15.00000000 20.00000000
-1.58064516 9.41935484 10.00000000 15.00000000 20.00000000
-1.58064516 9.70967742 10.00000000 15.00000000 20.00000000
-1.58064516 10.00000000 10.00000000 15.00000000 20.00000000
-1.87096774 1.00000000 10.00000000 10.00000000 12.50000000
-1.87096774 1.29032258 10.00000000 10.00000000 12.50000000
-1.87096774 1.58064516 10.00000000 10.00000000 12.50000000
-1.87096774 1.87096774 10.00000000 10.00000000 12.50000000
-1.87096774 2.16129032 10.00000000 10.00000000 12.50000000
-1.87096774 2.45161290 10.00000000 10.00000000 12.50000000
-1.87096774 2.74193548 10.00000000 10.00000000 12.50000000
-1.87096774 3.03225806 10.00000000 10.02032322 12.52040460
-1.87096774 3.32258065 10.00000000 10.21723908 12.72618837
-1.87096774 3.61290323 10.00000000 10.43854143 12.97859532
-1.87096774 3.90322581 10.00000000 10.68860515 13.30323372
-1.87096774 4.19354839 10.00000000 10.98519415 13.75455390
-1.87096774 4.48387097 10.00000000 11.36896201 14.43109544
-1.87096774 4.77419355 10.00000000 11.91319586 15.48909397
-1.87096774 5.06451613 10.00000000 12.68223479 17.02303230
-1.87096774 5.35483871 10.00000000 13.34274407 18.15544945
-1.87096774 5.64516129 10.00000000 13.79246624 18.75419392
-1.87096774 5.93548387 10.00000000 14.13081618 19.12558840
-1.87096774 6.22580645 10.00000000 14.41328213 19.41290031
-1.87096774 6.51612903 10.00000000 14.65879553 19.65878725
-1.87096774 6.80645161 10.00000000 14.87303754 19.87303753
-1.87096774 7.09677419 10.00000000 15.00000000 20.00000000
-1.87096774 7.38709677 10.00000000 15.00000000 20.00000000
-1.87096774 7.67741935 10.00000000 15.00000000 20.00000000
-1.87096774 7.96774194 10.00000000 15.00000000 20.00000000
-1.87096774 8.25806452 10.00000000 15.00000000 20.00000000
-1.87096774 8.54838710 10.00000000 15.00000000 20.00000000
-1.87096774 8.83870968 10.00000000 15.00000000 20.00000000
-1.87096774 9.12903226 10.00000000 15.00000000 20.00000000
-1.87096774 9.41935484 10.00000000 15.00000000 20.00000000
-1.87096774 9.70967742 10.00000000 15.00000000 20.00000000
-1.87096774 10.00000000 10.00000000 15.00000000 20.00000000
-2.16129032 1.00000000 10.00000000 10.00000000 12.50000000
-2.16129032 1.29032258 10.00000000 10.00000000 12.50000000
-2.16129032 1.58064516 10.00000000 10.00000000 12.50000000
-2.16129032 1.87096774 10.00000000 10.00000000 12.50000000
-2.16129032 2.16129032 10.00000000 10.00000000 12.50000000
-2.16129032 2.45161290 10.00000000 10.00000000 12.50000000
-2.16129032 2.74193548 10.00000000 10.00000000 12.50000000
-2.16129032 3.03225806 10.00000000 10.02032322 12.52040460
-2.16129032 3.32258065 10.00000000 10.21723908 12.72618837
-2.16129032 3.61290323 10.00000000 10.43854143 12.97859532
-2.16129032 3.90322581 10.00000000 10.68860515 13.30323372
-2.16129032 4.19354839 10.00000000 10.98519415 13.75455390
-2.16129032 4.48387097 10.00000000 11.36896201 14.43109544
-2.16129032 4.77419355 10.00000000 11.91319586 15.48909397
-2.16129032 5.06451613 10.00000000 12.68223479 17.02303230
-2.16129032 5.35483871 10.00000000 13.34274407 18.15544945
-2.16129032 5.64516129 10.00000000 13.79246624 18.75419392
-2.16129032 5.93548387 10.00000000 14.13081618 19.12558840
-2.16129032 6.22580645 10.00000000 14.41328213 19.41290031
-2.16129032 6.51612903 10.00000000 14.65879553 19.65878725
-2.16129032 6.80645161 10.00000000 14.87303754 19.87303753
-2.16129032 7.09677419 10.00000000 15.00000000 20.00000000
-2.16129032 7.38709677 10.00000000 15.00000000 20.00000000
-2.16129032 7.67741935 10.00000000 15.00000000 20.00000000
-2.16129032 7.96774194 10.00000000 15.00000000 20.00000000
-2.16129032 8.25806452 10.00000000 15.00000000 20.00000000
-2.16129032 8.54838710 10.00000000 15.00000000 20.00000000
-2.16129032 8.83870968 10.00000000 15.00000000 20.00000000
-2.16129032 9.12903226 10.00000000 15.00000000 20.00000000
-2.16129032 9.41935484 10.00000000 15.00000000 20.00000000
-2.16129032 9.70967742 10.00000000 15.00000000 20.00000000
-2.16129032 10.00000000 10.00000000 15.00000000 20.00000000
-2.45161290 1.00000000 10.00000000 10.00000000 12.50000000
-2.45161290 1.29032258 10.00000000 10.00000000 12.50000000
-2.45161290 1.58064516 10.00000000 10.00000000 12.50000000
-2.45161290 1.87096774 10.00000000 10.00000000 12.50000000
-2.45161290 2.16129032 10.00000000 10.00000000 12.50000000
-2.45161290 2.45161290 10.00000000 10.00000000 12.50000000
-2.45161290 2.74193548 10.00000000 10.00000000 12.50000000
-2.45161290 3.03225806 10.00000000 10.02032322 12.52040460
-2.45161290 3.32258065 10.00000000 10.21723908 12.72618837
-2.45161290 3.61290323 10.00000000 10.43854143 12.97859532
-2.45161290 3.90322581 10.00000000 10.68860515 13.30323372
-2.45161290 4.19354839 10.00000000 10.98519415 13.75455390
-2.45161290 4.48387097 10.00000000 11.36896201 14.43109544
-2.45161290 4.77419355 10.00000000 11.91319586 15.48909397
-2.45161290 5.06451613 10.00000000 12.68223479 17.02303230
-2.45161290 5.35483871 10.00000000 13.34274407 18.15544945
-2.45161290 5.64516129 10.00000000 13.79246624 18.75419392
-2.45161290 5.93548387 10.00000000 14.13081618 19.12558840
-2.45161290 6.22580645 10.00000000 14.41328213 19.41290031
-2.45161290 6.51612903 10.00000000 14.65879553 19.65878725
-2.45161290 6.80645161 10.00000000 14.87303754 19.87303753
-2.45161290 7.09677419 10.00000000 15.00000000 20.00000000
-2.45161290 7.38709677 10.00000000 15.00000000 20.00000000
-2.45161290 7.67741935 10.00000000 15.00000000 20.00000000
-2.45161290 7.96774194 10.00000000 15.00000000 20.00000000
-2.45161290 8.25806452 10.00000000 15.00000000 20.00000000
-2.45161290 8.54838710 10.00000000 15.00000000 20.00000000
-2.45161290 8.83870968 10.00000000 15.00000000 20.00000000
-2.45161290 9.12903226 10.00000000 15.00000000 20.00000000
-2.45161290 9.41935484 10.00000000 15.00000000 20.00000000
-2.45161290 9.70967742 10.00000000 15.00000000 20.00000000
-2.45161290 10.00000000 10.00000000 15.00000000 20.00000000
-2.74193548 1.00000000 10.00000000 10.00000000 12.50000000
-2.74193548 1.29032258 10.00000000 10.00000000 12.50000000
-2.74193548 1.58064516 10.00000000 10.00000000 12.50000000
-2.74193548 1.87096774 10.00000000 10.00000000 12.50000000
-2.74193548 2.16129032 10.00000000 10.00000000 12.50000000
-2.74193548 2.45161290 10.00000000 10.00000000 12.50000000
-2.74193548 2.74193548 10.00000000 10.00000000 12.50000000
-2.74193548 3.03225806 10.00000000 10.02032322 12.52040460
-2.74193548 3.32258065 10.00000000 10.21723908 12.72618837
-2.74193548 3.61290323 10.00000000 10.43854143 12.97859532
-2.74193548 3.90322581 10.00000000 10.68860515 13.30323372
-2.74193548 4.19354839 10.00000000 10.98519415 13.75455390
-2.74193548 4.48387097 10.00000000 11.36896201 14.43109544
-2.74193548 4.77419355 10.00000000 11.91319586 15.48909397
-2.74193548 5.06451613 10.00000000 12.68223479 17.02303230
-2.74193548 5.35483871 10.00000000 13.34274407 18.15544945
-2.74193548 5.64516129 10.00000000 13.79246624 18.75419392
-2.74193548 5.93548387 10.00000000 14.13081618 19.12558840
-2.74193548 6.22580645 10.00000000 14.41328213 19.41290031
-2.74193548 6.51612903 10.00000000 14.65879553 19.65878725
-2.74193548 6.80645161 10.00000000 14.87303754 19.87303753
-2.74193548 7.09677419 10.00000000 15.00000000 20.00000000
-2.74193548 7.38709677 10.00000000 15.00000000 20.00000000
-2.74193548 7.67741935 10.00000000 15.00000000 20.00000000
-2.74193548 7.96774194 10.00000000 15.00000000 20.00000000
-2.74193548 8.25806452 10.00000000 15.00000000 20.00000000
-2.74193548 8.54838710 10.00000000 15.00000000 20.00000000
-2.74193548 8.83870968 10.00000000 15.00000000 20.00000000
-2.74193548 9.12903226 10.00000000 15.00000000 20.00000000
-2.74193548 9.41935484 10.00000000 15.00000000 20.00000000
-2.74193548 9.70967742 10.00000000 15.00000000 20.00000000
-2.74193548 10.00000000 10.00000000 15.00000000 20.00000000
-3.03225806 1.00000000 10.00000000 10.02056414 12.53036255
-3.03225806 1.29032258 10.00000000 10.02056414 12.53036255
-3.03225806 1.58064516 10.00000000 10.02056414 12.53036255
-3.03225806 1.87096774 10.00000000 10.02056414 12.53036255
-3.03225806 2.16129032 10.00000000 10.02056414 12.53036255
-3.03225806 2.45161290 10.00000000 10.02056414 12.53036255
-3.03225806 2.74193548 10.00000000 10.02056414 12.53036255
-3.03225806 3.03225806 10.00008162 10.04023401 12.54971361
-3.03225806 3.32258065 10.00084536 10.23133043 12.74581753
-3.03225806 3.61290323 10.00166050 10.44709908 12.98846248
-3.03225806 3.90322581 10.00253632 10.69213103 13.30366093
-3.03225806 4.19354839 10.00350696 10.98431132 13.74623534
-3.03225806 4.48387097 10.00465122 11.36442108 14.41531219
-3.03225806 4.77419355 10.00613539 11.90630175 15.46893972
-3.03225806 5.06451613 10.00830466 12.67597755 17.00612582
-3.03225806 5.35483871 10.01079710 13.33923254 18.14567412
-3.03225806 5.64516129 10.01307288 13.79127531 18.74912170
-3.03225806 5.93548387 10.01499275 14.13114438 19.12316822
-3.03225806 6.22580645 10.01659745 14.41445725 19.41211259
-3.03225806 6.51612903 10.01801781 14.66014744 19.65891493
-3.03225806 6.80645161 10.01938833 14.87383528 19.87334753
-3.03225806 7.09677419 10.02032454 15.00000000 20.00000000
-3.03225806 7.38709677 10.02032454 15.00000000 20.00000000
-3.03225806 7.67741935 10.02032454 15.00000000 20.00000000
-3.03225806 7.96774194 10.02032454 15.00000000 20.00000000
-3.03225806 8.25806452 10.02032454 15.00000000 20.00000000
-3.03225806 8.54838710 10.02032454 15.00000000 20.00000000
-3.03225806 8.83870968 10.02032454 15.00000000 20.00000000
-3.03225806 9.12903226 10.02032454 15.00000000 20.00000000
-3.03225806 9.41935484 10.02032454 15.00000000 20.00000000
-3.03225806 9.70967742 10.02032454 15.00000000 20.00000000
-3.03225806 10.00000000 10.02032454 15.00000000 20.00000000
-3.32258065 1.00000000 10.00000000 10.23852600 12.81465712
-3.32258065 1.29032258 10.00000000 10.23852600 12.81465712
-3.32258065 1.58064516 10.00000000 10.23852600 12.81465712
-3.32258065 1.87096774 10.00000000 10.23852600 12.81465712
-3.32258065 2.16129032 10.00000000 10.23852600 12.81465712
-3.32258065 2.45161290 10.00000000 10.23852600 12.81465712
-3.32258065 2.74193548 10.00000000 10.23852600 12.81465712
-3.32258065 3.03225806 10.00081091 10.25216001 12.82509445
-3.32258065 3.32258065 10.00847573 10.39024810 12.94131554
-3.32258065 3.61290323 10.01682656 10.55678831 13.10652832
-3.32258065 3.90322581 10.02600789 10.75843537 13.34992628
-3.32258065 4.19354839 10.03642525 11.01464869 13.72980008
-3.32258065 4.48387097 10.04898564 11.36779630 14.35055538
-3.32258065 4.77419355 10.06563624 11.89543354 15.38280506
-3.32258065 5.06451613 10.09043159 12.66530578 16.93433074
-3.32258065 5.35483871 10.11905829 13.33050784 18.08725853
-3.32258065 5.64516129 10.14531886 13.79087513 18.71123750
-3.32258065 5.93548387 10.16705394 14.13888710 19.10302935
-3.32258065 6.22580645 10.18433380 14.42710664 19.40531141
-3.32258065 6.51612903 10.19847233 14.67287318 19.66004764
-3.32258065 6.80645161 10.21090121 14.88093570 19.87607311
-3.32258065 7.09677419 10.21874952 15.00000000 20.00000000
-3.32258065 7.38709677 10.21874952 15.00000000 20.00000000
-3.32258065 7.67741935 10.21874952 15.00000000 20.00000000
-3.32258065 7.96774194 10.21874952 15.00000000 20.00000000
-3.32258065 8.25806452 10.21874952 15.00000000 20.00000000
-3.32258065 8.54838710 10.21874952 15.00000000 20.00000000
-3.32258065 8.83870968 10.21874952 15.00000000 20.00000000
-3.32258065 9.12903226 10.21874952 15.00000000 20.00000000
-3.32258065 9.41935484 10.21874952 15.00000000 20.00000000
-3.32258065 9.70967742 10.21874952 15.00000000 20.00000000
-3.32258065 10.00000000 10.21874952 15.00000000 20.00000000
-3.61290323 1.00000000 10.00000000 10.50490830 13.12845546
-3.61290323 1.29032258 10.00000000 10.50490830 13.12845546
-3.61290323 1.58064516 10.00000000 10.50490830 13.12845546
-3.61290323 1.87096774 10.00000000 10.50490830 13.12845546
-3.61290323 2.16129032 10.00000000 10.50490830 13.12845546
-3.61290323 2.45161290 10.00000000 10.50490830 13.12845546
-3.61290323 2.74193548 10.00000000 10.50490830 13.12845546
-3.61290323 3.03225806 10.00151654 10.51262673 13.13088541
-3.61290323 3.32258065 10.01600168 10.59992682 13.17930400
-3.61290323 3.61290323 10.03212956 10.72120213 13.28528620
-3.61290323 3.90322581 10.05031902 10.88533698 13.48054126
-3.61290323 4.19354839 10.07154360 11.11425892 13.82721937
-3.61290323 4.48387097 10.09785029 11.45287584 14.43542451
-3.61290323 4.77419355 10.13366827 11.98002190 15.48143735
-3.61290323 5.06451613 10.18719850 12.73374607 17.00406518
-3.61290323 5.35483871 10.24796420 13.36174755 18.08140820
-3.61290323 5.64516129 10.30403654 13.80875389 18.68736063
-3.61290323 5.93548387 10.35025162 14.15521373 19.08606379
-3.61290323 6.22580645 10.38608863 14.44355382 19.39936608
-3.61290323 6.51612903 10.41383257 14.68673503 19.66149620
-3.61290323 6.80645161 10.43623515 14.88800549 19.87887528
-3.61290323 7.09677419 10.44926133 15.00000088 20.00000000
-3.61290323 7.38709677 10.44926133 15.00000088 20.00000000
-3.61290323 7.67741935 10.44926133 15.00000088 20.00000000
-3.61290323 7.96774194 10.44926133 15.00000088 20.00000000
-3.61290323 8.25806452 10.44926133 15.00000088 20.00000000
-3.61290323 8.54838710 10.44926133 15.00000088 20.00000000
-3.61290323 8.83870968 10.44926133 15.00000088 20.00000000
-3.61290323 9.12903226 10.44926133 15.00000088 20.00000000
-3.61290323 9.41935484 10.44926133 15.00000088 20.00000000
-3.61290323 9.70967742 10.44926133 15.00000088 20.00000000
-3.61290323 10.00000000 10.44926133 15.00000088 20.00000000
-3.90322581 1.00000000 10.00000000 10.81017051 13.50482619
-3.90322581 1.29032258 10.00000000 10.81017051 13.50482619
-3.90322581 1.58064516 10.00000000 10.81017051 13.50482619
-3.90322581 1.87096774 10.00000000 10.81017051 13.50482619
-3.90322581 2.16129032 10.00000000 10.81017051 13.50482619
-3.90322581 2.45161290 10.00000000 10.81017051 13.50482619
-3.90322581 2.74193548 10.00000000 10.81017051 13.50482619
-3.90322581 3.03225806 10.00219148 10.81256800 13.49994499
-3.90322581 3.32258065 10.02334161 10.85552124 13.49103677
-3.90322581 3.61290323 10.04741939 10.93971057 13.55528460
-3.90322581 3.90322581 10.07534164 11.07630295 13.72649949
-3.90322581 4.19354839 10.10893601 11.29025424 14.07090979
-3.90322581 4.48387097 10.15193928 11.62903831 14.70330070
-3.90322581 4.77419355 10.21233649 12.16677306 15.79128080
-3.90322581 5.06451613 10.30009318 12.86586763 17.18478750
-3.90322581 5.35483871 10.39754980 13.42561609 18.11553344
-3.90322581 5.64516129 10.48826068 13.84290562 18.67501261
-3.90322581 5.93548387 10.56389908 14.17975972 19.07251531
-3.90322581 6.22580645 10.62276486 14.46381877 19.39494339
-3.90322581 6.51612903 10.66748610 14.70188269 19.66385099
-3.90322581 6.80645161 10.70191101 14.89518965 19.88205071
-3.90322581 7.09677419 10.72100391 15.00002113 20.00000000
-3.90322581 7.38709677 10.72100391 15.00002113 20.00000000
-3.90322581 7.67741935 10.72100391 15.00002113 20.00000000
-3.90322581 7.96774194 10.72100391 15.00002113 20.00000000
-3.90322581 8.25806452 10.72100391 15.00002113 20.00000000
-3.90322581 8.54838710 10.72100391 15.00002113 20.00000000
-3.90322581 8.83870968 10.72100391 15.00002113 20.00000000
-3.90322581 9.12903226 10.72100391 15.00002113 20.00000000
-3.90322581 9.41935484 10.72100391 15.00002113 20.00000000
-3.90322581 9.70967742 10.72100391 15.00002113 20.00000000
-3.90322581 10.00000000 10.72100391 15.00002113 20.00000000
-4.19354839 1.00000000 10.00000000 11.15752390 14.00262973
-4.19354839 1.29032258 10.00000000 11.15752390 14.00262973
-4.19354839 1.58064516 10.00000000 11.15752390 14.00262973
-4.19354839 1.87096774 10.00000000 11.15752390 14.00262973
-4.19354839 2.16129032 10.00000000 11.15752390 14.00262973
-4.19354839 2.45161290 10.00000000 11.15752390 14.00262973
-4.19354839 2.74193548 10.00000000 11.15752390 14.00262973
-4.19354839 3.03225806 10.00284797 11.15550089 13.99105017
-4.19354839 3.32258065 10.03061130 11.16343190 13.93454481
-4.19354839 3.61290323 10.06293737 11.22200777 13.97446418
-4.19354839 3.90322581 10.10150367 11.34453978 14.14653042
-4.19354839 4.19354839 10.14947661 11.55849242 14.51982064
-4.19354839 4.48387097 10.21306769 11.91049442 15.20610247
-4.19354839 4.77419355 10.30455207 12.44702544 16.30551023
-4.19354839 5.06451613 10.42825336 13.03462310 17.41989968
-4.19354839 5.35483871 10.56483051 13.51054329 18.16893632
-4.19354839 5.64516129 10.69399611 13.89010562 18.67059669
-4.19354839 5.93548387 10.80488969 14.21182688 19.06294905
-4.19354839 6.22580645 10.89398583 14.48780444 19.39301254
-4.19354839 6.51612903 10.96315550 14.71842615 19.66783672
-4.19354839 6.80645161 11.01688740 14.90267275 19.88592684
-4.19354839 7.09677419 11.04734052 15.00021055 20.00000000
-4.19354839 7.38709677 11.04734052 15.00021055 20.00000000
-4.19354839 7.67741935 11.04734052 15.00021055 20.00000000
-4.19354839 7.96774194 11.04734052 15.00021055 20.00000000
-4.19354839 8.25806452 11.04734052 15.00021055 20.00000000
-4.19354839 8.54838710 11.04734052 15.00021055 20.00000000
-4.19354839 8.83870968 11.04734052 15.00021055 20.00000000
-4.19354839 9.12903226 11.04734052 15.00021055 20.00000000
-4.19354839 9.41935484 11.04734052 15.00021055 20.00000000
-4.19354839 9.70967742 11.04734052 15.00021055 20.00000000
-4.19354839 10.00000000 11.04734052 15.00021055 20.00000000
-4.48387097 1.00000000 10.00000000 11.56528482 14.70576330
-4.48387097 1.29032258 10.00000000 11.56528482 14.70576330
-4.48387097 1.58064516 10.00000000 11.56528482 14.70576330
-4.48387097 1.87096774 10.00000000 11.56528482 14.70576330
-4.48387097 2.16129032 10.00000000 11.56528482 14.70576330
-4.48387097 2.45161290 10.00000000 11.56528482 14.70576330
-4.48387097 2.74193548 10.00000000 11.56528482 14.70576330
-4.48387097 3.03225806 10.00351833 11.55997110 14.68853149
-4.48387097 3.32258065 10.03814879 11.54406758 14.59669714
-4.48387097 3.61290323 10.07937305 11.59012375 14.63057323
-4.48387097 3.90322581 10.12999914 11.71265167 14.82664243
-4.48387097 4.19354839 10.19514264 11.93798653 15.24939300
-4.48387097 4.48387097 10.28453809 12.29965873 15.97812311
-4.48387097 4.77419355 10.40728869 12.75130857 16.85678574
-4.48387097 5.06451613 10.56626545 13.21039199 17.64813719
-4.48387097 5.35483871 10.74201361 13.60560816 18.22456849
-4.48387097 5.64516129 10.91294483 13.94712330 18.67257728
-4.48387097 5.93548387 11.06666959 14.25051940 19.05879821
-4.48387097 6.22580645 11.19709582 14.51530775 19.39489256
-4.48387097 6.51612903 11.30393014 14.73651306 19.67429340
-4.48387097 6.80645161 11.39171986 14.91090478 19.89084781
-4.48387097 7.09677419 11.44506880 15.00128458 20.00000000
-4.48387097 7.38709677 11.44506880 15.00128458 20.00000000
-4.48387097 7.67741935 11.44506880 15.00128458 20.00000000
-4.48387097 7.96774194 11.44506880 15.00128458 20.00000000
-4.48387097 8.25806452 11.44506880 15.00128458 20.00000000
-4.48387097 8.54838710 11.44506880 15.00128458 20.00000000
-4.48387097 8.83870968 11.44506880 15.00128458 20.00000000
-4.48387097 9.12903226 11.44506880 15.00128458 20.00000000
-4.48387097 9.41935484 11.44506880 15.00128458 20.00000000
-4.48387097 9.70967742 11.44506880 15.00128458 20.00000000
-4.48387097 10.00000000 11.44506880 15.00128458 20.00000000
-4.77419355 1.00000000 10.00000000 12.05898046 15.70102169
-4.77419355 1.29032258 10.00000000 12.05898046 15.70102169
-4.77419355 1.58064516 10.00000000 12.05898046 15.70102169
-4.77419355 1.87096774 10.00000000 12.05898046 15.70102169
-4.77419355 2.16129032 10.00000000 12.05898046 15.70102169
-4.77419355 2.45161290 10.00000000 12.05898046 15.70102169
-4.77419355 2.74193548 10.00000000 12.05898046 15.70102169
-4.77419355 3.03225806 10.00425780 12.05183116 15.68076127
-4.77419355 3.32258065 10.04656050 12.02438408 15.57411145
-4.77419355 3.61290323 10.09802059 12.06833124 15.61725364
-4.77419355 3.90322581 10.16302652 12.19562117 15.84003779
-4.77419355 4.19354839 10.24884203 12.41521338 16.25899815
-4.77419355 4.48387097 10.36281190 12.69904450 16.77664315
-4.77419355 4.77419355 10.51269012 13.02442268 17.31761601
-4.77419355 5.06451613 10.70326374 13.37314904 17.83311892
-4.77419355 5.35483871 10.91644419 13.70398283 18.27798568
-4.77419355 5.64516129 11.13258860 14.01140956 18.68338981
-4.77419355 5.93548387 11.33885271 14.29485387 19.06262803
-4.77419355 6.22580645 11.52611738 14.54611158 19.40221067
-4.77419355 6.51612903 11.69068129 14.75656882 19.68409833
-4.77419355 6.80645161 11.83652379 14.92121904 19.89713492
-4.77419355 7.09677419 11.93184447 15.00571281 20.00000000
-4.77419355 7.38709677 11.93184447 15.00571281 20.00000000
-4.77419355 7.67741935 11.93184447 15.00571281 20.00000000
-4.77419355 7.96774194 11.93184447 15.00571281 20.00000000
-4.77419355 8.25806452 11.93184447 15.00571281 20.00000000
-4.77419355 8.54838710 11.93184447 15.00571281 20.00000000
-4.77419355 8.83870968 11.93184447 15.00571281 20.00000000
-4.77419355 9.12903226 11.93184447 15.00571281 20.00000000
-4.77419355 9.41935484 11.93184447 15.00571281 20.00000000
-4.77419355 9.70967742 11.93184447 15.00571281 20.00000000
-4.77419355 10.00000000 11.93184447 15.00571281 20.00000000
-5.06451613 1.00000000 10.00000000 12.62161977 16.93336867
-5.06451613 1.29032258 10.00000000 12.62161977 16.93336867
-5.06451613 1.58064516 10.00000000 12.62161977 16.93336867
-5.06451613 1.87096774 10.00000000 12.62161977 16.93336867
-5.06451613 2.16129032 10.00000000 12.62161977 16.93336867
-5.06451613 2.45161290 10.00000000 12.62161977 16.93336867
-5.06451613 2.74193548 10.00000000 12.62161977 16.93336867
-5.06451613 3.03225806 10.00514671 12.61436601 16.91498077
-5.06451613 3.32258065 10.05669829 12.58189344 16.81059366
-5.06451613 3.61290323 10.12016954 12.60900573 16.81743639
-5.06451613 3.90322581 10.20030048 12.69329287 16.92465057
-5.06451613 4.19354839 10.30333031 12.82979245 17.11064279
-5.06451613 4.48387097 10.43676106 13.01355965 17.35314038
-5.06451613 4.77419355 10.60858414 13.24246568 17.64074677
-5.06451613 5.06451613 10.82506593 13.51723830 17.97839577
-5.06451613 5.35483871 11.07335436 13.80267877 18.33779748
-5.06451613 5.64516129 11.33833932 14.08082078 18.70901812
-5.06451613 5.93548387 11.60813624 14.34372309 19.07791541
-5.06451613 6.22580645 11.87123458 14.58015261 19.41671660
-5.06451613 6.51612903 12.12014276 14.77981816 19.69800848
-5.06451613 6.80645161 12.35752048 14.93719431 19.90501710
-5.06451613 7.09677419 12.52110295 15.02031920 20.00000000
-5.06451613 7.38709677 12.52110295 15.02031920 20.00000000
-5.06451613 7.67741935 12.52110295 15.02031920 20.00000000
-5.06451613 7.96774194 12.52110295 15.02031920 20.00000000
-5.06451613 8.25806452 12.52110295 15.02031920 20.00000000
-5.06451613 8.54838710 12.52110295 15.02031920 20.00000000
-5.06451613 8.83870968 12.52110295 15.02031920 20.00000000
-5.06451613 9.12903226 12.52110295 15.02031920 20.00000000
-5.06451613 9.41935484 12.52110295 15.02031920 20.00000000
-5.06451613 9.70967742 12.52110295 15.02031920 20.00000000
-5.06451613 10.00000000 12.52110295 15.02031920 20.00000000
-5.35483871 1.00000000 10.00000000 13.01386190 17.72252667
-5.35483871 1.29032258 10.00000000 13.01386190 17.72252667
-5.35483871 1.58064516 10.00000000 13.01386190 17.72252667
-5.35483871 1.87096774 10.00000000 13.01386190 17.72252667
-5.35483871 2.16129032 10.00000000 13.01386190 17.72252667
-5.35483871 2.45161290 10.00000000 13.01386190 17.72252667
-5.35483871 2.74193548 10.00000000 13.01386190 17.72252667
-5.35483871 3.03225806 10.00601495 13.00686969 17.70685129
-5.35483871 3.32258065 10.06634293 12.96547134 17.59385080
-5.35483871 3.61290323 10.14023145 12.96440313 17.53452108
-5.35483871 3.90322581 10.23227056 13.00488842 17.52903392
-5.35483871 4.19354839 10.34858062 13.08810799 17.57595632
-5.35483871 4.48387097 10.49681892 13.21678700 17.67789446
-5.35483871 4.77419355 10.68605152 13.39618613 17.84588275
-5.35483871 5.06451613 10.92582927 13.63255921 18.09900113
-5.35483871 5.35483871 11.20991976 13.89010102 18.40855831
-5.35483871 5.64516129 11.52857074 14.14622502 18.75108786
-5.35483871 5.93548387 11.87259469 14.39188070 19.10579009
-5.35483871 6.22580645 12.23015522 14.61596607 19.43909490
-5.35483871 6.51612903 12.59107968 14.80868432 19.71627593
-5.35483871 6.80645161 12.95594174 14.96716502 19.91453659
-5.35483871 7.09677419 13.21476275 15.06095073 20.00000000
-5.35483871 7.38709677 13.21476275 15.06095073 20.00000000
-5.35483871 7.67741935 13.21476275 15.06095073 20.00000000
-5.35483871 7.96774194 13.21476275 15.06095073 20.00000000
-5.35483871 8.25806452 13.21476275 15.06095073 20.00000000
-5.35483871 8.54838710 13.21476275 15.06095073 20.00000000
-5.35483871 8.83870968 13.21476275 15.06095073 20.00000000
-5.35483871 9.12903226 13.21476275 15.06095073 20.00000000
-5.35483871 9.41935484 13.21476275 15.06095073 20.00000000
-5.35483871 9.70967742 13.21476275 15.06095073 20.00000000
-5.35483871 10.00000000 13.21476275 15.06095073 20.00000000
-5.64516129 1.00000000 10.00000000 13.24478345 18.10948914
-5.64516129 1.29032258 10.00000000 13.24478345 18.10948914
-5.64516129 1.58064516 10.00000000 13.24478345 18.10948914
-5.64516129 1.87096774 10.00000000 13.24478345 18.10948914
-5.64516129 2.16129032 10.00000000 13.24478345 18.10948914
-5.64516129 2.45161290 10.00000000 13.24478345 18.10948914
-5.64516129 2.74193548 10.00000000 13.24478345 18.10948914
-5.64516129 3.03225806 10.00676630 13.23777415 18.09507267
-5.64516129 3.32258065 10.07445919 13.19087287 17.97991142
-5.64516129 3.61290323 10.15668214 13.17534466 17.89493493
-5.64516129 3.90322581 10.25790645 13.19448141 17.84556990
-5.64516129 4.19354839 10.38436340 13.25231438 17.83870593
-5.64516129 4.48387097 10.54440886 13.35439086 17.88514140
-5.64516129 4.77419355 10.74903309 13.50842487 18.00199210
-5.64516129 5.06451613 11.01198391 13.72314620 18.21285792
-5.64516129 5.35483871 11.33358994 13.96248512 18.48921917
-5.64516129 5.64516129 11.71006848 14.20295570 18.80628061
-5.64516129 5.93548387 12.13699441 14.43664044 19.14441571
-5.64516129 6.22580645 12.60472073 14.65433972 19.46851033
-5.64516129 6.51612903 13.10163256 14.84960699 19.73841715
-5.64516129 6.80645161 13.62372773 15.02857701 19.92548914
-5.64516129 7.09677419 13.99614692 15.15882564 20.00000000
-5.64516129 7.38709677 13.99614692 15.15882564 20.00000000
-5.64516129 7.67741935 13.99614692 15.15882564 20.00000000
-5.64516129 7.96774194 13.99614692 15.15882564 20.00000000
-5.64516129 8.25806452 13.99614692 15.15882564 20.00000000
-5.64516129 8.54838710 13.99614692 15.15882564 20.00000000
-5.64516129 8.83870968 13.99614692 15.15882564 20.00000000
-5.64516129 9.12903226 13.99614692 15.15882564 20.00000000
-5.64516129 9.41935484 13.99614692 15.15882564 20.00000000
-5.64516129 9.70967742 13.99614692 15.15882564 20.00000000
-5.64516129 10.00000000 13.99614692 15.15882564 20.00000000
-5.93548387 1.00000000 10.00000000 13.40120867 18.33397089
-5.93548387 1.29032258 10.00000000 13.40120867 18.33397089
-5.93548387 1.58064516 10.00000000 13.40120867 18.33397089
-5.93548387 1.87096774 10.00000000 13.40120867 18.33397089
-5.93548387 2.16129032 10.00000000 13.40120867 18.33397089
-5.93548387 2.45161290 10.00000000 13.40120867 18.33397089
-5.93548387 2.74193548 10.00000000 13.40120867 18.33397089
-5.93548387 3.03225806 10.00744380 13.39407329 18.32019470
-5.93548387 3.32258065 10.08152139 13.34352984 18.20598565
-5.93548387 3.61290323 10.17060647 13.32009277 18.11340822
-5.93548387 3.90322581 10.27923715 13.32771096 18.04912878
-5.93548387 4.19354839 10.41406163 13.37128448 18.02197505
-5.93548387 4.48387097 10.58455108 13.45730945 18.04456687
-5.93548387 4.77419355 10.80408104 13.59471590 18.13562017
-5.93548387 5.06451613 11.09099369 13.79430829 18.32113067
-5.93548387 5.35483871 11.45208902 14.02065538 18.57338072
-5.93548387 5.64516129 11.89026400 14.25075408 18.86869733
-5.93548387 5.93548387 12.40745964 14.47898935 19.19011429
-5.93548387 6.22580645 12.99767141 14.70031056 19.50287840
-5.93548387 6.51612903 13.64712779 14.91660867 19.76327022
-5.93548387 6.80645161 14.34097951 15.15349351 19.93748440
-5.93548387 7.09677419 14.82768590 15.36421869 20.00000000
-5.93548387 7.38709677 14.82768590 15.36421869 20.00000000
-5.93548387 7.67741935 14.82768590 15.36421869 20.00000000
-5.93548387 7.96774194 14.82768590 15.36421869 20.00000000
-5.93548387 8.25806452 14.82768590 15.36421869 20.00000000
-5.93548387 8.54838710 14.82768590 15.36421869 20.00000000
-5.93548387 8.83870968 14.82768590 15.36421869 20.00000000
-5.93548387 9.12903226 14.82768590 15.36421869 20.00000000
-5.93548387 9.41935484 14.82768590 15.36421869 20.00000000
-5.93548387 9.70967742 14.82768590 15.36421869 20.00000000
-5.93548387 10.00000000 14.82768590 15.36421869 20.00000000
-6.22580645 1.00000000 10.00000000 13.52140723 18.49028183
-6.22580645 1.29032258 10.00000000 13.52140723 18.49028183
-6.22580645 1.58064516 10.00000000 13.52140723 18.49028183
-6.22580645 1.87096774 10.00000000 13.52140723 18.49028183
-6.22580645 2.16129032 10.00000000 13.52140723 18.49028183
-6.22580645 2.45161290 10.00000000 13.52140723 18.49028183
-6.22580645 2.74193548 10.00000000 13.52140723 18.49028183
-6.22580645 3.03225806 10.00810302 13.51414064 18.47696951
-6.22580645 3.32258065 10.08815300 13.46083531 18.36487771
-6.22580645 3.61290323 10.18335204 13.43182492 18.27056725
-6.22580645 3.90322581 10.29853084 13.43120310 18.20072122
-6.22580645 4.19354839 10.44105662 13.46414597 18.16435180
-6.22580645 4.48387097 10.62187043 13.53764372 18.17434053
-6.22580645 4.77419355 10.85711240 13.66162818 18.24992950
-6.22580645 5.06451613 11.17010593 13.84903800 18.41864073
-6.22580645 5.35483871 11.57429140 14.06601569 18.65350731
-6.22580645 5.64516129 12.07969940 14.29125163 18.93164466
-6.22580645 5.93548387 12.69488978 14.52340191 19.23816286
-6.22580645 6.22580645 13.41621771 14.76582129 19.53932638
-6.22580645 6.51612903 14.22291873 15.03682794 19.78943564
-6.22580645 6.80645161 15.07877121 15.39191301 19.95021830
-6.22580645 7.09677419 15.65721613 15.73541361 20.00000000
-6.22580645 7.38709677 15.65721613 15.73541361 20.00000000
-6.22580645 7.67741935 15.65721613 15.73541361 20.00000000
-6.22580645 7.96774194 15.65721613 15.73541361 20.00000000
-6.22580645 8.25806452 15.65721613 15.73541361 20.00000000
-6.22580645 8.54838710 15.65721613 15.73541361 20.00000000
-6.22580645 8.83870968 15.65721613 15.73541361 20.00000000
-6.22580645 9.12903226 15.65721613 15.73541361 20.00000000
-6.22580645 9.41935484 15.65721613 15.73541361 20.00000000
-6.22580645 9.70967742 15.65721613 15.73541361 20.00000000
-6.22580645 10.00000000 15.65721613 15.73541361 20.00000000
-6.51612903 1.00000000 10.00000000 13.61972094 18.60880619
-6.51612903 1.29032258 10.00000000 13.61972094 18.60880619
-6.51612903 1.58064516 10.00000000 13.61972094 18.60880619
-6.51612903 1.87096774 10.00000000 13.61972094 18.60880619
-6.51612903 2.16129032 10.00000000 13.61972094 18.60880619
-6.51612903 2.45161290 10.00000000 13.61972094 18.60880619
-6.51612903 2.74193548 10.00000000 13.61972094 18.60880619
-6.51612903 3.03225806 10.00879607 13.61234668 18.59585828
-6.51612903 3.32258065 10.09491449 13.55680524 18.48591333
-6.51612903 3.61290323 10.19606794 13.52317278 18.39148132
-6.51612903 3.90322581 10.31763361 13.51550375 18.31902161
-6.51612903 4.19354839 10.46805711 13.53910437 18.27742836
-6.51612903 4.48387097 10.66021718 13.60138870 18.27957680
-6.51612903 4.77419355 10.91360186 13.71334196 18.34495215
-6.51612903 5.06451613 11.25720210 13.89035326 18.50206810
-6.51612903 5.35483871 11.71156099 14.10154931 18.72464991
-6.51612903 5.64516129 12.29365018 14.32963573 18.99000850
-6.51612903 5.93548387 13.01651193 14.58179014 19.28447671
-6.51612903 6.22580645 13.87303537 14.87722915 19.57556793
-6.51612903 6.51612903 14.82531306 15.25898022 19.81660791
-6.51612903 6.80645161 15.80446772 15.80314051 19.96387362
-6.51612903 7.09677419 16.43160099 16.29997299 20.00000000
-6.51612903 7.38709677 16.43160099 16.29997299 20.00000000
-6.51612903 7.67741935 16.43160099 16.29997299 20.00000000
-6.51612903 7.96774194 16.43160099 16.29997299 20.00000000
-6.51612903 8.25806452 16.43160099 16.29997299 20.00000000
-6.51612903 8.54838710 16.43160099 16.29997299 20.00000000
-6.51612903 8.83870968 16.43160099 16.29997299 20.00000000
-6.51612903 9.12903226 16.43160099 16.29997299 20.00000000
-6.51612903 9.41935484 16.43160099 16.29997299 20.00000000
-6.51612903 9.70967742 16.43160099 16.29997299 20.00000000
-6.51612903 10.00000000 16.43160099 16.29997299 20.00000000
-6.80645161 1.00000000 10.00000000 13.70214059 18.70056855
-6.80645161 1.29032258 10.00000000 13.70214059 18.70056855
-6.80645161 1.58064516 10.00000000 13.70214059 18.70056855
-6.80645161 1.87096774 10.00000000 13.70214059 18.70056855
-6.80645161 2.16129032 10.00000000 13.70214059 18.70056855
-6.80645161 2.45161290 10.00000000 13.70214059 18.70056855
-6.80645161 2.74193548 10.00000000 13.70214059 18.70056855
-6.80645161 3.03225806 10.00956688 13.69469565 18.68788903
-6.80645161 3.32258065 10.10223923 13.63745767 18.57975796
-6.80645161 3.61290323 10.20959709 13.59997149 18.48577395
-6.80645161 3.90322581 10.33793179 13.58608880 18.41208791
-6.80645161 4.19354839 10.49735957 13.60114711 18.36739388
-6.80645161 4.48387097 10.70355023 13.65298813 18.36446614
-6.80645161 4.77419355 10.98045881 13.75389532 18.42285704
-6.80645161 5.06451613 11.36399277 13.92258835 18.57166481
-6.80645161 5.35483871 11.88233270 14.13399003 18.78543130
-6.80645161 5.64516129 12.55749197 14.38001472 19.04156376
-6.80645161 5.93548387 13.40037073 14.68481595 19.32760098
-6.80645161 6.22580645 14.38806526 15.09217911 19.61310066
-6.80645161 6.51612903 15.45207816 15.66063766 19.84876184
-6.80645161 6.80645161 16.48822744 16.42159603 19.97852673
-6.80645161 7.09677419 17.11075039 17.00762602 20.00000000
-6.80645161 7.38709677 17.11075039 17.00762602 20.00000000
-6.80645161 7.67741935 17.11075039 17.00762602 20.00000000
-6.80645161 7.96774194 17.11075039 17.00762602 20.00000000
-6.80645161 8.25806452 17.11075039 17.00762602 20.00000000
-6.80645161 8.54838710 17.11075039 17.00762602 20.00000000
-6.80645161 8.83870968 17.11075039 17.00762602 20.00000000
-6.80645161 9.12903226 17.11075039 17.00762602 20.00000000
-6.80645161 9.41935484 17.11075039 17.00762602 20.00000000
-6.80645161 9.70967742 17.11075039 17.00762602 20.00000000
-6.80645161 10.00000000 17.11075039 17.00762602 20.00000000
-7.09677419 1.00000000 10.00000000 13.75000000 18.75000000
-7.09677419 1.29032258 10.00000000 13.75000000 18.75000000
-7.09677419 1.58064516 10.00000000 13.75000000 18.75000000
-7.09677419 1.87096774 10.00000000 13.75000000 18.75000000
-7.09677419 2.16129032 10.00000000 13.75000000 18.75000000
-7.09677419 2.45161290 10.00000000 13.75000000 18.75000000
-7.09677419 2.74193548 10.00000000 13.75000000 18.75000000
-7.09677419 3.03225806 10.01014215 13.74253652 18.73745586
-7.09677419 3.32258065 10.10759368 13.68455725 18.63042380
-7.09677419 3.61290323 10.21937858 13.64503060 18.53708695
-7.09677419 3.90322581 10.35276814 13.62755769 18.46331909
-7.09677419 4.19354839 10.51962543 13.63742744 18.41759948
-7.09677419 4.48387097 10.73840842 13.68281858 18.41253579
-7.09677419 4.77419355 11.03721734 13.77727807 18.46758374
-7.09677419 5.06451613 11.45766304 13.94303282 18.61200965
-7.09677419 5.35483871 12.03283452 14.16229115 18.82112467
-7.09677419 5.64516129 12.78467382 14.43913152 19.07300014
-7.09677419 5.93548387 13.71462338 14.81596996 19.35739569
-7.09677419 6.22580645 14.77874402 15.35015506 19.64585006
-7.09677419 6.51612903 15.88319867 16.07541438 19.87869941
-7.09677419 6.80645161 16.90953845 16.93241475 19.98661180
-7.09677419 7.09677419 17.50000000 17.50000000 20.00000000
-7.09677419 7.38709677 17.50000000 17.50000000 20.00000000
-7.09677419 7.67741935 17.50000000 17.50000000 20.00000000
-7.09677419 7.96774194 17.50000000 17.50000000 20.00000000
-7.09677419 8.25806452 17.50000000 17.50000000 20.00000000
-7.09677419 8.54838710 17.50000000 17.50000000 20.00000000
-7.09677419 8.83870968 17.50000000 17.50000000 20.00000000
-7.09677419 9.12903226 17.50000000 17.50000000 20.00000000
-7.09677419 9.41935484 17.50000000 17.50000000 20.00000000
-7.09677419 9.70967742 17.50000000 17.50000000 20.00000000
-7.09677419 10.00000000 17.50000000 17.50000000 20.00000000
-7.38709677 1.00000000 10.00000000 13.75000000 18.75000000
-7.38709677 1.29032258 10.00000000 13.75000000 18.75000000
-7.38709677 1.58064516 10.00000000 13.75000000 18.75000000
-7.38709677 1.87096774 10.00000000 13.75000000 18.75000000
-7.38709677 2.16129032 10.00000000 13.75000000 18.75000000
-7.38709677 2.45161290 10.00000000 13.75000000 18.75000000
-7.38709677 2.74193548 10.00000000 13.75000000 18.75000000
-7.38709677 3.03225806 10.01014215 13.74253652 18.73745586
-7.38709677 3.32258065 10.10759368 13.68455725 18.63042380
-7.38709677 3.61290323 10.21937858 13.64503060 18.53708695
-7.38709677 3.90322581 10.35276814 13.62755769 18.46331909
-7.38709677 4.19354839 10.51962543 13.63742744 18.41759948
-7.38709677 4.48387097 10.73840842 13.68281858 18.41253579
-7.38709677 4.77419355 11.03721734 13.77727807 18.46758374
-7.38709677 5.06451613 11.45766304 13.94303282 18.61200965
-7.38709677 5.35483871 12.03283452 14.16229115 18.82112467
-7.38709677 5.64516129 12.78467382 14.43913152 19.07300014
-7.38709677 5.93548387 13.71462338 14.81596996 19.35739569
-7.38709677 6.22580645 14.77874402 15.35015506 19.64585006
-7.38709677 6.51612903 15.88319867 16.07541438 19.87869941
-7.38709677 6.80645161 16.90953845 16.93241475 19.98661180
-7.38709677 7.09677419 17.50000000 17.50000000 20.00000000
-7.38709677 7.38709677 17.50000000 17.50000000 20.00000000
-7.38709677 7.67741935 17.50000000 17.50000000 20.00000000
-7.38709677 7.96774194 17.50000000 17.50000000 20.00000000
-7.38709677 8.25806452 17.50000000 17.50000000 20.00000000
-7.38709677 8.54838710 17.50000000 17.50000000 20.00000000
-7.38709677 8.83870968 17.50000000 17.50000000 20.00000000
-7.38709677 9.12903226 17.50000000 17.50000000 20.00000000
-7.38709677 9.41935484 17.50000000 17.50000000 20.00000000
-7.38709677 9.70967742 17.50000000 17.50000000 20.00000000
-7.38709677 10.00000000 17.50000000 17.50000000 20.00000000
-7.67741935 1.00000000 10.00000000 13.75000000 18.75000000
-7.67741935 1.29032258 10.00000000 13.75000000 18.75000000
-7.67741935 1.58064516 10.00000000 13.75000000 18.75000000
-7.67741935 1.87096774 10.00000000 13.75000000 18.75000000
-7.67741935 2.16129032 10.00000000 13.75000000 18.75000000
-7.67741935 2.45161290 10.00000000 13.75000000 18.75000000
-7.67741935 2.74193548 10.00000000 13.75000000 18.75000000
-7.67741935 3.03225806 10.01014215 13.74253652 18.73745586
-7.67741935 3.32258065 10.10759368 13.68455725 18.63042380
-7.67741935 3.61290323 10.21937858 13.64503060 18.53708695
-7.67741935 3.90322581 10.35276814 13.62755769 18.46331909
-7.67741935 4.19354839 10.51962543 13.63742744 18.41759948
-7.67741935 4.48387097 10.73840842 13.68281858 18.41253579
-7.67741935 4.77419355 11.03721734 13.77727807 18.46758374
-7.67741935 5.06451613 11.45766304 13.94303282 18.61200965
-7.67741935 5.35483871 12.03283452 14.16229115 18.82112467
-7.67741935 5.64516129 12.78467382 14.43913152 19.07300014
-7.67741935 5.93548387 13.71462338 14.81596996 19.35739569
-7.67741935 6.22580645 14.77874402 15.35015506 19.64585006
-7.67741935 6.51612903 15.88319867 16.07541438 19.87869941
-7.67741935 6.80645161 16.90953845 16.93241475 19.98661180
-7.67741935 7.09677419 17.50000000 17.50000000 20.00000000
-7.67741935 7.38709677 17.50000000 17.50000000 20.00000000
-7.67741935 7.67741935 17.50000000 17.50000000 20.00000000
-7.67741935 7.96774194 17.50000000 17.50000000 20.00000000
-7.67741935 8.25806452 17.50000000 17.50000000 20.00000000
-7.67741935 8.54838710 17.50000000 17.50000000 20.00000000
-7.67741935 8.83870968 17.50000000 17.50000000 20.00000000
-7.67741935 9.12903226 17.50000000 17.50000000 20.00000000
-7.67741935 9.41935484 17.50000000 17.50000000 20.00000000
-7.67741935 9.70967742 17.50000000 17.50000000 20.00000000
-7.67741935 10.00000000 17.50000000 17.50000000 20.00000000
-7.96774194 1.00000000 10.00000000 13.75000000 18.75000000
-7.96774194 1.29032258 10.00000000 13.75000000 18.75000000
-7.96774194 1.58064516 10.00000000 13.75000000 18.75000000
-7.96774194 1.87096774 10.00000000 13.75000000 18.75000000
-7.96774194 2.16129032 10.00000000 13.75000000 18.75000000
-7.96774194 2.45161290 10.00000000 13.75000000 18.75000000
-7.96774194 2.74193548 10.00000000 13.75000000 18.75000000
-7.96774194 3.03225806 10.01014215 13.74253652 18.73745586
-7.96774194 3.32258065 10.10759368 13.68455725 18.63042380
-7.96774194 3.61290323 10.21937858 13.64503060 18.53708695
-7.96774194 3.90322581 10.35276814 13.62755769 18.46331909
-7.96774194 4.19354839 10.51962543 13.63742744 18.41759948
-7.96774194 4.48387097 10.73840842 13.68281858 18.41253579
-7.96774194 4.77419355 11.03721734 13.77727807 18.46758374
-7.96774194 5.06451613 11.45766304 13.94303282 18.61200965
-7.96774194 5.35483871 12.03283452 14.16229115 18.82112467
-7.96774194 5.64516129 12.78467382 14.43913152 19.07300014
-7.96774194 5.93548387 13.71462338 14.81596996 19.35739569
-7.96774194 6.22580645 14.77874402 15.35015506 19.64585006
-7.96774194 6.51612903 15.88319867 16.07541438 19.87869941
-7.96774194 6.80645161 16.90953845 16.93241475 19.98661180
-7.96774194 7.09677419 17.50000000 17.50000000 20.00000000
-7.96774194 7.38709677 17.50000000 17.50000000 20.00000000
-7.96774194 7.67741935 17.50000000 17.50000000 20.00000000
-7.96774194 7.96774194 17.50000000 17.50000000 20.00000000
-7.96774194 8.25806452 17.50000000 17.50000000 20.00000000
-7.96774194 8.54838710 17.50000000 17.50000000 20.00000000
-7.96774194 8.83870968 17.50000000 17.50000000 20.00000000
-7.96774194 9.12903226 17.50000000 17.50000000 20.00000000
-7.96774194 9.41935484 17.50000000 17.50000000 20.00000000
-7.96774194 9.70967742 17.50000000 17.50000000 20.00000000
-7.96774194 10.00000000 17.50000000 17.50000000 20.00000000
-8.25806452 1.00000000 10.00000000 13.75000000 18.75000000
-8.25806452 1.29032258 10.00000000 13.75000000 18.75000000
-8.25806452 1.58064516 10.00000000 13.75000000 18.75000000
-8.25806452 1.87096774 10.00000000 13.75000000 18.75000000
-8.25806452 2.16129032 10.00000000 13.75000000 18.75000000
-8.25806452 2.45161290 10.00000000 13.75000000 18.75000000
-8.25806452 2.74193548 10.00000000 13.75000000 18.75000000
-8.25806452 3.03225806 10.01014215 13.74253652 18.73745586
-8.25806452 3.32258065 10.10759368 13.68455725 18.63042380
-8.25806452 3.61290323 10.21937858 13.64503060 18.53708695
-8.25806452 3.90322581 10.35276814 13.62755769 18.46331909
-8.25806452 4.19354839 10.51962543 13.63742744 18.41759948
-8.25806452 4.48387097 10.73840842 13.68281858 18.41253579
-8.25806452 4.77419355 11.03721734 13.77727807 18.46758374
-8.25806452 5.06451613 11.45766304 13.94303282 18.61200965
-8.25806452 5.35483871 12.03283452 14.16229115 18.82112467
-8.25806452 5.64516129 12.78467382 14.43913152 19.07300014
-8.25806452 5.93548387 13.71462338 14.81596996 19.35739569
-8.25806452 6.22580645 14.77874402 15.35015506 19.64585006
-8.25806452 6.51612903 15.88319867 16.07541438 19.87869941
-8.25806452 6.80645161 16.90953845 16.93241475 19.98661180
-8.25806452 7.09677419 17.50000000 17.50000000 20.00000000
-8.25806452 7.38709677 17.50000000 17.50000000 20.00000000
-8.25806452 7.67741935 17.50000000 17.50000000 20.00000000
-8.25806452 7.96774194 17.50000000 17.50000000 20.00000000
-8.25806452 8.25806452 17.50000000 17.50000000 20.00000000
-8.25806452 8.54838710 17.50000000 17.50000000 20.00000000
-8.25806452 8.83870968 17.50000000 17.50000000 20.00000000
-8.25806452 9.12903226 17.50000000 17.50000000 20.00000000
-8.25806452 9.41935484 17.50000000 17.50000000 20.00000000
-8.25806452 9.70967742 17.50000000 17.50000000 20.00000000
-8.25806452 10.00000000 17.50000000 17.50000000 20.00000000
-8.54838710 1.00000000 10.00000000 13.75000000 18.75000000
-8.54838710 1.29032258 10.00000000 13.75000000 18.75000000
-8.54838710 1.58064516 10.00000000 13.75000000 18.75000000
-8.54838710 1.87096774 10.00000000 13.75000000 18.75000000
-8.54838710 2.16129032 10.00000000 13.75000000 18.75000000
-8.54838710 2.45161290 10.00000000 13.75000000 18.75000000
-8.54838710 2.74193548 10.00000000 13.75000000 18.75000000
-8.54838710 3.03225806 10.01014215 13.74253652 18.73745586
-8.54838710 3.32258065 10.10759368 13.68455725 18.63042380
-8.54838710 3.61290323 10.21937858 13.64503060 18.53708695
-8.54838710 3.90322581 10.35276814 13.62755769 18.46331909
-8.54838710 4.19354839 10.51962543 13.63742744 18.41759948
-8.54838710 4.48387097 10.73840842 13.68281858 18.41253579
-8.54838710 4.77419355 11.03721734 13.77727807 18.46758374
-8.54838710 5.06451613 11.45766304 13.94303282 18.61200965
-8.54838710 5.35483871 12.03283452 14.16229115 18.82112467
-8.54838710 5.64516129 12.78467382 14.43913152 19.07300014
-8.54838710 5.93548387 13.71462338 14.81596996 19.35739569
-8.54838710 6.22580645 14.77874402 15.35015506 19.64585006
-8.54838710 6.51612903 15.88319867 16.07541438 19.87869941
-8.54838710 6.80645161 16.90953845 16.93241475 19.98661180
-8.54838710 7.09677419 17.50000000 17.50000000 20.00000000
-8.54838710 7.38709677 17.50000000 17.50000000 20.00000000
-8.54838710 7.67741935 17.50000000 17.50000000 20.00000000
-8.54838710 7.96774194 17.50000000 17.50000000 20.00000000
-8.54838710 8.25806452 17.50000000 17.50000000 20.00000000
-8.54838710 8.54838710 17.50000000 17.50000000 20.00000000
-8.54838710 8.83870968 17.50000000 17.50000000 20.00000000
-8.54838710 9.12903226 17.50000000 17.50000000 20.00000000
-8.54838710 9.41935484 17.50000000 17.50000000 20.00000000
-8.54838710 9.70967742 17.50000000 17.50000000 20.00000000
-8.54838710 10.00000000 17.50000000 17.50000000 20.00000000
-8.83870968 1.00000000 10.00000000 13.75000000 18.75000000
-8.83870968 1.29032258 10.00000000 13.75000000 18.75000000
-8.83870968 1.58064516 10.00000000 13.75000000 18.75000000
-8.83870968 1.87096774 10.00000000 13.75000000 18.75000000
-8.83870968 2.16129032 10.00000000 13.75000000 18.75000000
-8.83870968 2.45161290 10.00000000 13.75000000 18.75000000
-8.83870968 2.74193548 10.00000000 13.75000000 18.75000000
-8.83870968 3.03225806 10.01014215 13.74253652 18.73745586
-8.83870968 3.32258065 10.10759368 13.68455725 18.63042380
-8.83870968 3.61290323 10.21937858 13.64503060 18.53708695
-8.83870968 3.90322581 10.35276814 13.62755769 18.46331909
-8.83870968 4.19354839 10.51962543 13.63742744 18.41759948
-8.83870968 4.48387097 10.73840842 13.68281858 18.41253579
-8.83870968 4.77419355 11.03721734 13.77727807 18.46758374
-8.83870968 5.06451613 11.45766304 13.94303282 18.61200965
-8.83870968 5.35483871 12.03283452 14.16229115 18.82112467
-8.83870968 5.64516129 12.78467382 14.43913152 19.07300014
-8.83870968 5.93548387 13.71462338 14.81596996 19.35739569
-8.83870968 6.22580645 14.77874402 15.35015506 19.64585006
-8.83870968 6.51612903 15.88319867 16.07541438 19.87869941
-8.83870968 6.80645161 16.90953845 16.93241475 19.98661180
-8.83870968 7.09677419 17.50000000 17.50000000 20.00000000
-8.83870968 7.38709677 17.50000000 17.50000000 20.00000000
-8.83870968 7.67741935 17.50000000 17.50000000 20.00000000
-8.83870968 7.96774194 17.50000000 17.50000000 20.00000000
-8.83870968 8.25806452 17.50000000 17.50000000 20.00000000
-8.83870968 8.54838710 17.50000000 17.50000000 20.00000000
-8.83870968 8.83870968 17.50000000 17.50000000 20.00000000
-8.83870968 9.12903226 17.50000000 17.50000000 20.00000000
-8.83870968 9.41935484 17.50000000 17.50000000 20.00000000
-8.83870968 9.70967742 17.50000000 17.50000000 20.00000000
-8.83870968 10.00000000 17.50000000 17.50000000 20.00000000
-9.12903226 1.00000000 10.00000000 13.75000000 18.75000000
-9.12903226 1.29032258 10.00000000 13.75000000 18.75000000
-9.12903226 1.58064516 10.00000000 13.75000000 18.75000000
-9.12903226 1.87096774 10.00000000 13.75000000 18.75000000
-9.12903226 2.16129032 10.00000000 13.75000000 18.75000000
-9.12903226 2.45161290 10.00000000 13.75000000 18.75000000
-9.12903226 2.74193548 10.00000000 13.75000000 18.75000000
-9.12903226 3.03225806 10.01014215 13.74253652 18.73745586
-9.12903226 3.32258065 10.10759368 13.68455725 18.63042380
-9.12903226 3.61290323 10.21937858 13.64503060 18.53708695
-9.12903226 3.90322581 10.35276814 13.62755769 18.46331909
-9.12903226 4.19354839 10.51962543 13.63742744 18.41759948
-9.12903226 4.48387097 10.73840842 13.68281858 18.41253579
-9.12903226 4.77419355 11.03721734 13.77727807 18.46758374
-9.12903226 5.06451613 11.45766304 13.94303282 18.61200965
-9.12903226 5.35483871 12.03283452 14.16229115 18.82112467
-9.12903226 5.64516129 12.78467382 14.43913152 19.07300014
-9.12903226 5.93548387 13.71462338 14.81596996 19.35739569
-9.12903226 6.22580645 14.77874402 15.35015506 19.64585006
-9.12903226 6.51612903 15.88319867 16.07541438 19.87869941
-9.12903226 6.80645161 16.90953845 16.93241475 19.98661180
-9.12903226 7.09677419 17.50000000 17.50000000 20.00000000
-9.12903226 7.38709677 17.50000000 17.50000000 20.00000000
-9.12903226 7.67741935 17.50000000 17.50000000 20.00000000
-9.12903226 7.96774194 17.50000000 17.50000000 20.00000000
-9.12903226 8.25806452 17.50000000 17.50000000 20.00000000
-9.12903226 8.54838710 17.50000000 17.50000000 20.00000000
-9.12903226 8.83870968 17.50000000 17.50000000 20.00000000
-9.12903226 9.12903226 17.50000000 17.50000000 20.00000000
-9.12903226 9.41935484 17.50000000 17.50000000 20.00000000
-9.12903226 9.70967742 17.50000000 17.50000000 20.00000000
-9.12903226 10.00000000 17.50000000 17.50000000 20.00000000
-9.41935484 1.00000000 10.00000000 13.75000000 18.75000000
-9.41935484 1.29032258 10.00000000 13.75000000 18.75000000
-9.41935484 1.58064516 10.00000000 13.75000000 18.75000000
-9.41935484 1.87096774 10.00000000 13.75000000 18.75000000
-9.41935484 2.16129032 10.00000000 13.75000000 18.75000000
-9.41935484 2.45161290 10.00000000 13.75000000 18.75000000
-9.41935484 2.74193548 10.00000000 13.75000000 18.75000000
-9.41935484 3.03225806 10.01014215 13.74253652 18.73745586
-9.41935484 3.32258065 10.10759368 13.68455725 18.63042380
-9.41935484 3.61290323 10.21937858 13.64503060 18.53708695
-9.41935484 3.90322581 10.35276814 13.62755769 18.46331909
-9.41935484 4.19354839 10.51962543 13.63742744 18.41759948
-9.41935484 4.48387097 10.73840842 13.68281858 18.41253579
-9.41935484 4.77419355 11.03721734 13.77727807 18.46758374
-9.41935484 5.06451613 11.45766304 13.94303282 18.61200965
-9.41935484 5.35483871 12.03283452 14.16229115 18.82112467
-9.41935484 5.64516129 12.78467382 14.43913152 19.07300014
-9.41935484 5.93548387 13.71462338 14.81596996 19.35739569
-9.41935484 6.22580645 14.77874402 15.35015506 19.64585006
-9.41935484 6.51612903 15.88319867 16.07541438 19.87869941
-9.41935484 6.80645161 16.90953845 16.93241475 19.98661180
-9.41935484 7.09677419 17.50000000 17.50000000 20.00000000
-9.41935484 7.38709677 17.50000000 17.50000000 20.00000000
-9.41935484 7.67741935 17.50000000 17.50000000 20.00000000
-9.41935484 7.96774194 17.50000000 17.50000000 20.00000000
-9.41935484 8.25806452 17.50000000 17.50000000 20.00000000
-9.41935484 8.54838710 17.50000000 17.50000000 20.00000000
-9.41935484 8.83870968 17.50000000 17.50000000 20.00000000
-9.41935484 9.12903226 17.50000000 17.50000000 20.00000000
-9.41935484 9.41935484 17.50000000 17.50000000 20.00000000
-9.41935484 9.70967742 17.50000000 17.50000000 20.00000000
-9.41935484 10.00000000 17.50000000 17.50000000 20.00000000
-9.70967742 1.00000000 10.00000000 13.75000000 18.75000000
-9.70967742 1.29032258 10.00000000 13.75000000 18.75000000
-9.70967742 1.58064516 10.00000000 13.75000000 18.75000000
-9.70967742 1.87096774 10.00000000 13.75000000 18.75000000
-9.70967742 2.16129032 10.00000000 13.75000000 18.75000000
-9.70967742 2.45161290 10.00000000 13.75000000 18.75000000
-9.70967742 2.74193548 10.00000000 13.75000000 18.75000000
-9.70967742 3.03225806 10.01014215 13.74253652 18.73745586
-9.70967742 3.32258065 10.10759368 13.68455725 18.63042380
-9.70967742 3.61290323 10.21937858 13.64503060 18.53708695
-9.70967742 3.90322581 10.35276814 13.62755769 18.46331909
-9.70967742 4.19354839 10.51962543 13.63742744 18.41759948
-9.70967742 4.48387097 10.73840842 13.68281858 18.41253579
-9.70967742 4.77419355 11.03721734 13.77727807 18.46758374
-9.70967742 5.06451613 11.45766304 13.94303282 18.61200965
-9.70967742 5.35483871 12.03283452 14.16229115 18.82112467
-9.70967742 5.64516129 12.78467382 14.43913152 19.07300014
-9.70967742 5.93548387 13.71462338 14.81596996 19.35739569
-9.70967742 6.22580645 14.77874402 15.35015506 19.64585006
-9.70967742 6.51612903 15.88319867 16.07541438 19.87869941
-9.70967742 6.80645161 16.90953845 16.93241475 19.98661180
-9.70967742 7.09677419 17.50000000 17.50000000 20.00000000
-9.70967742 7.38709677 17.50000000 17.50000000 20.00000000
-9.70967742 7.67741935 17.50000000 17.50000000 20.00000000
-9.70967742 7.96774194 17.50000000 17.50000000 20.00000000
-9.70967742 8.25806452 17.50000000 17.50000000 20.00000000
-9.70967742 8.54838710 17.50000000 17.50000000 20.00000000
-9.70967742 8.83870968 17.50000000 17.50000000 20.00000000
-9.70967742 9.12903226 17.50000000 17.50000000 20.00000000
-9.70967742 9.41935484 17.50000000 17.50000000 20.00000000
-9.70967742 9.70967742 17.50000000 17.50000000 20.00000000
-9.70967742 10.00000000 17.50000000 17.50000000 20.00000000
-10.00000000 1.00000000 10.00000000 13.75000000 18.75000000
-10.00000000 1.29032258 10.00000000 13.75000000 18.75000000
-10.00000000 1.58064516 10.00000000 13.75000000 18.75000000
-10.00000000 1.87096774 10.00000000 13.75000000 18.75000000
-10.00000000 2.16129032 10.00000000 13.75000000 18.75000000
-10.00000000 2.45161290 10.00000000 13.75000000 18.75000000
-10.00000000 2.74193548 10.00000000 13.75000000 18.75000000
-10.00000000 3.03225806 10.01014215 13.74253652 18.73745586
-10.00000000 3.32258065 10.10759368 13.68455725 18.63042380
-10.00000000 3.61290323 10.21937858 13.64503060 18.53708695
-10.00000000 3.90322581 10.35276814 13.62755769 18.46331909
-10.00000000 4.19354839 10.51962543 13.63742744 18.41759948
-10.00000000 4.48387097 10.73840842 13.68281858 18.41253579
-10.00000000 4.77419355 11.03721734 13.77727807 18.46758374
-10.00000000 5.06451613 11.45766304 13.94303282 18.61200965
-10.00000000 5.35483871 12.03283452 14.16229115 18.82112467
-10.00000000 5.64516129 12.78467382 14.43913152 19.07300014
-10.00000000 5.93548387 13.71462338 14.81596996 19.35739569
-10.00000000 6.22580645 14.77874402 15.35015506 19.64585006
-10.00000000 6.51612903 15.88319867 16.07541438 19.87869941
-10.00000000 6.80645161 16.90953845 16.93241475 19.98661180
-10.00000000 7.09677419 17.50000000 17.50000000 20.00000000
-10.00000000 7.38709677 17.50000000 17.50000000 20.00000000
-10.00000000 7.67741935 17.50000000 17.50000000 20.00000000
-10.00000000 7.96774194 17.50000000 17.50000000 20.00000000
-10.00000000 8.25806452 17.50000000 17.50000000 20.00000000
-10.00000000 8.54838710 17.50000000 17.50000000 20.00000000
-10.00000000 8.83870968 17.50000000 17.50000000 20.00000000
-10.00000000 9.12903226 17.50000000 17.50000000 20.00000000
-10.00000000 9.41935484 17.50000000 17.50000000 20.00000000
-10.00000000 9.70967742 17.50000000 17.50000000 20.00000000
-10.00000000 10.00000000 17.50000000 17.50000000 20.00000000
+FoodQuality Service CheapTip AverageTip GenerousTip
+1.000000000 1.000000000 10.000000000 10.000000000 12.500000000
+1.000000000 1.290322581 10.000000000 10.000000000 12.500000000
+1.000000000 1.580645161 10.000000000 10.000000000 12.500000000
+1.000000000 1.870967742 10.000000000 10.000000000 12.500000000
+1.000000000 2.161290323 10.000000000 10.000000000 12.500000000
+1.000000000 2.451612903 10.000000000 10.000000000 12.500000000
+1.000000000 2.741935484 10.000000000 10.000000000 12.500000000
+1.000000000 3.032258065 10.000000000 10.020323221 12.520404599
+1.000000000 3.322580645 10.000000000 10.217239082 12.726188365
+1.000000000 3.612903226 10.000000000 10.438541426 12.978595315
+1.000000000 3.903225806 10.000000000 10.688605148 13.303233716
+1.000000000 4.193548387 10.000000000 10.985194151 13.754553905
+1.000000000 4.483870968 10.000000000 11.368962007 14.431095437
+1.000000000 4.774193548 10.000000000 11.913195856 15.489093970
+1.000000000 5.064516129 10.000000000 12.682234786 17.023032304
+1.000000000 5.354838710 10.000000000 13.342744072 18.155449447
+1.000000000 5.645161290 10.000000000 13.792466240 18.754193916
+1.000000000 5.935483871 10.000000000 14.130816184 19.125588403
+1.000000000 6.225806452 10.000000000 14.413282130 19.412900315
+1.000000000 6.516129032 10.000000000 14.658795531 19.658787254
+1.000000000 6.806451613 10.000000000 14.873037538 19.873037533
+1.000000000 7.096774194 10.000000000 15.000000000 20.000000000
+1.000000000 7.387096774 10.000000000 15.000000000 20.000000000
+1.000000000 7.677419355 10.000000000 15.000000000 20.000000000
+1.000000000 7.967741935 10.000000000 15.000000000 20.000000000
+1.000000000 8.258064516 10.000000000 15.000000000 20.000000000
+1.000000000 8.548387097 10.000000000 15.000000000 20.000000000
+1.000000000 8.838709677 10.000000000 15.000000000 20.000000000
+1.000000000 9.129032258 10.000000000 15.000000000 20.000000000
+1.000000000 9.419354839 10.000000000 15.000000000 20.000000000
+1.000000000 9.709677419 10.000000000 15.000000000 20.000000000
+1.000000000 10.000000000 10.000000000 15.000000000 20.000000000
+1.290322581 1.000000000 10.000000000 10.000000000 12.500000000
+1.290322581 1.290322581 10.000000000 10.000000000 12.500000000
+1.290322581 1.580645161 10.000000000 10.000000000 12.500000000
+1.290322581 1.870967742 10.000000000 10.000000000 12.500000000
+1.290322581 2.161290323 10.000000000 10.000000000 12.500000000
+1.290322581 2.451612903 10.000000000 10.000000000 12.500000000
+1.290322581 2.741935484 10.000000000 10.000000000 12.500000000
+1.290322581 3.032258065 10.000000000 10.020323221 12.520404599
+1.290322581 3.322580645 10.000000000 10.217239082 12.726188365
+1.290322581 3.612903226 10.000000000 10.438541426 12.978595315
+1.290322581 3.903225806 10.000000000 10.688605148 13.303233716
+1.290322581 4.193548387 10.000000000 10.985194151 13.754553905
+1.290322581 4.483870968 10.000000000 11.368962007 14.431095437
+1.290322581 4.774193548 10.000000000 11.913195856 15.489093970
+1.290322581 5.064516129 10.000000000 12.682234786 17.023032304
+1.290322581 5.354838710 10.000000000 13.342744072 18.155449447
+1.290322581 5.645161290 10.000000000 13.792466240 18.754193916
+1.290322581 5.935483871 10.000000000 14.130816184 19.125588403
+1.290322581 6.225806452 10.000000000 14.413282130 19.412900315
+1.290322581 6.516129032 10.000000000 14.658795531 19.658787254
+1.290322581 6.806451613 10.000000000 14.873037538 19.873037533
+1.290322581 7.096774194 10.000000000 15.000000000 20.000000000
+1.290322581 7.387096774 10.000000000 15.000000000 20.000000000
+1.290322581 7.677419355 10.000000000 15.000000000 20.000000000
+1.290322581 7.967741935 10.000000000 15.000000000 20.000000000
+1.290322581 8.258064516 10.000000000 15.000000000 20.000000000
+1.290322581 8.548387097 10.000000000 15.000000000 20.000000000
+1.290322581 8.838709677 10.000000000 15.000000000 20.000000000
+1.290322581 9.129032258 10.000000000 15.000000000 20.000000000
+1.290322581 9.419354839 10.000000000 15.000000000 20.000000000
+1.290322581 9.709677419 10.000000000 15.000000000 20.000000000
+1.290322581 10.000000000 10.000000000 15.000000000 20.000000000
+1.580645161 1.000000000 10.000000000 10.000000000 12.500000000
+1.580645161 1.290322581 10.000000000 10.000000000 12.500000000
+1.580645161 1.580645161 10.000000000 10.000000000 12.500000000
+1.580645161 1.870967742 10.000000000 10.000000000 12.500000000
+1.580645161 2.161290323 10.000000000 10.000000000 12.500000000
+1.580645161 2.451612903 10.000000000 10.000000000 12.500000000
+1.580645161 2.741935484 10.000000000 10.000000000 12.500000000
+1.580645161 3.032258065 10.000000000 10.020323221 12.520404599
+1.580645161 3.322580645 10.000000000 10.217239082 12.726188365
+1.580645161 3.612903226 10.000000000 10.438541426 12.978595315
+1.580645161 3.903225806 10.000000000 10.688605148 13.303233716
+1.580645161 4.193548387 10.000000000 10.985194151 13.754553905
+1.580645161 4.483870968 10.000000000 11.368962007 14.431095437
+1.580645161 4.774193548 10.000000000 11.913195856 15.489093970
+1.580645161 5.064516129 10.000000000 12.682234786 17.023032304
+1.580645161 5.354838710 10.000000000 13.342744072 18.155449447
+1.580645161 5.645161290 10.000000000 13.792466240 18.754193916
+1.580645161 5.935483871 10.000000000 14.130816184 19.125588403
+1.580645161 6.225806452 10.000000000 14.413282130 19.412900315
+1.580645161 6.516129032 10.000000000 14.658795531 19.658787254
+1.580645161 6.806451613 10.000000000 14.873037538 19.873037533
+1.580645161 7.096774194 10.000000000 15.000000000 20.000000000
+1.580645161 7.387096774 10.000000000 15.000000000 20.000000000
+1.580645161 7.677419355 10.000000000 15.000000000 20.000000000
+1.580645161 7.967741935 10.000000000 15.000000000 20.000000000
+1.580645161 8.258064516 10.000000000 15.000000000 20.000000000
+1.580645161 8.548387097 10.000000000 15.000000000 20.000000000
+1.580645161 8.838709677 10.000000000 15.000000000 20.000000000
+1.580645161 9.129032258 10.000000000 15.000000000 20.000000000
+1.580645161 9.419354839 10.000000000 15.000000000 20.000000000
+1.580645161 9.709677419 10.000000000 15.000000000 20.000000000
+1.580645161 10.000000000 10.000000000 15.000000000 20.000000000
+1.870967742 1.000000000 10.000000000 10.000000000 12.500000000
+1.870967742 1.290322581 10.000000000 10.000000000 12.500000000
+1.870967742 1.580645161 10.000000000 10.000000000 12.500000000
+1.870967742 1.870967742 10.000000000 10.000000000 12.500000000
+1.870967742 2.161290323 10.000000000 10.000000000 12.500000000
+1.870967742 2.451612903 10.000000000 10.000000000 12.500000000
+1.870967742 2.741935484 10.000000000 10.000000000 12.500000000
+1.870967742 3.032258065 10.000000000 10.020323221 12.520404599
+1.870967742 3.322580645 10.000000000 10.217239082 12.726188365
+1.870967742 3.612903226 10.000000000 10.438541426 12.978595315
+1.870967742 3.903225806 10.000000000 10.688605148 13.303233716
+1.870967742 4.193548387 10.000000000 10.985194151 13.754553905
+1.870967742 4.483870968 10.000000000 11.368962007 14.431095437
+1.870967742 4.774193548 10.000000000 11.913195856 15.489093970
+1.870967742 5.064516129 10.000000000 12.682234786 17.023032304
+1.870967742 5.354838710 10.000000000 13.342744072 18.155449447
+1.870967742 5.645161290 10.000000000 13.792466240 18.754193916
+1.870967742 5.935483871 10.000000000 14.130816184 19.125588403
+1.870967742 6.225806452 10.000000000 14.413282130 19.412900315
+1.870967742 6.516129032 10.000000000 14.658795531 19.658787254
+1.870967742 6.806451613 10.000000000 14.873037538 19.873037533
+1.870967742 7.096774194 10.000000000 15.000000000 20.000000000
+1.870967742 7.387096774 10.000000000 15.000000000 20.000000000
+1.870967742 7.677419355 10.000000000 15.000000000 20.000000000
+1.870967742 7.967741935 10.000000000 15.000000000 20.000000000
+1.870967742 8.258064516 10.000000000 15.000000000 20.000000000
+1.870967742 8.548387097 10.000000000 15.000000000 20.000000000
+1.870967742 8.838709677 10.000000000 15.000000000 20.000000000
+1.870967742 9.129032258 10.000000000 15.000000000 20.000000000
+1.870967742 9.419354839 10.000000000 15.000000000 20.000000000
+1.870967742 9.709677419 10.000000000 15.000000000 20.000000000
+1.870967742 10.000000000 10.000000000 15.000000000 20.000000000
+2.161290323 1.000000000 10.000000000 10.000000000 12.500000000
+2.161290323 1.290322581 10.000000000 10.000000000 12.500000000
+2.161290323 1.580645161 10.000000000 10.000000000 12.500000000
+2.161290323 1.870967742 10.000000000 10.000000000 12.500000000
+2.161290323 2.161290323 10.000000000 10.000000000 12.500000000
+2.161290323 2.451612903 10.000000000 10.000000000 12.500000000
+2.161290323 2.741935484 10.000000000 10.000000000 12.500000000
+2.161290323 3.032258065 10.000000000 10.020323221 12.520404599
+2.161290323 3.322580645 10.000000000 10.217239082 12.726188365
+2.161290323 3.612903226 10.000000000 10.438541426 12.978595315
+2.161290323 3.903225806 10.000000000 10.688605148 13.303233716
+2.161290323 4.193548387 10.000000000 10.985194151 13.754553905
+2.161290323 4.483870968 10.000000000 11.368962007 14.431095437
+2.161290323 4.774193548 10.000000000 11.913195856 15.489093970
+2.161290323 5.064516129 10.000000000 12.682234786 17.023032304
+2.161290323 5.354838710 10.000000000 13.342744072 18.155449447
+2.161290323 5.645161290 10.000000000 13.792466240 18.754193916
+2.161290323 5.935483871 10.000000000 14.130816184 19.125588403
+2.161290323 6.225806452 10.000000000 14.413282130 19.412900315
+2.161290323 6.516129032 10.000000000 14.658795531 19.658787254
+2.161290323 6.806451613 10.000000000 14.873037538 19.873037533
+2.161290323 7.096774194 10.000000000 15.000000000 20.000000000
+2.161290323 7.387096774 10.000000000 15.000000000 20.000000000
+2.161290323 7.677419355 10.000000000 15.000000000 20.000000000
+2.161290323 7.967741935 10.000000000 15.000000000 20.000000000
+2.161290323 8.258064516 10.000000000 15.000000000 20.000000000
+2.161290323 8.548387097 10.000000000 15.000000000 20.000000000
+2.161290323 8.838709677 10.000000000 15.000000000 20.000000000
+2.161290323 9.129032258 10.000000000 15.000000000 20.000000000
+2.161290323 9.419354839 10.000000000 15.000000000 20.000000000
+2.161290323 9.709677419 10.000000000 15.000000000 20.000000000
+2.161290323 10.000000000 10.000000000 15.000000000 20.000000000
+2.451612903 1.000000000 10.000000000 10.000000000 12.500000000
+2.451612903 1.290322581 10.000000000 10.000000000 12.500000000
+2.451612903 1.580645161 10.000000000 10.000000000 12.500000000
+2.451612903 1.870967742 10.000000000 10.000000000 12.500000000
+2.451612903 2.161290323 10.000000000 10.000000000 12.500000000
+2.451612903 2.451612903 10.000000000 10.000000000 12.500000000
+2.451612903 2.741935484 10.000000000 10.000000000 12.500000000
+2.451612903 3.032258065 10.000000000 10.020323221 12.520404599
+2.451612903 3.322580645 10.000000000 10.217239082 12.726188365
+2.451612903 3.612903226 10.000000000 10.438541426 12.978595315
+2.451612903 3.903225806 10.000000000 10.688605148 13.303233716
+2.451612903 4.193548387 10.000000000 10.985194151 13.754553905
+2.451612903 4.483870968 10.000000000 11.368962007 14.431095437
+2.451612903 4.774193548 10.000000000 11.913195856 15.489093970
+2.451612903 5.064516129 10.000000000 12.682234786 17.023032304
+2.451612903 5.354838710 10.000000000 13.342744072 18.155449447
+2.451612903 5.645161290 10.000000000 13.792466240 18.754193916
+2.451612903 5.935483871 10.000000000 14.130816184 19.125588403
+2.451612903 6.225806452 10.000000000 14.413282130 19.412900315
+2.451612903 6.516129032 10.000000000 14.658795531 19.658787254
+2.451612903 6.806451613 10.000000000 14.873037538 19.873037533
+2.451612903 7.096774194 10.000000000 15.000000000 20.000000000
+2.451612903 7.387096774 10.000000000 15.000000000 20.000000000
+2.451612903 7.677419355 10.000000000 15.000000000 20.000000000
+2.451612903 7.967741935 10.000000000 15.000000000 20.000000000
+2.451612903 8.258064516 10.000000000 15.000000000 20.000000000
+2.451612903 8.548387097 10.000000000 15.000000000 20.000000000
+2.451612903 8.838709677 10.000000000 15.000000000 20.000000000
+2.451612903 9.129032258 10.000000000 15.000000000 20.000000000
+2.451612903 9.419354839 10.000000000 15.000000000 20.000000000
+2.451612903 9.709677419 10.000000000 15.000000000 20.000000000
+2.451612903 10.000000000 10.000000000 15.000000000 20.000000000
+2.741935484 1.000000000 10.000000000 10.000000000 12.500000000
+2.741935484 1.290322581 10.000000000 10.000000000 12.500000000
+2.741935484 1.580645161 10.000000000 10.000000000 12.500000000
+2.741935484 1.870967742 10.000000000 10.000000000 12.500000000
+2.741935484 2.161290323 10.000000000 10.000000000 12.500000000
+2.741935484 2.451612903 10.000000000 10.000000000 12.500000000
+2.741935484 2.741935484 10.000000000 10.000000000 12.500000000
+2.741935484 3.032258065 10.000000000 10.020323221 12.520404599
+2.741935484 3.322580645 10.000000000 10.217239082 12.726188365
+2.741935484 3.612903226 10.000000000 10.438541426 12.978595315
+2.741935484 3.903225806 10.000000000 10.688605148 13.303233716
+2.741935484 4.193548387 10.000000000 10.985194151 13.754553905
+2.741935484 4.483870968 10.000000000 11.368962007 14.431095437
+2.741935484 4.774193548 10.000000000 11.913195856 15.489093970
+2.741935484 5.064516129 10.000000000 12.682234786 17.023032304
+2.741935484 5.354838710 10.000000000 13.342744072 18.155449447
+2.741935484 5.645161290 10.000000000 13.792466240 18.754193916
+2.741935484 5.935483871 10.000000000 14.130816184 19.125588403
+2.741935484 6.225806452 10.000000000 14.413282130 19.412900315
+2.741935484 6.516129032 10.000000000 14.658795531 19.658787254
+2.741935484 6.806451613 10.000000000 14.873037538 19.873037533
+2.741935484 7.096774194 10.000000000 15.000000000 20.000000000
+2.741935484 7.387096774 10.000000000 15.000000000 20.000000000
+2.741935484 7.677419355 10.000000000 15.000000000 20.000000000
+2.741935484 7.967741935 10.000000000 15.000000000 20.000000000
+2.741935484 8.258064516 10.000000000 15.000000000 20.000000000
+2.741935484 8.548387097 10.000000000 15.000000000 20.000000000
+2.741935484 8.838709677 10.000000000 15.000000000 20.000000000
+2.741935484 9.129032258 10.000000000 15.000000000 20.000000000
+2.741935484 9.419354839 10.000000000 15.000000000 20.000000000
+2.741935484 9.709677419 10.000000000 15.000000000 20.000000000
+2.741935484 10.000000000 10.000000000 15.000000000 20.000000000
+3.032258065 1.000000000 10.000000000 10.020564138 12.530362554
+3.032258065 1.290322581 10.000000000 10.020564138 12.530362554
+3.032258065 1.580645161 10.000000000 10.020564138 12.530362554
+3.032258065 1.870967742 10.000000000 10.020564138 12.530362554
+3.032258065 2.161290323 10.000000000 10.020564138 12.530362554
+3.032258065 2.451612903 10.000000000 10.020564138 12.530362554
+3.032258065 2.741935484 10.000000000 10.020564138 12.530362554
+3.032258065 3.032258065 10.000081623 10.040234008 12.549713610
+3.032258065 3.322580645 10.000845356 10.231330430 12.745817533
+3.032258065 3.612903226 10.001660504 10.447099078 12.988462480
+3.032258065 3.903225806 10.002536324 10.692131028 13.303660935
+3.032258065 4.193548387 10.003506957 10.984311315 13.746235339
+3.032258065 4.483870968 10.004651223 11.364421081 14.415312194
+3.032258065 4.774193548 10.006135391 11.906301747 15.468939718
+3.032258065 5.064516129 10.008304662 12.675977549 17.006125822
+3.032258065 5.354838710 10.010797104 13.339232540 18.145674121
+3.032258065 5.645161290 10.013072877 13.791275308 18.749121698
+3.032258065 5.935483871 10.014992751 14.131144375 19.123168222
+3.032258065 6.225806452 10.016597454 14.414457255 19.412112587
+3.032258065 6.516129032 10.018017808 14.660147444 19.658914932
+3.032258065 6.806451613 10.019388331 14.873835282 19.873347530
+3.032258065 7.096774194 10.020324537 15.000000000 20.000000000
+3.032258065 7.387096774 10.020324537 15.000000000 20.000000000
+3.032258065 7.677419355 10.020324537 15.000000000 20.000000000
+3.032258065 7.967741935 10.020324537 15.000000000 20.000000000
+3.032258065 8.258064516 10.020324537 15.000000000 20.000000000
+3.032258065 8.548387097 10.020324537 15.000000000 20.000000000
+3.032258065 8.838709677 10.020324537 15.000000000 20.000000000
+3.032258065 9.129032258 10.020324537 15.000000000 20.000000000
+3.032258065 9.419354839 10.020324537 15.000000000 20.000000000
+3.032258065 9.709677419 10.020324537 15.000000000 20.000000000
+3.032258065 10.000000000 10.020324537 15.000000000 20.000000000
+3.322580645 1.000000000 10.000000000 10.238526001 12.814657118
+3.322580645 1.290322581 10.000000000 10.238526001 12.814657118
+3.322580645 1.580645161 10.000000000 10.238526001 12.814657118
+3.322580645 1.870967742 10.000000000 10.238526001 12.814657118
+3.322580645 2.161290323 10.000000000 10.238526001 12.814657118
+3.322580645 2.451612903 10.000000000 10.238526001 12.814657118
+3.322580645 2.741935484 10.000000000 10.238526001 12.814657118
+3.322580645 3.032258065 10.000810912 10.252160009 12.825094452
+3.322580645 3.322580645 10.008475729 10.390248102 12.941315539
+3.322580645 3.612903226 10.016826559 10.556788308 13.106528324
+3.322580645 3.903225806 10.026007885 10.758435372 13.349926281
+3.322580645 4.193548387 10.036425250 11.014648689 13.729800083
+3.322580645 4.483870968 10.048985641 11.367796303 14.350555384
+3.322580645 4.774193548 10.065636239 11.895433538 15.382805064
+3.322580645 5.064516129 10.090431587 12.665305783 16.934330737
+3.322580645 5.354838710 10.119058291 13.330507836 18.087258535
+3.322580645 5.645161290 10.145318864 13.790875134 18.711237499
+3.322580645 5.935483871 10.167053939 14.138887104 19.103029349
+3.322580645 6.225806452 10.184333797 14.427106637 19.405311407
+3.322580645 6.516129032 10.198472326 14.672873177 19.660047640
+3.322580645 6.806451613 10.210901210 14.880935703 19.876073110
+3.322580645 7.096774194 10.218749520 15.000000005 20.000000000
+3.322580645 7.387096774 10.218749520 15.000000005 20.000000000
+3.322580645 7.677419355 10.218749520 15.000000005 20.000000000
+3.322580645 7.967741935 10.218749520 15.000000005 20.000000000
+3.322580645 8.258064516 10.218749520 15.000000005 20.000000000
+3.322580645 8.548387097 10.218749520 15.000000005 20.000000000
+3.322580645 8.838709677 10.218749520 15.000000005 20.000000000
+3.322580645 9.129032258 10.218749520 15.000000005 20.000000000
+3.322580645 9.419354839 10.218749520 15.000000005 20.000000000
+3.322580645 9.709677419 10.218749520 15.000000005 20.000000000
+3.322580645 10.000000000 10.218749520 15.000000005 20.000000000
+3.612903226 1.000000000 10.000000000 10.504908296 13.128455463
+3.612903226 1.290322581 10.000000000 10.504908296 13.128455463
+3.612903226 1.580645161 10.000000000 10.504908296 13.128455463
+3.612903226 1.870967742 10.000000000 10.504908296 13.128455463
+3.612903226 2.161290323 10.000000000 10.504908296 13.128455463
+3.612903226 2.451612903 10.000000000 10.504908296 13.128455463
+3.612903226 2.741935484 10.000000000 10.504908296 13.128455463
+3.612903226 3.032258065 10.001516539 10.512626733 13.130885405
+3.612903226 3.322580645 10.016001683 10.599926822 13.179304000
+3.612903226 3.612903226 10.032129555 10.721202126 13.285286198
+3.612903226 3.903225806 10.050319022 10.885336976 13.480541261
+3.612903226 4.193548387 10.071543600 11.114258924 13.827219367
+3.612903226 4.483870968 10.097850290 11.452875842 14.435424511
+3.612903226 4.774193548 10.133668269 11.980021902 15.481437354
+3.612903226 5.064516129 10.187198497 12.733746068 17.004065185
+3.612903226 5.354838710 10.247964197 13.361747553 18.081408199
+3.612903226 5.645161290 10.304036539 13.808753893 18.687360629
+3.612903226 5.935483871 10.350251618 14.155213729 19.086063787
+3.612903226 6.225806452 10.386088635 14.443553815 19.399366077
+3.612903226 6.516129032 10.413832571 14.686735031 19.661496202
+3.612903226 6.806451613 10.436235155 14.888005490 19.878875276
+3.612903226 7.096774194 10.449261329 15.000000885 20.000000000
+3.612903226 7.387096774 10.449261329 15.000000885 20.000000000
+3.612903226 7.677419355 10.449261329 15.000000885 20.000000000
+3.612903226 7.967741935 10.449261329 15.000000885 20.000000000
+3.612903226 8.258064516 10.449261329 15.000000885 20.000000000
+3.612903226 8.548387097 10.449261329 15.000000885 20.000000000
+3.612903226 8.838709677 10.449261329 15.000000885 20.000000000
+3.612903226 9.129032258 10.449261329 15.000000885 20.000000000
+3.612903226 9.419354839 10.449261329 15.000000885 20.000000000
+3.612903226 9.709677419 10.449261329 15.000000885 20.000000000
+3.612903226 10.000000000 10.449261329 15.000000885 20.000000000
+3.903225806 1.000000000 10.000000000 10.810170511 13.504826188
+3.903225806 1.290322581 10.000000000 10.810170511 13.504826188
+3.903225806 1.580645161 10.000000000 10.810170511 13.504826188
+3.903225806 1.870967742 10.000000000 10.810170511 13.504826188
+3.903225806 2.161290323 10.000000000 10.810170511 13.504826188
+3.903225806 2.451612903 10.000000000 10.810170511 13.504826188
+3.903225806 2.741935484 10.000000000 10.810170511 13.504826188
+3.903225806 3.032258065 10.002191475 10.812567996 13.499944985
+3.903225806 3.322580645 10.023341607 10.855521242 13.491036767
+3.903225806 3.612903226 10.047419391 10.939710572 13.555284598
+3.903225806 3.903225806 10.075341637 11.076302955 13.726499490
+3.903225806 4.193548387 10.108936013 11.290254243 14.070909786
+3.903225806 4.483870968 10.151939277 11.629038311 14.703300699
+3.903225806 4.774193548 10.212336488 12.166773063 15.791280803
+3.903225806 5.064516129 10.300093175 12.865867633 17.184787504
+3.903225806 5.354838710 10.397549799 13.425616094 18.115533442
+3.903225806 5.645161290 10.488260676 13.842905617 18.675012612
+3.903225806 5.935483871 10.563899084 14.179759717 19.072515315
+3.903225806 6.225806452 10.622764862 14.463818768 19.394943387
+3.903225806 6.516129032 10.667486100 14.701882692 19.663850989
+3.903225806 6.806451613 10.701911006 14.895189653 19.882050715
+3.903225806 7.096774194 10.721003908 15.000021130 20.000000000
+3.903225806 7.387096774 10.721003908 15.000021130 20.000000000
+3.903225806 7.677419355 10.721003908 15.000021130 20.000000000
+3.903225806 7.967741935 10.721003908 15.000021130 20.000000000
+3.903225806 8.258064516 10.721003908 15.000021130 20.000000000
+3.903225806 8.548387097 10.721003908 15.000021130 20.000000000
+3.903225806 8.838709677 10.721003908 15.000021130 20.000000000
+3.903225806 9.129032258 10.721003908 15.000021130 20.000000000
+3.903225806 9.419354839 10.721003908 15.000021130 20.000000000
+3.903225806 9.709677419 10.721003908 15.000021130 20.000000000
+3.903225806 10.000000000 10.721003908 15.000021130 20.000000000
+4.193548387 1.000000000 10.000000000 11.157523904 14.002629729
+4.193548387 1.290322581 10.000000000 11.157523904 14.002629729
+4.193548387 1.580645161 10.000000000 11.157523904 14.002629729
+4.193548387 1.870967742 10.000000000 11.157523904 14.002629729
+4.193548387 2.161290323 10.000000000 11.157523904 14.002629729
+4.193548387 2.451612903 10.000000000 11.157523904 14.002629729
+4.193548387 2.741935484 10.000000000 11.157523904 14.002629729
+4.193548387 3.032258065 10.002847967 11.155500895 13.991050173
+4.193548387 3.322580645 10.030611301 11.163431904 13.934544815
+4.193548387 3.612903226 10.062937365 11.222007768 13.974464175
+4.193548387 3.903225806 10.101503669 11.344539784 14.146530424
+4.193548387 4.193548387 10.149476613 11.558492423 14.519820638
+4.193548387 4.483870968 10.213067693 11.910494416 15.206102473
+4.193548387 4.774193548 10.304552071 12.447025439 16.305510232
+4.193548387 5.064516129 10.428253360 13.034623096 17.419899680
+4.193548387 5.354838710 10.564830507 13.510543286 18.168936315
+4.193548387 5.645161290 10.693996106 13.890105622 18.670596691
+4.193548387 5.935483871 10.804889687 14.211826878 19.062949046
+4.193548387 6.225806452 10.893985831 14.487804439 19.393012538
+4.193548387 6.516129032 10.963155502 14.718426145 19.667836719
+4.193548387 6.806451613 11.016887401 14.902672746 19.885926843
+4.193548387 7.096774194 11.047340520 15.000210546 20.000000000
+4.193548387 7.387096774 11.047340520 15.000210546 20.000000000
+4.193548387 7.677419355 11.047340520 15.000210546 20.000000000
+4.193548387 7.967741935 11.047340520 15.000210546 20.000000000
+4.193548387 8.258064516 11.047340520 15.000210546 20.000000000
+4.193548387 8.548387097 11.047340520 15.000210546 20.000000000
+4.193548387 8.838709677 11.047340520 15.000210546 20.000000000
+4.193548387 9.129032258 11.047340520 15.000210546 20.000000000
+4.193548387 9.419354839 11.047340520 15.000210546 20.000000000
+4.193548387 9.709677419 11.047340520 15.000210546 20.000000000
+4.193548387 10.000000000 11.047340520 15.000210546 20.000000000
+4.483870968 1.000000000 10.000000000 11.565284816 14.705763295
+4.483870968 1.290322581 10.000000000 11.565284816 14.705763295
+4.483870968 1.580645161 10.000000000 11.565284816 14.705763295
+4.483870968 1.870967742 10.000000000 11.565284816 14.705763295
+4.483870968 2.161290323 10.000000000 11.565284816 14.705763295
+4.483870968 2.451612903 10.000000000 11.565284816 14.705763295
+4.483870968 2.741935484 10.000000000 11.565284816 14.705763295
+4.483870968 3.032258065 10.003518332 11.559971097 14.688531488
+4.483870968 3.322580645 10.038148789 11.544067577 14.596697135
+4.483870968 3.612903226 10.079373052 11.590123754 14.630573226
+4.483870968 3.903225806 10.129999142 11.712651674 14.826642427
+4.483870968 4.193548387 10.195142637 11.937986529 15.249393001
+4.483870968 4.483870968 10.284538090 12.299658730 15.978123106
+4.483870968 4.774193548 10.407288688 12.751308571 16.856785744
+4.483870968 5.064516129 10.566265451 13.210391988 17.648137186
+4.483870968 5.354838710 10.742013612 13.605608156 18.224568495
+4.483870968 5.645161290 10.912944832 13.947123303 18.672577283
+4.483870968 5.935483871 11.066669588 14.250519401 19.058798213
+4.483870968 6.225806452 11.197095817 14.515307747 19.394892563
+4.483870968 6.516129032 11.303930141 14.736513059 19.674293402
+4.483870968 6.806451613 11.391719855 14.910904783 19.890847813
+4.483870968 7.096774194 11.445068797 15.001284580 20.000000000
+4.483870968 7.387096774 11.445068797 15.001284580 20.000000000
+4.483870968 7.677419355 11.445068797 15.001284580 20.000000000
+4.483870968 7.967741935 11.445068797 15.001284580 20.000000000
+4.483870968 8.258064516 11.445068797 15.001284580 20.000000000
+4.483870968 8.548387097 11.445068797 15.001284580 20.000000000
+4.483870968 8.838709677 11.445068797 15.001284580 20.000000000
+4.483870968 9.129032258 11.445068797 15.001284580 20.000000000
+4.483870968 9.419354839 11.445068797 15.001284580 20.000000000
+4.483870968 9.709677419 11.445068797 15.001284580 20.000000000
+4.483870968 10.000000000 11.445068797 15.001284580 20.000000000
+4.774193548 1.000000000 10.000000000 12.058980464 15.701021693
+4.774193548 1.290322581 10.000000000 12.058980464 15.701021693
+4.774193548 1.580645161 10.000000000 12.058980464 15.701021693
+4.774193548 1.870967742 10.000000000 12.058980464 15.701021693
+4.774193548 2.161290323 10.000000000 12.058980464 15.701021693
+4.774193548 2.451612903 10.000000000 12.058980464 15.701021693
+4.774193548 2.741935484 10.000000000 12.058980464 15.701021693
+4.774193548 3.032258065 10.004257800 12.051831158 15.680761274
+4.774193548 3.322580645 10.046560497 12.024384078 15.574111451
+4.774193548 3.612903226 10.098020591 12.068331239 15.617253641
+4.774193548 3.903225806 10.163026519 12.195621174 15.840037790
+4.774193548 4.193548387 10.248842025 12.415213380 16.258998150
+4.774193548 4.483870968 10.362811901 12.699044498 16.776643149
+4.774193548 4.774193548 10.512690124 13.024422676 17.317616013
+4.774193548 5.064516129 10.703263743 13.373149036 17.833118921
+4.774193548 5.354838710 10.916444195 13.703982825 18.277985683
+4.774193548 5.645161290 11.132588599 14.011409556 18.683389813
+4.774193548 5.935483871 11.338852711 14.294853866 19.062628031
+4.774193548 6.225806452 11.526117376 14.546111577 19.402210670
+4.774193548 6.516129032 11.690681294 14.756568825 19.684098329
+4.774193548 6.806451613 11.836523788 14.921219044 19.897134924
+4.774193548 7.096774194 11.931844472 15.005712815 20.000000000
+4.774193548 7.387096774 11.931844472 15.005712815 20.000000000
+4.774193548 7.677419355 11.931844472 15.005712815 20.000000000
+4.774193548 7.967741935 11.931844472 15.005712815 20.000000000
+4.774193548 8.258064516 11.931844472 15.005712815 20.000000000
+4.774193548 8.548387097 11.931844472 15.005712815 20.000000000
+4.774193548 8.838709677 11.931844472 15.005712815 20.000000000
+4.774193548 9.129032258 11.931844472 15.005712815 20.000000000
+4.774193548 9.419354839 11.931844472 15.005712815 20.000000000
+4.774193548 9.709677419 11.931844472 15.005712815 20.000000000
+4.774193548 10.000000000 11.931844472 15.005712815 20.000000000
+5.064516129 1.000000000 10.000000000 12.621619769 16.933368673
+5.064516129 1.290322581 10.000000000 12.621619769 16.933368673
+5.064516129 1.580645161 10.000000000 12.621619769 16.933368673
+5.064516129 1.870967742 10.000000000 12.621619769 16.933368673
+5.064516129 2.161290323 10.000000000 12.621619769 16.933368673
+5.064516129 2.451612903 10.000000000 12.621619769 16.933368673
+5.064516129 2.741935484 10.000000000 12.621619769 16.933368673
+5.064516129 3.032258065 10.005146712 12.614366006 16.914980770
+5.064516129 3.322580645 10.056698295 12.581893441 16.810593662
+5.064516129 3.612903226 10.120169544 12.609005731 16.817436387
+5.064516129 3.903225806 10.200300484 12.693292869 16.924650571
+5.064516129 4.193548387 10.303330308 12.829792446 17.110642790
+5.064516129 4.483870968 10.436761057 13.013559654 17.353140381
+5.064516129 4.774193548 10.608584137 13.242465682 17.640746773
+5.064516129 5.064516129 10.825065934 13.517238305 17.978395774
+5.064516129 5.354838710 11.073354364 13.802678770 18.337797480
+5.064516129 5.645161290 11.338339319 14.080820782 18.709018123
+5.064516129 5.935483871 11.608136235 14.343723093 19.077915408
+5.064516129 6.225806452 11.871234576 14.580152615 19.416716601
+5.064516129 6.516129032 12.120142764 14.779818162 19.698008481
+5.064516129 6.806451613 12.357520482 14.937194312 19.905017104
+5.064516129 7.096774194 12.521102945 15.020319196 20.000000000
+5.064516129 7.387096774 12.521102945 15.020319196 20.000000000
+5.064516129 7.677419355 12.521102945 15.020319196 20.000000000
+5.064516129 7.967741935 12.521102945 15.020319196 20.000000000
+5.064516129 8.258064516 12.521102945 15.020319196 20.000000000
+5.064516129 8.548387097 12.521102945 15.020319196 20.000000000
+5.064516129 8.838709677 12.521102945 15.020319196 20.000000000
+5.064516129 9.129032258 12.521102945 15.020319196 20.000000000
+5.064516129 9.419354839 12.521102945 15.020319196 20.000000000
+5.064516129 9.709677419 12.521102945 15.020319196 20.000000000
+5.064516129 10.000000000 12.521102945 15.020319196 20.000000000
+5.354838710 1.000000000 10.000000000 13.013861899 17.722526667
+5.354838710 1.290322581 10.000000000 13.013861899 17.722526667
+5.354838710 1.580645161 10.000000000 13.013861899 17.722526667
+5.354838710 1.870967742 10.000000000 13.013861899 17.722526667
+5.354838710 2.161290323 10.000000000 13.013861899 17.722526667
+5.354838710 2.451612903 10.000000000 13.013861899 17.722526667
+5.354838710 2.741935484 10.000000000 13.013861899 17.722526667
+5.354838710 3.032258065 10.006014949 13.006869691 17.706851286
+5.354838710 3.322580645 10.066342933 12.965471340 17.593850801
+5.354838710 3.612903226 10.140231454 12.964403129 17.534521084
+5.354838710 3.903225806 10.232270564 13.004888418 17.529033919
+5.354838710 4.193548387 10.348580620 13.088107989 17.575956320
+5.354838710 4.483870968 10.496818921 13.216786998 17.677894459
+5.354838710 4.774193548 10.686051524 13.396186129 17.845882749
+5.354838710 5.064516129 10.925829268 13.632559211 18.099001135
+5.354838710 5.354838710 11.209919760 13.890101018 18.408558307
+5.354838710 5.645161290 11.528570742 14.146225018 18.751087862
+5.354838710 5.935483871 11.872594688 14.391880702 19.105790086
+5.354838710 6.225806452 12.230155222 14.615966067 19.439094903
+5.354838710 6.516129032 12.591079681 14.808684323 19.716275926
+5.354838710 6.806451613 12.955941737 14.967165018 19.914536590
+5.354838710 7.096774194 13.214762751 15.060950730 20.000000000
+5.354838710 7.387096774 13.214762751 15.060950730 20.000000000
+5.354838710 7.677419355 13.214762751 15.060950730 20.000000000
+5.354838710 7.967741935 13.214762751 15.060950730 20.000000000
+5.354838710 8.258064516 13.214762751 15.060950730 20.000000000
+5.354838710 8.548387097 13.214762751 15.060950730 20.000000000
+5.354838710 8.838709677 13.214762751 15.060950730 20.000000000
+5.354838710 9.129032258 13.214762751 15.060950730 20.000000000
+5.354838710 9.419354839 13.214762751 15.060950730 20.000000000
+5.354838710 9.709677419 13.214762751 15.060950730 20.000000000
+5.354838710 10.000000000 13.214762751 15.060950730 20.000000000
+5.645161290 1.000000000 10.000000000 13.244783448 18.109489138
+5.645161290 1.290322581 10.000000000 13.244783448 18.109489138
+5.645161290 1.580645161 10.000000000 13.244783448 18.109489138
+5.645161290 1.870967742 10.000000000 13.244783448 18.109489138
+5.645161290 2.161290323 10.000000000 13.244783448 18.109489138
+5.645161290 2.451612903 10.000000000 13.244783448 18.109489138
+5.645161290 2.741935484 10.000000000 13.244783448 18.109489138
+5.645161290 3.032258065 10.006766298 13.237774154 18.095072669
+5.645161290 3.322580645 10.074459191 13.190872866 17.979911424
+5.645161290 3.612903226 10.156682138 13.175344657 17.894934931
+5.645161290 3.903225806 10.257906448 13.194481414 17.845569901
+5.645161290 4.193548387 10.384363399 13.252314383 17.838705930
+5.645161290 4.483870968 10.544408861 13.354390862 17.885141400
+5.645161290 4.774193548 10.749033088 13.508424871 18.001992097
+5.645161290 5.064516129 11.011983915 13.723146199 18.212857917
+5.645161290 5.354838710 11.333589940 13.962485123 18.489219169
+5.645161290 5.645161290 11.710068477 14.202955697 18.806280615
+5.645161290 5.935483871 12.136994407 14.436640443 19.144415713
+5.645161290 6.225806452 12.604720729 14.654339717 19.468510328
+5.645161290 6.516129032 13.101632560 14.849606989 19.738417145
+5.645161290 6.806451613 13.623727732 15.028577014 19.925489144
+5.645161290 7.096774194 13.996146922 15.158825640 20.000000000
+5.645161290 7.387096774 13.996146922 15.158825640 20.000000000
+5.645161290 7.677419355 13.996146922 15.158825640 20.000000000
+5.645161290 7.967741935 13.996146922 15.158825640 20.000000000
+5.645161290 8.258064516 13.996146922 15.158825640 20.000000000
+5.645161290 8.548387097 13.996146922 15.158825640 20.000000000
+5.645161290 8.838709677 13.996146922 15.158825640 20.000000000
+5.645161290 9.129032258 13.996146922 15.158825640 20.000000000
+5.645161290 9.419354839 13.996146922 15.158825640 20.000000000
+5.645161290 9.709677419 13.996146922 15.158825640 20.000000000
+5.645161290 10.000000000 13.996146922 15.158825640 20.000000000
+5.935483871 1.000000000 10.000000000 13.401208666 18.333970891
+5.935483871 1.290322581 10.000000000 13.401208666 18.333970891
+5.935483871 1.580645161 10.000000000 13.401208666 18.333970891
+5.935483871 1.870967742 10.000000000 13.401208666 18.333970891
+5.935483871 2.161290323 10.000000000 13.401208666 18.333970891
+5.935483871 2.451612903 10.000000000 13.401208666 18.333970891
+5.935483871 2.741935484 10.000000000 13.401208666 18.333970891
+5.935483871 3.032258065 10.007443801 13.394073286 18.320194702
+5.935483871 3.322580645 10.081521395 13.343529838 18.205985651
+5.935483871 3.612903226 10.170606472 13.320092774 18.113408216
+5.935483871 3.903225806 10.279237154 13.327710961 18.049128779
+5.935483871 4.193548387 10.414061629 13.371284478 18.021975049
+5.935483871 4.483870968 10.584551085 13.457309453 18.044566871
+5.935483871 4.774193548 10.804081039 13.594715896 18.135620170
+5.935483871 5.064516129 11.090993693 13.794308290 18.321130673
+5.935483871 5.354838710 11.452089024 14.020655377 18.573380719
+5.935483871 5.645161290 11.890263995 14.250754084 18.868697334
+5.935483871 5.935483871 12.407459638 14.478989354 19.190114288
+5.935483871 6.225806452 12.997671406 14.700310557 19.502878399
+5.935483871 6.516129032 13.647127791 14.916608672 19.763270216
+5.935483871 6.806451613 14.340979512 15.153493506 19.937484405
+5.935483871 7.096774194 14.827685905 15.364218694 20.000000000
+5.935483871 7.387096774 14.827685905 15.364218694 20.000000000
+5.935483871 7.677419355 14.827685905 15.364218694 20.000000000
+5.935483871 7.967741935 14.827685905 15.364218694 20.000000000
+5.935483871 8.258064516 14.827685905 15.364218694 20.000000000
+5.935483871 8.548387097 14.827685905 15.364218694 20.000000000
+5.935483871 8.838709677 14.827685905 15.364218694 20.000000000
+5.935483871 9.129032258 14.827685905 15.364218694 20.000000000
+5.935483871 9.419354839 14.827685905 15.364218694 20.000000000
+5.935483871 9.709677419 14.827685905 15.364218694 20.000000000
+5.935483871 10.000000000 14.827685905 15.364218694 20.000000000
+6.225806452 1.000000000 10.000000000 13.521407226 18.490281826
+6.225806452 1.290322581 10.000000000 13.521407226 18.490281826
+6.225806452 1.580645161 10.000000000 13.521407226 18.490281826
+6.225806452 1.870967742 10.000000000 13.521407226 18.490281826
+6.225806452 2.161290323 10.000000000 13.521407226 18.490281826
+6.225806452 2.451612903 10.000000000 13.521407226 18.490281826
+6.225806452 2.741935484 10.000000000 13.521407226 18.490281826
+6.225806452 3.032258065 10.008103023 13.514140641 18.476969515
+6.225806452 3.322580645 10.088153003 13.460835310 18.364877707
+6.225806452 3.612903226 10.183352044 13.431824922 18.270567249
+6.225806452 3.903225806 10.298530841 13.431203100 18.200721216
+6.225806452 4.193548387 10.441056619 13.464145973 18.164351799
+6.225806452 4.483870968 10.621870428 13.537643724 18.174340531
+6.225806452 4.774193548 10.857112400 13.661628176 18.249929499
+6.225806452 5.064516129 11.170105930 13.849038003 18.418640731
+6.225806452 5.354838710 11.574291401 14.066015685 18.653507307
+6.225806452 5.645161290 12.079699400 14.291251628 18.931644662
+6.225806452 5.935483871 12.694889781 14.523401908 19.238162865
+6.225806452 6.225806452 13.416217710 14.765821293 19.539326380
+6.225806452 6.516129032 14.222918735 15.036827937 19.789435643
+6.225806452 6.806451613 15.078771212 15.391913006 19.950218302
+6.225806452 7.096774194 15.657216132 15.735413612 20.000000000
+6.225806452 7.387096774 15.657216132 15.735413612 20.000000000
+6.225806452 7.677419355 15.657216132 15.735413612 20.000000000
+6.225806452 7.967741935 15.657216132 15.735413612 20.000000000
+6.225806452 8.258064516 15.657216132 15.735413612 20.000000000
+6.225806452 8.548387097 15.657216132 15.735413612 20.000000000
+6.225806452 8.838709677 15.657216132 15.735413612 20.000000000
+6.225806452 9.129032258 15.657216132 15.735413612 20.000000000
+6.225806452 9.419354839 15.657216132 15.735413612 20.000000000
+6.225806452 9.709677419 15.657216132 15.735413612 20.000000000
+6.225806452 10.000000000 15.657216132 15.735413612 20.000000000
+6.516129032 1.000000000 10.000000000 13.619720941 18.608806194
+6.516129032 1.290322581 10.000000000 13.619720941 18.608806194
+6.516129032 1.580645161 10.000000000 13.619720941 18.608806194
+6.516129032 1.870967742 10.000000000 13.619720941 18.608806194
+6.516129032 2.161290323 10.000000000 13.619720941 18.608806194
+6.516129032 2.451612903 10.000000000 13.619720941 18.608806194
+6.516129032 2.741935484 10.000000000 13.619720941 18.608806194
+6.516129032 3.032258065 10.008796065 13.612346679 18.595858277
+6.516129032 3.322580645 10.094914486 13.556805241 18.485913330
+6.516129032 3.612903226 10.196067943 13.523172782 18.391481322
+6.516129032 3.903225806 10.317633610 13.515503749 18.319021613
+6.516129032 4.193548387 10.468057112 13.539104368 18.277428362
+6.516129032 4.483870968 10.660217177 13.601388696 18.279576799
+6.516129032 4.774193548 10.913601861 13.713341965 18.344952152
+6.516129032 5.064516129 11.257202098 13.890353256 18.502068098
+6.516129032 5.354838710 11.711560991 14.101549313 18.724649911
+6.516129032 5.645161290 12.293650185 14.329635734 18.990008501
+6.516129032 5.935483871 13.016511933 14.581790143 19.284476712
+6.516129032 6.225806452 13.873035372 14.877229146 19.575567933
+6.516129032 6.516129032 14.825313064 15.258980220 19.816607913
+6.516129032 6.806451613 15.804467725 15.803140508 19.963873617
+6.516129032 7.096774194 16.431600988 16.299972993 20.000000000
+6.516129032 7.387096774 16.431600988 16.299972993 20.000000000
+6.516129032 7.677419355 16.431600988 16.299972993 20.000000000
+6.516129032 7.967741935 16.431600988 16.299972993 20.000000000
+6.516129032 8.258064516 16.431600988 16.299972993 20.000000000
+6.516129032 8.548387097 16.431600988 16.299972993 20.000000000
+6.516129032 8.838709677 16.431600988 16.299972993 20.000000000
+6.516129032 9.129032258 16.431600988 16.299972993 20.000000000
+6.516129032 9.419354839 16.431600988 16.299972993 20.000000000
+6.516129032 9.709677419 16.431600988 16.299972993 20.000000000
+6.516129032 10.000000000 16.431600988 16.299972993 20.000000000
+6.806451613 1.000000000 10.000000000 13.702140588 18.700568553
+6.806451613 1.290322581 10.000000000 13.702140588 18.700568553
+6.806451613 1.580645161 10.000000000 13.702140588 18.700568553
+6.806451613 1.870967742 10.000000000 13.702140588 18.700568553
+6.806451613 2.161290323 10.000000000 13.702140588 18.700568553
+6.806451613 2.451612903 10.000000000 13.702140588 18.700568553
+6.806451613 2.741935484 10.000000000 13.702140588 18.700568553
+6.806451613 3.032258065 10.009566877 13.694695654 18.687889031
+6.806451613 3.322580645 10.102239226 13.637457673 18.579757963
+6.806451613 3.612903226 10.209597091 13.599971487 18.485773947
+6.806451613 3.903225806 10.337931790 13.586088799 18.412087907
+6.806451613 4.193548387 10.497359572 13.601147106 18.367393881
+6.806451613 4.483870968 10.703550229 13.652988131 18.364466144
+6.806451613 4.774193548 10.980458810 13.753895322 18.422857042
+6.806451613 5.064516129 11.363992774 13.922588347 18.571664806
+6.806451613 5.354838710 11.882332702 14.133990028 18.785431300
+6.806451613 5.645161290 12.557491974 14.380014720 19.041563761
+6.806451613 5.935483871 13.400370731 14.684815949 19.327600979
+6.806451613 6.225806452 14.388065262 15.092179113 19.613100661
+6.806451613 6.516129032 15.452078155 15.660637661 19.848761837
+6.806451613 6.806451613 16.488227443 16.421596031 19.978526735
+6.806451613 7.096774194 17.110750392 17.007626023 20.000000000
+6.806451613 7.387096774 17.110750392 17.007626023 20.000000000
+6.806451613 7.677419355 17.110750392 17.007626023 20.000000000
+6.806451613 7.967741935 17.110750392 17.007626023 20.000000000
+6.806451613 8.258064516 17.110750392 17.007626023 20.000000000
+6.806451613 8.548387097 17.110750392 17.007626023 20.000000000
+6.806451613 8.838709677 17.110750392 17.007626023 20.000000000
+6.806451613 9.129032258 17.110750392 17.007626023 20.000000000
+6.806451613 9.419354839 17.110750392 17.007626023 20.000000000
+6.806451613 9.709677419 17.110750392 17.007626023 20.000000000
+6.806451613 10.000000000 17.110750392 17.007626023 20.000000000
+7.096774194 1.000000000 10.000000000 13.750000000 18.750000000
+7.096774194 1.290322581 10.000000000 13.750000000 18.750000000
+7.096774194 1.580645161 10.000000000 13.750000000 18.750000000
+7.096774194 1.870967742 10.000000000 13.750000000 18.750000000
+7.096774194 2.161290323 10.000000000 13.750000000 18.750000000
+7.096774194 2.451612903 10.000000000 13.750000000 18.750000000
+7.096774194 2.741935484 10.000000000 13.750000000 18.750000000
+7.096774194 3.032258065 10.010142154 13.742536520 18.737455859
+7.096774194 3.322580645 10.107593677 13.684557246 18.630423796
+7.096774194 3.612903226 10.219378581 13.645030600 18.537086952
+7.096774194 3.903225806 10.352768137 13.627557695 18.463319088
+7.096774194 4.193548387 10.519625429 13.637427439 18.417599484
+7.096774194 4.483870968 10.738408418 13.682818578 18.412535791
+7.096774194 4.774193548 11.037217342 13.777278068 18.467583744
+7.096774194 5.064516129 11.457663040 13.943032824 18.612009655
+7.096774194 5.354838710 12.032834518 14.162291151 18.821124666
+7.096774194 5.645161290 12.784673825 14.439131521 19.073000135
+7.096774194 5.935483871 13.714623381 14.815969959 19.357395690
+7.096774194 6.225806452 14.778744019 15.350155064 19.645850060
+7.096774194 6.516129032 15.883198672 16.075414380 19.878699414
+7.096774194 6.806451613 16.909538446 16.932414748 19.986611801
+7.096774194 7.096774194 17.500000000 17.500000000 20.000000000
+7.096774194 7.387096774 17.500000000 17.500000000 20.000000000
+7.096774194 7.677419355 17.500000000 17.500000000 20.000000000
+7.096774194 7.967741935 17.500000000 17.500000000 20.000000000
+7.096774194 8.258064516 17.500000000 17.500000000 20.000000000
+7.096774194 8.548387097 17.500000000 17.500000000 20.000000000
+7.096774194 8.838709677 17.500000000 17.500000000 20.000000000
+7.096774194 9.129032258 17.500000000 17.500000000 20.000000000
+7.096774194 9.419354839 17.500000000 17.500000000 20.000000000
+7.096774194 9.709677419 17.500000000 17.500000000 20.000000000
+7.096774194 10.000000000 17.500000000 17.500000000 20.000000000
+7.387096774 1.000000000 10.000000000 13.750000000 18.750000000
+7.387096774 1.290322581 10.000000000 13.750000000 18.750000000
+7.387096774 1.580645161 10.000000000 13.750000000 18.750000000
+7.387096774 1.870967742 10.000000000 13.750000000 18.750000000
+7.387096774 2.161290323 10.000000000 13.750000000 18.750000000
+7.387096774 2.451612903 10.000000000 13.750000000 18.750000000
+7.387096774 2.741935484 10.000000000 13.750000000 18.750000000
+7.387096774 3.032258065 10.010142154 13.742536520 18.737455859
+7.387096774 3.322580645 10.107593677 13.684557246 18.630423796
+7.387096774 3.612903226 10.219378581 13.645030600 18.537086952
+7.387096774 3.903225806 10.352768137 13.627557695 18.463319088
+7.387096774 4.193548387 10.519625429 13.637427439 18.417599484
+7.387096774 4.483870968 10.738408418 13.682818578 18.412535791
+7.387096774 4.774193548 11.037217342 13.777278068 18.467583744
+7.387096774 5.064516129 11.457663040 13.943032824 18.612009655
+7.387096774 5.354838710 12.032834518 14.162291151 18.821124666
+7.387096774 5.645161290 12.784673825 14.439131521 19.073000135
+7.387096774 5.935483871 13.714623381 14.815969959 19.357395690
+7.387096774 6.225806452 14.778744019 15.350155064 19.645850060
+7.387096774 6.516129032 15.883198672 16.075414380 19.878699414
+7.387096774 6.806451613 16.909538446 16.932414748 19.986611801
+7.387096774 7.096774194 17.500000000 17.500000000 20.000000000
+7.387096774 7.387096774 17.500000000 17.500000000 20.000000000
+7.387096774 7.677419355 17.500000000 17.500000000 20.000000000
+7.387096774 7.967741935 17.500000000 17.500000000 20.000000000
+7.387096774 8.258064516 17.500000000 17.500000000 20.000000000
+7.387096774 8.548387097 17.500000000 17.500000000 20.000000000
+7.387096774 8.838709677 17.500000000 17.500000000 20.000000000
+7.387096774 9.129032258 17.500000000 17.500000000 20.000000000
+7.387096774 9.419354839 17.500000000 17.500000000 20.000000000
+7.387096774 9.709677419 17.500000000 17.500000000 20.000000000
+7.387096774 10.000000000 17.500000000 17.500000000 20.000000000
+7.677419355 1.000000000 10.000000000 13.750000000 18.750000000
+7.677419355 1.290322581 10.000000000 13.750000000 18.750000000
+7.677419355 1.580645161 10.000000000 13.750000000 18.750000000
+7.677419355 1.870967742 10.000000000 13.750000000 18.750000000
+7.677419355 2.161290323 10.000000000 13.750000000 18.750000000
+7.677419355 2.451612903 10.000000000 13.750000000 18.750000000
+7.677419355 2.741935484 10.000000000 13.750000000 18.750000000
+7.677419355 3.032258065 10.010142154 13.742536520 18.737455859
+7.677419355 3.322580645 10.107593677 13.684557246 18.630423796
+7.677419355 3.612903226 10.219378581 13.645030600 18.537086952
+7.677419355 3.903225806 10.352768137 13.627557695 18.463319088
+7.677419355 4.193548387 10.519625429 13.637427439 18.417599484
+7.677419355 4.483870968 10.738408418 13.682818578 18.412535791
+7.677419355 4.774193548 11.037217342 13.777278068 18.467583744
+7.677419355 5.064516129 11.457663040 13.943032824 18.612009655
+7.677419355 5.354838710 12.032834518 14.162291151 18.821124666
+7.677419355 5.645161290 12.784673825 14.439131521 19.073000135
+7.677419355 5.935483871 13.714623381 14.815969959 19.357395690
+7.677419355 6.225806452 14.778744019 15.350155064 19.645850060
+7.677419355 6.516129032 15.883198672 16.075414380 19.878699414
+7.677419355 6.806451613 16.909538446 16.932414748 19.986611801
+7.677419355 7.096774194 17.500000000 17.500000000 20.000000000
+7.677419355 7.387096774 17.500000000 17.500000000 20.000000000
+7.677419355 7.677419355 17.500000000 17.500000000 20.000000000
+7.677419355 7.967741935 17.500000000 17.500000000 20.000000000
+7.677419355 8.258064516 17.500000000 17.500000000 20.000000000
+7.677419355 8.548387097 17.500000000 17.500000000 20.000000000
+7.677419355 8.838709677 17.500000000 17.500000000 20.000000000
+7.677419355 9.129032258 17.500000000 17.500000000 20.000000000
+7.677419355 9.419354839 17.500000000 17.500000000 20.000000000
+7.677419355 9.709677419 17.500000000 17.500000000 20.000000000
+7.677419355 10.000000000 17.500000000 17.500000000 20.000000000
+7.967741935 1.000000000 10.000000000 13.750000000 18.750000000
+7.967741935 1.290322581 10.000000000 13.750000000 18.750000000
+7.967741935 1.580645161 10.000000000 13.750000000 18.750000000
+7.967741935 1.870967742 10.000000000 13.750000000 18.750000000
+7.967741935 2.161290323 10.000000000 13.750000000 18.750000000
+7.967741935 2.451612903 10.000000000 13.750000000 18.750000000
+7.967741935 2.741935484 10.000000000 13.750000000 18.750000000
+7.967741935 3.032258065 10.010142154 13.742536520 18.737455859
+7.967741935 3.322580645 10.107593677 13.684557246 18.630423796
+7.967741935 3.612903226 10.219378581 13.645030600 18.537086952
+7.967741935 3.903225806 10.352768137 13.627557695 18.463319088
+7.967741935 4.193548387 10.519625429 13.637427439 18.417599484
+7.967741935 4.483870968 10.738408418 13.682818578 18.412535791
+7.967741935 4.774193548 11.037217342 13.777278068 18.467583744
+7.967741935 5.064516129 11.457663040 13.943032824 18.612009655
+7.967741935 5.354838710 12.032834518 14.162291151 18.821124666
+7.967741935 5.645161290 12.784673825 14.439131521 19.073000135
+7.967741935 5.935483871 13.714623381 14.815969959 19.357395690
+7.967741935 6.225806452 14.778744019 15.350155064 19.645850060
+7.967741935 6.516129032 15.883198672 16.075414380 19.878699414
+7.967741935 6.806451613 16.909538446 16.932414748 19.986611801
+7.967741935 7.096774194 17.500000000 17.500000000 20.000000000
+7.967741935 7.387096774 17.500000000 17.500000000 20.000000000
+7.967741935 7.677419355 17.500000000 17.500000000 20.000000000
+7.967741935 7.967741935 17.500000000 17.500000000 20.000000000
+7.967741935 8.258064516 17.500000000 17.500000000 20.000000000
+7.967741935 8.548387097 17.500000000 17.500000000 20.000000000
+7.967741935 8.838709677 17.500000000 17.500000000 20.000000000
+7.967741935 9.129032258 17.500000000 17.500000000 20.000000000
+7.967741935 9.419354839 17.500000000 17.500000000 20.000000000
+7.967741935 9.709677419 17.500000000 17.500000000 20.000000000
+7.967741935 10.000000000 17.500000000 17.500000000 20.000000000
+8.258064516 1.000000000 10.000000000 13.750000000 18.750000000
+8.258064516 1.290322581 10.000000000 13.750000000 18.750000000
+8.258064516 1.580645161 10.000000000 13.750000000 18.750000000
+8.258064516 1.870967742 10.000000000 13.750000000 18.750000000
+8.258064516 2.161290323 10.000000000 13.750000000 18.750000000
+8.258064516 2.451612903 10.000000000 13.750000000 18.750000000
+8.258064516 2.741935484 10.000000000 13.750000000 18.750000000
+8.258064516 3.032258065 10.010142154 13.742536520 18.737455859
+8.258064516 3.322580645 10.107593677 13.684557246 18.630423796
+8.258064516 3.612903226 10.219378581 13.645030600 18.537086952
+8.258064516 3.903225806 10.352768137 13.627557695 18.463319088
+8.258064516 4.193548387 10.519625429 13.637427439 18.417599484
+8.258064516 4.483870968 10.738408418 13.682818578 18.412535791
+8.258064516 4.774193548 11.037217342 13.777278068 18.467583744
+8.258064516 5.064516129 11.457663040 13.943032824 18.612009655
+8.258064516 5.354838710 12.032834518 14.162291151 18.821124666
+8.258064516 5.645161290 12.784673825 14.439131521 19.073000135
+8.258064516 5.935483871 13.714623381 14.815969959 19.357395690
+8.258064516 6.225806452 14.778744019 15.350155064 19.645850060
+8.258064516 6.516129032 15.883198672 16.075414380 19.878699414
+8.258064516 6.806451613 16.909538446 16.932414748 19.986611801
+8.258064516 7.096774194 17.500000000 17.500000000 20.000000000
+8.258064516 7.387096774 17.500000000 17.500000000 20.000000000
+8.258064516 7.677419355 17.500000000 17.500000000 20.000000000
+8.258064516 7.967741935 17.500000000 17.500000000 20.000000000
+8.258064516 8.258064516 17.500000000 17.500000000 20.000000000
+8.258064516 8.548387097 17.500000000 17.500000000 20.000000000
+8.258064516 8.838709677 17.500000000 17.500000000 20.000000000
+8.258064516 9.129032258 17.500000000 17.500000000 20.000000000
+8.258064516 9.419354839 17.500000000 17.500000000 20.000000000
+8.258064516 9.709677419 17.500000000 17.500000000 20.000000000
+8.258064516 10.000000000 17.500000000 17.500000000 20.000000000
+8.548387097 1.000000000 10.000000000 13.750000000 18.750000000
+8.548387097 1.290322581 10.000000000 13.750000000 18.750000000
+8.548387097 1.580645161 10.000000000 13.750000000 18.750000000
+8.548387097 1.870967742 10.000000000 13.750000000 18.750000000
+8.548387097 2.161290323 10.000000000 13.750000000 18.750000000
+8.548387097 2.451612903 10.000000000 13.750000000 18.750000000
+8.548387097 2.741935484 10.000000000 13.750000000 18.750000000
+8.548387097 3.032258065 10.010142154 13.742536520 18.737455859
+8.548387097 3.322580645 10.107593677 13.684557246 18.630423796
+8.548387097 3.612903226 10.219378581 13.645030600 18.537086952
+8.548387097 3.903225806 10.352768137 13.627557695 18.463319088
+8.548387097 4.193548387 10.519625429 13.637427439 18.417599484
+8.548387097 4.483870968 10.738408418 13.682818578 18.412535791
+8.548387097 4.774193548 11.037217342 13.777278068 18.467583744
+8.548387097 5.064516129 11.457663040 13.943032824 18.612009655
+8.548387097 5.354838710 12.032834518 14.162291151 18.821124666
+8.548387097 5.645161290 12.784673825 14.439131521 19.073000135
+8.548387097 5.935483871 13.714623381 14.815969959 19.357395690
+8.548387097 6.225806452 14.778744019 15.350155064 19.645850060
+8.548387097 6.516129032 15.883198672 16.075414380 19.878699414
+8.548387097 6.806451613 16.909538446 16.932414748 19.986611801
+8.548387097 7.096774194 17.500000000 17.500000000 20.000000000
+8.548387097 7.387096774 17.500000000 17.500000000 20.000000000
+8.548387097 7.677419355 17.500000000 17.500000000 20.000000000
+8.548387097 7.967741935 17.500000000 17.500000000 20.000000000
+8.548387097 8.258064516 17.500000000 17.500000000 20.000000000
+8.548387097 8.548387097 17.500000000 17.500000000 20.000000000
+8.548387097 8.838709677 17.500000000 17.500000000 20.000000000
+8.548387097 9.129032258 17.500000000 17.500000000 20.000000000
+8.548387097 9.419354839 17.500000000 17.500000000 20.000000000
+8.548387097 9.709677419 17.500000000 17.500000000 20.000000000
+8.548387097 10.000000000 17.500000000 17.500000000 20.000000000
+8.838709677 1.000000000 10.000000000 13.750000000 18.750000000
+8.838709677 1.290322581 10.000000000 13.750000000 18.750000000
+8.838709677 1.580645161 10.000000000 13.750000000 18.750000000
+8.838709677 1.870967742 10.000000000 13.750000000 18.750000000
+8.838709677 2.161290323 10.000000000 13.750000000 18.750000000
+8.838709677 2.451612903 10.000000000 13.750000000 18.750000000
+8.838709677 2.741935484 10.000000000 13.750000000 18.750000000
+8.838709677 3.032258065 10.010142154 13.742536520 18.737455859
+8.838709677 3.322580645 10.107593677 13.684557246 18.630423796
+8.838709677 3.612903226 10.219378581 13.645030600 18.537086952
+8.838709677 3.903225806 10.352768137 13.627557695 18.463319088
+8.838709677 4.193548387 10.519625429 13.637427439 18.417599484
+8.838709677 4.483870968 10.738408418 13.682818578 18.412535791
+8.838709677 4.774193548 11.037217342 13.777278068 18.467583744
+8.838709677 5.064516129 11.457663040 13.943032824 18.612009655
+8.838709677 5.354838710 12.032834518 14.162291151 18.821124666
+8.838709677 5.645161290 12.784673825 14.439131521 19.073000135
+8.838709677 5.935483871 13.714623381 14.815969959 19.357395690
+8.838709677 6.225806452 14.778744019 15.350155064 19.645850060
+8.838709677 6.516129032 15.883198672 16.075414380 19.878699414
+8.838709677 6.806451613 16.909538446 16.932414748 19.986611801
+8.838709677 7.096774194 17.500000000 17.500000000 20.000000000
+8.838709677 7.387096774 17.500000000 17.500000000 20.000000000
+8.838709677 7.677419355 17.500000000 17.500000000 20.000000000
+8.838709677 7.967741935 17.500000000 17.500000000 20.000000000
+8.838709677 8.258064516 17.500000000 17.500000000 20.000000000
+8.838709677 8.548387097 17.500000000 17.500000000 20.000000000
+8.838709677 8.838709677 17.500000000 17.500000000 20.000000000
+8.838709677 9.129032258 17.500000000 17.500000000 20.000000000
+8.838709677 9.419354839 17.500000000 17.500000000 20.000000000
+8.838709677 9.709677419 17.500000000 17.500000000 20.000000000
+8.838709677 10.000000000 17.500000000 17.500000000 20.000000000
+9.129032258 1.000000000 10.000000000 13.750000000 18.750000000
+9.129032258 1.290322581 10.000000000 13.750000000 18.750000000
+9.129032258 1.580645161 10.000000000 13.750000000 18.750000000
+9.129032258 1.870967742 10.000000000 13.750000000 18.750000000
+9.129032258 2.161290323 10.000000000 13.750000000 18.750000000
+9.129032258 2.451612903 10.000000000 13.750000000 18.750000000
+9.129032258 2.741935484 10.000000000 13.750000000 18.750000000
+9.129032258 3.032258065 10.010142154 13.742536520 18.737455859
+9.129032258 3.322580645 10.107593677 13.684557246 18.630423796
+9.129032258 3.612903226 10.219378581 13.645030600 18.537086952
+9.129032258 3.903225806 10.352768137 13.627557695 18.463319088
+9.129032258 4.193548387 10.519625429 13.637427439 18.417599484
+9.129032258 4.483870968 10.738408418 13.682818578 18.412535791
+9.129032258 4.774193548 11.037217342 13.777278068 18.467583744
+9.129032258 5.064516129 11.457663040 13.943032824 18.612009655
+9.129032258 5.354838710 12.032834518 14.162291151 18.821124666
+9.129032258 5.645161290 12.784673825 14.439131521 19.073000135
+9.129032258 5.935483871 13.714623381 14.815969959 19.357395690
+9.129032258 6.225806452 14.778744019 15.350155064 19.645850060
+9.129032258 6.516129032 15.883198672 16.075414380 19.878699414
+9.129032258 6.806451613 16.909538446 16.932414748 19.986611801
+9.129032258 7.096774194 17.500000000 17.500000000 20.000000000
+9.129032258 7.387096774 17.500000000 17.500000000 20.000000000
+9.129032258 7.677419355 17.500000000 17.500000000 20.000000000
+9.129032258 7.967741935 17.500000000 17.500000000 20.000000000
+9.129032258 8.258064516 17.500000000 17.500000000 20.000000000
+9.129032258 8.548387097 17.500000000 17.500000000 20.000000000
+9.129032258 8.838709677 17.500000000 17.500000000 20.000000000
+9.129032258 9.129032258 17.500000000 17.500000000 20.000000000
+9.129032258 9.419354839 17.500000000 17.500000000 20.000000000
+9.129032258 9.709677419 17.500000000 17.500000000 20.000000000
+9.129032258 10.000000000 17.500000000 17.500000000 20.000000000
+9.419354839 1.000000000 10.000000000 13.750000000 18.750000000
+9.419354839 1.290322581 10.000000000 13.750000000 18.750000000
+9.419354839 1.580645161 10.000000000 13.750000000 18.750000000
+9.419354839 1.870967742 10.000000000 13.750000000 18.750000000
+9.419354839 2.161290323 10.000000000 13.750000000 18.750000000
+9.419354839 2.451612903 10.000000000 13.750000000 18.750000000
+9.419354839 2.741935484 10.000000000 13.750000000 18.750000000
+9.419354839 3.032258065 10.010142154 13.742536520 18.737455859
+9.419354839 3.322580645 10.107593677 13.684557246 18.630423796
+9.419354839 3.612903226 10.219378581 13.645030600 18.537086952
+9.419354839 3.903225806 10.352768137 13.627557695 18.463319088
+9.419354839 4.193548387 10.519625429 13.637427439 18.417599484
+9.419354839 4.483870968 10.738408418 13.682818578 18.412535791
+9.419354839 4.774193548 11.037217342 13.777278068 18.467583744
+9.419354839 5.064516129 11.457663040 13.943032824 18.612009655
+9.419354839 5.354838710 12.032834518 14.162291151 18.821124666
+9.419354839 5.645161290 12.784673825 14.439131521 19.073000135
+9.419354839 5.935483871 13.714623381 14.815969959 19.357395690
+9.419354839 6.225806452 14.778744019 15.350155064 19.645850060
+9.419354839 6.516129032 15.883198672 16.075414380 19.878699414
+9.419354839 6.806451613 16.909538446 16.932414748 19.986611801
+9.419354839 7.096774194 17.500000000 17.500000000 20.000000000
+9.419354839 7.387096774 17.500000000 17.500000000 20.000000000
+9.419354839 7.677419355 17.500000000 17.500000000 20.000000000
+9.419354839 7.967741935 17.500000000 17.500000000 20.000000000
+9.419354839 8.258064516 17.500000000 17.500000000 20.000000000
+9.419354839 8.548387097 17.500000000 17.500000000 20.000000000
+9.419354839 8.838709677 17.500000000 17.500000000 20.000000000
+9.419354839 9.129032258 17.500000000 17.500000000 20.000000000
+9.419354839 9.419354839 17.500000000 17.500000000 20.000000000
+9.419354839 9.709677419 17.500000000 17.500000000 20.000000000
+9.419354839 10.000000000 17.500000000 17.500000000 20.000000000
+9.709677419 1.000000000 10.000000000 13.750000000 18.750000000
+9.709677419 1.290322581 10.000000000 13.750000000 18.750000000
+9.709677419 1.580645161 10.000000000 13.750000000 18.750000000
+9.709677419 1.870967742 10.000000000 13.750000000 18.750000000
+9.709677419 2.161290323 10.000000000 13.750000000 18.750000000
+9.709677419 2.451612903 10.000000000 13.750000000 18.750000000
+9.709677419 2.741935484 10.000000000 13.750000000 18.750000000
+9.709677419 3.032258065 10.010142154 13.742536520 18.737455859
+9.709677419 3.322580645 10.107593677 13.684557246 18.630423796
+9.709677419 3.612903226 10.219378581 13.645030600 18.537086952
+9.709677419 3.903225806 10.352768137 13.627557695 18.463319088
+9.709677419 4.193548387 10.519625429 13.637427439 18.417599484
+9.709677419 4.483870968 10.738408418 13.682818578 18.412535791
+9.709677419 4.774193548 11.037217342 13.777278068 18.467583744
+9.709677419 5.064516129 11.457663040 13.943032824 18.612009655
+9.709677419 5.354838710 12.032834518 14.162291151 18.821124666
+9.709677419 5.645161290 12.784673825 14.439131521 19.073000135
+9.709677419 5.935483871 13.714623381 14.815969959 19.357395690
+9.709677419 6.225806452 14.778744019 15.350155064 19.645850060
+9.709677419 6.516129032 15.883198672 16.075414380 19.878699414
+9.709677419 6.806451613 16.909538446 16.932414748 19.986611801
+9.709677419 7.096774194 17.500000000 17.500000000 20.000000000
+9.709677419 7.387096774 17.500000000 17.500000000 20.000000000
+9.709677419 7.677419355 17.500000000 17.500000000 20.000000000
+9.709677419 7.967741935 17.500000000 17.500000000 20.000000000
+9.709677419 8.258064516 17.500000000 17.500000000 20.000000000
+9.709677419 8.548387097 17.500000000 17.500000000 20.000000000
+9.709677419 8.838709677 17.500000000 17.500000000 20.000000000
+9.709677419 9.129032258 17.500000000 17.500000000 20.000000000
+9.709677419 9.419354839 17.500000000 17.500000000 20.000000000
+9.709677419 9.709677419 17.500000000 17.500000000 20.000000000
+9.709677419 10.000000000 17.500000000 17.500000000 20.000000000
+10.000000000 1.000000000 10.000000000 13.750000000 18.750000000
+10.000000000 1.290322581 10.000000000 13.750000000 18.750000000
+10.000000000 1.580645161 10.000000000 13.750000000 18.750000000
+10.000000000 1.870967742 10.000000000 13.750000000 18.750000000
+10.000000000 2.161290323 10.000000000 13.750000000 18.750000000
+10.000000000 2.451612903 10.000000000 13.750000000 18.750000000
+10.000000000 2.741935484 10.000000000 13.750000000 18.750000000
+10.000000000 3.032258065 10.010142154 13.742536520 18.737455859
+10.000000000 3.322580645 10.107593677 13.684557246 18.630423796
+10.000000000 3.612903226 10.219378581 13.645030600 18.537086952
+10.000000000 3.903225806 10.352768137 13.627557695 18.463319088
+10.000000000 4.193548387 10.519625429 13.637427439 18.417599484
+10.000000000 4.483870968 10.738408418 13.682818578 18.412535791
+10.000000000 4.774193548 11.037217342 13.777278068 18.467583744
+10.000000000 5.064516129 11.457663040 13.943032824 18.612009655
+10.000000000 5.354838710 12.032834518 14.162291151 18.821124666
+10.000000000 5.645161290 12.784673825 14.439131521 19.073000135
+10.000000000 5.935483871 13.714623381 14.815969959 19.357395690
+10.000000000 6.225806452 14.778744019 15.350155064 19.645850060
+10.000000000 6.516129032 15.883198672 16.075414380 19.878699414
+10.000000000 6.806451613 16.909538446 16.932414748 19.986611801
+10.000000000 7.096774194 17.500000000 17.500000000 20.000000000
+10.000000000 7.387096774 17.500000000 17.500000000 20.000000000
+10.000000000 7.677419355 17.500000000 17.500000000 20.000000000
+10.000000000 7.967741935 17.500000000 17.500000000 20.000000000
+10.000000000 8.258064516 17.500000000 17.500000000 20.000000000
+10.000000000 8.548387097 17.500000000 17.500000000 20.000000000
+10.000000000 8.838709677 17.500000000 17.500000000 20.000000000
+10.000000000 9.129032258 17.500000000 17.500000000 20.000000000
+10.000000000 9.419354839 17.500000000 17.500000000 20.000000000
+10.000000000 9.709677419 17.500000000 17.500000000 20.000000000
+10.000000000 10.000000000 17.500000000 17.500000000 20.000000000
diff --git a/examples/takagi-sugeno/octave/sugeno_tip_calculator.fll b/examples/takagi-sugeno/octave/sugeno_tip_calculator.fll
index 611d6eb..1b51806 100644
--- a/examples/takagi-sugeno/octave/sugeno_tip_calculator.fll
+++ b/examples/takagi-sugeno/octave/sugeno_tip_calculator.fll
@@ -1,44 +1,46 @@
-Engine: Sugeno-Tip-Calculator
+Engine: sugeno_tip_calculator
InputVariable: FoodQuality
enabled: true
range: 1.000 10.000
+ lock-range: false
term: Bad Trapezoid 0.000 1.000 3.000 7.000
term: Good Trapezoid 3.000 7.000 10.000 11.000
InputVariable: Service
enabled: true
range: 1.000 10.000
+ lock-range: false
term: Bad Trapezoid 0.000 1.000 3.000 7.000
term: Good Trapezoid 3.000 7.000 10.000 11.000
OutputVariable: CheapTip
enabled: true
range: 5.000 25.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
- lock-range: false
term: Low Constant 10.000
term: Medium Constant 15.000
term: High Constant 20.000
OutputVariable: AverageTip
enabled: true
range: 5.000 25.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
- lock-range: false
term: Low Constant 10.000
term: Medium Constant 15.000
term: High Constant 20.000
OutputVariable: GenerousTip
enabled: true
range: 5.000 25.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage TakagiSugeno
default: nan
lock-previous: false
- lock-range: false
term: Low Constant 10.000
term: Medium Constant 15.000
term: High Constant 20.000
@@ -46,7 +48,8 @@ RuleBlock:
enabled: true
conjunction: EinsteinProduct
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if FoodQuality is extremely Bad and Service is extremely Bad then CheapTip is extremely Low and AverageTip is very Low and GenerousTip is Low
rule: if FoodQuality is Good and Service is extremely Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium
rule: if FoodQuality is very Good and Service is very Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High
diff --git a/examples/takagi-sugeno/octave/sugeno_tip_calculator.java b/examples/takagi-sugeno/octave/sugeno_tip_calculator.java
index 939649e..d64e722 100644
--- a/examples/takagi-sugeno/octave/sugeno_tip_calculator.java
+++ b/examples/takagi-sugeno/octave/sugeno_tip_calculator.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,73 +13,85 @@ import com.fuzzylite.variable.*;
public class sugeno_tip_calculator{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("Sugeno-Tip-Calculator");
+engine.setName("sugeno_tip_calculator");
+engine.setDescription("");
-InputVariable inputVariable1 = new InputVariable();
-inputVariable1.setEnabled(true);
-inputVariable1.setName("FoodQuality");
-inputVariable1.setRange(1.000, 10.000);
-inputVariable1.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable1.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine.addInputVariable(inputVariable1);
+InputVariable FoodQuality = new InputVariable();
+FoodQuality.setName("FoodQuality");
+FoodQuality.setDescription("");
+FoodQuality.setEnabled(true);
+FoodQuality.setRange(1.000, 10.000);
+FoodQuality.setLockValueInRange(false);
+FoodQuality.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+FoodQuality.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine.addInputVariable(FoodQuality);
-InputVariable inputVariable2 = new InputVariable();
-inputVariable2.setEnabled(true);
-inputVariable2.setName("Service");
-inputVariable2.setRange(1.000, 10.000);
-inputVariable2.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
-inputVariable2.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
-engine.addInputVariable(inputVariable2);
+InputVariable Service = new InputVariable();
+Service.setName("Service");
+Service.setDescription("");
+Service.setEnabled(true);
+Service.setRange(1.000, 10.000);
+Service.setLockValueInRange(false);
+Service.addTerm(new Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000));
+Service.addTerm(new Trapezoid("Good", 3.000, 7.000, 10.000, 11.000));
+engine.addInputVariable(Service);
-OutputVariable outputVariable1 = new OutputVariable();
-outputVariable1.setEnabled(true);
-outputVariable1.setName("CheapTip");
-outputVariable1.setRange(5.000, 25.000);
-outputVariable1.fuzzyOutput().setAccumulation(null);
-outputVariable1.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable1.setDefaultValue(Double.NaN);
-outputVariable1.setLockPreviousOutputValue(false);
-outputVariable1.setLockOutputValueInRange(false);
-outputVariable1.addTerm(new Constant("Low", 10.000));
-outputVariable1.addTerm(new Constant("Medium", 15.000));
-outputVariable1.addTerm(new Constant("High", 20.000));
-engine.addOutputVariable(outputVariable1);
+OutputVariable CheapTip = new OutputVariable();
+CheapTip.setName("CheapTip");
+CheapTip.setDescription("");
+CheapTip.setEnabled(true);
+CheapTip.setRange(5.000, 25.000);
+CheapTip.setLockValueInRange(false);
+CheapTip.setAggregation(null);
+CheapTip.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+CheapTip.setDefaultValue(Double.NaN);
+CheapTip.setLockPreviousValue(false);
+CheapTip.addTerm(new Constant("Low", 10.000));
+CheapTip.addTerm(new Constant("Medium", 15.000));
+CheapTip.addTerm(new Constant("High", 20.000));
+engine.addOutputVariable(CheapTip);
-OutputVariable outputVariable2 = new OutputVariable();
-outputVariable2.setEnabled(true);
-outputVariable2.setName("AverageTip");
-outputVariable2.setRange(5.000, 25.000);
-outputVariable2.fuzzyOutput().setAccumulation(null);
-outputVariable2.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable2.setDefaultValue(Double.NaN);
-outputVariable2.setLockPreviousOutputValue(false);
-outputVariable2.setLockOutputValueInRange(false);
-outputVariable2.addTerm(new Constant("Low", 10.000));
-outputVariable2.addTerm(new Constant("Medium", 15.000));
-outputVariable2.addTerm(new Constant("High", 20.000));
-engine.addOutputVariable(outputVariable2);
+OutputVariable AverageTip = new OutputVariable();
+AverageTip.setName("AverageTip");
+AverageTip.setDescription("");
+AverageTip.setEnabled(true);
+AverageTip.setRange(5.000, 25.000);
+AverageTip.setLockValueInRange(false);
+AverageTip.setAggregation(null);
+AverageTip.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+AverageTip.setDefaultValue(Double.NaN);
+AverageTip.setLockPreviousValue(false);
+AverageTip.addTerm(new Constant("Low", 10.000));
+AverageTip.addTerm(new Constant("Medium", 15.000));
+AverageTip.addTerm(new Constant("High", 20.000));
+engine.addOutputVariable(AverageTip);
-OutputVariable outputVariable3 = new OutputVariable();
-outputVariable3.setEnabled(true);
-outputVariable3.setName("GenerousTip");
-outputVariable3.setRange(5.000, 25.000);
-outputVariable3.fuzzyOutput().setAccumulation(null);
-outputVariable3.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
-outputVariable3.setDefaultValue(Double.NaN);
-outputVariable3.setLockPreviousOutputValue(false);
-outputVariable3.setLockOutputValueInRange(false);
-outputVariable3.addTerm(new Constant("Low", 10.000));
-outputVariable3.addTerm(new Constant("Medium", 15.000));
-outputVariable3.addTerm(new Constant("High", 20.000));
-engine.addOutputVariable(outputVariable3);
+OutputVariable GenerousTip = new OutputVariable();
+GenerousTip.setName("GenerousTip");
+GenerousTip.setDescription("");
+GenerousTip.setEnabled(true);
+GenerousTip.setRange(5.000, 25.000);
+GenerousTip.setLockValueInRange(false);
+GenerousTip.setAggregation(null);
+GenerousTip.setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+GenerousTip.setDefaultValue(Double.NaN);
+GenerousTip.setLockPreviousValue(false);
+GenerousTip.addTerm(new Constant("Low", 10.000));
+GenerousTip.addTerm(new Constant("Medium", 15.000));
+GenerousTip.addTerm(new Constant("High", 20.000));
+engine.addOutputVariable(GenerousTip);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(new EinsteinProduct());
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(null);
+ruleBlock.setImplication(null);
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if FoodQuality is extremely Bad and Service is extremely Bad then CheapTip is extremely Low and AverageTip is very Low and GenerousTip is Low", engine));
ruleBlock.addRule(Rule.parse("if FoodQuality is Good and Service is extremely Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium", engine));
ruleBlock.addRule(Rule.parse("if FoodQuality is very Good and Service is very Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High", engine));
diff --git a/examples/takagi-sugeno/octave/sugeno_tip_calculator.pdf b/examples/takagi-sugeno/octave/sugeno_tip_calculator.pdf
new file mode 100644
index 0000000..f138223
--- /dev/null
+++ b/examples/takagi-sugeno/octave/sugeno_tip_calculator.pdf
Binary files differ
diff --git a/examples/tsukamoto/tsukamoto.R b/examples/tsukamoto/tsukamoto.R
new file mode 100644
index 0000000..51fbdd4
--- /dev/null
+++ b/examples/tsukamoto/tsukamoto.R
@@ -0,0 +1,126 @@
+#Code automatically generated with fuzzylite 6.0.
+
+library(ggplot2);
+
+engine.name = "tsukamoto"
+engine.fll = "Engine: tsukamoto
+InputVariable: X
+ enabled: true
+ range: -10.000 10.000
+ lock-range: false
+ term: small Bell -10.000 5.000 3.000
+ term: medium Bell 0.000 5.000 3.000
+ term: large Bell 10.000 5.000 3.000
+OutputVariable: Ramps
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: b Ramp 0.600 0.400
+ term: a Ramp 0.000 0.250
+ term: c Ramp 0.700 1.000
+OutputVariable: Sigmoids
+ enabled: true
+ range: 0.020 1.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: b Sigmoid 0.500 -30.000
+ term: a Sigmoid 0.130 30.000
+ term: c Sigmoid 0.830 30.000
+OutputVariable: ZSShapes
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: b ZShape 0.300 0.600
+ term: a SShape 0.000 0.250
+ term: c SShape 0.700 1.000
+OutputVariable: Concaves
+ enabled: true
+ range: 0.000 1.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage Automatic
+ default: nan
+ lock-previous: false
+ term: b Concave 0.500 0.400
+ term: a Concave 0.240 0.250
+ term: c Concave 0.900 1.000
+RuleBlock:
+ enabled: true
+ conjunction: none
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if X is small then Ramps is a and Sigmoids is a and ZSShapes is a and Concaves is a
+ rule: if X is medium then Ramps is b and Sigmoids is b and ZSShapes is b and Concaves is b
+ rule: if X is large then Ramps is c and Sigmoids is c and ZSShapes is c and Concaves is c"
+
+engine.fldFile = "tsukamoto.fld"
+if (require(data.table)) {
+ engine.df = data.table::fread(engine.fldFile, sep="auto", header="auto")
+} else {
+ engine.df = read.table(engine.fldFile, header=TRUE)
+}
+
+engine.plot.i1_o1 = ggplot(engine.df, aes(X, Ramps)) +
+ geom_line(aes(color=Ramps), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("X vs Ramps")
+
+engine.plot.o1_i1 = ggplot(engine.df, aes(X, Ramps)) +
+ geom_line(aes(color=Ramps), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("Ramps vs X")
+
+engine.plot.i1_o2 = ggplot(engine.df, aes(X, Sigmoids)) +
+ geom_line(aes(color=Sigmoids), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("X vs Sigmoids")
+
+engine.plot.o2_i1 = ggplot(engine.df, aes(X, Sigmoids)) +
+ geom_line(aes(color=Sigmoids), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("Sigmoids vs X")
+
+engine.plot.i1_o3 = ggplot(engine.df, aes(X, ZSShapes)) +
+ geom_line(aes(color=ZSShapes), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("X vs ZSShapes")
+
+engine.plot.o3_i1 = ggplot(engine.df, aes(X, ZSShapes)) +
+ geom_line(aes(color=ZSShapes), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("ZSShapes vs X")
+
+engine.plot.i1_o4 = ggplot(engine.df, aes(X, Concaves)) +
+ geom_line(aes(color=Concaves), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ ggtitle("X vs Concaves")
+
+engine.plot.o4_i1 = ggplot(engine.df, aes(X, Concaves)) +
+ geom_line(aes(color=Concaves), size=3, lineend="round", linejoin="mitre") +
+ scale_color_gradient(low="yellow", high="red") +
+ coord_flip() +
+ ggtitle("Concaves vs X")
+
+if (require(gridExtra)) {
+ engine.plots = arrangeGrob(engine.plot.i1_o1, engine.plot.o1_i1, engine.plot.i1_o2, engine.plot.o2_i1, engine.plot.i1_o3, engine.plot.o3_i1, engine.plot.i1_o4, engine.plot.o4_i1, ncol=2, top=engine.name)
+ ggsave(paste0(engine.name, ".pdf"), engine.plots)
+ if (require(grid)) {
+ grid.newpage()
+ grid.draw(engine.plots)
+ }
+}
diff --git a/examples/tsukamoto/tsukamoto.cpp b/examples/tsukamoto/tsukamoto.cpp
index 4432936..a50c53d 100644
--- a/examples/tsukamoto/tsukamoto.cpp
+++ b/examples/tsukamoto/tsukamoto.cpp
@@ -1,85 +1,96 @@
#include <fl/Headers.h>
int main(int argc, char** argv){
+//Code automatically generated with fuzzylite 6.0.
+
using namespace fl;
Engine* engine = new Engine;
-engine->setName("");
+engine->setName("tsukamoto");
+engine->setDescription("");
-InputVariable* inputVariable = new InputVariable;
-inputVariable->setEnabled(true);
-inputVariable->setName("X");
-inputVariable->setRange(-10.000, 10.000);
-inputVariable->addTerm(new Bell("small", -10.000, 5.000, 3.000));
-inputVariable->addTerm(new Bell("medium", 0.000, 5.000, 3.000));
-inputVariable->addTerm(new Bell("large", 10.000, 5.000, 3.000));
-engine->addInputVariable(inputVariable);
+InputVariable* X = new InputVariable;
+X->setName("X");
+X->setDescription("");
+X->setEnabled(true);
+X->setRange(-10.000, 10.000);
+X->setLockValueInRange(false);
+X->addTerm(new Bell("small", -10.000, 5.000, 3.000));
+X->addTerm(new Bell("medium", 0.000, 5.000, 3.000));
+X->addTerm(new Bell("large", 10.000, 5.000, 3.000));
+engine->addInputVariable(X);
-OutputVariable* outputVariable1 = new OutputVariable;
-outputVariable1->setEnabled(true);
-outputVariable1->setName("Ramps");
-outputVariable1->setRange(0.000, 1.000);
-outputVariable1->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable1->setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable1->setDefaultValue(fl::nan);
-outputVariable1->setLockPreviousOutputValue(false);
-outputVariable1->setLockOutputValueInRange(false);
-outputVariable1->addTerm(new Ramp("b", 0.600, 0.400));
-outputVariable1->addTerm(new Ramp("a", 0.000, 0.250));
-outputVariable1->addTerm(new Ramp("c", 0.700, 1.000));
-engine->addOutputVariable(outputVariable1);
+OutputVariable* Ramps = new OutputVariable;
+Ramps->setName("Ramps");
+Ramps->setDescription("");
+Ramps->setEnabled(true);
+Ramps->setRange(0.000, 1.000);
+Ramps->setLockValueInRange(false);
+Ramps->setAggregation(fl::null);
+Ramps->setDefuzzifier(new WeightedAverage("Automatic"));
+Ramps->setDefaultValue(fl::nan);
+Ramps->setLockPreviousValue(false);
+Ramps->addTerm(new Ramp("b", 0.600, 0.400));
+Ramps->addTerm(new Ramp("a", 0.000, 0.250));
+Ramps->addTerm(new Ramp("c", 0.700, 1.000));
+engine->addOutputVariable(Ramps);
-OutputVariable* outputVariable2 = new OutputVariable;
-outputVariable2->setEnabled(true);
-outputVariable2->setName("Sigmoids");
-outputVariable2->setRange(0.020, 1.000);
-outputVariable2->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable2->setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable2->setDefaultValue(fl::nan);
-outputVariable2->setLockPreviousOutputValue(false);
-outputVariable2->setLockOutputValueInRange(false);
-outputVariable2->addTerm(new Sigmoid("b", 0.500, -30.000));
-outputVariable2->addTerm(new Sigmoid("a", 0.130, 30.000));
-outputVariable2->addTerm(new Sigmoid("c", 0.830, 30.000));
-engine->addOutputVariable(outputVariable2);
+OutputVariable* Sigmoids = new OutputVariable;
+Sigmoids->setName("Sigmoids");
+Sigmoids->setDescription("");
+Sigmoids->setEnabled(true);
+Sigmoids->setRange(0.020, 1.000);
+Sigmoids->setLockValueInRange(false);
+Sigmoids->setAggregation(fl::null);
+Sigmoids->setDefuzzifier(new WeightedAverage("Automatic"));
+Sigmoids->setDefaultValue(fl::nan);
+Sigmoids->setLockPreviousValue(false);
+Sigmoids->addTerm(new Sigmoid("b", 0.500, -30.000));
+Sigmoids->addTerm(new Sigmoid("a", 0.130, 30.000));
+Sigmoids->addTerm(new Sigmoid("c", 0.830, 30.000));
+engine->addOutputVariable(Sigmoids);
-OutputVariable* outputVariable3 = new OutputVariable;
-outputVariable3->setEnabled(true);
-outputVariable3->setName("ZSShapes");
-outputVariable3->setRange(0.000, 1.000);
-outputVariable3->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable3->setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable3->setDefaultValue(fl::nan);
-outputVariable3->setLockPreviousOutputValue(false);
-outputVariable3->setLockOutputValueInRange(false);
-outputVariable3->addTerm(new ZShape("b", 0.300, 0.600));
-outputVariable3->addTerm(new SShape("a", 0.000, 0.250));
-outputVariable3->addTerm(new SShape("c", 0.700, 1.000));
-engine->addOutputVariable(outputVariable3);
+OutputVariable* ZSShapes = new OutputVariable;
+ZSShapes->setName("ZSShapes");
+ZSShapes->setDescription("");
+ZSShapes->setEnabled(true);
+ZSShapes->setRange(0.000, 1.000);
+ZSShapes->setLockValueInRange(false);
+ZSShapes->setAggregation(fl::null);
+ZSShapes->setDefuzzifier(new WeightedAverage("Automatic"));
+ZSShapes->setDefaultValue(fl::nan);
+ZSShapes->setLockPreviousValue(false);
+ZSShapes->addTerm(new ZShape("b", 0.300, 0.600));
+ZSShapes->addTerm(new SShape("a", 0.000, 0.250));
+ZSShapes->addTerm(new SShape("c", 0.700, 1.000));
+engine->addOutputVariable(ZSShapes);
-OutputVariable* outputVariable4 = new OutputVariable;
-outputVariable4->setEnabled(true);
-outputVariable4->setName("Concaves");
-outputVariable4->setRange(0.000, 1.000);
-outputVariable4->fuzzyOutput()->setAccumulation(fl::null);
-outputVariable4->setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable4->setDefaultValue(fl::nan);
-outputVariable4->setLockPreviousOutputValue(false);
-outputVariable4->setLockOutputValueInRange(false);
-outputVariable4->addTerm(new Concave("b", 0.500, 0.400));
-outputVariable4->addTerm(new Concave("a", 0.240, 0.250));
-outputVariable4->addTerm(new Concave("c", 0.900, 1.000));
-engine->addOutputVariable(outputVariable4);
+OutputVariable* Concaves = new OutputVariable;
+Concaves->setName("Concaves");
+Concaves->setDescription("");
+Concaves->setEnabled(true);
+Concaves->setRange(0.000, 1.000);
+Concaves->setLockValueInRange(false);
+Concaves->setAggregation(fl::null);
+Concaves->setDefuzzifier(new WeightedAverage("Automatic"));
+Concaves->setDefaultValue(fl::nan);
+Concaves->setLockPreviousValue(false);
+Concaves->addTerm(new Concave("b", 0.500, 0.400));
+Concaves->addTerm(new Concave("a", 0.240, 0.250));
+Concaves->addTerm(new Concave("c", 0.900, 1.000));
+engine->addOutputVariable(Concaves);
RuleBlock* ruleBlock = new RuleBlock;
-ruleBlock->setEnabled(true);
ruleBlock->setName("");
+ruleBlock->setDescription("");
+ruleBlock->setEnabled(true);
ruleBlock->setConjunction(fl::null);
ruleBlock->setDisjunction(fl::null);
-ruleBlock->setActivation(fl::null);
-ruleBlock->addRule(fl::Rule::parse("if X is small then Ramps is a and Sigmoids is a and ZSShapes is a and Concaves is a", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is medium then Ramps is b and Sigmoids is b and ZSShapes is b and Concaves is b", engine));
-ruleBlock->addRule(fl::Rule::parse("if X is large then Ramps is c and Sigmoids is c and ZSShapes is c and Concaves is c", engine));
+ruleBlock->setImplication(fl::null);
+ruleBlock->setActivation(new General);
+ruleBlock->addRule(Rule::parse("if X is small then Ramps is a and Sigmoids is a and ZSShapes is a and Concaves is a", engine));
+ruleBlock->addRule(Rule::parse("if X is medium then Ramps is b and Sigmoids is b and ZSShapes is b and Concaves is b", engine));
+ruleBlock->addRule(Rule::parse("if X is large then Ramps is c and Sigmoids is c and ZSShapes is c and Concaves is c", engine));
engine->addRuleBlock(ruleBlock);
diff --git a/examples/tsukamoto/tsukamoto.fcl b/examples/tsukamoto/tsukamoto.fcl
index 16a4bbd..b26fc60 100644
--- a/examples/tsukamoto/tsukamoto.fcl
+++ b/examples/tsukamoto/tsukamoto.fcl
@@ -1,4 +1,6 @@
-FUNCTION_BLOCK
+//Code automatically generated with fuzzylite 6.0.
+
+FUNCTION_BLOCK tsukamoto
VAR_INPUT
X: REAL;
diff --git a/examples/tsukamoto/tsukamoto.fis b/examples/tsukamoto/tsukamoto.fis
index 6dc1b4f..0127bdd 100644
--- a/examples/tsukamoto/tsukamoto.fis
+++ b/examples/tsukamoto/tsukamoto.fis
@@ -1,13 +1,16 @@
+#Code automatically generated with fuzzylite 6.0.
+
[System]
-Name=''
+Name='tsukamoto'
Type='tsukamoto'
+Version=6.0
NumInputs=1
NumOutputs=4
NumRules=3
-AndMethod=''
-OrMethod=''
-ImpMethod=''
-AggMethod=''
+AndMethod='min'
+OrMethod='max'
+ImpMethod='min'
+AggMethod='max'
DefuzzMethod='wtaver'
[Input1]
diff --git a/examples/tsukamoto/tsukamoto.fld b/examples/tsukamoto/tsukamoto.fld
index 85e0cc3..a62de71 100644
--- a/examples/tsukamoto/tsukamoto.fld
+++ b/examples/tsukamoto/tsukamoto.fld
@@ -1,1026 +1,1025 @@
-#@Engine: ;
-#@InputVariable: X; @OutputVariable: Ramps; @OutputVariable: Sigmoids; @OutputVariable: ZSShapes; @OutputVariable: Concaves;
--10.00000000 0.25536331 0.99441852 0.25580927 0.25221216
--9.98044966 0.25542354 0.99434929 0.25587749 0.25223783
--9.96089932 0.25548454 0.99427909 0.25594671 0.25226383
--9.94134897 0.25554631 0.99420791 0.25601699 0.25229018
--9.92179863 0.25560889 0.99413572 0.25608842 0.25231688
--9.90224829 0.25567226 0.99406252 0.25616107 0.25234393
--9.88269795 0.25573645 0.99398828 0.25623502 0.25237134
--9.86314761 0.25580146 0.99391299 0.25631034 0.25239911
--9.84359726 0.25586731 0.99383664 0.25638712 0.25242725
--9.82404692 0.25593401 0.99375920 0.25646543 0.25245576
--9.80449658 0.25600158 0.99368066 0.25654534 0.25248466
--9.78494624 0.25607001 0.99360101 0.25662695 0.25251393
--9.76539589 0.25613933 0.99352023 0.25671031 0.25254360
--9.74584555 0.25620954 0.99343829 0.25679552 0.25257366
--9.72629521 0.25628067 0.99335519 0.25688266 0.25260413
--9.70674487 0.25635271 0.99327090 0.25697179 0.25263500
--9.68719453 0.25642570 0.99318540 0.25706301 0.25266629
--9.66764418 0.25649962 0.99309868 0.25715639 0.25269800
--9.64809384 0.25657451 0.99301071 0.25725200 0.25273013
--9.62854350 0.25665038 0.99292148 0.25734994 0.25276269
--9.60899316 0.25672722 0.99283097 0.25745027 0.25279570
--9.58944282 0.25680507 0.99273915 0.25755308 0.25282915
--9.56989247 0.25688393 0.99264601 0.25765846 0.25286305
--9.55034213 0.25696382 0.99255153 0.25776647 0.25289740
--9.53079179 0.25704474 0.99245567 0.25787721 0.25293223
--9.51124145 0.25712672 0.99235844 0.25799075 0.25296752
--9.49169110 0.25720976 0.58805202 0.25810718 0.25300329
--9.47214076 0.25729388 0.58066402 0.25822657 0.25303955
--9.45259042 0.25737909 0.57354840 0.25834901 0.25307630
--9.43304008 0.25746541 0.56668617 0.25847459 0.25311356
--9.41348974 0.25755285 0.56006026 0.25860337 0.25315132
--9.39393939 0.25764143 0.55365530 0.25873546 0.25318959
--9.37438905 0.25773114 0.54745738 0.25887092 0.25322839
--9.35483871 0.25782202 0.54145387 0.25900985 0.25326772
--9.33528837 0.25791407 0.53563327 0.25915232 0.25330758
--9.31573803 0.25800731 0.52998510 0.25929843 0.25334800
--9.29618768 0.25810174 0.52449975 0.25944825 0.25338896
--9.27663734 0.25819739 0.51916841 0.25960187 0.25343050
--9.25708700 0.25829425 0.51398297 0.25975938 0.25347260
--9.23753666 0.25839236 0.50893596 0.25992086 0.25351528
--9.21798631 0.25849171 0.50402049 0.26008639 0.25355855
--9.19843597 0.25859233 0.49923015 0.26025607 0.25360242
--9.17888563 0.25869422 0.49455902 0.26042997 0.25364689
--9.15933529 0.25879739 0.49000161 0.26060819 0.25369198
--9.13978495 0.25890186 0.48555278 0.26079081 0.25373769
--9.12023460 0.25900763 0.48120775 0.26097791 0.25378404
--9.10068426 0.25911473 0.47696208 0.26116960 0.25383103
--9.08113392 0.25922315 0.47281158 0.26136594 0.25387867
--9.06158358 0.25933291 0.46875235 0.26156704 0.25392698
--9.04203324 0.25944402 0.46478074 0.26177298 0.25397596
--9.02248289 0.25955649 0.46089330 0.26198385 0.25402563
--9.00293255 0.25967032 0.45708680 0.26219974 0.25407598
--8.98338221 0.25978553 0.45335820 0.26242074 0.25412704
--8.96383187 0.25990212 0.44970464 0.26264693 0.25417882
--8.94428152 0.26002010 0.44612342 0.26287842 0.25423132
--8.92473118 0.26013948 0.44261197 0.26311528 0.25428456
--8.90518084 0.26026027 0.43916789 0.26335761 0.25433855
--8.88563050 0.26038246 0.43578890 0.26360551 0.25439330
--8.86608016 0.26050607 0.43247284 0.26385906 0.25444882
--8.84652981 0.26063110 0.42921765 0.26411836 0.25450512
--8.82697947 0.26075756 0.42602140 0.26438350 0.25456221
--8.80742913 0.26088545 0.42288224 0.26465457 0.25462012
--8.78787879 0.26101476 0.41979841 0.26493167 0.25467884
--8.76832845 0.26114551 0.41676826 0.26521489 0.25473840
--8.74877810 0.26127769 0.41379019 0.26550432 0.25479880
--8.72922776 0.26141131 0.41086270 0.26580007 0.25486006
--8.70967742 0.26154637 0.40798435 0.26610222 0.25492219
--8.69012708 0.26168285 0.40515377 0.26641087 0.25498521
--8.67057674 0.26182077 0.40236964 0.26672612 0.25504913
--8.65102639 0.26196012 0.39963073 0.26704806 0.25511396
--8.63147605 0.26210090 0.39693583 0.26737680 0.25517972
--8.61192571 0.26224309 0.39428381 0.26771243 0.25524642
--8.59237537 0.26238670 0.39167359 0.26805504 0.25531408
--8.57282502 0.26253172 0.38910410 0.26840474 0.25538271
--8.55327468 0.26267815 0.38657437 0.26876163 0.25545233
--8.53372434 0.26282596 0.38408343 0.26912580 0.25552295
--8.51417400 0.26297516 0.38163037 0.26949735 0.25559459
--8.49462366 0.26312573 0.37921432 0.26987640 0.25566727
--8.47507331 0.26327766 0.37683443 0.27026303 0.25574100
--8.45552297 0.26343094 0.37448990 0.27065735 0.25581580
--8.43597263 0.26358556 0.37217995 0.27105946 0.25589168
--8.41642229 0.26374149 0.36990385 0.27146946 0.25596867
--8.39687195 0.26389873 0.36766087 0.27188746 0.25604678
--8.37732160 0.26405725 0.36545035 0.27231356 0.25612603
--8.35777126 0.26421704 0.36327163 0.27274787 0.25620644
--8.33822092 0.26437808 0.36112406 0.27319049 0.25628802
--8.31867058 0.26454034 0.35900705 0.27364153 0.25637081
--8.29912023 0.26470380 0.35692002 0.27410108 0.25645480
--8.27956989 0.26486844 0.35486241 0.27456927 0.25654004
--8.26001955 0.26503424 0.35283367 0.27504619 0.25662653
--8.24046921 0.26520116 0.35083330 0.27553195 0.25671429
--8.22091887 0.26536918 0.34886080 0.27602666 0.25680336
--8.20136852 0.26553826 0.34691568 0.27653044 0.25689375
--8.18181818 0.26570839 0.34499749 0.27704338 0.25698547
--8.16226784 0.26587952 0.34310579 0.27756560 0.25707856
--8.14271750 0.26605163 0.34124015 0.27809722 0.25717304
--8.12316716 0.26622467 0.33940016 0.27863833 0.25726893
--8.10361681 0.26639862 0.33758544 0.27918905 0.25736625
--8.08406647 0.26657343 0.33579560 0.27974951 0.25746504
--8.06451613 0.26674906 0.33403029 0.28031979 0.25756530
--8.04496579 0.26692548 0.33228915 0.28090003 0.25766708
--8.02541544 0.26710264 0.33057184 0.28149034 0.25777038
--8.00586510 0.26728050 0.32887806 0.28209082 0.25787525
--7.98631476 0.26745901 0.32720748 0.28270160 0.25798171
--7.96676442 0.26763813 0.32555981 0.28332279 0.25808978
--7.94721408 0.26781782 0.32393477 0.28395451 0.25819950
--7.92766373 0.26799801 0.32233209 0.28459687 0.25831088
--7.90811339 0.26817867 0.32075149 0.28524999 0.25842397
--7.88856305 0.26835973 0.31919274 0.28591400 0.25853879
--7.86901271 0.26854116 0.31765559 0.28658900 0.25865536
--7.84946237 0.26872288 0.31613980 0.28727512 0.25877373
--7.82991202 0.26890486 0.31464517 0.28797248 0.25889393
--7.81036168 0.26908703 0.31317148 0.28868119 0.25901598
--7.79081134 0.26926933 0.31171853 0.28940139 0.25913991
--7.77126100 0.26945171 0.31028613 0.29013319 0.25926577
--7.75171065 0.26963410 0.30887410 0.29087671 0.25939359
--7.73216031 0.26981645 0.30748225 0.29163208 0.25952340
--7.71260997 0.26999870 0.30611044 0.29239941 0.25965524
--7.69305963 0.27018077 0.30475850 0.29317884 0.25978914
--7.67350929 0.27036262 0.30342628 0.29397049 0.25992514
--7.65395894 0.27054417 0.30211365 0.29477449 0.26006328
--7.63440860 0.27072536 0.30082047 0.29559095 0.26020361
--7.61485826 0.27090613 0.29954662 0.29642001 0.26034615
--7.59530792 0.27108641 0.29829198 0.29726179 0.26049095
--7.57575758 0.27126613 0.29705644 0.29811642 0.26063805
--7.55620723 0.27144524 0.29583991 0.29898403 0.26078749
--7.53665689 0.27162365 0.29464228 0.29986474 0.26093932
--7.51710655 0.27180131 0.29346347 0.30075869 0.26109358
--7.49755621 0.27197815 0.29230341 0.30166600 0.26125032
--7.47800587 0.27215410 0.29116201 0.30258681 0.26140958
--7.45845552 0.27232911 0.29003921 0.30352124 0.26157141
--7.43890518 0.27250309 0.28893495 0.30446943 0.26173586
--7.41935484 0.27267600 0.28784918 0.30543150 0.26190297
--7.39980450 0.27284776 0.28678185 0.30640760 0.26207280
--7.38025415 0.27301831 0.28573293 0.30739784 0.26224540
--7.36070381 0.27318759 0.28470237 0.30840237 0.26242082
--7.34115347 0.27335555 0.28369016 0.30942131 0.26259911
--7.32160313 0.27352212 0.28269627 0.31045480 0.26278032
--7.30205279 0.27368724 0.28172069 0.31150298 0.26296452
--7.28250244 0.27385086 0.28076341 0.31256597 0.26315176
--7.26295210 0.27401293 0.27982443 0.31364392 0.26334210
--7.24340176 0.27417340 0.27890375 0.31473695 0.26353559
--7.22385142 0.27433221 0.27800139 0.31584521 0.26373230
--7.20430108 0.27448932 0.27711736 0.31696883 0.26393229
--7.18475073 0.27464470 0.27625167 0.31810794 0.26413562
--7.16520039 0.27479829 0.27540437 0.31926268 0.26434235
--7.14565005 0.27495007 0.27457548 0.32043318 0.26455255
--7.12609971 0.27510001 0.27376505 0.32161959 0.26476629
--7.10654936 0.27524806 0.27297311 0.32282204 0.26498362
--7.08699902 0.27539422 0.27219973 0.32404067 0.26520463
--7.06744868 0.27553845 0.27144495 0.30753520 0.26542938
--7.04789834 0.27568076 0.27070885 0.30845025 0.26565794
--7.02834800 0.27582111 0.26999148 0.30937445 0.26589039
--7.00879765 0.27595952 0.26929292 0.31030773 0.26612679
--6.98924731 0.27609598 0.26861326 0.31125006 0.26636723
--6.96969697 0.27623051 0.26795257 0.31220136 0.26661178
--6.95014663 0.27636310 0.26731094 0.31316160 0.26686051
--6.93059629 0.27649379 0.26668847 0.31413068 0.26711352
--6.91104594 0.27662260 0.26608527 0.31510855 0.26737086
--6.89149560 0.27674956 0.26550142 0.31609512 0.26763264
--6.87194526 0.27687471 0.26493705 0.31709032 0.26789893
--6.85239492 0.27699811 0.26439227 0.31809405 0.26816981
--6.83284457 0.27711981 0.26386720 0.31910623 0.26844537
--6.81329423 0.27723987 0.26336196 0.32012674 0.26872570
--6.79374389 0.27735837 0.26287669 0.32115549 0.26901088
--6.77419355 0.27747540 0.26241151 0.32219236 0.26930100
--6.75464321 0.27759103 0.26196656 0.32323723 0.26959616
--6.73509286 0.27770537 0.26154199 0.32428998 0.26989644
--6.71554252 0.27781854 0.26113794 0.32535049 0.27020193
--6.69599218 0.27793065 0.26075456 0.32641860 0.27051273
--6.67644184 0.27804182 0.26039201 0.32749418 0.27082893
--6.65689150 0.27815221 0.26005044 0.32857707 0.27115063
--6.63734115 0.27826197 0.25973002 0.32966712 0.27147791
--6.61779081 0.27837124 0.25943090 0.33076416 0.27181089
--6.59824047 0.27848021 0.25915325 0.33186801 0.27214965
--6.57869013 0.27858906 0.25889725 0.33297850 0.27249429
--6.55913978 0.27869798 0.25866306 0.33409544 0.27284492
--6.53958944 0.27880717 0.25845086 0.33521862 0.27320162
--6.52003910 0.27891685 0.25826082 0.33634786 0.27356450
--6.50048876 0.27902726 0.25809313 0.33748292 0.27393366
--6.48093842 0.27913862 0.25794795 0.33862361 0.27430919
--6.46138807 0.27925118 0.25782548 0.22105200 0.27469120
--6.44183773 0.27936521 0.25772589 0.22159093 0.27507979
--6.42228739 0.27948098 0.25764936 0.22213788 0.27547505
--6.40273705 0.27959877 0.25759607 0.22269302 0.27587708
--6.38318671 0.27971888 0.25756620 0.22325651 0.27628599
--6.36363636 0.27984160 0.25755993 0.22382853 0.27670186
--6.34408602 0.27996726 0.25757744 0.22440924 0.27712480
--6.32453568 0.28009616 0.25761891 0.22499883 0.27755490
--6.30498534 0.28022866 0.25768450 0.22559746 0.27799226
--6.28543500 0.28036509 0.25777439 0.22620530 0.27843697
--6.26588465 0.28050581 0.25788874 0.22682253 0.27888913
--6.24633431 0.28065117 0.25802772 0.22744932 0.27934881
--6.22678397 0.28080154 0.25819149 0.22808583 0.27981612
--6.20723363 0.28095730 0.25838019 0.22873224 0.28029113
--6.18768328 0.28111883 0.25859399 0.22938871 0.28077394
--6.16813294 0.28128652 0.25883301 0.23005539 0.28126462
--6.14858260 0.28146076 0.25909739 0.23073246 0.28176325
--6.12903226 0.28164195 0.25938726 0.23142006 0.28226991
--6.10948192 0.28183050 0.25970274 0.23211835 0.28278467
--6.08993157 0.28202680 0.26004394 0.23282747 0.28330760
--6.07038123 0.28223127 0.26041095 0.23354755 0.28383876
--6.05083089 0.28244431 0.26080387 0.23427874 0.28437822
--6.03128055 0.28266633 0.26122278 0.23502115 0.28492603
--6.01173021 0.28289774 0.26166773 0.23577491 0.28548224
--5.99217986 0.28313895 0.26213878 0.23654012 0.28604690
--5.97262952 0.28339035 0.26263598 0.23731689 0.28662005
--5.95307918 0.28365234 0.26315935 0.23810530 0.28720173
--5.93352884 0.28392532 0.26370889 0.23890543 0.28779197
--5.91397849 0.28420967 0.26428461 0.23971736 0.28839080
--5.89442815 0.28450577 0.26488648 0.24054113 0.28899822
--5.87487781 0.28481399 0.26551446 0.24137679 0.28961426
--5.85532747 0.28513468 0.26616849 0.24222438 0.29023892
--5.83577713 0.28546820 0.26684850 0.24308390 0.29087220
--5.81622678 0.28581486 0.26755440 0.24395535 0.29151408
--5.79667644 0.28617500 0.26828606 0.24483872 0.29216456
--5.77712610 0.28654892 0.26904334 0.24573397 0.29282359
--5.75757576 0.28693689 0.26982610 0.24664106 0.29349116
--5.73802542 0.28733919 0.27063415 0.24755991 0.29416722
--5.71847507 0.28775607 0.27146727 0.24849044 0.29485171
--5.69892473 0.28818775 0.27232525 0.24943254 0.29554458
--5.67937439 0.28863444 0.27320784 0.25038609 0.29624576
--5.65982405 0.28909631 0.27411475 0.25135093 0.29695517
--5.64027370 0.28957354 0.27504568 0.25232690 0.29767272
--5.62072336 0.29006624 0.27600031 0.25331381 0.29839832
--5.60117302 0.29057452 0.27697829 0.25431144 0.29913186
--5.58162268 0.29109847 0.27797922 0.25531956 0.29987322
--5.56207234 0.29163813 0.27900271 0.25633792 0.30062228
--5.54252199 0.29219351 0.28004832 0.25736622 0.30137889
--5.52297165 0.29276463 0.28111560 0.25840417 0.30214291
--5.50342131 0.29335143 0.28220405 0.25945144 0.30291419
--5.48387097 0.29395384 0.28331316 0.26050768 0.30369256
--5.46432063 0.29457176 0.28444240 0.26157251 0.30447783
--5.44477028 0.29520506 0.28559119 0.26264553 0.30526982
--5.42521994 0.29585357 0.28675895 0.26372632 0.30606834
--5.40566960 0.29651711 0.28794504 0.26481444 0.30687318
--5.38611926 0.29719542 0.28914883 0.26590941 0.30768412
--5.36656891 0.29788827 0.29036965 0.26701075 0.30850093
--5.34701857 0.29859534 0.29160680 0.26811794 0.30959606
--5.32746823 0.29931632 0.29285957 0.26923045 0.31255914
--5.30791789 0.30005086 0.29412720 0.27034772 0.31560324
--5.28836755 0.30079856 0.29540894 0.27146917 0.31872899
--5.26881720 0.30155902 0.29670400 0.27259421 0.32193695
--5.24926686 0.30233179 0.29801157 0.27372222 0.32522758
--5.22971652 0.30311639 0.29933084 0.27485258 0.32860128
--5.21016618 0.30391234 0.30066094 0.27598463 0.33205837
--5.19061584 0.30471910 0.30200102 0.27711771 0.33559908
--5.17106549 0.30553614 0.30335020 0.27825115 0.33922353
--5.15151515 0.30636288 0.30470760 0.27938424 0.34293178
--5.13196481 0.30719873 0.30607229 0.28051629 0.34672379
--5.11241447 0.30804308 0.30744337 0.28164658 0.35059941
--5.09286413 0.30889530 0.30881991 0.28277439 0.35455840
--5.07331378 0.30975474 0.31020096 0.28389899 0.35860043
--5.05376344 0.31062076 0.31158558 0.28501965 0.36272505
--5.03421310 0.31149268 0.31297283 0.28613561 0.36693173
--5.01466276 0.31236980 0.31436174 0.28724615 0.37121982
--4.99511241 0.31325146 0.31575135 0.28835051 0.37558859
--4.97556207 0.31413694 0.31714072 0.28944794 0.38003717
--4.95601173 0.31502554 0.31852887 0.29053772 0.38456461
--4.93646139 0.31591657 0.31991485 0.29161908 0.38916987
--4.91691105 0.31680931 0.32129770 0.29269131 0.39385177
--4.89736070 0.31770307 0.32267649 0.29375368 0.39860905
--4.87781036 0.31859713 0.32405026 0.29480546 0.40344034
--4.85826002 0.31949082 0.32541809 0.29584595 0.40834419
--4.83870968 0.32038343 0.32677905 0.29687444 0.41331902
--4.81915934 0.32127429 0.32813223 0.29789027 0.41836318
--4.79960899 0.32216274 0.32947674 0.29889274 0.42347491
--4.78005865 0.32304812 0.33081168 0.29988122 0.42865235
--4.76050831 0.32392979 0.33213619 0.30085506 0.43389358
--4.74095797 0.32480712 0.33344941 0.30181365 0.43919656
--4.72140762 0.32567952 0.33475052 0.30275638 0.44455918
--4.70185728 0.32654638 0.33603870 0.30368268 0.44997927
--4.68230694 0.32740716 0.33731315 0.30459200 0.45545454
--4.66275660 0.32826130 0.33857310 0.30548380 0.46098267
--4.64320626 0.32910828 0.33981780 0.30635758 0.46656124
--4.62365591 0.32994760 0.34104652 0.30721284 0.47218778
--4.60410557 0.33077879 0.34225856 0.30804914 0.47785976
--4.58455523 0.33160141 0.34345323 0.30886605 0.48357458
--4.56500489 0.33241502 0.34462988 0.30966315 0.48932962
--4.54545455 0.33321925 0.34578788 0.31044008 0.49512217
--4.52590420 0.33401372 0.34692662 0.31119648 0.50094952
--4.50635386 0.33479809 0.34804554 0.31193203 0.50680889
--4.48680352 0.33557205 0.34914407 0.31264645 0.51269748
--4.46725318 0.33633532 0.35022169 0.31333947 0.51861248
--4.44770283 0.33708765 0.35127791 0.31401085 0.52455103
--4.42815249 0.33782881 0.35231226 0.31466039 0.53051027
--4.40860215 0.33855860 0.35332428 0.31528792 0.53648733
--4.38905181 0.33927686 0.35431358 0.31589329 0.54247930
--4.36950147 0.33998343 0.35527974 0.31647638 0.54848332
--4.34995112 0.34067821 0.35622242 0.31703709 0.55449650
--4.33040078 0.34136111 0.35714127 0.31757537 0.56051596
--4.31085044 0.34203205 0.35803598 0.31809118 0.56653883
--4.29130010 0.34269101 0.35890626 0.31858450 0.57256227
--4.27174976 0.34333796 0.35975186 0.31905537 0.57858345
--4.25219941 0.34397292 0.36057253 0.31950381 0.58459957
--4.23264907 0.34459593 0.36136807 0.31992991 0.59060786
--4.21309873 0.34520703 0.36213827 0.32033374 0.59660557
--4.19354839 0.34580630 0.36288299 0.32071544 0.60259002
--4.17399804 0.34639383 0.36360206 0.32107514 0.60855853
--4.15444770 0.34696975 0.36429536 0.32141299 0.61450850
--4.13489736 0.34753417 0.36496280 0.32172919 0.62043736
--4.11534702 0.34808726 0.36560429 0.32202393 0.62634260
--4.09579668 0.34862917 0.36621977 0.32229745 0.63222176
--4.07624633 0.34916008 0.36680918 0.32254997 0.63807243
--4.05669599 0.34968019 0.36737251 0.32278177 0.64389229
--4.03714565 0.35018970 0.36790973 0.32299311 0.64967904
--4.01759531 0.35068883 0.36842087 0.32318430 0.65543047
--3.99804497 0.35117780 0.36890593 0.32335563 0.66114445
--3.97849462 0.35165685 0.36936495 0.32350743 0.66607967
--3.95894428 0.35212622 0.36979798 0.32364003 0.67088865
--3.93939394 0.35258618 0.37020509 0.32375378 0.67569095
--3.91984360 0.35303697 0.37058635 0.32384905 0.68048353
--3.90029326 0.35347885 0.37094184 0.32392619 0.68526345
--3.88074291 0.35391210 0.37127166 0.32398558 0.69002788
--3.86119257 0.35433698 0.37157593 0.32402762 0.69477409
--3.84164223 0.35475378 0.37185474 0.32405270 0.69949943
--3.82209189 0.35516275 0.37210824 0.32406121 0.70420138
--3.80254154 0.35556419 0.37233655 0.32405358 0.70887750
--3.78299120 0.35595836 0.37253982 0.32403020 0.71352546
--3.76344086 0.35634554 0.37271818 0.32399150 0.71814304
--3.74389052 0.35672600 0.37287180 0.32393791 0.72272810
--3.72434018 0.35710002 0.37300083 0.32386984 0.72727863
--3.70478983 0.35746787 0.37310544 0.32378772 0.73179269
--3.68523949 0.35782980 0.37318579 0.32369198 0.73626848
--3.66568915 0.35818609 0.37324205 0.32358305 0.74070425
--3.64613881 0.35853699 0.37327440 0.32346137 0.74509839
--3.62658847 0.35888275 0.37328302 0.32332736 0.74944936
--3.60703812 0.35922362 0.37326808 0.32318145 0.75375574
--3.58748778 0.35955985 0.37322976 0.32302407 0.75801618
--3.56793744 0.35989167 0.37316825 0.32285564 0.76222942
--3.54838710 0.36021932 0.37308373 0.32267660 0.76639432
--3.52883675 0.36054301 0.37297638 0.32248736 0.77050981
--3.50928641 0.36086296 0.37284639 0.32228834 0.77457490
--3.48973607 0.36117939 0.37269393 0.32207995 0.77858868
--3.47018573 0.36149250 0.37251919 0.32186261 0.78255036
--3.45063539 0.36180248 0.37232235 0.32163672 0.78645919
--3.43108504 0.36210952 0.37210359 0.32140268 0.79031451
--3.41153470 0.36241382 0.37186308 0.32116089 0.79411575
--3.39198436 0.36271553 0.37160101 0.32091174 0.79786239
--3.37243402 0.36301483 0.37131753 0.32065561 0.80155400
--3.35288368 0.36331188 0.37101284 0.32039289 0.80519021
--3.33333333 0.36360682 0.37068708 0.32012395 0.80877072
--3.31378299 0.36389981 0.37034043 0.31984915 0.81229530
--3.29423265 0.36419098 0.36997305 0.31956887 0.81576376
--3.27468231 0.36448046 0.36958509 0.31928344 0.81917600
--3.25513196 0.36476837 0.36917672 0.31899322 0.82253195
--3.23558162 0.36505483 0.36874807 0.31869855 0.82583161
--3.21603128 0.36533994 0.36829930 0.31839976 0.82907504
--3.19648094 0.36562381 0.36783056 0.31809719 0.83226232
--3.17693060 0.36590653 0.36734197 0.31779114 0.83539361
--3.15738025 0.36618819 0.36683367 0.31748193 0.83846910
--3.13782991 0.36646888 0.36630580 0.31716987 0.84148902
--3.11827957 0.36674865 0.36575847 0.31685526 0.84445365
--3.09872923 0.36702760 0.36519182 0.31653838 0.84736331
--3.07917889 0.36730577 0.36460594 0.31621951 0.85021835
--3.05962854 0.36758323 0.36400096 0.31589894 0.85301915
--3.04007820 0.36786002 0.36337697 0.31557693 0.85576614
--3.02052786 0.36813620 0.36273409 0.31525375 0.85845977
--3.00097752 0.36841181 0.36207240 0.31492964 0.86110051
--2.98142717 0.36868687 0.36139199 0.31460485 0.86368888
--2.96187683 0.36896143 0.36069296 0.31427963 0.86622540
--2.94232649 0.36923551 0.35997537 0.31395420 0.86871062
--2.92277615 0.36950913 0.35923931 0.31362880 0.87114513
--2.90322581 0.36978231 0.35848484 0.31330363 0.87352952
--2.88367546 0.37005506 0.35771203 0.31297891 0.87586441
--2.86412512 0.37032740 0.35692093 0.31265485 0.87815042
--2.84457478 0.37059933 0.35611159 0.31233164 0.88038820
--2.82502444 0.37087086 0.35528407 0.31200948 0.88257841
--2.80547410 0.37114199 0.35443839 0.31168854 0.88472172
--2.78592375 0.37141271 0.35357461 0.31136901 0.88681882
--2.76637341 0.37168301 0.35269274 0.31105106 0.88887039
--2.74682307 0.37195290 0.35179281 0.31073485 0.89087714
--2.72727273 0.37222235 0.35087484 0.31042055 0.89283977
--2.70772239 0.37249137 0.34993884 0.31010831 0.89475900
--2.68817204 0.37275992 0.34898482 0.30979827 0.89663554
--2.66862170 0.37302800 0.34801277 0.30949058 0.89847013
--2.64907136 0.37329558 0.34702268 0.30918537 0.90026347
--2.62952102 0.37356265 0.34601456 0.30888278 0.90201630
--2.60997067 0.37382919 0.34498837 0.30858292 0.90372935
--2.59042033 0.37409516 0.34394409 0.30828592 0.90540334
--2.57086999 0.37436055 0.34288169 0.30799190 0.90703900
--2.55131965 0.37462533 0.34180113 0.30770095 0.90863705
--2.53176931 0.37488947 0.34070238 0.30741319 0.91019823
--2.51221896 0.37515294 0.33958537 0.30712872 0.91172323
--2.49266862 0.37541573 0.33845005 0.30684763 0.91321279
--2.47311828 0.37567779 0.33729635 0.30657001 0.91466762
--2.45356794 0.37593911 0.33612422 0.30629594 0.91608841
--2.43401760 0.37619964 0.33493356 0.30602552 0.91747588
--2.41446725 0.37645936 0.33372429 0.30575880 0.91883071
--2.39491691 0.37671824 0.33249633 0.30549587 0.92015360
--2.37536657 0.37697625 0.33124957 0.30523680 0.92144523
--2.35581623 0.37723336 0.32998391 0.30498165 0.92270627
--2.33626588 0.37748954 0.32869922 0.30473048 0.92393739
--2.31671554 0.37774476 0.32739540 0.30448334 0.92513926
--2.29716520 0.37799899 0.32607232 0.30424029 0.92631251
--2.27761486 0.37825219 0.32472983 0.30400139 0.92745780
--2.25806452 0.37850435 0.32336779 0.30376667 0.92857575
--2.23851417 0.37875542 0.32198605 0.30353617 0.92966700
--2.21896383 0.37900539 0.32058445 0.30330995 0.93073215
--2.19941349 0.37925422 0.31916281 0.30308803 0.93177181
--2.17986315 0.37950189 0.31772096 0.30287045 0.93278658
--2.16031281 0.37974838 0.31625872 0.30265723 0.93377705
--2.14076246 0.37999364 0.31477587 0.30244841 0.93474379
--2.12121212 0.38023766 0.31327223 0.30224402 0.93568736
--2.10166178 0.38048042 0.31174757 0.30204406 0.93660833
--2.08211144 0.38072189 0.31020166 0.30184856 0.93750724
--2.06256109 0.38096205 0.30863427 0.30165754 0.93838462
--2.04301075 0.38120086 0.30704516 0.30147101 0.93924099
--2.02346041 0.38143833 0.30543406 0.30128899 0.94007688
--2.00391007 0.38167441 0.30380071 0.30111147 0.94089279
--1.98435973 0.38190910 0.30214483 0.30093848 0.94168921
--1.96480938 0.38214237 0.30046612 0.30077001 0.94246662
--1.94525904 0.38237421 0.29876429 0.30060607 0.94322550
--1.92570870 0.38260459 0.29703900 0.30044665 0.94396631
--1.90615836 0.38283351 0.29528995 0.30029176 0.94468950
--1.88660802 0.38306095 0.29351677 0.30014139 0.94539552
--1.86705767 0.38328689 0.29171912 0.29999555 0.94608479
--1.84750733 0.38351131 0.28989661 0.29985421 0.94675774
--1.82795699 0.38373422 0.28804887 0.29971737 0.94741478
--1.80840665 0.38395559 0.28617550 0.29958503 0.94805630
--1.78885630 0.38417542 0.28427606 0.29945716 0.94868271
--1.76930596 0.38439369 0.28235013 0.29933377 0.94929439
--1.74975562 0.38461040 0.28039725 0.29921482 0.94989169
--1.73020528 0.38482553 0.27841695 0.29910031 0.95047500
--1.71065494 0.38503909 0.27640875 0.29899021 0.95104466
--1.69110459 0.38525107 0.27437212 0.29888451 0.95160102
--1.67155425 0.38546146 0.27230653 0.29878319 0.95214440
--1.65200391 0.38567026 0.27021144 0.29868623 0.95267514
--1.63245357 0.38587746 0.26808627 0.29859359 0.95319355
--1.61290323 0.38608307 0.26593042 0.29850526 0.95369994
--1.59335288 0.38628708 0.26374326 0.29842122 0.95419460
--1.57380254 0.38648949 0.26152415 0.29834142 0.95467784
--1.55425220 0.38669030 0.25927240 0.29826586 0.95514992
--1.53470186 0.38688951 0.25698731 0.29819449 0.95561113
--1.51515152 0.38708713 0.25466815 0.29812729 0.95606172
--1.49560117 0.38728316 0.25231415 0.29806423 0.95650196
--1.47605083 0.38747760 0.24992451 0.29800528 0.95693210
--1.45650049 0.38767046 0.24749839 0.29795039 0.95735237
--1.43695015 0.38786174 0.24503493 0.29789955 0.95776302
--1.41739980 0.38805144 0.24253321 0.29785271 0.95816426
--1.39784946 0.38823958 0.23999229 0.29780985 0.95855632
--1.37829912 0.38842616 0.23741118 0.29777091 0.95893941
--1.35874878 0.38861120 0.23478883 0.29773588 0.95931374
--1.33919844 0.38879469 0.23212416 0.29770470 0.95967950
--1.31964809 0.38897665 0.22941604 0.29767735 0.96003688
--1.30009775 0.38915709 0.22666328 0.29765378 0.96038608
--1.28054741 0.38933602 0.22386463 0.29763395 0.96072727
--1.26099707 0.38951345 0.22101879 0.29761783 0.96106062
--1.24144673 0.38968940 0.21812439 0.29760537 0.96138631
--1.22189638 0.38986387 0.21518000 0.29759653 0.96170448
--1.20234604 0.39003688 0.21218409 0.29759127 0.96201530
--1.18279570 0.39020844 0.20913510 0.29758955 0.96231892
--1.16324536 0.39037857 0.20603135 0.29759132 0.96261547
--1.14369501 0.39054728 0.20287109 0.29759655 0.96290511
--1.12414467 0.39071459 0.19965248 0.29760518 0.96318796
--1.10459433 0.39088052 0.19637355 0.29761717 0.96346415
--1.08504399 0.39104507 0.19303228 0.29763248 0.96373380
--1.06549365 0.39120826 0.18962647 0.29765106 0.96399703
--1.04594330 0.39137012 0.18615385 0.29767287 0.96425397
--1.02639296 0.39153066 0.18261198 0.29769787 0.96450470
--1.00684262 0.39168990 0.17899831 0.29772599 0.96474935
--0.98729228 0.39184786 0.17531012 0.29775720 0.96498801
--0.96774194 0.39200455 0.17154451 0.29779146 0.96522078
--0.94819159 0.39215999 0.16769843 0.29782870 0.96544775
--0.92864125 0.39231420 0.16376861 0.29786890 0.96566902
--0.90909091 0.39246721 0.15975159 0.29791198 0.96588465
--0.88954057 0.39261903 0.15564368 0.29795792 0.96609474
--0.86999022 0.39276968 0.15144091 0.29800666 0.96629937
--0.85043988 0.39291918 0.14713908 0.29805815 0.96649861
--0.83088954 0.39306756 0.14273366 0.29811234 0.96669252
--0.81133920 0.39321483 0.13821982 0.29816918 0.96688118
--0.79178886 0.39336101 0.13359235 0.29822862 0.96706465
--0.77223851 0.39350614 0.12884566 0.29829062 0.96724300
--0.75268817 0.39365021 0.12397373 0.29835512 0.96741628
--0.73313783 0.39379327 0.11897006 0.29842207 0.96758455
--0.71358749 0.39393532 0.11382760 0.29849142 0.96774786
--0.69403715 0.39407640 0.10853873 0.29856312 0.96790626
--0.67448680 0.39421653 0.10309517 0.29863712 0.96805980
--0.65493646 0.39435571 0.09748790 0.29871337 0.96820853
--0.63538612 0.39449399 0.09170709 0.29879182 0.96835249
--0.61583578 0.39463138 0.08574196 0.29887242 0.96849172
--0.59628543 0.39476790 0.07958071 0.29895510 0.96862627
--0.57673509 0.39490358 0.07321033 0.29903984 0.96875616
--0.55718475 0.39503843 0.06661648 0.29912656 0.96888143
--0.53763441 0.39517249 0.05978327 0.29921522 0.96900212
--0.51808407 0.39530577 0.05269303 0.29930577 0.96911826
--0.49853372 0.39543829 0.02702221 0.29939816 0.96922987
--0.47898338 0.39557009 0.02710570 0.29949233 0.96933699
--0.45943304 0.39570118 0.02719048 0.29958823 0.96943964
--0.43988270 0.39583158 0.02727658 0.29968581 0.96953785
--0.42033236 0.39596132 0.02736399 0.29978501 0.96963164
--0.40078201 0.39609042 0.02745275 0.29988580 0.96972102
--0.38123167 0.39621890 0.02754285 0.29998810 0.96980603
--0.36168133 0.39634679 0.02763432 0.30009187 0.96988668
--0.34213099 0.39647411 0.02772717 0.30019707 0.96996299
--0.32258065 0.39660088 0.02782142 0.30030362 0.97003498
--0.30303030 0.39672712 0.02791707 0.30041150 0.97010265
--0.28347996 0.39685287 0.02801416 0.30052063 0.97016603
--0.26392962 0.39697813 0.02811268 0.30063097 0.97022513
--0.24437928 0.39710294 0.02821267 0.30074246 0.97027996
--0.22482893 0.39722731 0.02831413 0.30085507 0.97033053
--0.20527859 0.39735127 0.02841709 0.30096872 0.97037685
--0.18572825 0.39747485 0.02852157 0.30108337 0.97041893
--0.16617791 0.39759805 0.02862757 0.30119897 0.97045678
--0.14662757 0.39772092 0.02873512 0.30131547 0.97049041
--0.12707722 0.39784346 0.02884424 0.30143281 0.97051982
--0.10752688 0.39796571 0.02895495 0.30155094 0.97054502
--0.08797654 0.39808768 0.02906727 0.30166981 0.97056601
--0.06842620 0.39820940 0.02918122 0.30178937 0.97058280
--0.04887586 0.39833089 0.02929681 0.30190957 0.97059539
--0.02932551 0.39845217 0.02941408 0.30203035 0.97060378
--0.00977517 0.39857327 0.02953303 0.30215167 0.97060797
-0.00977517 0.39869420 0.02965370 0.30227347 0.97060797
-0.02932551 0.39881500 0.02977611 0.30239578 0.97060378
-0.04887586 0.39893568 0.02990027 0.30251870 0.97059539
-0.06842620 0.39905626 0.03002622 0.30264232 0.97058280
-0.08797654 0.39917677 0.03015397 0.30276673 0.97056601
-0.10752688 0.39929724 0.03028355 0.30289204 0.97054502
-0.12707722 0.39941767 0.03041499 0.30301833 0.97051982
-0.14662757 0.39953811 0.03054831 0.30314572 0.97049041
-0.16617791 0.39965856 0.03068353 0.30327430 0.97045678
-0.18572825 0.39977905 0.03082068 0.30340416 0.97041893
-0.20527859 0.39989961 0.03095980 0.30353540 0.97037685
-0.22482893 0.40002026 0.03110089 0.30366813 0.97033053
-0.24437928 0.40014101 0.03124400 0.30380243 0.97027996
-0.26392962 0.40026190 0.03138915 0.30393841 0.97022513
-0.28347996 0.40038295 0.03153637 0.30407617 0.97016603
-0.30303030 0.40050418 0.03168569 0.30421581 0.97010265
-0.32258065 0.40062561 0.03183714 0.30435742 0.97003498
-0.34213099 0.40074727 0.03199074 0.30450111 0.96996299
-0.36168133 0.40086919 0.03214654 0.30464697 0.96988668
-0.38123167 0.40099137 0.03230455 0.30479511 0.96980603
-0.40078201 0.40111386 0.03246482 0.30494562 0.96972102
-0.42033236 0.40123667 0.03262737 0.30509860 0.96963164
-0.43988270 0.40135983 0.03279223 0.30525416 0.96953785
-0.45943304 0.40148337 0.03295945 0.30541239 0.96943964
-0.47898338 0.40160730 0.03312905 0.30557341 0.96933699
-0.49853372 0.40173166 0.03330108 0.30573729 0.96922987
-0.51808407 0.40185647 0.05922858 0.30590416 0.96911826
-0.53763441 0.40198175 0.06657672 0.30607411 0.96900212
-0.55718475 0.40210754 0.07366911 0.30624724 0.96888143
-0.57673509 0.40223386 0.08052345 0.30642365 0.96875616
-0.59628543 0.40236073 0.08715568 0.30660345 0.96862627
-0.61583578 0.40248819 0.09358021 0.30678673 0.96849172
-0.63538612 0.40261626 0.09981007 0.30697361 0.96835249
-0.65493646 0.40274497 0.10585714 0.30716418 0.96820853
-0.67448680 0.40287435 0.11173223 0.30735855 0.96805980
-0.69403715 0.40300443 0.11744524 0.30755682 0.96790626
-0.71358749 0.40313524 0.12300522 0.30775909 0.96774786
-0.73313783 0.40326681 0.12842052 0.30796547 0.96758455
-0.75268817 0.40339917 0.13369880 0.30817607 0.96741628
-0.77223851 0.40353235 0.13884717 0.30839098 0.96724300
-0.79178886 0.40366639 0.14387218 0.30861031 0.96706465
-0.81133920 0.40380131 0.14877990 0.30883417 0.96688118
-0.83088954 0.40393715 0.15357598 0.30906267 0.96669252
-0.85043988 0.40407395 0.15826569 0.30929590 0.96649861
-0.86999022 0.40421174 0.16285390 0.30953397 0.96629937
-0.88954057 0.40435056 0.16734521 0.30977699 0.96609474
-0.90909091 0.40449043 0.17174388 0.31002508 0.96588465
-0.92864125 0.40463141 0.17605391 0.31027832 0.96566902
-0.94819159 0.40477353 0.18027907 0.31053684 0.96544775
-0.96774194 0.40491682 0.18442287 0.31080073 0.96522078
-0.98729228 0.40506134 0.18848864 0.31107011 0.96498801
-1.00684262 0.40520711 0.19247951 0.31134509 0.96474935
-1.02639296 0.40535418 0.19639840 0.31162577 0.96450470
-1.04594330 0.40550260 0.20024811 0.31191226 0.96425397
-1.06549365 0.40565241 0.20403127 0.31220468 0.96399703
-1.08504399 0.40580365 0.20775035 0.31250312 0.96373380
-1.10459433 0.40595638 0.21140771 0.31280771 0.96346415
-1.12414467 0.40611063 0.21500558 0.31311855 0.96318796
-1.14369501 0.40626646 0.21854609 0.31343575 0.96290511
-1.16324536 0.40642392 0.22203123 0.31375942 0.96261547
-1.18279570 0.40658305 0.22546293 0.31408968 0.96231892
-1.20234604 0.40674392 0.22884301 0.31442663 0.96201530
-1.22189638 0.40690658 0.23217320 0.31477040 0.96170448
-1.24144673 0.40707108 0.23545515 0.31512109 0.96138631
-1.26099707 0.40723748 0.23869044 0.31547881 0.96106062
-1.28054741 0.40740583 0.24188058 0.31584368 0.96072727
-1.30009775 0.40757621 0.24502701 0.31621581 0.96038608
-1.31964809 0.40774867 0.24813110 0.31659532 0.96003688
-1.33919844 0.40792327 0.25119417 0.31698232 0.95967950
-1.35874878 0.40810008 0.25421749 0.31737693 0.95931374
-1.37829912 0.40827917 0.25720227 0.31777926 0.95893941
-1.39784946 0.40846060 0.26014966 0.31818942 0.95855632
-1.41739980 0.40864445 0.26306079 0.31860755 0.95816426
-1.43695015 0.40883079 0.26593671 0.31903374 0.95776302
-1.45650049 0.40901969 0.26877848 0.31946812 0.95735237
-1.47605083 0.40921123 0.27158706 0.31991081 0.95693210
-1.49560117 0.40940549 0.27436342 0.32036193 0.95650196
-1.51515152 0.40960255 0.27710847 0.32082159 0.95606172
-1.53470186 0.40980249 0.27982310 0.32128991 0.95561113
-1.55425220 0.41000539 0.28250816 0.32176702 0.95514992
-1.57380254 0.41021136 0.28516447 0.32225302 0.95467784
-1.59335288 0.41042046 0.28779284 0.32274806 0.95419460
-1.61290323 0.41063280 0.29039402 0.32325223 0.95369994
-1.63245357 0.41084847 0.29296875 0.32376568 0.95319355
-1.65200391 0.41106757 0.29551777 0.32428851 0.95267514
-1.67155425 0.41129019 0.29804175 0.32482085 0.95214440
-1.69110459 0.41151644 0.30054138 0.32536283 0.95160102
-1.71065494 0.41174642 0.30301730 0.32591456 0.95104466
-1.73020528 0.41198024 0.30547015 0.32647618 0.95047500
-1.74975562 0.41221802 0.30790053 0.32704780 0.94989169
-1.76930596 0.41245985 0.31030905 0.32762956 0.94929439
-1.78885630 0.41270586 0.31269628 0.32822157 0.94868271
-1.80840665 0.41295616 0.31506279 0.32882396 0.94805630
-1.82795699 0.41321089 0.31740911 0.32943686 0.94741478
-1.84750733 0.41347015 0.31973578 0.33006040 0.94675774
-1.86705767 0.41373409 0.32204331 0.33069471 0.94608479
-1.88660802 0.41400282 0.32433220 0.33133990 0.94539552
-1.90615836 0.41427649 0.32660296 0.33199611 0.94468950
-1.92570870 0.41455522 0.32885604 0.33266348 0.94396631
-1.94525904 0.41483917 0.33109193 0.33334212 0.94322550
-1.96480938 0.41512847 0.33331107 0.33403217 0.94246662
-1.98435973 0.41542327 0.33551390 0.33473375 0.94168921
-2.00391007 0.41572373 0.33770086 0.33544701 0.94089279
-2.02346041 0.41602999 0.33987237 0.33617207 0.94007688
-2.04301075 0.41634221 0.34202886 0.33690906 0.93924099
-2.06256109 0.41666056 0.34417071 0.33765812 0.93838462
-2.08211144 0.41698519 0.34629833 0.33841937 0.93750724
-2.10166178 0.41731628 0.34841211 0.33919295 0.93660833
-2.12121212 0.41765400 0.35051242 0.33997900 0.93568736
-2.14076246 0.41799853 0.35259965 0.34077764 0.93474379
-2.16031281 0.41835004 0.35467416 0.34158902 0.93377705
-2.17986315 0.41870872 0.35673630 0.34241327 0.93278658
-2.19941349 0.41907476 0.35878644 0.34325051 0.93177181
-2.21896383 0.41944834 0.36082491 0.34410090 0.93073215
-2.23851417 0.41982967 0.36285207 0.34496456 0.92966700
-2.25806452 0.42021893 0.36486824 0.34584163 0.92857575
-2.27761486 0.42061635 0.36687376 0.34673225 0.92745780
-2.29716520 0.42102212 0.36886895 0.34763655 0.92631251
-2.31671554 0.42143645 0.37085414 0.34855468 0.92513926
-2.33626588 0.42185957 0.37282964 0.34948677 0.92393739
-2.35581623 0.42229169 0.37479577 0.35043295 0.92270627
-2.37536657 0.42273303 0.37675284 0.35139337 0.92144523
-2.39491691 0.42318383 0.37870114 0.35236817 0.92015360
-2.41446725 0.42364432 0.38064099 0.35335748 0.91883071
-2.43401760 0.42411473 0.38257267 0.35436144 0.91747588
-2.45356794 0.42459530 0.38449650 0.35538020 0.91608841
-2.47311828 0.42508629 0.38641275 0.35641389 0.91466762
-2.49266862 0.42558794 0.38832172 0.35746266 0.91321279
-2.51221896 0.42610050 0.39022370 0.35852664 0.91172323
-2.53176931 0.42662423 0.39211897 0.35960597 0.91019823
-2.55131965 0.42715941 0.39400781 0.36070079 0.90863705
-2.57086999 0.42770628 0.39589052 0.36181125 0.90703900
-2.59042033 0.42826512 0.39776735 0.36293748 0.90540334
-2.60997067 0.42883622 0.39963860 0.36407963 0.90372935
-2.62952102 0.42941984 0.40150454 0.36523784 0.90201630
-2.64907136 0.43001627 0.40336544 0.36641224 0.90026347
-2.66862170 0.43062579 0.40522158 0.36760298 0.89847013
-2.68817204 0.43124871 0.40707323 0.36881020 0.89663554
-2.70772239 0.43188530 0.40892066 0.37003404 0.89475900
-2.72727273 0.43253588 0.41076414 0.37127464 0.89283977
-2.74682307 0.43320075 0.41260394 0.37253214 0.89087714
-2.76637341 0.43388020 0.41444034 0.37380669 0.88887039
-2.78592375 0.43457456 0.41627360 0.37509841 0.88681882
-2.80547410 0.43528413 0.41810399 0.37640745 0.88472172
-2.82502444 0.43600923 0.41993178 0.37773396 0.88257841
-2.84457478 0.43675018 0.42175723 0.37907806 0.88038820
-2.86412512 0.43750731 0.42358063 0.38043990 0.87815042
-2.88367546 0.43828094 0.42540223 0.38181962 0.87586441
-2.90322581 0.43907140 0.42722230 0.38321736 0.87352952
-2.92277615 0.43987902 0.42904112 0.38463325 0.87114513
-2.94232649 0.44070415 0.43085895 0.38606743 0.86871062
-2.96187683 0.44154710 0.43267607 0.38752004 0.86622540
-2.98142717 0.44240824 0.43449274 0.38899122 0.86368888
-3.00097752 0.44328789 0.43630924 0.39048109 0.86110051
-3.02052786 0.44418641 0.43812584 0.39198980 0.85845977
-3.04007820 0.44510413 0.43994281 0.39351747 0.85576614
-3.05962854 0.44604141 0.44176043 0.39506425 0.85301915
-3.07917889 0.44699859 0.44357897 0.39663027 0.85021835
-3.09872923 0.44797603 0.44539870 0.39821565 0.84736331
-3.11827957 0.44897407 0.44721990 0.39982052 0.84445365
-3.13782991 0.44999308 0.44904286 0.40144503 0.84148902
-3.15738025 0.45103339 0.45086784 0.40308929 0.83846910
-3.17693060 0.45209536 0.45269513 0.40475343 0.83539361
-3.19648094 0.45317935 0.45452500 0.40643757 0.83226232
-3.21603128 0.45428571 0.45635774 0.40814185 0.82907504
-3.23558162 0.45541479 0.45819363 0.40986639 0.82583161
-3.25513196 0.45656693 0.46003295 0.41161130 0.82253195
-3.27468231 0.45774250 0.46187599 0.41337671 0.81917600
-3.29423265 0.45894184 0.46372302 0.41516274 0.81576376
-3.31378299 0.46016529 0.46557435 0.41696950 0.81229530
-3.33333333 0.46141320 0.46743024 0.41879711 0.80877072
-3.35288368 0.46268591 0.46929099 0.42064567 0.80519021
-3.37243402 0.46398377 0.47115689 0.42251531 0.80155400
-3.39198436 0.46530710 0.47302822 0.42440612 0.79786239
-3.41153470 0.46665624 0.47490527 0.42631822 0.79411575
-3.43108504 0.46803152 0.47678833 0.42825170 0.79031451
-3.45063539 0.46943327 0.47867768 0.43020668 0.78645919
-3.47018573 0.47086180 0.48057362 0.43218323 0.78255036
-3.48973607 0.47231743 0.48247644 0.43418147 0.77858868
-3.50928641 0.47380048 0.48438641 0.43620148 0.77457490
-3.52883675 0.47531124 0.48630384 0.43824335 0.77050981
-3.54838710 0.47685002 0.48822899 0.44030716 0.76639432
-3.56793744 0.47841710 0.49016217 0.44239299 0.76222942
-3.58748778 0.48001278 0.49210365 0.44450093 0.75801618
-3.60703812 0.48163733 0.49405371 0.44663104 0.75375574
-3.62658847 0.48329102 0.49601264 0.44878339 0.74944936
-3.64613881 0.48497412 0.49798072 0.45095805 0.74509839
-3.66568915 0.48668688 0.49995821 0.45315507 0.74070425
-3.68523949 0.48842954 0.50194540 0.45537451 0.73626848
-3.70478983 0.49020234 0.50394256 0.45761641 0.73179269
-3.72434018 0.49200551 0.50594994 0.45988082 0.72727863
-3.74389052 0.49383927 0.50796783 0.46216778 0.72272810
-3.76344086 0.49570382 0.50999646 0.46447730 0.71814304
-3.78299120 0.49759935 0.51203610 0.46680943 0.71352546
-3.80254154 0.49952606 0.51408701 0.46916416 0.70887750
-3.82209189 0.50148411 0.51614941 0.47154152 0.70420138
-3.84164223 0.50347366 0.51822356 0.47394150 0.69949943
-3.86119257 0.50549486 0.52030968 0.47636409 0.69477409
-3.88074291 0.50754785 0.52240801 0.47880928 0.69002788
-3.90029326 0.50963274 0.52451875 0.48127704 0.68526345
-3.91984360 0.51174965 0.52664211 0.48376734 0.68048353
-3.93939394 0.51389867 0.52877831 0.48628014 0.67569095
-3.95894428 0.51607987 0.53092754 0.48881538 0.67088865
-3.97849462 0.51829332 0.53308997 0.49137299 0.66607967
-3.99804497 0.52053908 0.53526579 0.49395290 0.66126712
-4.01759531 0.52281717 0.53745515 0.49655503 0.65645423
-4.03714565 0.52512761 0.53965822 0.49917927 0.65164432
-4.05669599 0.52747040 0.54187512 0.50182551 0.64684078
-4.07624633 0.52984553 0.54410600 0.50449362 0.64204710
-4.09579668 0.53225297 0.54635096 0.50718347 0.63726685
-4.11534702 0.53469265 0.54861012 0.50989490 0.63250367
-4.13489736 0.53716452 0.55088356 0.51262775 0.62776129
-4.15444770 0.53966849 0.55317135 0.51538183 0.62304350
-4.17399804 0.54220446 0.55547356 0.51815694 0.61835416
-4.19354839 0.54477229 0.55779023 0.52095288 0.61369720
-4.21309873 0.54737185 0.56012140 0.52376941 0.60907659
-4.23264907 0.55000298 0.56246706 0.52660628 0.60449637
-4.25219941 0.55266550 0.56482723 0.52946322 0.59996060
-4.27174976 0.55535920 0.56720187 0.53233996 0.59547341
-4.29130010 0.55808386 0.56959095 0.53523620 0.59103894
-4.31085044 0.56083925 0.57199441 0.53815161 0.58666137
-4.33040078 0.56362510 0.57441217 0.54108585 0.58234490
-4.34995112 0.56644112 0.57684414 0.54403858 0.57809373
-4.36950147 0.56928702 0.57929020 0.54700940 0.57391209
-4.38905181 0.57216247 0.58175021 0.54999792 0.56980419
-4.40860215 0.57506712 0.58422403 0.55300373 0.56577423
-4.42815249 0.57800060 0.58671148 0.55602638 0.56182640
-4.44770283 0.58096254 0.58921236 0.55906541 0.55796486
-4.46725318 0.58395251 0.59172646 0.56212036 0.55419374
-4.48680352 0.58697008 0.59425354 0.56519070 0.55051713
-4.50635386 0.59001480 0.59679334 0.56827592 0.54693907
-4.52590420 0.59308621 0.59934560 0.57137549 0.54346354
-4.54545455 0.59618378 0.60191000 0.57448882 0.54009445
-4.56500489 0.59930702 0.60448623 0.57761535 0.53683563
-4.58455523 0.60245538 0.60707397 0.58075446 0.53369084
-4.60410557 0.60562829 0.60967284 0.58390552 0.53066374
-4.62365591 0.60882517 0.61228247 0.58706790 0.52775789
-4.64320626 0.61204543 0.61490247 0.59024092 0.52497674
-4.66275660 0.61528842 0.61753242 0.59342389 0.52232362
-4.68230694 0.61855351 0.62017190 0.59661613 0.51980173
-4.70185728 0.62184004 0.62282044 0.59981689 0.51741416
-4.72140762 0.62514730 0.62547759 0.60302544 0.51516383
-4.74095797 0.62847459 0.62814287 0.60624103 0.51305353
-4.76050831 0.63182120 0.63081577 0.60946287 0.51108589
-4.78005865 0.63518636 0.63349578 0.61269018 0.50926338
-4.79960899 0.63856932 0.63618238 0.61592215 0.50758830
-4.81915934 0.64196929 0.63887503 0.61915797 0.50606278
-4.83870968 0.64538547 0.64157318 0.62239680 0.50468876
-4.85826002 0.64881705 0.64427626 0.62563779 0.50346801
-4.87781036 0.65226318 0.64698371 0.62888010 0.50240209
-4.89736070 0.65572301 0.64969495 0.63212285 0.50149240
-4.91691105 0.65919569 0.65240939 0.63536518 0.50074011
-4.93646139 0.66268033 0.65512643 0.63860621 0.50014620
-4.95601173 0.66617603 0.65784548 0.64184504 0.49971146
-4.97556207 0.66968188 0.66056593 0.64508078 0.49943646
-4.99511241 0.67319697 0.66328718 0.64831254 0.49932156
-5.01466276 0.67672036 0.66600862 0.65153943 0.49936694
-5.03421310 0.68025111 0.66872965 0.65476053 0.49957254
-5.05376344 0.68378826 0.67144964 0.65797495 0.49993810
-5.07331378 0.68733086 0.67416801 0.66118179 0.50046317
-5.09286413 0.69087793 0.67688415 0.66438017 0.50114708
-5.11241447 0.69442850 0.67959745 0.66756917 0.50198896
-5.13196481 0.69798158 0.68230734 0.67074794 0.50298772
-5.15151515 0.70153618 0.68501322 0.67391557 0.50414211
-5.17106549 0.70509133 0.68771452 0.67707121 0.50545064
-5.19061584 0.70864600 0.69041066 0.68021399 0.50691167
-5.21016618 0.71219922 0.69310110 0.68334306 0.50852334
-5.22971652 0.71574999 0.69578529 0.68645759 0.51028363
-5.24926686 0.71929730 0.69846268 0.68955675 0.51219033
-5.26881720 0.72284016 0.70113276 0.69263974 0.51424107
-5.28836755 0.72637758 0.70379502 0.69570575 0.51643329
-5.30791789 0.72990856 0.70644897 0.69875400 0.51876431
-5.32746823 0.73343212 0.70909413 0.70178375 0.52123127
-5.34701857 0.73694728 0.71173004 0.70479424 0.52383116
-5.36656891 0.74045306 0.71435626 0.70778476 0.52834849
-5.38611926 0.74394850 0.71697236 0.71075459 0.53319112
-5.40566960 0.74743264 0.71957793 0.71370307 0.53808403
-5.42521994 0.75090453 0.72217258 0.71662953 0.54302486
-5.44477028 0.75436324 0.72475594 0.71953333 0.54801114
-5.46432063 0.75780784 0.72732767 0.72241387 0.55304039
-5.48387097 0.76123741 0.72988742 0.72527054 0.55811004
-5.50342131 0.76465106 0.73243490 0.72810280 0.56321751
-5.52297165 0.76804790 0.73496980 0.73091008 0.56836017
-5.54252199 0.77142706 0.73749186 0.73369189 0.57353534
-5.56207234 0.77478769 0.74000083 0.73644772 0.57874032
-5.58162268 0.77812895 0.74249647 0.73917711 0.58397239
-5.60117302 0.78145002 0.74497859 0.74187963 0.58922882
-5.62072336 0.78475011 0.74744698 0.74455485 0.59450683
-5.64027370 0.78802843 0.74990149 0.74720240 0.59980366
-5.65982405 0.79128423 0.75234195 0.74982190 0.60511654
-5.67937439 0.79451675 0.75476825 0.75241302 0.61044269
-5.69892473 0.79772529 0.75718028 0.75497545 0.61577935
-5.71847507 0.80090915 0.75957794 0.75750891 0.62112374
-5.73802542 0.80406764 0.76196116 0.76001313 0.62647314
-5.75757576 0.80720013 0.76432990 0.76248788 0.63182481
-5.77712610 0.81030597 0.76668411 0.76493294 0.63717604
-5.79667644 0.81338457 0.76902378 0.76734814 0.64252415
-5.81622678 0.81643535 0.77134891 0.76973330 0.64786651
-5.83577713 0.81945775 0.77365952 0.77208829 0.65320049
-5.85532747 0.82245123 0.77595565 0.77441300 0.65852353
-5.87487781 0.82541529 0.77823733 0.77670732 0.66383309
-5.89442815 0.82834944 0.78050464 0.77897120 0.66912668
-5.91397849 0.83125324 0.78275765 0.78120457 0.67440188
-5.93352884 0.83412624 0.78499646 0.78340742 0.67965630
-5.95307918 0.83696804 0.78722118 0.78557972 0.68488761
-5.97262952 0.83977827 0.78943193 0.78772150 0.69009354
-5.99217986 0.84255656 0.79162883 0.78983279 0.69527187
-6.01173021 0.84530258 0.79381204 0.79191363 0.70042046
-6.03128055 0.84801604 0.79598171 0.79396409 0.70553722
-6.05083089 0.85069664 0.79813800 0.79598427 0.71062014
-6.07038123 0.85334414 0.80028109 0.79797425 0.71566727
-6.08993157 0.85595830 0.80241118 0.79993416 0.72067672
-6.10948192 0.85853893 0.80452845 0.80186413 0.72564668
-6.12903226 0.86108583 0.80663311 0.80376431 0.73057543
-6.14858260 0.86359885 0.80872538 0.80563486 0.73546128
-6.16813294 0.86607786 0.81080547 0.80747596 0.74030266
-6.18768328 0.86852275 0.81287361 0.80928779 0.74509805
-6.20723363 0.87093343 0.81493003 0.81107057 0.74984600
-6.22678397 0.87330984 0.81697498 0.81282449 0.75454514
-6.24633431 0.87565193 0.81900870 0.81454979 0.75919419
-6.26588465 0.87795968 0.82103143 0.81624669 0.76379192
-6.28543500 0.88023310 0.82304345 0.81791545 0.76833719
-6.30498534 0.88247220 0.82504500 0.81955631 0.77282893
-6.32453568 0.88467703 0.82703636 0.82116954 0.77726615
-6.34408602 0.88684765 0.82901778 0.82275541 0.78164793
-6.36363636 0.88898414 0.83098955 0.82431419 0.78597341
-6.38318671 0.89108660 0.83295193 0.82584617 0.79024181
-6.40273705 0.89315515 0.83490520 0.82735164 0.79445242
-6.42228739 0.89518992 0.83684964 0.82883089 0.79860462
-6.44183773 0.89719107 0.83878553 0.83028423 0.80269781
-6.46138807 0.89915876 0.84071316 0.83171196 0.80673151
-6.48093842 0.90109317 0.84263280 0.97483764 0.81070526
-6.50048876 0.90299452 0.84454476 0.97547436 0.81461869
-6.52003910 0.90486301 0.84644930 0.97608412 0.81847150
-6.53958944 0.90669887 0.84834672 0.97666772 0.82226342
-6.55913978 0.90850234 0.85023730 0.97722592 0.82599427
-6.57869013 0.91027368 0.85212134 0.97775947 0.82966390
-6.59824047 0.91201316 0.85399912 0.97826913 0.83327224
-6.61779081 0.91372105 0.85587093 0.97875562 0.83681926
-6.63734115 0.91539764 0.85773706 0.97921968 0.84030499
-6.65689150 0.91704323 0.85959780 0.97966202 0.84372951
-6.67644184 0.91865814 0.86145344 0.98008333 0.84709293
-6.69599218 0.92024267 0.86330426 0.98048432 0.85039543
-6.71554252 0.92179717 0.86515054 0.98086564 0.85363723
-6.73509286 0.92332196 0.86699259 0.98122798 0.85681859
-6.75464321 0.92481739 0.86883067 0.98157197 0.85993981
-6.77419355 0.92628380 0.87066509 0.98189825 0.86300123
-6.79374389 0.92772156 0.87249611 0.98220746 0.86600323
-6.81329423 0.92913103 0.87432403 0.98250020 0.86894621
-6.83284457 0.93051258 0.87614913 0.98277707 0.87183064
-6.85239492 0.93186657 0.87797168 0.98303866 0.87465700
-6.87194526 0.93319339 0.87979197 0.98328553 0.87742578
-6.89149560 0.93449342 0.88161029 0.98351826 0.88013753
-6.91104594 0.93576703 0.88342689 0.98373738 0.88279282
-6.93059629 0.93701463 0.88524208 0.98394343 0.88539223
-6.95014663 0.93823660 0.88705612 0.98413693 0.88793639
-6.96969697 0.93943333 0.88886929 0.98431839 0.89042593
-6.98924731 0.94060521 0.89068186 0.98448831 0.89286151
-7.00879765 0.94175264 0.89249411 0.98464716 0.89524380
-7.02834800 0.94287603 0.89430632 0.98479541 0.89757349
-7.04789834 0.94397575 0.89611875 0.98493353 0.89985130
-7.06744868 0.94505222 0.89793168 0.98506196 0.90207795
-7.08699902 0.94610582 0.89974539 1.00259247 0.90425418
-7.10654936 0.94713696 0.90156014 1.00238083 0.90638073
-7.12609971 0.94814602 0.90337620 1.00216769 0.90845837
-7.14565005 0.94913341 0.90519386 1.00195327 0.91048786
-7.16520039 0.95009951 0.90701337 1.00173781 0.91246998
-7.18475073 0.95104471 0.90883501 1.00152151 0.91440550
-7.20430108 0.95196941 0.91065904 1.00130460 0.91629523
-7.22385142 0.95287399 0.91248575 1.00108726 0.91813995
-7.24340176 0.95375884 0.91431540 1.00086971 0.91994046
-7.26295210 0.95462433 0.91614827 1.00065213 0.92169756
-7.28250244 0.95547085 0.91798461 1.00043469 0.92341204
-7.30205279 0.95629877 0.91982472 1.00021759 0.92508472
-7.32160313 0.95710846 0.92166885 1.00000098 0.92671639
-7.34115347 0.95790029 0.92351729 0.99978504 0.92830784
-7.36070381 0.95867463 0.92537030 0.99956992 0.92985989
-7.38025415 0.95943184 0.92722817 0.99935578 0.93137332
-7.39980450 0.96017227 0.92909117 0.99914275 0.93284893
-7.41935484 0.96089627 0.93095958 0.99893099 0.93428750
-7.43890518 0.96160420 0.93283368 0.99872062 0.93568982
-7.45845552 0.96229640 0.93471375 0.99851177 0.93705667
-7.47800587 0.96297321 0.93660007 0.99830458 0.93838882
-7.49755621 0.96363497 0.93849292 0.99809915 0.93968703
-7.51710655 0.96428200 0.94039260 0.99789560 0.94095207
-7.53665689 0.96491463 0.94229940 0.99769404 0.94218468
-7.55620723 0.96553319 0.94421361 0.99749457 0.94338562
-7.57575758 0.96613799 0.94613551 0.99729729 0.94455562
-7.59530792 0.96672933 0.94806541 0.99710230 0.94569540
-7.61485826 0.96730754 0.95000362 0.99690968 0.94680568
-7.63440860 0.96787291 0.95195042 0.99671952 0.94788718
-7.65395894 0.96842573 0.95390614 0.99653190 0.94894060
-7.67350929 0.96896631 0.95587107 0.99634690 0.94996661
-7.69305963 0.96949491 0.95784555 0.99616458 0.95096592
-7.71260997 0.97001184 0.95982988 0.99598502 0.95193918
-7.73216031 0.97051736 0.96182438 0.99580829 0.95288706
-7.75171065 0.97101174 0.96382940 0.99563443 0.95381020
-7.77126100 0.97149526 0.96584525 0.99546352 0.95470925
-7.79081134 0.97196816 0.96787229 0.99529559 0.95558483
-7.81036168 0.97243072 0.96991084 0.99513071 0.95643756
-7.82991202 0.97288318 0.97196127 0.99496892 0.95726805
-7.84946237 0.97332579 0.97402392 0.99481026 0.95807688
-7.86901271 0.97375878 0.97609916 0.99465476 0.95886465
-7.88856305 0.97418240 0.97818736 0.99450248 0.95963193
-7.90811339 0.97459688 0.98028888 0.99435344 0.96037927
-7.92766373 0.97500244 0.98240413 0.99420766 0.96110724
-7.94721408 0.97539930 0.98453348 0.99406519 0.96181636
-7.96676442 0.97578769 0.98667733 0.99392605 0.96250716
-7.98631476 0.97616781 0.98883609 0.99379025 0.96318017
-8.00586510 0.97653987 0.99101018 0.99365782 0.96383588
-8.02541544 0.97690408 0.99320002 0.99352877 0.96447478
-8.04496579 0.97726064 0.99540605 0.99340312 0.96509738
-8.06451613 0.97760973 0.99762871 0.99328089 0.96570412
-8.08406647 0.97795155 0.99986845 0.99316207 0.96629548
-8.10361681 0.97828628 1.00212575 0.99304669 0.96687191
-8.12316716 0.97861410 1.00440109 0.99293474 0.96743383
-8.14271750 0.97893519 1.00669495 0.99282623 0.96798170
-8.16226784 0.97924973 1.00900784 0.99272116 0.96851591
-8.18181818 0.97955787 1.01134027 0.99261953 0.96903688
-8.20136852 0.97985979 1.01369278 0.99252134 0.96954500
-8.22091887 0.98015563 1.01606592 0.99242658 0.97004067
-8.24046921 0.98044557 1.01846025 0.99233525 0.97052425
-8.26001955 0.98072974 1.02087634 0.99224733 0.97099612
-8.27956989 0.98100831 1.02331480 0.99216283 0.97145664
-8.29912023 0.98128140 1.02577623 0.99208172 0.97190614
-8.31867058 0.98154917 1.02826127 0.99200400 0.97234497
-8.33822092 0.98181174 1.03077057 0.99192965 0.97277346
-8.35777126 0.98206926 1.03330481 0.99185866 0.97319192
-8.37732160 0.98232185 1.03586468 0.99179100 0.97360067
-8.39687195 0.98256963 1.03845090 0.99172666 0.97400001
-8.41642229 0.98281274 1.04106421 0.99166562 0.97439022
-8.43597263 0.98305128 1.04370538 0.99160786 0.97477159
-8.45552297 0.98328538 1.04637521 0.99155335 0.97514441
-8.47507331 0.98351515 1.04907452 0.99150208 0.97550893
-8.49462366 0.98374070 1.05180416 0.99145401 0.97586541
-8.51417400 0.98396213 1.05456502 0.99140911 0.97621410
-8.53372434 0.98417955 1.05735801 0.99136737 0.97655526
-8.55327468 0.98439305 1.06018409 0.99132875 0.97688910
-8.57282502 0.98460275 1.06304425 0.99129323 0.97721587
-8.59237537 0.98480873 1.06593951 0.99126076 0.97753578
-8.61192571 0.98501108 1.06887095 0.99123133 0.97784904
-8.63147605 0.98520990 1.07183967 0.99120489 0.97815586
-8.65102639 0.98540526 1.07484684 0.99118142 0.97845644
-8.67057674 0.98559727 1.07789367 0.99116087 0.97875098
-8.69012708 0.98578599 1.08098141 0.99114322 0.97903965
-8.70967742 0.98597150 1.08411138 0.99112843 0.97932265
-8.72922776 0.98615390 1.08728495 0.99111645 0.97960014
-8.74877810 0.98633324 1.09050355 0.99110726 0.97987228
-8.76832845 0.98650960 1.09376870 0.99110080 0.98013926
-8.78787879 0.98668306 1.09708195 0.99109706 0.98040121
-8.80742913 0.98685368 1.10044496 0.99109597 0.98065828
-8.82697947 0.98702152 1.10385944 0.99109750 0.98091064
-8.84652981 0.98718666 1.10732722 0.99110161 0.98115841
-8.86608016 0.98734915 1.11085019 0.99110826 0.98140172
-8.88563050 0.98750905 1.11443035 0.99111740 0.98164072
-8.90518084 0.98766643 1.11806981 0.99112899 0.98187552
-8.92473118 0.98782133 1.12177078 0.99114299 0.98210624
-8.94428152 0.98797382 1.12553560 0.99115934 0.98233301
-8.96383187 0.98812395 1.12936673 0.99117801 0.98255592
-8.98338221 0.98827177 1.13326677 0.99119894 0.98277510
-9.00293255 0.98841732 1.13723848 0.99122209 0.98299063
-9.02248289 0.98856067 1.14128478 0.99124742 0.98320263
-9.04203324 0.98870185 1.14540875 0.99127487 0.98341118
-9.06158358 0.98884091 1.14961369 0.99130439 0.98361638
-9.08113392 0.98897789 1.15390306 0.99133594 0.98381831
-9.10068426 0.98911284 1.15828058 0.99136946 0.98401706
-9.12023460 0.98924580 1.16275020 0.99140491 0.98421271
-9.13978495 0.98937681 1.16731614 0.99144224 0.98440534
-9.15933529 0.98950591 1.17198289 0.99148138 0.98459502
-9.17888563 0.98963313 1.17675529 0.99152230 0.98478183
-9.19843597 0.98975852 1.18163850 0.99156495 0.98496583
-9.21798631 0.98988210 1.18663807 0.99160925 0.98514709
-9.23753666 0.99000391 1.19175996 0.99165518 0.98532567
-9.25708700 0.99012399 1.19701060 0.99170266 0.98550164
-9.27663734 0.99024237 1.20239694 0.99175165 0.98567504
-9.29618768 0.99035907 1.20792650 0.99180209 0.98584595
-9.31573803 0.99047414 1.21360740 0.99185393 0.98601441
-9.33528837 0.99058759 1.21944852 0.99190712 0.98618047
-9.35483871 0.99069947 1.22545948 0.99196159 0.98634419
-9.37438905 0.99080979 1.23165082 0.99201729 0.98650560
-9.39393939 0.99091858 1.23803406 0.99207417 0.98666477
-9.41348974 0.99102587 1.24462188 0.99213217 0.98682172
-9.43304008 0.99113169 1.25142821 0.99219123 0.98697651
-9.45259042 0.99123605 1.25846848 0.99225130 0.98712918
-9.47214076 0.99133899 1.26575977 0.99231231 0.98727976
-9.49169110 0.99144053 1.27332111 0.99237422 0.98742829
-9.51124145 0.99154069 0.99216431 0.99243695 0.98757567
-9.53079179 0.99163949 0.99226267 0.99250046 0.98772003
-9.55034213 0.99173696 0.99235962 0.99256469 0.98786248
-9.56989247 0.99183312 0.99245521 0.99262957 0.98800306
-9.58944282 0.99192798 0.99254945 0.99269504 0.98814178
-9.60899316 0.99202157 0.99264235 0.99276106 0.98827868
-9.62854350 0.99211391 0.99273394 0.99282754 0.98841378
-9.64809384 0.99220501 0.99282425 0.99289445 0.98854710
-9.66764418 0.99229491 0.99291328 0.99296171 0.98867868
-9.68719453 0.99238360 0.99300107 0.99302927 0.98880853
-9.70674487 0.99247112 0.99308762 0.99309706 0.98893669
-9.72629521 0.99255748 0.99317296 0.99316502 0.98906317
-9.74584555 0.99264269 0.99325711 0.99323309 0.98918801
-9.76539589 0.99272679 0.99334008 0.99330122 0.98931121
-9.78494624 0.99280977 0.99342189 0.99336933 0.98943282
-9.80449658 0.99289166 0.99350256 0.99343736 0.98955285
-9.82404692 0.99297248 0.99358211 0.99350526 0.98967131
-9.84359726 0.99305223 0.99366056 0.99357296 0.98978825
-9.86314761 0.99313094 0.99373791 0.99364040 0.98990367
-9.88269795 0.99320862 0.99381420 0.99370751 0.99001760
-9.90224829 0.99328529 0.99388943 0.99377423 0.99013005
-9.92179863 0.99336096 0.99396362 0.99384049 0.99024106
-9.94134897 0.99343565 0.99403678 0.99390625 0.99035064
-9.96089932 0.99350936 0.99410894 0.99397142 0.99045881
-9.98044966 0.99358212 0.99418010 0.99403594 0.99056560
-10.00000000 0.99365393 0.99425029 0.99409976 0.99067101
+X Ramps Sigmoids ZSShapes Concaves
+-10.000000000 0.255363311 0.994418517 0.255809266 0.252212158
+-9.980449658 0.255423538 0.994349291 0.255877491 0.252237827
+-9.960899316 0.255484536 0.994279093 0.255946708 0.252263834
+-9.941348974 0.255546315 0.994207907 0.256016992 0.252290183
+-9.921798631 0.255608886 0.994135720 0.256088420 0.252316880
+-9.902248289 0.255672260 0.994062515 0.256161070 0.252343930
+-9.882697947 0.255736449 0.993988277 0.256235018 0.252371338
+-9.863147605 0.255801463 0.993912989 0.256310342 0.252399110
+-9.843597263 0.255867314 0.993836635 0.256387118 0.252427249
+-9.824046921 0.255934014 0.993759200 0.256465426 0.252455763
+-9.804496579 0.256001575 0.993680665 0.256545342 0.252484655
+-9.784946237 0.256070009 0.993601014 0.256626945 0.252513932
+-9.765395894 0.256139328 0.993520229 0.256710313 0.252543600
+-9.745845552 0.256209543 0.993438294 0.256795525 0.252573664
+-9.726295210 0.256280668 0.993355189 0.256882659 0.252604130
+-9.706744868 0.256352715 0.993270897 0.256971794 0.252635003
+-9.687194526 0.256425696 0.993185399 0.257063010 0.252666290
+-9.667644184 0.256499625 0.993098676 0.257156386 0.252697997
+-9.648093842 0.256574514 0.993010710 0.257252001 0.252730129
+-9.628543500 0.256650376 0.992921480 0.257349935 0.252762694
+-9.608993157 0.256727223 0.992830967 0.257450269 0.252795698
+-9.589442815 0.256805071 0.992739150 0.257553083 0.252829146
+-9.569892473 0.256883930 0.992646010 0.257658457 0.252863046
+-9.550342131 0.256963815 0.992551525 0.257766473 0.252897404
+-9.530791789 0.257044740 0.992455675 0.257877210 0.252932226
+-9.511241447 0.257126716 0.992358437 0.257990751 0.252967521
+-9.491691105 0.257209759 0.588052019 0.258107177 0.253003294
+-9.472140762 0.257293880 0.580664022 0.258226570 0.253039553
+-9.452590420 0.257379094 0.573548403 0.258349012 0.253076305
+-9.433040078 0.257465414 0.566686170 0.258474586 0.253113557
+-9.413489736 0.257552853 0.560060263 0.258603373 0.253151317
+-9.393939394 0.257641426 0.553655304 0.258735458 0.253189591
+-9.374389052 0.257731144 0.547457382 0.258870922 0.253228389
+-9.354838710 0.257822021 0.541453869 0.259009850 0.253267717
+-9.335288368 0.257914071 0.535633273 0.259152325 0.253307584
+-9.315738025 0.258007306 0.529985101 0.259298431 0.253347997
+-9.296187683 0.258101740 0.524499751 0.259448253 0.253388965
+-9.276637341 0.258197385 0.519168409 0.259601875 0.253430495
+-9.257086999 0.258294254 0.513982971 0.259759382 0.253472597
+-9.237536657 0.258392360 0.508935965 0.259920859 0.253515278
+-9.217986315 0.258491714 0.504020487 0.260086393 0.253558549
+-9.198435973 0.258592329 0.499230149 0.260256068 0.253602416
+-9.178885630 0.258694217 0.494559024 0.260429971 0.253646889
+-9.159335288 0.258797390 0.490001608 0.260608188 0.253691978
+-9.139784946 0.258901859 0.485552776 0.260790807 0.253737692
+-9.120234604 0.259007634 0.481207751 0.260977914 0.253784039
+-9.100684262 0.259114728 0.476962075 0.261169597 0.253831030
+-9.081133920 0.259223150 0.472811577 0.261365945 0.253878674
+-9.061583578 0.259332910 0.468752351 0.261567044 0.253926982
+-9.042033236 0.259444019 0.464780737 0.261772983 0.253975962
+-9.022482893 0.259556486 0.460893297 0.261983853 0.254025626
+-9.002932551 0.259670319 0.457086800 0.262199741 0.254075983
+-8.983382209 0.259785527 0.453358204 0.262420737 0.254127045
+-8.963831867 0.259902119 0.449704644 0.262646932 0.254178821
+-8.944281525 0.260020101 0.446123417 0.262878416 0.254231324
+-8.924731183 0.260139481 0.442611971 0.263115280 0.254284563
+-8.905180841 0.260260266 0.439167894 0.263357615 0.254338550
+-8.885630499 0.260382462 0.435788903 0.263605512 0.254393298
+-8.866080156 0.260506073 0.432472838 0.263859064 0.254448816
+-8.846529814 0.260631104 0.429217651 0.264118363 0.254505117
+-8.826979472 0.260757561 0.426021398 0.264383501 0.254562214
+-8.807429130 0.260885446 0.422882236 0.264654573 0.254620118
+-8.787878788 0.261014762 0.419798412 0.264931671 0.254678842
+-8.768328446 0.261145511 0.416768259 0.265214890 0.254738398
+-8.748778104 0.261277695 0.413790193 0.265504324 0.254798800
+-8.729227761 0.261411313 0.410862703 0.265800069 0.254860061
+-8.709677419 0.261546367 0.407984352 0.266102219 0.254922193
+-8.690127077 0.261682855 0.405153768 0.266410871 0.254985212
+-8.670576735 0.261820774 0.402369643 0.266726120 0.255049129
+-8.651026393 0.261960123 0.399630729 0.267048064 0.255113960
+-8.631476051 0.262100897 0.396935833 0.267376801 0.255179719
+-8.611925709 0.262243093 0.394283815 0.267712426 0.255246420
+-8.592375367 0.262386704 0.391673585 0.268055040 0.255314078
+-8.572825024 0.262531724 0.389104103 0.268404740 0.255382709
+-8.553274682 0.262678146 0.386574370 0.268761626 0.255452328
+-8.533724340 0.262825961 0.384083432 0.269125797 0.255522950
+-8.514173998 0.262975160 0.381630374 0.269497353 0.255594592
+-8.494623656 0.263125731 0.379214319 0.269876396 0.255667269
+-8.475073314 0.263277664 0.376834428 0.270263026 0.255740998
+-8.455522972 0.263430945 0.374489895 0.270657345 0.255815797
+-8.435972630 0.263585560 0.372179948 0.271059456 0.255891682
+-8.416422287 0.263741495 0.369903845 0.271469460 0.255968670
+-8.396871945 0.263898732 0.367660875 0.271887462 0.256046780
+-8.377321603 0.264057254 0.365450354 0.272313565 0.256126030
+-8.357771261 0.264217043 0.363271626 0.272747873 0.256206439
+-8.338220919 0.264378078 0.361124062 0.273190492 0.256288024
+-8.318670577 0.264540339 0.359007055 0.273641526 0.256370806
+-8.299120235 0.264703801 0.356920024 0.274101082 0.256454804
+-8.279569892 0.264868442 0.354862409 0.274569267 0.256540038
+-8.260019550 0.265034236 0.352833675 0.275046187 0.256626528
+-8.240469208 0.265201156 0.350833302 0.275531949 0.256714295
+-8.220918866 0.265369175 0.348860796 0.276026663 0.256803360
+-8.201368524 0.265538263 0.346915677 0.276530437 0.256893746
+-8.181818182 0.265708390 0.344997488 0.277043381 0.256985473
+-8.162267840 0.265879523 0.343105787 0.277565603 0.257078564
+-8.142717498 0.266051628 0.341240148 0.278097216 0.257173043
+-8.123167155 0.266224672 0.339400163 0.278638329 0.257268931
+-8.103616813 0.266398617 0.337585441 0.279189055 0.257366255
+-8.084066471 0.266573427 0.335795604 0.279749506 0.257465037
+-8.064516129 0.266749060 0.334030289 0.280319794 0.257565302
+-8.044965787 0.266925479 0.332289147 0.280900034 0.257667076
+-8.025415445 0.267102639 0.330571844 0.281490338 0.257770384
+-8.005865103 0.267280498 0.328878058 0.282090823 0.257875253
+-7.986314761 0.267459012 0.327207479 0.282701602 0.257981710
+-7.966764418 0.267638134 0.325559813 0.283322792 0.258089781
+-7.947214076 0.267817816 0.323934772 0.283954510 0.258199496
+-7.927663734 0.267998010 0.322332086 0.284596871 0.258310882
+-7.908113392 0.268178666 0.320751491 0.285249995 0.258423969
+-7.888563050 0.268359732 0.319192738 0.285913998 0.258538786
+-7.869012708 0.268541155 0.317655585 0.286589000 0.258655364
+-7.849462366 0.268722883 0.316139803 0.287275119 0.258773734
+-7.829912023 0.268904858 0.314645172 0.287972477 0.258893927
+-7.810361681 0.269087026 0.313171482 0.288681194 0.259015976
+-7.790811339 0.269269328 0.311718532 0.289401390 0.259139914
+-7.771260997 0.269451706 0.310286130 0.290133187 0.259265774
+-7.751710655 0.269634101 0.308874096 0.290876708 0.259393591
+-7.732160313 0.269816452 0.307482254 0.291632076 0.259523400
+-7.712609971 0.269998697 0.306110441 0.292399413 0.259655237
+-7.693059629 0.270180774 0.304758500 0.293178844 0.259789138
+-7.673509286 0.270362620 0.303426284 0.293970494 0.259925141
+-7.653958944 0.270544172 0.302113652 0.294774488 0.260063283
+-7.634408602 0.270725364 0.300820472 0.295590951 0.260203605
+-7.614858260 0.270906132 0.299546621 0.296420009 0.260346146
+-7.595307918 0.271086411 0.298291981 0.297261790 0.260490946
+-7.575757576 0.271266134 0.297056445 0.298116421 0.260638047
+-7.556207234 0.271445235 0.295839910 0.298984029 0.260787491
+-7.536656891 0.271623649 0.294642282 0.299864743 0.260939322
+-7.517106549 0.271801309 0.293463474 0.300758692 0.261093584
+-7.497556207 0.271978149 0.292303406 0.301666005 0.261250322
+-7.478005865 0.272154103 0.291162006 0.302586812 0.261409582
+-7.458455523 0.272329105 0.290039206 0.303521243 0.261571412
+-7.438905181 0.272503091 0.288934948 0.304469430 0.261735858
+-7.419354839 0.272675996 0.287849178 0.305431504 0.261902971
+-7.399804497 0.272847756 0.286781851 0.306407596 0.262072801
+-7.380254154 0.273018309 0.285732927 0.307397839 0.262245398
+-7.360703812 0.273187593 0.284702372 0.308402365 0.262420815
+-7.341153470 0.273355548 0.283690161 0.309421308 0.262599105
+-7.321603128 0.273522115 0.282696272 0.310454800 0.262780323
+-7.302052786 0.273687238 0.281720692 0.311502976 0.262964523
+-7.282502444 0.273850860 0.280763413 0.312565971 0.263151763
+-7.262952102 0.274012930 0.279824432 0.313643918 0.263342101
+-7.243401760 0.274173395 0.278903754 0.314736952 0.263535594
+-7.223851417 0.274332208 0.278001390 0.315845209 0.263732304
+-7.204301075 0.274489324 0.277117355 0.316968825 0.263932292
+-7.184750733 0.274644699 0.276251673 0.318107935 0.264135619
+-7.165200391 0.274798294 0.275404370 0.319262675 0.264342350
+-7.145650049 0.274950074 0.274575482 0.320433182 0.264552551
+-7.126099707 0.275100006 0.273765048 0.321619592 0.264766285
+-7.106549365 0.275248062 0.272973113 0.322822043 0.264983623
+-7.086999022 0.275394218 0.272199729 0.324040670 0.265204631
+-7.067448680 0.275538454 0.271444953 0.307535201 0.265429380
+-7.047898338 0.275680755 0.270708847 0.308450253 0.265657942
+-7.028347996 0.275821113 0.269991479 0.309374445 0.265890388
+-7.008797654 0.275959522 0.269292923 0.310307730 0.266126792
+-6.989247312 0.276095984 0.268613257 0.311250056 0.266367230
+-6.969696970 0.276230505 0.267952566 0.312201365 0.266611778
+-6.950146628 0.276363100 0.267310940 0.313161596 0.266860514
+-6.930596285 0.276493788 0.266688473 0.314130682 0.267113515
+-6.911045943 0.276622596 0.266085265 0.315108551 0.267370864
+-6.891495601 0.276749557 0.265501422 0.316095125 0.267632640
+-6.871945259 0.276874713 0.264937052 0.317090322 0.267898927
+-6.852394917 0.276998112 0.264392272 0.318094054 0.268169809
+-6.832844575 0.277119810 0.263867201 0.319106226 0.268445370
+-6.813294233 0.277239873 0.263361963 0.320126738 0.268725698
+-6.793743891 0.277358374 0.262876688 0.321155486 0.269010879
+-6.774193548 0.277475395 0.262411508 0.322192355 0.269301002
+-6.754643206 0.277591028 0.261966562 0.323237230 0.269596157
+-6.735092864 0.277705372 0.261541991 0.324289983 0.269896435
+-6.715542522 0.277818538 0.261137942 0.325350486 0.270201928
+-6.695992180 0.277930645 0.260754565 0.326418598 0.270512728
+-6.676441838 0.278041824 0.260392013 0.327494177 0.270828929
+-6.656891496 0.278152214 0.260050443 0.328577070 0.271150626
+-6.637341153 0.278261967 0.259730017 0.329667118 0.271477914
+-6.617790811 0.278371242 0.259430897 0.330764156 0.271810890
+-6.598240469 0.278480211 0.259153251 0.331868010 0.272149651
+-6.578690127 0.278589058 0.258897247 0.332978499 0.272494294
+-6.559139785 0.278697976 0.258663058 0.334095435 0.272844918
+-6.539589443 0.278807169 0.258450858 0.335218622 0.273201620
+-6.520039101 0.278916853 0.258260822 0.336347856 0.273564501
+-6.500488759 0.279027256 0.258093128 0.337482925 0.273933658
+-6.480938416 0.279138616 0.257947954 0.338623608 0.274309192
+-6.461388074 0.279251182 0.257825481 0.221051999 0.274691202
+-6.441837732 0.279365214 0.257725889 0.221590933 0.275079788
+-6.422287390 0.279480984 0.257649358 0.222137883 0.275475048
+-6.402737048 0.279598775 0.257596069 0.222693019 0.275877081
+-6.383186706 0.279718880 0.257566201 0.223256511 0.276285986
+-6.363636364 0.279841602 0.257559934 0.223828528 0.276701860
+-6.344086022 0.279967255 0.257577444 0.224409243 0.277124800
+-6.324535679 0.280096164 0.257618909 0.224998829 0.277554903
+-6.304985337 0.280228662 0.257684501 0.225597457 0.277992263
+-6.285434995 0.280365093 0.257774389 0.226205300 0.278436973
+-6.265884653 0.280505807 0.257888742 0.226822530 0.278889126
+-6.246334311 0.280651166 0.258027723 0.227449317 0.279348812
+-6.226783969 0.280801538 0.258191489 0.228085831 0.279816119
+-6.207233627 0.280957297 0.258380194 0.228732239 0.280291134
+-6.187683284 0.281118828 0.258593987 0.229388706 0.280773941
+-6.168132942 0.281286517 0.258833007 0.230055394 0.281264621
+-6.148582600 0.281460758 0.259097390 0.230732461 0.281763253
+-6.129032258 0.281641951 0.259387263 0.231420063 0.282269913
+-6.109481916 0.281830496 0.259702743 0.232118350 0.282784672
+-6.089931574 0.282026799 0.260043940 0.232827466 0.283307600
+-6.070381232 0.282231267 0.260410954 0.233547551 0.283838762
+-6.050830890 0.282444309 0.260803873 0.234278737 0.284378218
+-6.031280547 0.282666331 0.261222776 0.235021150 0.284926025
+-6.011730205 0.282897743 0.261667729 0.235774908 0.285482236
+-5.992179863 0.283138948 0.262138784 0.236540120 0.286046897
+-5.972629521 0.283390349 0.262635982 0.237316886 0.286620050
+-5.953079179 0.283652343 0.263159348 0.238105297 0.287201731
+-5.933528837 0.283925323 0.263708892 0.238905431 0.287791972
+-5.913978495 0.284209675 0.264284609 0.239717357 0.288390797
+-5.894428152 0.284505775 0.264886477 0.240541130 0.288998224
+-5.874877810 0.284813992 0.265514457 0.241376794 0.289614265
+-5.855327468 0.285134684 0.266168491 0.242224377 0.290238925
+-5.835777126 0.285468197 0.266848503 0.243083895 0.290872201
+-5.816226784 0.285814864 0.267554397 0.243955347 0.291514085
+-5.796676442 0.286175003 0.268286057 0.244838717 0.292164558
+-5.777126100 0.286548917 0.269043344 0.245733970 0.292823594
+-5.757575758 0.286936891 0.269826101 0.246641058 0.293491162
+-5.738025415 0.287339193 0.270634145 0.247559911 0.294167217
+-5.718475073 0.287756071 0.271467272 0.248490441 0.294851710
+-5.698924731 0.288187751 0.272325255 0.249432542 0.295544581
+-5.679374389 0.288634438 0.273207839 0.250386088 0.296245761
+-5.659824047 0.289096314 0.274114750 0.251350930 0.296955171
+-5.640273705 0.289573537 0.275045684 0.252326899 0.297672725
+-5.620723363 0.290066237 0.276000313 0.253313807 0.298398324
+-5.601173021 0.290574522 0.276978285 0.254311439 0.299131862
+-5.581622678 0.291098468 0.277979219 0.255319561 0.299873222
+-5.562072336 0.291638125 0.279002709 0.256337915 0.300622278
+-5.542521994 0.292193515 0.280048322 0.257366220 0.301378891
+-5.522971652 0.292764628 0.281115598 0.258404172 0.302142915
+-5.503421310 0.293351425 0.282204050 0.259451443 0.302914192
+-5.483870968 0.293953836 0.283313164 0.260507680 0.303692556
+-5.464320626 0.294571759 0.284442401 0.261572509 0.304477830
+-5.444770283 0.295205060 0.285591192 0.262645531 0.305269824
+-5.425219941 0.295853575 0.286758945 0.263726323 0.306068343
+-5.405669599 0.296517105 0.287945040 0.264814441 0.306873179
+-5.386119257 0.297195423 0.289148832 0.265909414 0.307684115
+-5.366568915 0.297888265 0.290369651 0.267010752 0.308500925
+-5.347018573 0.298595340 0.291606802 0.268117942 0.309596055
+-5.327468231 0.299316323 0.292859566 0.269230449 0.312559135
+-5.307917889 0.300050859 0.294127200 0.270347716 0.315603239
+-5.288367546 0.300798562 0.295408941 0.271469168 0.318728992
+-5.268817204 0.301559019 0.296704001 0.272594208 0.321936947
+-5.249266862 0.302331786 0.298011575 0.273722223 0.325227579
+-5.229716520 0.303116392 0.299330835 0.274852580 0.328601284
+-5.210166178 0.303912338 0.300660938 0.275984632 0.332058374
+-5.190615836 0.304719103 0.302001020 0.277117713 0.335599077
+-5.171065494 0.305536140 0.303350205 0.278251145 0.339223532
+-5.151515152 0.306362878 0.304707598 0.279384238 0.342931785
+-5.131964809 0.307198726 0.306072293 0.280516287 0.346723791
+-5.112414467 0.308043075 0.307443373 0.281646579 0.350599408
+-5.092864125 0.308895296 0.308819908 0.282774390 0.354558399
+-5.073313783 0.309754745 0.310200960 0.283898991 0.358600425
+-5.053763441 0.310620761 0.311585585 0.285019646 0.362725048
+-5.034213099 0.311492675 0.312972829 0.286135612 0.366931729
+-5.014662757 0.312369804 0.314361738 0.287246147 0.371219824
+-4.995112414 0.313251457 0.315751354 0.288350506 0.375588587
+-4.975562072 0.314136938 0.317140716 0.289447943 0.380037168
+-4.956011730 0.315025543 0.318528866 0.290537715 0.384564614
+-4.936461388 0.315916570 0.319914846 0.291619084 0.389169867
+-4.916911046 0.316809312 0.321297703 0.292691315 0.393851765
+-4.897360704 0.317703066 0.322676489 0.293753680 0.398609045
+-4.877810362 0.318597132 0.324050262 0.294805461 0.403440342
+-4.858260020 0.319490815 0.325418091 0.295845948 0.408344189
+-4.838709677 0.320383428 0.326779051 0.296874445 0.413319022
+-4.819159335 0.321274292 0.328132233 0.297890266 0.418363180
+-4.799608993 0.322162740 0.329476736 0.298892742 0.423474905
+-4.780058651 0.323048118 0.330811677 0.299881219 0.428652350
+-4.760508309 0.323929786 0.332136187 0.300855059 0.433893576
+-4.740957967 0.324807121 0.333449414 0.301813645 0.439196556
+-4.721407625 0.325679516 0.334750524 0.302756379 0.444559184
+-4.701857283 0.326546384 0.336038701 0.303682682 0.449979267
+-4.682306940 0.327407160 0.337313152 0.304592000 0.455454542
+-4.662756598 0.328261298 0.338573103 0.305483801 0.460982668
+-4.643206256 0.329108277 0.339817802 0.306357577 0.466561238
+-4.623655914 0.329947599 0.341046522 0.307212843 0.472187778
+-4.604105572 0.330778792 0.342258557 0.308049144 0.477859756
+-4.584555230 0.331601407 0.343453227 0.308866048 0.483574582
+-4.565004888 0.332415024 0.344629876 0.309663151 0.489329616
+-4.545454545 0.333219249 0.345787876 0.310440077 0.495122171
+-4.525904203 0.334013717 0.346926622 0.311196477 0.500949516
+-4.506353861 0.334798087 0.348045536 0.311932032 0.506808887
+-4.486803519 0.335572050 0.349144067 0.312646449 0.512697484
+-4.467253177 0.336335323 0.350221692 0.313339466 0.518612482
+-4.447702835 0.337087653 0.351277912 0.314010850 0.524551034
+-4.428152493 0.337828813 0.352312257 0.314660394 0.530510274
+-4.408602151 0.338558605 0.353324284 0.315287924 0.536487326
+-4.389051808 0.339276860 0.354313575 0.315893291 0.542479305
+-4.369501466 0.339983434 0.355279741 0.316476377 0.548483325
+-4.349951124 0.340678212 0.356222417 0.317037090 0.554496502
+-4.330400782 0.341361105 0.357141266 0.317575368 0.560515958
+-4.310850440 0.342032049 0.358035977 0.318091175 0.566538831
+-4.291300098 0.342691006 0.358906261 0.318584502 0.572562270
+-4.271749756 0.343337961 0.359751858 0.319055367 0.578583450
+-4.252199413 0.343972925 0.360572531 0.319503812 0.584599570
+-4.232649071 0.344595929 0.361368066 0.319929907 0.590607856
+-4.213098729 0.345207029 0.362138273 0.320333744 0.596605571
+-4.193548387 0.345806299 0.362882985 0.320715440 0.602590015
+-4.173998045 0.346393834 0.363602057 0.321075135 0.608558530
+-4.154447703 0.346969748 0.364295364 0.321412990 0.614508500
+-4.134897361 0.347534173 0.364962804 0.321729188 0.620437361
+-4.115347019 0.348087259 0.365604293 0.322023932 0.626342600
+-4.095796676 0.348629168 0.366219767 0.322297447 0.632221758
+-4.076246334 0.349160080 0.366809181 0.322549972 0.638072433
+-4.056695992 0.349680189 0.367372507 0.322781769 0.643892285
+-4.037145650 0.350189698 0.367909733 0.322993113 0.649679036
+-4.017595308 0.350688825 0.368420866 0.323184297 0.655430473
+-3.998044966 0.351177796 0.368905927 0.323355628 0.661144451
+-3.978494624 0.351656848 0.369364949 0.323507428 0.666079666
+-3.958944282 0.352126225 0.369797984 0.323640031 0.670888651
+-3.939393939 0.352586178 0.370205092 0.323753785 0.675690949
+-3.919843597 0.353036965 0.370586349 0.323849047 0.680483527
+-3.900293255 0.353478850 0.370941841 0.323926187 0.685263450
+-3.880742913 0.353912099 0.371271664 0.323985583 0.690027883
+-3.861192571 0.354336983 0.371575927 0.324027622 0.694774089
+-3.841642229 0.354753776 0.371854744 0.324052698 0.699499433
+-3.822091887 0.355162752 0.372108242 0.324061214 0.704201381
+-3.802541544 0.355564188 0.372336553 0.324053577 0.708877501
+-3.782991202 0.355958358 0.372539817 0.324030201 0.713525463
+-3.763440860 0.356345538 0.372718183 0.323991504 0.718143038
+-3.743890518 0.356726002 0.372871802 0.323937907 0.722728101
+-3.724340176 0.357100021 0.373000833 0.323869836 0.727278628
+-3.704789834 0.357467865 0.373105440 0.323787717 0.731792694
+-3.685239492 0.357829800 0.373185789 0.323691979 0.736268477
+-3.665689150 0.358186087 0.373242052 0.323583053 0.740704251
+-3.646138807 0.358536986 0.373274403 0.323461369 0.745098390
+-3.626588465 0.358882748 0.373283019 0.323327357 0.749449365
+-3.607038123 0.359223622 0.373268079 0.323181447 0.753755740
+-3.587487781 0.359559852 0.373229764 0.323024067 0.758016176
+-3.567937439 0.359891672 0.373168254 0.322855643 0.762229423
+-3.548387097 0.360219316 0.373083733 0.322676600 0.766394324
+-3.528836755 0.360543005 0.372976384 0.322487358 0.770509809
+-3.509286413 0.360862959 0.372846389 0.322288336 0.774574896
+-3.489736070 0.361179388 0.372693931 0.322079949 0.778588685
+-3.470185728 0.361492495 0.372519192 0.321862607 0.782550361
+-3.450635386 0.361802477 0.372322351 0.321636715 0.786459190
+-3.431085044 0.362109524 0.372103589 0.321402676 0.790314512
+-3.411534702 0.362413816 0.371863082 0.321160886 0.794115748
+-3.391984360 0.362715529 0.371601006 0.320911736 0.797862389
+-3.372434018 0.363014830 0.371317533 0.320655611 0.801553999
+-3.352883675 0.363311877 0.371012835 0.320392891 0.805190210
+-3.333333333 0.363606822 0.370687079 0.320123950 0.808770721
+-3.313782991 0.363899811 0.370340429 0.319849154 0.812295296
+-3.294232649 0.364190979 0.369973047 0.319568865 0.815763759
+-3.274682307 0.364480457 0.369585091 0.319283438 0.819175996
+-3.255131965 0.364768368 0.369176715 0.318993219 0.822531948
+-3.235581623 0.365054826 0.368748070 0.318698549 0.825831611
+-3.216031281 0.365339939 0.368299304 0.318399763 0.829075035
+-3.196480938 0.365623810 0.367830557 0.318097186 0.832262318
+-3.176930596 0.365906532 0.367341969 0.317791138 0.835393608
+-3.157380254 0.366188194 0.366833674 0.317481932 0.838469096
+-3.137829912 0.366468876 0.366305800 0.317169872 0.841489018
+-3.118279570 0.366748655 0.365758474 0.316855256 0.844453651
+-3.098729228 0.367027599 0.365191816 0.316538375 0.847363310
+-3.079178886 0.367305771 0.364605940 0.316219511 0.850218348
+-3.059628543 0.367583229 0.364000957 0.315898941 0.853019152
+-3.040078201 0.367860024 0.363376974 0.315576933 0.855766142
+-3.020527859 0.368136203 0.362734089 0.315253747 0.858459769
+-3.000977517 0.368411807 0.362072400 0.314929638 0.861100512
+-2.981427175 0.368686873 0.361391995 0.314604853 0.863688877
+-2.961876833 0.368961431 0.360692960 0.314279630 0.866225396
+-2.942326491 0.369235508 0.359975374 0.313954203 0.868710622
+-2.922776149 0.369509128 0.359239312 0.313628796 0.871145133
+-2.903225806 0.369782308 0.358484842 0.313303629 0.873529524
+-2.883675464 0.370055062 0.357712027 0.312978912 0.875864408
+-2.864125122 0.370327403 0.356920926 0.312654850 0.878150418
+-2.844574780 0.370599335 0.356111589 0.312331640 0.880388198
+-2.825024438 0.370870863 0.355284065 0.312009475 0.882578408
+-2.805474096 0.371141988 0.354438393 0.311688539 0.884721720
+-2.785923754 0.371412706 0.353574609 0.311369010 0.886818816
+-2.766373412 0.371683012 0.352692741 0.311051060 0.888870388
+-2.746823069 0.371952898 0.351792813 0.310734855 0.890877137
+-2.727272727 0.372222354 0.350874844 0.310420554 0.892839769
+-2.707722385 0.372491367 0.349938843 0.310108310 0.894758999
+-2.688172043 0.372759921 0.348984818 0.309798272 0.896635544
+-2.668621701 0.373027999 0.348012767 0.309490580 0.898470126
+-2.649071359 0.373295584 0.347022684 0.309185371 0.900263470
+-2.629521017 0.373562653 0.346014557 0.308882776 0.902016302
+-2.609970674 0.373829186 0.344988366 0.308582920 0.903729349
+-2.590420332 0.374095160 0.343944087 0.308285921 0.905403340
+-2.570869990 0.374360548 0.342881689 0.307991895 0.907039000
+-2.551319648 0.374625326 0.341801133 0.307700951 0.908637054
+-2.531769306 0.374889468 0.340702376 0.307413194 0.910198225
+-2.512218964 0.375152945 0.339585366 0.307128722 0.911723233
+-2.492668622 0.375415730 0.338450047 0.306847630 0.913212792
+-2.473118280 0.375677793 0.337296355 0.306570009 0.914667616
+-2.453567937 0.375939106 0.336124218 0.306295944 0.916088410
+-2.434017595 0.376199638 0.334933559 0.306025517 0.917475877
+-2.414467253 0.376459360 0.333724294 0.305758803 0.918830710
+-2.394916911 0.376718242 0.332496330 0.305495875 0.920153600
+-2.375366569 0.376976253 0.331249569 0.305236802 0.921445229
+-2.355816227 0.377233364 0.329983905 0.304981649 0.922706271
+-2.336265885 0.377489543 0.328699224 0.304730476 0.923937393
+-2.316715543 0.377744760 0.327395405 0.304483339 0.925139256
+-2.297165200 0.377998986 0.326072319 0.304240293 0.926312509
+-2.277614858 0.378252192 0.324729829 0.304001387 0.927457796
+-2.258064516 0.378504347 0.323367790 0.303766666 0.928575750
+-2.238514174 0.378755423 0.321986050 0.303536174 0.929666996
+-2.218963832 0.379005391 0.320584447 0.303309949 0.930732148
+-2.199413490 0.379254224 0.319162811 0.303088030 0.931771812
+-2.179863148 0.379501895 0.317720964 0.302870448 0.932786585
+-2.160312805 0.379748375 0.316258717 0.302657234 0.933777052
+-2.140762463 0.379993640 0.314775875 0.302448415 0.934743790
+-2.121212121 0.380237664 0.313272230 0.302244016 0.935687364
+-2.101661779 0.380480422 0.311747568 0.302044058 0.936608331
+-2.082111437 0.380721890 0.310201661 0.301848561 0.937507236
+-2.062561095 0.380962045 0.308634274 0.301657541 0.938384615
+-2.043010753 0.381200865 0.307045161 0.301471013 0.939240993
+-2.023460411 0.381438328 0.305434064 0.301288987 0.940076883
+-2.003910068 0.381674413 0.303800713 0.301111474 0.940892790
+-1.984359726 0.381909101 0.302144831 0.300938480 0.941689209
+-1.964809384 0.382142372 0.300466123 0.300770010 0.942466622
+-1.945259042 0.382374209 0.298764287 0.300606066 0.943225502
+-1.925708700 0.382604595 0.297039004 0.300446651 0.943966312
+-1.906158358 0.382833513 0.295289947 0.300291761 0.944689503
+-1.886608016 0.383060948 0.293516769 0.300141395 0.945395519
+-1.867057674 0.383286886 0.291719115 0.299995546 0.946084790
+-1.847507331 0.383511314 0.289896612 0.299854208 0.946757739
+-1.827956989 0.383734219 0.288048873 0.299717372 0.947414776
+-1.808406647 0.383955590 0.286175495 0.299585028 0.948056303
+-1.788856305 0.384175416 0.284276059 0.299457164 0.948682713
+-1.769305963 0.384393687 0.282350129 0.299333766 0.949294386
+-1.749755621 0.384610396 0.280397251 0.299214820 0.949891695
+-1.730205279 0.384825534 0.278416954 0.299100308 0.950475002
+-1.710654936 0.385039095 0.276408745 0.298990212 0.951044661
+-1.691104594 0.385251073 0.274372115 0.298884514 0.951601015
+-1.671554252 0.385461463 0.272306532 0.298783193 0.952144399
+-1.652003910 0.385670261 0.270211443 0.298686226 0.952675137
+-1.632453568 0.385877464 0.268086272 0.298593591 0.953193547
+-1.612903226 0.386083071 0.265930419 0.298505263 0.953699936
+-1.593352884 0.386287079 0.263743260 0.298421216 0.954194602
+-1.573802542 0.386489488 0.261524145 0.298341424 0.954677836
+-1.554252199 0.386690300 0.259272397 0.298265859 0.955149920
+-1.534701857 0.386889514 0.256987311 0.298194492 0.955611127
+-1.515151515 0.387087133 0.254668150 0.298127293 0.956061722
+-1.495601173 0.387283161 0.252314149 0.298064232 0.956501963
+-1.476050831 0.387477601 0.249924508 0.298005277 0.956932100
+-1.456500489 0.387670457 0.247498391 0.297950394 0.957352373
+-1.436950147 0.387861735 0.245034930 0.297899552 0.957763018
+-1.417399804 0.388051441 0.242533214 0.297852715 0.958164261
+-1.397849462 0.388239582 0.239992294 0.297809848 0.958556321
+-1.378299120 0.388426164 0.237411179 0.297770915 0.958939411
+-1.358748778 0.388611197 0.234788830 0.297735879 0.959313737
+-1.339198436 0.388794690 0.232124163 0.297704704 0.959679498
+-1.319648094 0.388976651 0.229416043 0.297677350 0.960036884
+-1.300097752 0.389157091 0.226663282 0.297653780 0.960386082
+-1.280547410 0.389336021 0.223864633 0.297633953 0.960727271
+-1.260997067 0.389513452 0.221018793 0.297617830 0.961060623
+-1.241446725 0.389689397 0.218124393 0.297605370 0.961386306
+-1.221896383 0.389863868 0.215179996 0.297596531 0.961704480
+-1.202346041 0.390036878 0.212184094 0.297591272 0.962015301
+-1.182795699 0.390208441 0.209135102 0.297589550 0.962318918
+-1.163245357 0.390378571 0.206031353 0.297591322 0.962615475
+-1.143695015 0.390547284 0.202871093 0.297596546 0.962905110
+-1.124144673 0.390714593 0.199652476 0.297605176 0.963187958
+-1.104594330 0.390880516 0.196373555 0.297617169 0.963464147
+-1.085043988 0.391045067 0.193032275 0.297632480 0.963733799
+-1.065493646 0.391208264 0.189626469 0.297651063 0.963997034
+-1.045943304 0.391370124 0.186153846 0.297672874 0.964253966
+-1.026392962 0.391530664 0.182611982 0.297697865 0.964504704
+-1.006842620 0.391689902 0.178998311 0.297725991 0.964749353
+-0.987292278 0.391847857 0.175310115 0.297757204 0.964988014
+-0.967741935 0.392004545 0.171544508 0.297791458 0.965220784
+-0.948191593 0.392159988 0.167698426 0.297828704 0.965447755
+-0.928641251 0.392314203 0.163768611 0.297868896 0.965669016
+-0.909090909 0.392467210 0.159751593 0.297911985 0.965884652
+-0.889540567 0.392619030 0.155643675 0.297957922 0.966094744
+-0.869990225 0.392769681 0.151440909 0.298006659 0.966299371
+-0.850439883 0.392919184 0.147139076 0.298058147 0.966498605
+-0.830889541 0.393067561 0.142733659 0.298112336 0.966692519
+-0.811339198 0.393214831 0.138219816 0.298169178 0.966881180
+-0.791788856 0.393361015 0.133592348 0.298228621 0.967064653
+-0.772238514 0.393506135 0.128845663 0.298290618 0.967243000
+-0.752688172 0.393650212 0.123973734 0.298355116 0.967416279
+-0.733137830 0.393793268 0.118970057 0.298422067 0.967584547
+-0.713587488 0.393935324 0.113827597 0.298491418 0.967747856
+-0.694037146 0.394076403 0.108538729 0.298563120 0.967906258
+-0.674486804 0.394216525 0.103095170 0.298637122 0.968059801
+-0.654936461 0.394355714 0.097487905 0.298713373 0.968208531
+-0.635386119 0.394493991 0.091707092 0.298791821 0.968352491
+-0.615835777 0.394631379 0.085741965 0.298872415 0.968491723
+-0.596285435 0.394767900 0.079580712 0.298955104 0.968626265
+-0.576735093 0.394903577 0.073210334 0.299039836 0.968756156
+-0.557184751 0.395038432 0.066616483 0.299126559 0.968881429
+-0.537634409 0.395172488 0.059783269 0.299215221 0.969002119
+-0.518084066 0.395305768 0.052693032 0.299305771 0.969118256
+-0.498533724 0.395438294 0.027022210 0.299398157 0.969229871
+-0.478983382 0.395570089 0.027105698 0.299492326 0.969336990
+-0.459433040 0.395701176 0.027190482 0.299588227 0.969439642
+-0.439882698 0.395831578 0.027276576 0.299685807 0.969537849
+-0.420332356 0.395961317 0.027363993 0.299785014 0.969631636
+-0.400782014 0.396090417 0.027452746 0.299885796 0.969721024
+-0.381231672 0.396218900 0.027542850 0.299988100 0.969806034
+-0.361681329 0.396346790 0.027634320 0.300091874 0.969886685
+-0.342130987 0.396474108 0.027727170 0.300197067 0.969962994
+-0.322580645 0.396600879 0.027821415 0.300303624 0.970034979
+-0.303030303 0.396727124 0.027917072 0.300411495 0.970102654
+-0.283479961 0.396852867 0.028014156 0.300520627 0.970166034
+-0.263929619 0.396978131 0.028112683 0.300630968 0.970225132
+-0.244379277 0.397102938 0.028212670 0.300742464 0.970279960
+-0.224828935 0.397227311 0.028314135 0.300855065 0.970330530
+-0.205278592 0.397351272 0.028417094 0.300968718 0.970376851
+-0.185728250 0.397474846 0.028521567 0.301083370 0.970418933
+-0.166177908 0.397598053 0.028627570 0.301198970 0.970456784
+-0.146627566 0.397720918 0.028735122 0.301315466 0.970490410
+-0.127077224 0.397843462 0.028844244 0.301432806 0.970519820
+-0.107526882 0.397965709 0.028954953 0.301550937 0.970545018
+-0.087976540 0.398087681 0.029067270 0.301669809 0.970566009
+-0.068426197 0.398209400 0.029181216 0.301789369 0.970582797
+-0.048875855 0.398330889 0.029296811 0.301909567 0.970595386
+-0.029325513 0.398452171 0.029414076 0.302030350 0.970603777
+-0.009775171 0.398573268 0.029533032 0.302151666 0.970607972
+0.009775171 0.398694203 0.029653702 0.302273469 0.970607972
+0.029325513 0.398814999 0.029776108 0.302395784 0.970603777
+0.048875855 0.398935677 0.029900272 0.302518700 0.970595386
+0.068426197 0.399056261 0.030026219 0.302642316 0.970582797
+0.087976540 0.399176774 0.030153971 0.302766728 0.970566009
+0.107526882 0.399297237 0.030283554 0.302892036 0.970545018
+0.127077224 0.399417674 0.030414991 0.303018334 0.970519820
+0.146627566 0.399538106 0.030548308 0.303145722 0.970490410
+0.166177908 0.399658558 0.030683531 0.303274297 0.970456784
+0.185728250 0.399779052 0.030820685 0.303404158 0.970418933
+0.205278592 0.399899611 0.030959797 0.303535401 0.970376851
+0.224828935 0.400020257 0.031100894 0.303668126 0.970330530
+0.244379277 0.400141014 0.031244004 0.303802430 0.970279960
+0.263929619 0.400261905 0.031389154 0.303938413 0.970225132
+0.283479961 0.400382953 0.031536374 0.304076173 0.970166034
+0.303030303 0.400504181 0.031685692 0.304215810 0.970102654
+0.322580645 0.400625614 0.031837138 0.304357422 0.970034979
+0.342130987 0.400747274 0.031990743 0.304501109 0.969962994
+0.361681329 0.400869186 0.032146536 0.304646971 0.969886685
+0.381231672 0.400991373 0.032304550 0.304795106 0.969806034
+0.400782014 0.401113861 0.032464815 0.304945616 0.969721024
+0.420332356 0.401236673 0.032627365 0.305098601 0.969631636
+0.439882698 0.401359833 0.032792232 0.305254160 0.969537849
+0.459433040 0.401483368 0.032959451 0.305412395 0.969439642
+0.478983382 0.401607302 0.033129054 0.305573406 0.969336990
+0.498533724 0.401731660 0.033301077 0.305737294 0.969229871
+0.518084066 0.401856469 0.059228582 0.305904161 0.969118256
+0.537634409 0.401981754 0.066576722 0.306074108 0.969002119
+0.557184751 0.402107541 0.073669107 0.306247236 0.968881429
+0.576735093 0.402233859 0.080523447 0.306423648 0.968756156
+0.596285435 0.402360733 0.087155681 0.306603447 0.968626265
+0.615835777 0.402488191 0.093580208 0.306786733 0.968491723
+0.635386119 0.402616261 0.099810074 0.306973611 0.968352491
+0.654936461 0.402744973 0.105857144 0.307164182 0.968208531
+0.674486804 0.402874354 0.111732235 0.307358550 0.968059801
+0.694037146 0.403004434 0.117445237 0.307556820 0.967906258
+0.713587488 0.403135242 0.123005220 0.307759093 0.967747856
+0.733137830 0.403266811 0.128420516 0.307965475 0.967584547
+0.752688172 0.403399170 0.133698805 0.308176069 0.967416279
+0.772238514 0.403532350 0.138847172 0.308390980 0.967243000
+0.791788856 0.403666386 0.143872177 0.308610313 0.967064653
+0.811339198 0.403801308 0.148779899 0.308834173 0.966881180
+0.830889541 0.403937152 0.153575984 0.309062665 0.966692519
+0.850439883 0.404073951 0.158265687 0.309295896 0.966498605
+0.869990225 0.404211740 0.162853905 0.309533970 0.966299371
+0.889540567 0.404350555 0.167345209 0.309776995 0.966094744
+0.909090909 0.404490433 0.171743876 0.310025076 0.965884652
+0.928641251 0.404631412 0.176053910 0.310278321 0.965669016
+0.948191593 0.404773529 0.180279066 0.310536838 0.965447755
+0.967741935 0.404916824 0.184422872 0.310800733 0.965220784
+0.987292278 0.405061338 0.188488644 0.311070115 0.964988014
+1.006842620 0.405207110 0.192479506 0.311345091 0.964749353
+1.026392962 0.405354184 0.196398403 0.311625771 0.964504704
+1.045943304 0.405502603 0.200248115 0.311912263 0.964253966
+1.065493646 0.405652411 0.204031268 0.312204677 0.963997034
+1.085043988 0.405803653 0.207750348 0.312503122 0.963733799
+1.104594330 0.405956376 0.211407710 0.312807708 0.963464147
+1.124144673 0.406110628 0.215005583 0.313118546 0.963187958
+1.143695015 0.406266458 0.218546087 0.313435746 0.962905110
+1.163245357 0.406423915 0.222031233 0.313759420 0.962615475
+1.182795699 0.406583053 0.225462935 0.314089679 0.962318918
+1.202346041 0.406743922 0.228843012 0.314426634 0.962015301
+1.221896383 0.406906579 0.232173199 0.314770399 0.961704480
+1.241446725 0.407071078 0.235455149 0.315121086 0.961386306
+1.260997067 0.407237476 0.238690441 0.315478807 0.961060623
+1.280547410 0.407405833 0.241880579 0.315843677 0.960727271
+1.300097752 0.407576209 0.245027006 0.316215809 0.960386082
+1.319648094 0.407748666 0.248131097 0.316595318 0.960036884
+1.339198436 0.407923267 0.251194171 0.316982319 0.959679498
+1.358748778 0.408100078 0.254217491 0.317376926 0.959313737
+1.378299120 0.408279166 0.257202267 0.317779255 0.958939411
+1.397849462 0.408460599 0.260149660 0.318189423 0.958556321
+1.417399804 0.408644448 0.263060786 0.318607545 0.958164261
+1.436950147 0.408830786 0.265936714 0.319033739 0.957763018
+1.456500489 0.409019687 0.268778475 0.319468122 0.957352373
+1.476050831 0.409211228 0.271587059 0.319910813 0.956932100
+1.495601173 0.409405488 0.274363417 0.320361928 0.956501963
+1.515151515 0.409602546 0.277108469 0.320821587 0.956061722
+1.534701857 0.409802487 0.279823099 0.321289910 0.955611127
+1.554252199 0.410005394 0.282508160 0.321767015 0.955149920
+1.573802542 0.410211355 0.285164474 0.322253024 0.954677836
+1.593352884 0.410420460 0.287792837 0.322748056 0.954194602
+1.612903226 0.410632801 0.290394016 0.323252234 0.953699936
+1.632453568 0.410848471 0.292968754 0.323765677 0.953193547
+1.652003910 0.411067568 0.295517767 0.324288509 0.952675137
+1.671554252 0.411290190 0.298041750 0.324820852 0.952144399
+1.691104594 0.411516441 0.300541377 0.325362830 0.951601015
+1.710654936 0.411746423 0.303017299 0.325914565 0.951044661
+1.730205279 0.411980245 0.305470146 0.326476181 0.950475002
+1.749755621 0.412218016 0.307900533 0.327047804 0.949891695
+1.769305963 0.412459849 0.310309053 0.327629558 0.949294386
+1.788856305 0.412705859 0.312696285 0.328221569 0.948682713
+1.808406647 0.412956165 0.315062788 0.328823962 0.948056303
+1.827956989 0.413210888 0.317409108 0.329436865 0.947414776
+1.847507331 0.413470153 0.319735776 0.330060404 0.946757739
+1.867057674 0.413734086 0.322043307 0.330694706 0.946084790
+1.886608016 0.414002820 0.324332205 0.331339900 0.945395519
+1.906158358 0.414276486 0.326602958 0.331996114 0.944689503
+1.925708700 0.414555223 0.328856044 0.332663476 0.943966312
+1.945259042 0.414839170 0.331091928 0.333342117 0.943225502
+1.964809384 0.415128472 0.333311065 0.334032167 0.942466622
+1.984359726 0.415423274 0.335513898 0.334733755 0.941689209
+2.003910068 0.415723728 0.337700860 0.335447012 0.940892790
+2.023460411 0.416029987 0.339872375 0.336172070 0.940076883
+2.043010753 0.416342210 0.342028856 0.336909060 0.939240993
+2.062561095 0.416660556 0.344170709 0.337658115 0.938384615
+2.082111437 0.416985191 0.346298330 0.338419368 0.937507236
+2.101661779 0.417316283 0.348412108 0.339192951 0.936608331
+2.121212121 0.417654004 0.350512425 0.339978998 0.935687364
+2.140762463 0.417998530 0.352599653 0.340777643 0.934743790
+2.160312805 0.418350041 0.354674158 0.341589020 0.933777052
+2.179863148 0.418708720 0.356736302 0.342413266 0.932786585
+2.199413490 0.419074756 0.358786437 0.343250513 0.931771812
+2.218963832 0.419448339 0.360824911 0.344100899 0.930732148
+2.238514174 0.419829666 0.362852066 0.344964560 0.929666996
+2.258064516 0.420218934 0.364868237 0.345841631 0.928575750
+2.277614858 0.420616350 0.366873757 0.346732250 0.927457796
+2.297165200 0.421022118 0.368868951 0.347636554 0.926312509
+2.316715543 0.421436453 0.370854140 0.348554680 0.925139256
+2.336265885 0.421859569 0.372829643 0.349486766 0.923937393
+2.355816227 0.422291687 0.374795771 0.350432950 0.922706271
+2.375366569 0.422733031 0.376752835 0.351393371 0.921445229
+2.394916911 0.423183830 0.378701139 0.352368168 0.920153600
+2.414467253 0.423644316 0.380640986 0.353357479 0.918830710
+2.434017595 0.424114726 0.382572673 0.354361444 0.917475877
+2.453567937 0.424595302 0.384496496 0.355380202 0.916088410
+2.473118280 0.425086289 0.386412749 0.356413894 0.914667616
+2.492668622 0.425587937 0.388321721 0.357462658 0.913212792
+2.512218964 0.426100499 0.390223699 0.358526635 0.911723233
+2.531769306 0.426624235 0.392118970 0.359605966 0.910198225
+2.551319648 0.427159405 0.394007815 0.360700791 0.908637054
+2.570869990 0.427706278 0.395890515 0.361811249 0.907039000
+2.590420332 0.428265123 0.397767351 0.362937483 0.905403340
+2.609970674 0.428836216 0.399638600 0.364079633 0.903729349
+2.629521017 0.429419836 0.401504537 0.365237839 0.902016302
+2.649071359 0.430016265 0.403365439 0.366412243 0.900263470
+2.668621701 0.430625792 0.405221577 0.367602984 0.898470126
+2.688172043 0.431248706 0.407073225 0.368810204 0.896635544
+2.707722385 0.431885303 0.408920655 0.370034044 0.894758999
+2.727272727 0.432535882 0.410764137 0.371274644 0.892839769
+2.746823069 0.433200746 0.412603942 0.372532144 0.890877137
+2.766373412 0.433880201 0.414440339 0.373806686 0.888870388
+2.785923754 0.434574556 0.416273598 0.375098408 0.886818816
+2.805474096 0.435284126 0.418103987 0.376407451 0.884721720
+2.825024438 0.436009227 0.419931775 0.377733955 0.882578408
+2.844574780 0.436750180 0.421757232 0.379078059 0.880388198
+2.864125122 0.437507308 0.423580626 0.380439902 0.878150418
+2.883675464 0.438280938 0.425402225 0.381819623 0.875864408
+2.903225806 0.439071398 0.427222300 0.383217359 0.873529524
+2.922776149 0.439879023 0.429041118 0.384633250 0.871145133
+2.942326491 0.440704145 0.430858952 0.386067432 0.868710622
+2.961876833 0.441547104 0.432676069 0.387520041 0.866225396
+2.981427175 0.442408239 0.434492743 0.388991215 0.863688877
+3.000977517 0.443287892 0.436309243 0.390481089 0.861100512
+3.020527859 0.444186407 0.438125842 0.391989797 0.858459769
+3.040078201 0.445104130 0.439942814 0.393517475 0.855766142
+3.059628543 0.446041409 0.441760430 0.395064254 0.853019152
+3.079178886 0.446998592 0.443578968 0.396630268 0.850218348
+3.098729228 0.447976030 0.445398700 0.398215648 0.847363310
+3.118279570 0.448974074 0.447219905 0.399820525 0.844453651
+3.137829912 0.449993075 0.449042858 0.401445028 0.841489018
+3.157380254 0.451033387 0.450867839 0.403089286 0.838469096
+3.176930596 0.452095362 0.452695126 0.404753425 0.835393608
+3.196480938 0.453179351 0.454524999 0.406437573 0.832262318
+3.216031281 0.454285709 0.456357739 0.408141854 0.829075035
+3.235581623 0.455414786 0.458193628 0.409866390 0.825831611
+3.255131965 0.456566933 0.460032949 0.411611303 0.822531948
+3.274682307 0.457742501 0.461875986 0.413376714 0.819175996
+3.294232649 0.458941837 0.463723023 0.415162741 0.815763759
+3.313782991 0.460165288 0.465574345 0.416969500 0.812295296
+3.333333333 0.461413199 0.467430239 0.418797106 0.808770721
+3.352883675 0.462685911 0.469290991 0.420645672 0.805190210
+3.372434018 0.463983765 0.471156887 0.422515308 0.801553999
+3.391984360 0.465307097 0.473028217 0.424406122 0.797862389
+3.411534702 0.466656239 0.474905267 0.426318219 0.794115748
+3.431085044 0.468031521 0.476788326 0.428251704 0.790314512
+3.450635386 0.469433268 0.478677682 0.430206676 0.786459190
+3.470185728 0.470861801 0.480573623 0.432183234 0.782550361
+3.489736070 0.472317434 0.482476438 0.434181471 0.778588685
+3.509286413 0.473800480 0.484386413 0.436201479 0.774574896
+3.528836755 0.475311241 0.486303836 0.438243346 0.770509809
+3.548387097 0.476850018 0.488228994 0.440307158 0.766394324
+3.567937439 0.478417103 0.490162170 0.442392993 0.762229423
+3.587487781 0.480012780 0.492103649 0.444500930 0.758016176
+3.607038123 0.481637330 0.494053714 0.446631040 0.753755740
+3.626588465 0.483291022 0.496012644 0.448783392 0.749449365
+3.646138807 0.484974119 0.497980719 0.450958049 0.745098390
+3.665689150 0.486686876 0.499958215 0.453155071 0.740704251
+3.685239492 0.488429538 0.501945405 0.455374509 0.736268477
+3.704789834 0.490202342 0.503942559 0.457616413 0.731792694
+3.724340176 0.492005515 0.505949945 0.459880823 0.727278628
+3.743890518 0.493839272 0.507967825 0.462167777 0.722728101
+3.763440860 0.495703820 0.509996460 0.464477305 0.718143038
+3.782991202 0.497599355 0.512036104 0.466809428 0.713525463
+3.802541544 0.499526060 0.514087007 0.469164163 0.708877501
+3.822091887 0.501484108 0.516149413 0.471541519 0.704201381
+3.841642229 0.503473659 0.518223561 0.473941496 0.699499433
+3.861192571 0.505494860 0.520309683 0.476364087 0.694774089
+3.880742913 0.507547847 0.522408005 0.478809276 0.690027883
+3.900293255 0.509632741 0.524518745 0.481277039 0.685263450
+3.919843597 0.511749649 0.526642114 0.483767340 0.680483527
+3.939393939 0.513898666 0.528778314 0.486280137 0.675690949
+3.958944282 0.516079869 0.530927538 0.488815375 0.670888651
+3.978494624 0.518293325 0.533089972 0.491372989 0.666079666
+3.998044966 0.520539081 0.535265788 0.493952902 0.661267120
+4.017595308 0.522817171 0.537455152 0.496555028 0.656454235
+4.037145650 0.525127612 0.539658217 0.499179267 0.651644322
+4.056695992 0.527470405 0.541875123 0.501825506 0.646840782
+4.076246334 0.529845534 0.544106000 0.504493619 0.642047101
+4.095796676 0.532252966 0.546350965 0.507183468 0.637266847
+4.115347019 0.534692652 0.548610121 0.509894901 0.632503669
+4.134897361 0.537164523 0.550883558 0.512627748 0.627761289
+4.154447703 0.539668492 0.553171352 0.515381829 0.623043500
+4.173998045 0.542204456 0.555473562 0.518156944 0.618354164
+4.193548387 0.544772290 0.557790233 0.520952880 0.613697201
+4.213098729 0.547371853 0.560121396 0.523769406 0.609076592
+4.232649071 0.550002983 0.562467062 0.526606275 0.604496365
+4.252199413 0.552665499 0.564827226 0.529463222 0.599960598
+4.271749756 0.555359199 0.567201868 0.532339963 0.595473405
+4.291300098 0.558083863 0.569590947 0.535236199 0.591038937
+4.310850440 0.560839249 0.571994406 0.538151608 0.586661369
+4.330400782 0.563625096 0.574412168 0.541085853 0.582344899
+4.349951124 0.566441120 0.576844136 0.544038576 0.578093735
+4.369501466 0.569287018 0.579290197 0.547009398 0.573912094
+4.389051808 0.572162465 0.581750215 0.549997921 0.569804190
+4.408602151 0.575067116 0.584224035 0.553003728 0.565774228
+4.428152493 0.578000602 0.586711483 0.556026379 0.561826396
+4.447702835 0.580962535 0.589212364 0.559065415 0.557964857
+4.467253177 0.583952505 0.591726462 0.562120355 0.554193739
+4.486803519 0.586970080 0.594253541 0.565190699 0.550517132
+4.506353861 0.590014805 0.596793345 0.568275924 0.546939073
+4.525904203 0.593086205 0.599345597 0.571375487 0.543463541
+4.545454545 0.596183783 0.601909999 0.574488824 0.540094448
+4.565004888 0.599307020 0.604486235 0.577615349 0.536835632
+4.584555230 0.602455376 0.607073967 0.580754457 0.533690844
+4.604105572 0.605628288 0.609672837 0.583905522 0.530663745
+4.623655914 0.608825173 0.612282470 0.587067897 0.527757894
+4.643206256 0.612045427 0.614902469 0.590240917 0.524976740
+4.662756598 0.615288423 0.617532422 0.593423894 0.522323618
+4.682306940 0.618553515 0.620171896 0.596616126 0.519801732
+4.701857283 0.621840036 0.622820441 0.599816889 0.517414159
+4.721407625 0.625147298 0.625477592 0.603025442 0.515163830
+4.740957967 0.628474594 0.628142866 0.606241027 0.513053531
+4.760508309 0.631821196 0.630815766 0.609462869 0.511085893
+4.780058651 0.635186360 0.633495779 0.612690179 0.509263383
+4.799608993 0.638569318 0.636182379 0.615922152 0.507588303
+4.819159335 0.641969289 0.638875028 0.619157968 0.506062780
+4.838709677 0.645385471 0.641573176 0.622396796 0.504688760
+4.858260020 0.648817045 0.644276261 0.625637791 0.503468006
+4.877810362 0.652263177 0.646983713 0.628880099 0.502402092
+4.897360704 0.655723015 0.649694950 0.632122854 0.501492397
+4.916911046 0.659195692 0.652409387 0.635365185 0.500740105
+4.936461388 0.662680328 0.655126430 0.638606208 0.500146198
+4.956011730 0.666176028 0.657845479 0.641845038 0.499711457
+4.975562072 0.669681882 0.660565932 0.645080783 0.499436455
+4.995112414 0.673196970 0.663287182 0.648312545 0.499321562
+5.014662757 0.676720360 0.666008622 0.651539426 0.499366939
+5.034213099 0.680251108 0.668729645 0.654760527 0.499572537
+5.053763441 0.683788262 0.671449643 0.657974949 0.499938103
+5.073313783 0.687330859 0.674168011 0.661181793 0.500463174
+5.092864125 0.690877929 0.676884147 0.664380165 0.501147082
+5.112414467 0.694428497 0.679597454 0.667569174 0.501988956
+5.131964809 0.697981578 0.682307340 0.670747935 0.502987722
+5.151515152 0.701536185 0.685013220 0.673915569 0.504142106
+5.171065494 0.705091325 0.687714518 0.677071207 0.505450642
+5.190615836 0.708646004 0.690410664 0.680213988 0.506911670
+5.210166178 0.712199225 0.693101102 0.683343063 0.508523343
+5.229716520 0.715749989 0.695785285 0.686457593 0.510283632
+5.249266862 0.719297300 0.698462678 0.689556754 0.512190333
+5.268817204 0.722840161 0.701132759 0.692639737 0.514241067
+5.288367546 0.726377577 0.703795021 0.695705746 0.516433293
+5.307917889 0.729908558 0.706448971 0.698754004 0.518764310
+5.327468231 0.733432118 0.709094133 0.701783750 0.521231265
+5.347018573 0.736947277 0.711730044 0.704794242 0.523831163
+5.366568915 0.740453059 0.714356261 0.707784757 0.528348490
+5.386119257 0.743948500 0.716972359 0.710754595 0.533191116
+5.405669599 0.747432640 0.719577928 0.713703072 0.538084034
+5.425219941 0.750904533 0.722172580 0.716629531 0.543024859
+5.444770283 0.754363240 0.724755944 0.719533334 0.548011143
+5.464320626 0.757807835 0.727327669 0.722413869 0.553040388
+5.483870968 0.761237407 0.729887424 0.725270545 0.558110043
+5.503421310 0.764651055 0.732434899 0.728102796 0.563217514
+5.522971652 0.768047895 0.734969801 0.730910082 0.568360169
+5.542521994 0.771427056 0.737491860 0.733691887 0.573535337
+5.562072336 0.774787686 0.740000828 0.736447718 0.578740320
+5.581622678 0.778128948 0.742496473 0.739177112 0.583972395
+5.601173021 0.781450023 0.744978587 0.741879629 0.589228817
+5.620723363 0.784750112 0.747446980 0.744554853 0.594506829
+5.640273705 0.788028433 0.749901485 0.747202397 0.599803661
+5.659824047 0.791284227 0.752341953 0.749821899 0.605116539
+5.679374389 0.794516752 0.754768254 0.752413022 0.610442691
+5.698924731 0.797725290 0.757180280 0.754975454 0.615779346
+5.718475073 0.800909145 0.759577940 0.757508910 0.621123745
+5.738025415 0.804067641 0.761961164 0.760013130 0.626473140
+5.757575758 0.807200126 0.764329899 0.762487877 0.631824806
+5.777126100 0.810305972 0.766684110 0.764932941 0.637176035
+5.796676442 0.813384574 0.769023782 0.767348137 0.642524151
+5.816226784 0.816435351 0.771348914 0.769733300 0.647866507
+5.835777126 0.819457745 0.773659524 0.772088292 0.653200489
+5.855327468 0.822451226 0.775955646 0.774412998 0.658523526
+5.874877810 0.825415285 0.778237329 0.776707323 0.663833086
+5.894428152 0.828349441 0.780504638 0.778971198 0.669126684
+5.913978495 0.831253236 0.782757652 0.781204571 0.674401884
+5.933528837 0.834126239 0.784996464 0.783407415 0.679656302
+5.953079179 0.836968044 0.787221183 0.785579722 0.684887610
+5.972629521 0.839778269 0.789431928 0.787721503 0.690093535
+5.992179863 0.842556558 0.791628832 0.789832789 0.695271867
+6.011730205 0.845302583 0.793812039 0.791913630 0.700420458
+6.031280547 0.848016037 0.795981706 0.793964094 0.705537222
+6.050830890 0.850696641 0.798137998 0.795984266 0.710620141
+6.070381232 0.853344140 0.800281095 0.797974247 0.715667266
+6.089931574 0.855958305 0.802411181 0.799934156 0.720676716
+6.109481916 0.858538928 0.804528452 0.801864127 0.725646682
+6.129032258 0.861085830 0.806633115 0.803764306 0.730575427
+6.148582600 0.863598854 0.808725380 0.805634858 0.735461284
+6.168132942 0.866077865 0.810805468 0.807475957 0.740302664
+6.187683284 0.868522753 0.812873607 0.809287792 0.745098049
+6.207233627 0.870933433 0.814930030 0.811070565 0.749845997
+6.226783969 0.873309839 0.816974977 0.812824489 0.754545140
+6.246334311 0.875651928 0.819008695 0.814549786 0.759194186
+6.265884653 0.877959681 0.821031434 0.816246692 0.763791917
+6.285434995 0.880233099 0.823043450 0.817915450 0.768337189
+6.304985337 0.882472202 0.825045003 0.819556313 0.772828933
+6.324535679 0.884677032 0.827036357 0.821169543 0.777266154
+6.344086022 0.886847652 0.829017781 0.822755409 0.781647928
+6.363636364 0.888984143 0.830989546 0.824314190 0.785973406
+6.383186706 0.891086603 0.832951925 0.825846168 0.790241807
+6.402737048 0.893155150 0.834905196 0.827351636 0.794452424
+6.422287390 0.895189920 0.836849638 0.828830889 0.798604616
+6.441837732 0.897191066 0.838785531 0.830284230 0.802697811
+6.461388074 0.899158755 0.840713158 0.831711965 0.806731506
+6.480938416 0.901093173 0.842632805 0.974837636 0.810705259
+6.500488759 0.902994519 0.844544755 0.975474355 0.814618695
+6.520039101 0.904863008 0.846449296 0.976084124 0.818471500
+6.539589443 0.906698868 0.848346715 0.976667723 0.822263423
+6.559139785 0.908502341 0.850237300 0.977225919 0.825994269
+6.578690127 0.910273681 0.852121339 0.977759471 0.829663902
+6.598240469 0.912013157 0.853999120 0.978269126 0.833272243
+6.617790811 0.913721045 0.855870932 0.978755621 0.836819264
+6.637341153 0.915397636 0.857737064 0.979219681 0.840304993
+6.656891496 0.917043229 0.859597803 0.979662018 0.843729506
+6.676441838 0.918658135 0.861453438 0.980083334 0.847092928
+6.695992180 0.920242672 0.863304256 0.980484317 0.850395431
+6.715542522 0.921797168 0.865150544 0.980865643 0.853637232
+6.735092864 0.923321958 0.866992589 0.981227976 0.856818591
+6.754643206 0.924817387 0.868830675 0.981571966 0.859939810
+6.774193548 0.926283803 0.870665088 0.981898253 0.863001228
+6.793743891 0.927721565 0.872496112 0.982207459 0.866003225
+6.813294233 0.929131034 0.874324031 0.982500198 0.868946215
+6.832844575 0.930512579 0.876149127 0.982777068 0.871830645
+6.852394917 0.931866572 0.877971680 0.983038655 0.874656996
+6.871945259 0.933193391 0.879791973 0.983285532 0.877425778
+6.891495601 0.934493417 0.881610285 0.983518258 0.880137530
+6.911045943 0.935767035 0.883426895 0.983737380 0.882792818
+6.930596285 0.937014632 0.885242080 0.983943431 0.885392235
+6.950146628 0.938236598 0.887056119 0.984136933 0.887936394
+6.969696970 0.939433326 0.888869286 0.984318393 0.890425933
+6.989247312 0.940605210 0.890681859 0.984488306 0.892861508
+7.008797654 0.941752645 0.892494111 0.984647156 0.895243797
+7.028347996 0.942876027 0.894306317 0.984795412 0.897573493
+7.047898338 0.943975752 0.896118751 0.984933532 0.899851304
+7.067448680 0.945052218 0.897931684 0.985061963 0.902077955
+7.086999022 0.946105820 0.899745389 1.002592474 0.904254182
+7.106549365 0.947136956 0.901560139 1.002380834 0.906380735
+7.126099707 0.948146019 0.903376205 1.002167690 0.908458371
+7.145650049 0.949133405 0.905193857 1.001953273 0.910487860
+7.165200391 0.950099506 0.907013367 1.001737809 0.912469977
+7.184750733 0.951044712 0.908835006 1.001521514 0.914405505
+7.204301075 0.951969413 0.910659044 1.001304598 0.916295232
+7.223851417 0.952873994 0.912485753 1.001087265 0.918139952
+7.243401760 0.953758841 0.914315403 1.000869711 0.919940461
+7.262952102 0.954624335 0.916148265 1.000652126 0.921697558
+7.282502444 0.955470853 0.917984613 1.000434693 0.923412044
+7.302052786 0.956298772 0.919824717 1.000217589 0.925084719
+7.321603128 0.957108463 0.921668851 1.000000985 0.926716386
+7.341153470 0.957900295 0.923517288 0.999785044 0.928307843
+7.360703812 0.958674632 0.925370304 0.999569925 0.929859890
+7.380254154 0.959431837 0.927228173 0.999355780 0.931373321
+7.399804497 0.960172265 0.929091173 0.999142754 0.932848928
+7.419354839 0.960896270 0.930959582 0.998930989 0.934287501
+7.438905181 0.961604200 0.932833679 0.998720619 0.935689822
+7.458455523 0.962296401 0.934713745 0.998511774 0.937056670
+7.478005865 0.962973211 0.936600065 0.998304577 0.938388818
+7.497556207 0.963634966 0.938492922 0.998099147 0.939687031
+7.517106549 0.964281998 0.940392605 0.997895597 0.940952069
+7.536656891 0.964914631 0.942299402 0.997694036 0.942184685
+7.556207234 0.965533188 0.944213605 0.997494567 0.943385622
+7.575757576 0.966137986 0.946135510 0.997297289 0.944555617
+7.595307918 0.966729334 0.948065413 0.997102296 0.945695397
+7.614858260 0.967307542 0.950003616 0.996909678 0.946805682
+7.634408602 0.967872909 0.951950421 0.996719519 0.947887182
+7.653958944 0.968425733 0.953906137 0.996531899 0.948940596
+7.673509286 0.968966306 0.955871074 0.996346896 0.949966615
+7.693059629 0.969494914 0.957845548 0.996164582 0.950965920
+7.712609971 0.970011839 0.959829876 0.995985025 0.951939181
+7.732160313 0.970517358 0.961824384 0.995808288 0.952887058
+7.751710655 0.971011741 0.963829399 0.995634434 0.953810202
+7.771260997 0.971495257 0.965845253 0.995463518 0.954709250
+7.790811339 0.971968165 0.967872286 0.995295594 0.955584830
+7.810361681 0.972430722 0.969910840 0.995130712 0.956437560
+7.829912023 0.972883181 0.971961266 0.994968918 0.957268046
+7.849462366 0.973325786 0.974023918 0.994810255 0.958076882
+7.869012708 0.973758780 0.976099158 0.994654763 0.958864652
+7.888563050 0.974182400 0.978187355 0.994502479 0.959631929
+7.908113392 0.974596876 0.980288884 0.994353435 0.960379274
+7.927663734 0.975002435 0.982404128 0.994207664 0.961107238
+7.947214076 0.975399300 0.984533476 0.994065193 0.961816357
+7.966764418 0.975787687 0.986677328 0.993926047 0.962507161
+7.986314761 0.976167809 0.988836091 0.993790249 0.963180165
+8.005865103 0.976539873 0.991010180 0.993657817 0.963835875
+8.025415445 0.976904083 0.993200021 0.993528771 0.964474784
+8.044965787 0.977260637 0.995406048 0.993403123 0.965097376
+8.064516129 0.977609728 0.997628707 0.993280887 0.965704121
+8.084066471 0.977951547 0.999868453 0.993162074 0.966295481
+8.103616813 0.978286278 1.002125754 0.993046689 0.966871906
+8.123167155 0.978614101 1.004401089 0.992934740 0.967433834
+8.142717498 0.978935194 1.006694948 0.992826230 0.967981696
+8.162267840 0.979249728 1.009007836 0.992721160 0.968515908
+8.181818182 0.979557870 1.011340271 0.992619530 0.969036877
+8.201368524 0.979859786 1.013692784 0.992521337 0.969545002
+8.220918866 0.980155633 1.016065922 0.992426578 0.970040668
+8.240469208 0.980445569 1.018460248 0.992335245 0.970524254
+8.260019550 0.980729744 1.020876341 0.992247331 0.970996125
+8.279569892 0.981008307 1.023314795 0.992162827 0.971456638
+8.299120235 0.981281401 1.025776226 0.992081721 0.971906142
+8.318670577 0.981549168 1.028261267 0.992004001 0.972344973
+8.338220919 0.981811743 1.030770569 0.991929651 0.972773460
+8.357771261 0.982069259 1.033304807 0.991858657 0.973191923
+8.377321603 0.982321847 1.035864677 0.991791000 0.973600671
+8.396871945 0.982569632 1.038450896 0.991726662 0.974000006
+8.416422287 0.982812738 1.041064207 0.991665623 0.974390219
+8.435972630 0.983051282 1.043705380 0.991607861 0.974771595
+8.455522972 0.983285382 1.046375209 0.991553354 0.975144408
+8.475073314 0.983515150 1.049074518 0.991502077 0.975508927
+8.494623656 0.983740696 1.051804159 0.991454006 0.975865408
+8.514173998 0.983962127 1.054565017 0.991409113 0.976214104
+8.533724340 0.984179547 1.057358011 0.991367372 0.976555258
+8.553274682 0.984393055 1.060184091 0.991328752 0.976889103
+8.572825024 0.984602750 1.063044249 0.991293226 0.977215870
+8.592375367 0.984808728 1.065939511 0.991260762 0.977535777
+8.611925709 0.985011080 1.068870948 0.991231327 0.977849039
+8.631476051 0.985209896 1.071839672 0.991204890 0.978155861
+8.651026393 0.985405263 1.074846843 0.991181417 0.978456444
+8.670576735 0.985597266 1.077893668 0.991160872 0.978750979
+8.690127077 0.985785986 1.080981408 0.991143221 0.979039655
+8.709677419 0.985971504 1.084111376 0.991128426 0.979322649
+8.729227761 0.986153896 1.087284946 0.991116451 0.979600136
+8.748778104 0.986333238 1.090503553 0.991107257 0.979872285
+8.768328446 0.986509602 1.093768697 0.991100805 0.980139256
+8.787878788 0.986683058 1.097081949 0.991097055 0.980401206
+8.807429130 0.986853675 1.100444956 0.991095968 0.980658285
+8.826979472 0.987021520 1.103859443 0.991097502 0.980910639
+8.846529814 0.987186656 1.107327221 0.991101614 0.981158407
+8.866080156 0.987349145 1.110850192 0.991108263 0.981401724
+8.885630499 0.987509049 1.114430354 0.991117404 0.981640720
+8.905180841 0.987666426 1.118069812 0.991128994 0.981875520
+8.924731183 0.987821332 1.121770781 0.991142989 0.982106245
+8.944281525 0.987973822 1.125535597 0.991159342 0.982333009
+8.963831867 0.988123950 1.129366725 0.991178008 0.982555924
+8.983382209 0.988271767 1.133266769 0.991198941 0.982775098
+9.002932551 0.988417324 1.137238482 0.991222093 0.982990633
+9.022482893 0.988560669 1.141284781 0.991247417 0.983202628
+9.042033236 0.988701848 1.145408755 0.991274865 0.983411179
+9.061583578 0.988840908 1.149613685 0.991304388 0.983616377
+9.081133920 0.988977892 1.153903056 0.991335936 0.983818309
+9.100684262 0.989112843 1.158280577 0.991369461 0.984017061
+9.120234604 0.989245803 1.162750199 0.991404910 0.984212713
+9.139784946 0.989376812 1.167316136 0.991442235 0.984405342
+9.159335288 0.989505909 1.171982895 0.991481384 0.984595024
+9.178885630 0.989633131 1.176755294 0.991522305 0.984781831
+9.198435973 0.989758516 1.181638503 0.991564945 0.984965831
+9.217986315 0.989882097 1.186638068 0.991609253 0.985147090
+9.237536657 0.990003911 1.191759957 0.991655175 0.985325671
+9.257086999 0.990123990 1.197010601 0.991702658 0.985501637
+9.276637341 0.990242367 1.202396944 0.991751648 0.985675044
+9.296187683 0.990359073 1.207926497 0.991802091 0.985845950
+9.315738025 0.990474139 1.213607404 0.991853933 0.986014408
+9.335288368 0.990587594 1.219448518 0.991907117 0.986180470
+9.354838710 0.990699467 1.225459479 0.991961589 0.986344185
+9.374389052 0.990809786 1.231650818 0.992017292 0.986505602
+9.393939394 0.990918578 1.238034064 0.992074172 0.986664767
+9.413489736 0.991025869 1.244621880 0.992132171 0.986821723
+9.433040078 0.991131686 1.251428214 0.992191233 0.986976513
+9.452590420 0.991236052 1.258468479 0.992251299 0.987129179
+9.472140762 0.991338993 1.265759770 0.992312314 0.987279759
+9.491691105 0.991440532 1.273321111 0.992374218 0.987428291
+9.511241447 0.991540692 0.992164312 0.992436955 0.987575668
+9.530791789 0.991639495 0.992262666 0.992500464 0.987720028
+9.550342131 0.991736963 0.992359625 0.992564688 0.987862482
+9.569892473 0.991833119 0.992455211 0.992629568 0.988003057
+9.589442815 0.991927981 0.992549446 0.992695043 0.988141779
+9.608993157 0.992021572 0.992642351 0.992761056 0.988278677
+9.628543500 0.992113910 0.992733945 0.992827544 0.988413775
+9.648093842 0.992205015 0.992824249 0.992894449 0.988547100
+9.667644184 0.992294906 0.992913284 0.992961710 0.988678678
+9.687194526 0.992383601 0.993001068 0.993029266 0.988808533
+9.706744868 0.992471119 0.993087620 0.993097056 0.988936690
+9.726295210 0.992557478 0.993172960 0.993165018 0.989063173
+9.745845552 0.992642695 0.993257106 0.993233092 0.989188007
+9.765395894 0.992726786 0.993340077 0.993301216 0.989311215
+9.784946237 0.992809769 0.993421890 0.993369327 0.989432820
+9.804496579 0.992891660 0.993502563 0.993437363 0.989552846
+9.824046921 0.992972476 0.993582113 0.993505262 0.989671314
+9.843597263 0.993052231 0.993660558 0.993572961 0.989788247
+9.863147605 0.993130943 0.993737915 0.993640397 0.989903667
+9.882697947 0.993208625 0.993814199 0.993707507 0.990017596
+9.902248289 0.993285293 0.993889428 0.993774227 0.990130054
+9.921798631 0.993360962 0.993963617 0.993840495 0.990241062
+9.941348974 0.993435646 0.994036782 0.993906246 0.990350642
+9.960899316 0.993509359 0.994108939 0.993971416 0.990458813
+9.980449658 0.993582116 0.994180103 0.994035940 0.990565596
+10.000000000 0.993653931 0.994250289 0.994099756 0.990671009
diff --git a/examples/tsukamoto/tsukamoto.fll b/examples/tsukamoto/tsukamoto.fll
index 29ce437..0437d5d 100644
--- a/examples/tsukamoto/tsukamoto.fll
+++ b/examples/tsukamoto/tsukamoto.fll
@@ -1,51 +1,52 @@
-Engine:
+Engine: tsukamoto
InputVariable: X
enabled: true
range: -10.000 10.000
+ lock-range: false
term: small Bell -10.000 5.000 3.000
term: medium Bell 0.000 5.000 3.000
term: large Bell 10.000 5.000 3.000
OutputVariable: Ramps
enabled: true
range: 0.000 1.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage Automatic
default: nan
lock-previous: false
- lock-range: false
term: b Ramp 0.600 0.400
term: a Ramp 0.000 0.250
term: c Ramp 0.700 1.000
OutputVariable: Sigmoids
enabled: true
range: 0.020 1.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage Automatic
default: nan
lock-previous: false
- lock-range: false
term: b Sigmoid 0.500 -30.000
term: a Sigmoid 0.130 30.000
term: c Sigmoid 0.830 30.000
OutputVariable: ZSShapes
enabled: true
range: 0.000 1.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage Automatic
default: nan
lock-previous: false
- lock-range: false
term: b ZShape 0.300 0.600
term: a SShape 0.000 0.250
term: c SShape 0.700 1.000
OutputVariable: Concaves
enabled: true
range: 0.000 1.000
- accumulation: none
+ lock-range: false
+ aggregation: none
defuzzifier: WeightedAverage Automatic
default: nan
lock-previous: false
- lock-range: false
term: b Concave 0.500 0.400
term: a Concave 0.240 0.250
term: c Concave 0.900 1.000
@@ -53,7 +54,8 @@ RuleBlock:
enabled: true
conjunction: none
disjunction: none
- activation: none
+ implication: none
+ activation: General
rule: if X is small then Ramps is a and Sigmoids is a and ZSShapes is a and Concaves is a
rule: if X is medium then Ramps is b and Sigmoids is b and ZSShapes is b and Concaves is b
rule: if X is large then Ramps is c and Sigmoids is c and ZSShapes is c and Concaves is c \ No newline at end of file
diff --git a/examples/tsukamoto/tsukamoto.java b/examples/tsukamoto/tsukamoto.java
index e8cc824..f51d968 100644
--- a/examples/tsukamoto/tsukamoto.java
+++ b/examples/tsukamoto/tsukamoto.java
@@ -1,4 +1,5 @@
import com.fuzzylite.*;
+import com.fuzzylite.activation.*
import com.fuzzylite.defuzzifier.*;
import com.fuzzylite.factory.*;
import com.fuzzylite.hedge.*;
@@ -12,80 +13,91 @@ import com.fuzzylite.variable.*;
public class tsukamoto{
public static void main(String[] args){
+//Code automatically generated with fuzzylite 6.0.
+
Engine engine = new Engine();
-engine.setName("");
+engine.setName("tsukamoto");
+engine.setDescription("");
-InputVariable inputVariable = new InputVariable();
-inputVariable.setEnabled(true);
-inputVariable.setName("X");
-inputVariable.setRange(-10.000, 10.000);
-inputVariable.addTerm(new Bell("small", -10.000, 5.000, 3.000));
-inputVariable.addTerm(new Bell("medium", 0.000, 5.000, 3.000));
-inputVariable.addTerm(new Bell("large", 10.000, 5.000, 3.000));
-engine.addInputVariable(inputVariable);
+InputVariable X = new InputVariable();
+X.setName("X");
+X.setDescription("");
+X.setEnabled(true);
+X.setRange(-10.000, 10.000);
+X.setLockValueInRange(false);
+X.addTerm(new Bell("small", -10.000, 5.000, 3.000));
+X.addTerm(new Bell("medium", 0.000, 5.000, 3.000));
+X.addTerm(new Bell("large", 10.000, 5.000, 3.000));
+engine.addInputVariable(X);
-OutputVariable outputVariable1 = new OutputVariable();
-outputVariable1.setEnabled(true);
-outputVariable1.setName("Ramps");
-outputVariable1.setRange(0.000, 1.000);
-outputVariable1.fuzzyOutput().setAccumulation(null);
-outputVariable1.setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable1.setDefaultValue(Double.NaN);
-outputVariable1.setLockPreviousOutputValue(false);
-outputVariable1.setLockOutputValueInRange(false);
-outputVariable1.addTerm(new Ramp("b", 0.600, 0.400));
-outputVariable1.addTerm(new Ramp("a", 0.000, 0.250));
-outputVariable1.addTerm(new Ramp("c", 0.700, 1.000));
-engine.addOutputVariable(outputVariable1);
+OutputVariable Ramps = new OutputVariable();
+Ramps.setName("Ramps");
+Ramps.setDescription("");
+Ramps.setEnabled(true);
+Ramps.setRange(0.000, 1.000);
+Ramps.setLockValueInRange(false);
+Ramps.setAggregation(null);
+Ramps.setDefuzzifier(new WeightedAverage("Automatic"));
+Ramps.setDefaultValue(Double.NaN);
+Ramps.setLockPreviousValue(false);
+Ramps.addTerm(new Ramp("b", 0.600, 0.400));
+Ramps.addTerm(new Ramp("a", 0.000, 0.250));
+Ramps.addTerm(new Ramp("c", 0.700, 1.000));
+engine.addOutputVariable(Ramps);
-OutputVariable outputVariable2 = new OutputVariable();
-outputVariable2.setEnabled(true);
-outputVariable2.setName("Sigmoids");
-outputVariable2.setRange(0.020, 1.000);
-outputVariable2.fuzzyOutput().setAccumulation(null);
-outputVariable2.setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable2.setDefaultValue(Double.NaN);
-outputVariable2.setLockPreviousOutputValue(false);
-outputVariable2.setLockOutputValueInRange(false);
-outputVariable2.addTerm(new Sigmoid("b", 0.500, -30.000));
-outputVariable2.addTerm(new Sigmoid("a", 0.130, 30.000));
-outputVariable2.addTerm(new Sigmoid("c", 0.830, 30.000));
-engine.addOutputVariable(outputVariable2);
+OutputVariable Sigmoids = new OutputVariable();
+Sigmoids.setName("Sigmoids");
+Sigmoids.setDescription("");
+Sigmoids.setEnabled(true);
+Sigmoids.setRange(0.020, 1.000);
+Sigmoids.setLockValueInRange(false);
+Sigmoids.setAggregation(null);
+Sigmoids.setDefuzzifier(new WeightedAverage("Automatic"));
+Sigmoids.setDefaultValue(Double.NaN);
+Sigmoids.setLockPreviousValue(false);
+Sigmoids.addTerm(new Sigmoid("b", 0.500, -30.000));
+Sigmoids.addTerm(new Sigmoid("a", 0.130, 30.000));
+Sigmoids.addTerm(new Sigmoid("c", 0.830, 30.000));
+engine.addOutputVariable(Sigmoids);
-OutputVariable outputVariable3 = new OutputVariable();
-outputVariable3.setEnabled(true);
-outputVariable3.setName("ZSShapes");
-outputVariable3.setRange(0.000, 1.000);
-outputVariable3.fuzzyOutput().setAccumulation(null);
-outputVariable3.setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable3.setDefaultValue(Double.NaN);
-outputVariable3.setLockPreviousOutputValue(false);
-outputVariable3.setLockOutputValueInRange(false);
-outputVariable3.addTerm(new ZShape("b", 0.300, 0.600));
-outputVariable3.addTerm(new SShape("a", 0.000, 0.250));
-outputVariable3.addTerm(new SShape("c", 0.700, 1.000));
-engine.addOutputVariable(outputVariable3);
+OutputVariable ZSShapes = new OutputVariable();
+ZSShapes.setName("ZSShapes");
+ZSShapes.setDescription("");
+ZSShapes.setEnabled(true);
+ZSShapes.setRange(0.000, 1.000);
+ZSShapes.setLockValueInRange(false);
+ZSShapes.setAggregation(null);
+ZSShapes.setDefuzzifier(new WeightedAverage("Automatic"));
+ZSShapes.setDefaultValue(Double.NaN);
+ZSShapes.setLockPreviousValue(false);
+ZSShapes.addTerm(new ZShape("b", 0.300, 0.600));
+ZSShapes.addTerm(new SShape("a", 0.000, 0.250));
+ZSShapes.addTerm(new SShape("c", 0.700, 1.000));
+engine.addOutputVariable(ZSShapes);
-OutputVariable outputVariable4 = new OutputVariable();
-outputVariable4.setEnabled(true);
-outputVariable4.setName("Concaves");
-outputVariable4.setRange(0.000, 1.000);
-outputVariable4.fuzzyOutput().setAccumulation(null);
-outputVariable4.setDefuzzifier(new WeightedAverage("Automatic"));
-outputVariable4.setDefaultValue(Double.NaN);
-outputVariable4.setLockPreviousOutputValue(false);
-outputVariable4.setLockOutputValueInRange(false);
-outputVariable4.addTerm(new Concave("b", 0.500, 0.400));
-outputVariable4.addTerm(new Concave("a", 0.240, 0.250));
-outputVariable4.addTerm(new Concave("c", 0.900, 1.000));
-engine.addOutputVariable(outputVariable4);
+OutputVariable Concaves = new OutputVariable();
+Concaves.setName("Concaves");
+Concaves.setDescription("");
+Concaves.setEnabled(true);
+Concaves.setRange(0.000, 1.000);
+Concaves.setLockValueInRange(false);
+Concaves.setAggregation(null);
+Concaves.setDefuzzifier(new WeightedAverage("Automatic"));
+Concaves.setDefaultValue(Double.NaN);
+Concaves.setLockPreviousValue(false);
+Concaves.addTerm(new Concave("b", 0.500, 0.400));
+Concaves.addTerm(new Concave("a", 0.240, 0.250));
+Concaves.addTerm(new Concave("c", 0.900, 1.000));
+engine.addOutputVariable(Concaves);
RuleBlock ruleBlock = new RuleBlock();
-ruleBlock.setEnabled(true);
ruleBlock.setName("");
+ruleBlock.setDescription("");
+ruleBlock.setEnabled(true);
ruleBlock.setConjunction(null);
ruleBlock.setDisjunction(null);
-ruleBlock.setActivation(null);
+ruleBlock.setImplication(null);
+ruleBlock.setActivation(new General());
ruleBlock.addRule(Rule.parse("if X is small then Ramps is a and Sigmoids is a and ZSShapes is a and Concaves is a", engine));
ruleBlock.addRule(Rule.parse("if X is medium then Ramps is b and Sigmoids is b and ZSShapes is b and Concaves is b", engine));
ruleBlock.addRule(Rule.parse("if X is large then Ramps is c and Sigmoids is c and ZSShapes is c and Concaves is c", engine));
diff --git a/examples/tsukamoto/tsukamoto.pdf b/examples/tsukamoto/tsukamoto.pdf
new file mode 100644
index 0000000..9c4f375
--- /dev/null
+++ b/examples/tsukamoto/tsukamoto.pdf
Binary files differ
diff --git a/fuzzylite.png b/fuzzylite.png
index f2ba82a..52909ac 100644
--- a/fuzzylite.png
+++ b/fuzzylite.png
Binary files differ
diff --git a/fuzzylite.svg b/fuzzylite.svg
new file mode 100644
index 0000000..ec4e104
--- /dev/null
+++ b/fuzzylite.svg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2">
+<title>QtFuzzyLite</title>
+<desc>A fuzzy logic control library and application</desc>
+<defs>
+ <linearGradient
+ id="linearGradient3000"
+ x1="0%"
+ y1="0%"
+ x2="100%"
+ y2="100%">
+ <stop style="stop-color:#ffffAA;stop-opacity:1;" offset="0" />
+ <stop style="stop-color:#FF8A8A;stop-opacity:1;" offset="1" />
+ </linearGradient>
+
+ <linearGradient id="border-gradient" x1="0%" y1="0%" x2="100%" y2="100%">
+ <stop offset="0%" style="stop-color:#808000;stop-opacity:1" />
+ <stop offset="100%" style="stop-color:#800000;stop-opacity:1" />
+ </linearGradient>
+
+ <rect id='background' width='100' height='100' x='0' y='0' rx='0' ry='0' style='fill:none;fill:url(#linearGradient3000); stroke:url(#border-gradient);stroke-width:5;stroke-linecap: round;stroke-linejoin: round '/>
+ <polygon id='low' points='0,0 25,100 50,0' />
+ <polygon id='medium' points='25,0 50,100 75,0' />
+ <polygon id='high' points='50,0 75,100 100,0' />
+ <polygon id='fuzzy' points='25,0 34,36 59,36 65.95,64 84.1,64 100,0' />
+
+ <g id='fl' style='stroke:black;stroke-width:3;stroke-linecap: round;stroke-linejoin: round ' >
+ <use xlink:href='#low' style='fill:#ffff00; stroke:#808000;'/>
+ <use xlink:href='#medium' style='fill:#ff8000; stroke:#803f00;'/>
+ <use xlink:href='#high' style='fill:#ff0000; stroke:#800000;'/>
+ <use xlink:href='#fuzzy' style='fill:#00d200; stroke:#008000;'/>
+ <!-- <rect width="100" height="100" style="stroke:black; fill: none"/> -->
+ </g>
+</defs>
+ <use xlink:href='#background' transform='scale(1.28,1.28)'/>
+ <use xlink:href='#fl' transform='translate(0, 100) scale(1,-.95)' x='14' y='-12'/>
+
+ <!-- <line x1="50%" y1="0%" x2="50%" y2="100%" style="stroke:black; stroke-width:2"/>
+ <line x1="0%" y1="50%" x2="100%" y2="50%" style="stroke:black; stroke-width:2"/> -->
+
+
+</svg>
diff --git a/fuzzylite/CMakeLists.txt b/fuzzylite/CMakeLists.txt
index f00a71a..28435e2 100644
--- a/fuzzylite/CMakeLists.txt
+++ b/fuzzylite/CMakeLists.txt
@@ -1,17 +1,28 @@
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.8)
+
+if (APPLE)
+ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9)
+endif()
project(fuzzylite CXX)
+
+if (APPLE)
+ cmake_policy(SET CMP0042 NEW)
+endif()
+if (MSVC)
+ cmake_policy(SET CMP0054 NEW)
+endif()
+
+
###DEFINES SECTION
if(NOT CMAKE_VERBOSE_MAKEFILE)
set(CMAKE_VERBOSE_MAKEFILE false)
endif()
-set(FL_VERSION 5.1)
-add_definitions(-DFL_VERSION="${FL_VERSION}")
-
-set(FL_DATE "1507")
-add_definitions(-DFL_DATE="${FL_DATE}")
+if( NOT CMAKE_BUILD_TYPE )
+ set( CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE )
+endif()
add_definitions(-DFL_BUILD_PATH="${CMAKE_SOURCE_DIR}") #used to determine FL__FILE__
@@ -21,35 +32,50 @@ if(FL_BUILD_SHARED)
option(FL_BUILD_BINARY "Build fuzzylite binary" ON)
endif()
+option(FL_CPP98 "Builds utilizing C++98, i.e., passing -std=c++98" OFF)
option(FL_USE_FLOAT "Use fl::scalar as float" OFF)
-option(FL_BACKTRACE "Provide backtrace information in case of errors" OFF)
-option(FL_CPP11 "Builds utilizing C++11, i.e., passing -std=c++11" OFF)
+option(FL_BACKTRACE "Provide backtrace information in case of errors" ON)
-if(FL_CPP11 AND MSVC)
- message("Warning: MSVC not compatible with FL_CPP11 flag")
-endif()
+option(FL_BUILD_TESTS "Builds the unit tests" ON)
if(FL_USE_FLOAT)
add_definitions(-DFL_USE_FLOAT)
endif(FL_USE_FLOAT)
-if(NOT FL_BACKTRACE)
- add_definitions(-DFL_BACKTRACE_OFF)
+if(FL_BACKTRACE)
+ add_definitions(-DFL_BACKTRACE)
+endif()
+
+if (MSVC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19)
+#C++11 not available before Visual Studio 2015
+ if (NOT FL_CPP98)
+ set(FL_CPP98 ON)
+ endif()
endif()
-if(FL_CPP11)
- add_definitions(-DFL_CPP11)
+if(FL_CPP98)
+ add_definitions(-DFL_CPP98)
if(NOT MSVC)
+ #Set C++98 by default in Clang and others
+ add_definitions(-std=c++98)
+ endif()
+else()
+ if(NOT MSVC)
+ #Set C++11 by default in Clang and others
add_definitions(-std=c++11)
- endif(NOT MSVC)
-endif(FL_CPP11)
+ endif()
+endif(FL_CPP98)
+#Put all binaries in same location
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin)
if(NOT MSVC)
- set(CMAKE_CXX_FLAGS "-pedantic -Wall -Wextra ${CMAKE_CXX_FLAGS}")
+#TODO: Remove -Werror before release.
+#Add Unix compilation flags
+ set(CMAKE_CXX_FLAGS "-pedantic -Wall -Wextra -Werror ${CMAKE_CXX_FLAGS}")
+
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
@@ -59,38 +85,64 @@ if(NOT MSVC)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+#Address fl::null errors of literal null conversion
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-non-literal-null-conversion")
endif()
+
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 6)
+ #In GNU gcc v6, the default is C++11
+ if (FL_CPP98)
+ #set the default to C++98
+ #Fix error: 'template<class> class std::auto_ptr' is deprecated with gcc-6
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++98")
+ endif()
+ endif()
+ #In GNU gcc 4.7, Op::str(T, std::size_t(0)) raises a warning of type-limits
+ if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-type-limits")
+ endif()
+endif()
+
+
set(FL_LIBS)
if(MSVC)
+#Set compilation flags in Windows
set(CMAKE_CXX_FLAGS "/W4 /EHsc")
#Wx: Treat warnings as errors. W4: All warnings
#http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
#EHsc: call destructors on __try __catch, and to ignore C4530: C++ exception handler used. Note, unwind semantics are not enabled
+ #Add Backtrace library
if (FL_BACKTRACE)
set(FL_LIBS dbghelp)
endif()
endif()
+
+if(APPLE)
+#Fix ld: symbol(s) not found for architecture x86_64 on mac
+ set(FL_LIBS stdc++)
+endif()
+
+
###BUILD SECTION
include_directories(.)
-if (APPLE)
- cmake_policy(SET CMP0042 NEW)
-endif()
file(STRINGS FL_HEADERS fl-headers)
file(STRINGS FL_SOURCES fl-sources)
+file(STRINGS FL_TESTS fl-tests)
string(REGEX REPLACE "\n" " " ${fl-headers} ${fl-headers})
string(REGEX REPLACE "\n" " " ${fl-sources} ${fl-sources})
+string(REGEX REPLACE "\n" " " ${fl-tests} ${fl-tests})
message("${exepath}")
-set(CMAKE_DEBUG_POSTFIX d)
+set(CMAKE_DEBUG_POSTFIX debug)
if (MSVC OR CMAKE_GENERATOR STREQUAL Xcode)
if(FL_BUILD_SHARED)
@@ -119,16 +171,16 @@ endif()
if(FL_BUILD_SHARED)
set_target_properties(fl-shared PROPERTIES OUTPUT_NAME fuzzylite)
- set_target_properties(fl-shared PROPERTIES DEBUG_POSTFIX d)
- set_target_properties(fl-shared PROPERTIES COMPILE_DEFINITIONS "FL_EXPORT_LIBRARY")
- set_target_properties(fl-shared PROPERTIES VERSION 5.1)
+ set_target_properties(fl-shared PROPERTIES DEBUG_POSTFIX -debug)
+ target_compile_definitions(fl-shared PRIVATE FL_EXPORT_LIBRARY)
+ set_target_properties(fl-shared PROPERTIES VERSION 6.0)
target_link_libraries(fl-shared ${FL_LIBS})
endif()
if(FL_BUILD_STATIC)
set_target_properties(fl-static PROPERTIES OUTPUT_NAME fuzzylite-static)
- set_target_properties(fl-static PROPERTIES DEBUG_POSTFIX d)
- set_target_properties(fl-static PROPERTIES VERSION 5.1)
+ set_target_properties(fl-static PROPERTIES DEBUG_POSTFIX -debug)
+ set_target_properties(fl-static PROPERTIES VERSION 6.0)
target_link_libraries(fl-static ${FL_LIBS})
endif()
@@ -136,12 +188,40 @@ if(FL_BUILD_BINARY)
add_executable(fl-bin src/main.cpp)
set_target_properties(fl-bin PROPERTIES OUTPUT_NAME fuzzylite)
set_target_properties(fl-bin PROPERTIES OUTPUT_NAME fuzzylite IMPORT_PREFIX tmp-) #To prevent LNK1149 in Windows
- set_target_properties(fl-bin PROPERTIES DEBUG_POSTFIX d)
-
- set_target_properties(fl-bin PROPERTIES COMPILE_DEFINITIONS "FL_IMPORT_LIBRARY")
+ set_target_properties(fl-bin PROPERTIES DEBUG_POSTFIX -debug)
+ target_compile_definitions(fl-bin PRIVATE FL_IMPORT_LIBRARY) #if building with fl-shared
target_link_libraries(fl-bin fl-shared ${FL_LIBS})
endif(FL_BUILD_BINARY)
+if(FL_BUILD_TESTS)
+ add_executable(fl-test ${fl-headers} ${fl-tests})
+ set_target_properties(fl-test PROPERTIES OUTPUT_NAME fuzzylite-tests)
+ set_target_properties(fl-test PROPERTIES OUTPUT_NAME fuzzylite-tests IMPORT_PREFIX tmp-) #To prevent LNK1149 in Windows
+ set_target_properties(fl-test PROPERTIES DEBUG_POSTFIX -debug)
+
+ target_compile_definitions(fl-test PRIVATE FL_IMPORT_LIBRARY)
+ if (FL_CPP98)
+ target_compile_definitions(fl-test PRIVATE CATCH_CONFIG_NO_CPP11)
+ endif()
+
+ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+ #Ignore QuickTest macro expansion comparison: CHECK(xstr(4+10) == "4+10")
+ target_compile_options(fl-test PRIVATE -Wno-address)
+ endif()
+ if (MSVC)
+ target_compile_options(fl-test PRIVATE /wd4130)
+ endif()
+
+ target_link_libraries(fl-test fl-shared ${FL_LIBS})
+
+ enable_testing()
+ add_test(NAME RunTests COMMAND fl-test)
+# add_test(NAME ListTests COMMAND fl-test --list-tests)
+# set_tests_properties(ListTests PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ test case")
+# add_test(NAME ListTags COMMAND fl-test --list-tags)
+# set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tag")
+endif()
+
###INSTALL SECTION
if(NOT FL_INSTALL_BINDIR)
set(FL_INSTALL_BINDIR bin)
@@ -156,7 +236,7 @@ if(NOT FL_INSTALL_LIBDIR)
endif()
if(FL_BUILD_BINARY)
- install(TARGETS fl-bin
+ install(TARGETS fl-bin
RUNTIME DESTINATION ${FL_INSTALL_BINDIR}
LIBRARY DESTINATION ${FL_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${FL_INSTALL_LIBDIR}
@@ -164,7 +244,7 @@ if(FL_BUILD_BINARY)
endif()
if(FL_BUILD_SHARED)
- install(TARGETS fl-shared
+ install(TARGETS fl-shared
RUNTIME DESTINATION ${FL_INSTALL_BINDIR}
LIBRARY DESTINATION ${FL_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${FL_INSTALL_LIBDIR}
@@ -186,13 +266,26 @@ configure_file(${CMAKE_SOURCE_DIR}/fuzzylite.pc.in ${CMAKE_BINARY_DIR}/fuzzylite
install(FILES ${CMAKE_BINARY_DIR}/fuzzylite.pc DESTINATION ${FL_INSTALL_LIBDIR}/pkgconfig)
message("=====================================")
-message("fuzzylite v.${FL_VERSION}b${FL_DATE}\n")
+message("fuzzylite v6.0\n")
+message("FL_CPP98=${FL_CPP98}")
message("FL_USE_FLOAT=${FL_USE_FLOAT}")
-message("FL_CPP11=${FL_CPP11}")
message("FL_BACKTRACE=${FL_BACKTRACE}")
+message("FL_LIBS=${FL_LIBS}")
message("FL_INSTALL_BINDIR=${FL_INSTALL_BINDIR}")
message("FL_INSTALL_LIBDIR=${FL_INSTALL_LIBDIR}")
-message("Build=${CMAKE_BUILD_TYPE}")
+message("FL_BUILD_TESTS=${FL_BUILD_TESTS}")
+message("")
+message("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
+message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}")
+message("CMAKE_CXX_COMPILER_VERSION=${CMAKE_CXX_COMPILER_VERSION}")
+message("CMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}")
+message("CMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
+message("COMPILE_DEFINITIONS:")
+get_directory_property(fl-definitions DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS )
+foreach(d ${fl-definitions})
+ message( STATUS "Defined: " ${d} )
+endforeach()
+
message("=====================================\n")
###UNINSTALL SECTION
diff --git a/fuzzylite/FL_HEADERS b/fuzzylite/FL_HEADERS
index f8b578c..b852ad8 100644
--- a/fuzzylite/FL_HEADERS
+++ b/fuzzylite/FL_HEADERS
@@ -1,4 +1,14 @@
+fl/Benchmark.h
+fl/Complexity.h
fl/Console.h
+fl/activation/Activation.h
+fl/activation/First.h
+fl/activation/General.h
+fl/activation/Highest.h
+fl/activation/Last.h
+fl/activation/Lowest.h
+fl/activation/Proportional.h
+fl/activation/Threshold.h
fl/defuzzifier/Bisector.h
fl/defuzzifier/Centroid.h
fl/defuzzifier/Defuzzifier.h
@@ -7,10 +17,13 @@ fl/defuzzifier/LargestOfMaximum.h
fl/defuzzifier/MeanOfMaximum.h
fl/defuzzifier/SmallestOfMaximum.h
fl/defuzzifier/WeightedAverage.h
+fl/defuzzifier/WeightedAverageCustom.h
fl/defuzzifier/WeightedDefuzzifier.h
fl/defuzzifier/WeightedSum.h
+fl/defuzzifier/WeightedSumCustom.h
fl/Engine.h
fl/Exception.h
+fl/factory/ActivationFactory.h
fl/factory/CloningFactory.h
fl/factory/ConstructionFactory.h
fl/factory/DefuzzifierFactory.h
@@ -25,6 +38,7 @@ fl/Headers.h
fl/hedge/Any.h
fl/hedge/Extremely.h
fl/hedge/Hedge.h
+fl/hedge/HedgeFunction.h
fl/hedge/Not.h
fl/hedge/Seldom.h
fl/hedge/Somewhat.h
@@ -40,6 +54,7 @@ fl/imex/FllExporter.h
fl/imex/FllImporter.h
fl/imex/Importer.h
fl/imex/JavaExporter.h
+fl/imex/RScriptExporter.h
fl/norm/Norm.h
fl/norm/s/AlgebraicSum.h
fl/norm/s/BoundedSum.h
@@ -49,6 +64,8 @@ fl/norm/s/HamacherSum.h
fl/norm/s/Maximum.h
fl/norm/s/NilpotentMaximum.h
fl/norm/s/NormalizedSum.h
+fl/norm/s/SNormFunction.h
+fl/norm/s/UnboundedSum.h
fl/norm/SNorm.h
fl/norm/t/AlgebraicProduct.h
fl/norm/t/BoundedDifference.h
@@ -57,6 +74,7 @@ fl/norm/t/EinsteinProduct.h
fl/norm/t/HamacherProduct.h
fl/norm/t/Minimum.h
fl/norm/t/NilpotentMinimum.h
+fl/norm/t/TNormFunction.h
fl/norm/TNorm.h
fl/Operation.h
fl/rule/Antecedent.h
@@ -64,9 +82,10 @@ fl/rule/Consequent.h
fl/rule/Expression.h
fl/rule/RuleBlock.h
fl/rule/Rule.h
-fl/term/Accumulated.h
fl/term/Activated.h
+fl/term/Aggregated.h
fl/term/Bell.h
+fl/term/Binary.h
fl/term/Concave.h
fl/term/Constant.h
fl/term/Cosine.h
diff --git a/fuzzylite/FL_SOURCES b/fuzzylite/FL_SOURCES
index 64d07f9..16d8ab4 100644
--- a/fuzzylite/FL_SOURCES
+++ b/fuzzylite/FL_SOURCES
@@ -1,4 +1,13 @@
+src/Benchmark.cpp
+src/Complexity.cpp
src/Console.cpp
+src/activation/First.cpp
+src/activation/General.cpp
+src/activation/Highest.cpp
+src/activation/Last.cpp
+src/activation/Lowest.cpp
+src/activation/Proportional.cpp
+src/activation/Threshold.cpp
src/defuzzifier/Bisector.cpp
src/defuzzifier/Centroid.cpp
src/defuzzifier/IntegralDefuzzifier.cpp
@@ -6,12 +15,13 @@ src/defuzzifier/LargestOfMaximum.cpp
src/defuzzifier/MeanOfMaximum.cpp
src/defuzzifier/SmallestOfMaximum.cpp
src/defuzzifier/WeightedAverage.cpp
+src/defuzzifier/WeightedAverageCustom.cpp
src/defuzzifier/WeightedDefuzzifier.cpp
src/defuzzifier/WeightedSum.cpp
+src/defuzzifier/WeightedSumCustom.cpp
src/Engine.cpp
src/Exception.cpp
-src/factory/CloningFactory.cpp
-src/factory/ConstructionFactory.cpp
+src/factory/ActivationFactory.cpp
src/factory/DefuzzifierFactory.cpp
src/factory/FactoryManager.cpp
src/factory/FunctionFactory.cpp
@@ -22,6 +32,7 @@ src/factory/TNormFactory.cpp
src/fuzzylite.cpp
src/hedge/Any.cpp
src/hedge/Extremely.cpp
+src/hedge/HedgeFunction.cpp
src/hedge/Not.cpp
src/hedge/Seldom.cpp
src/hedge/Somewhat.cpp
@@ -37,6 +48,7 @@ src/imex/FllExporter.cpp
src/imex/FllImporter.cpp
src/imex/Importer.cpp
src/imex/JavaExporter.cpp
+src/imex/RScriptExporter.cpp
src/main.cpp
src/norm/s/AlgebraicSum.cpp
src/norm/s/BoundedSum.cpp
@@ -46,6 +58,8 @@ src/norm/s/HamacherSum.cpp
src/norm/s/Maximum.cpp
src/norm/s/NilpotentMaximum.cpp
src/norm/s/NormalizedSum.cpp
+src/norm/s/SNormFunction.cpp
+src/norm/s/UnboundedSum.cpp
src/norm/t/AlgebraicProduct.cpp
src/norm/t/BoundedDifference.cpp
src/norm/t/DrasticProduct.cpp
@@ -53,15 +67,16 @@ src/norm/t/EinsteinProduct.cpp
src/norm/t/HamacherProduct.cpp
src/norm/t/Minimum.cpp
src/norm/t/NilpotentMinimum.cpp
-src/Operation.cpp
+src/norm/t/TNormFunction.cpp
src/rule/Antecedent.cpp
src/rule/Consequent.cpp
src/rule/Expression.cpp
src/rule/RuleBlock.cpp
src/rule/Rule.cpp
-src/term/Accumulated.cpp
src/term/Activated.cpp
+src/term/Aggregated.cpp
src/term/Bell.cpp
+src/term/Binary.cpp
src/term/Concave.cpp
src/term/Constant.cpp
src/term/Cosine.cpp
diff --git a/fuzzylite/FL_TESTS b/fuzzylite/FL_TESTS
new file mode 100644
index 0000000..3897a77
--- /dev/null
+++ b/fuzzylite/FL_TESTS
@@ -0,0 +1,16 @@
+test/catch.hpp
+test/MainTest.cpp
+test/BenchmarkTest.cpp
+test/QuickTest.cpp
+test/activation/ThresholdTest.cpp
+test/hedge/HedgeFunctionTest.cpp
+test/imex/FldExporterTest.cpp
+test/imex/FllImporterTest.cpp
+test/imex/RScriptExporterTest.cpp
+test/norm/NormFunctionTest.cpp
+test/term/AggregatedTest.cpp
+test/term/DiscreteTest.cpp
+test/term/FunctionTest.cpp
+test/term/TrapezoidTest.cpp
+test/term/TriangleTest.cpp
+test/variable/VariableTest.cpp
diff --git a/fuzzylite/build.bat b/fuzzylite/build.bat
index 17f5b6d..11f62f8 100644
--- a/fuzzylite/build.bat
+++ b/fuzzylite/build.bat
@@ -13,7 +13,8 @@ for %%a in (%*) do (
if /I "%%a"=="release" set valid="yes"
if /I "%%a"=="debug" set valid="yes"
if /I "%%a"=="clean" set valid="yes"
-
+ if /I "%%a"=="documentation" set valid="yes"
+
if !valid!=="no" (
echo Invalid option: %%a
call:usage
@@ -38,13 +39,13 @@ goto:eof
echo.
echo ****************************************
echo STARTING: debug
-
+
if not exist debug mkdir debug
cd debug
- cmake .. -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Debug -DFL_BACKTRACE=ON -DFL_USE_FLOAT=OFF -DFL_CPP11=OFF
+ cmake .. -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Debug -DFL_BACKTRACE=ON -DFL_USE_FLOAT=OFF -DFL_CPP98=OFF -DFL_BUILD_TESTS=ON
nmake
cd ..
-
+
echo.
echo FINISHED: debug
echo ****************************************
@@ -55,13 +56,13 @@ goto:eof
echo.
echo ****************************************
echo STARTING: release
-
+
if not exist release mkdir release
cd release
- cmake .. -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DFL_BACKTRACE=OFF -DFL_USE_FLOAT=OFF -DFL_CPP11=OFF
+ cmake .. -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DFL_BACKTRACE=OFF -DFL_USE_FLOAT=OFF -DFL_CPP98=OFF -DFL_BUILD_TESTS=ON
nmake
cd ..
-
+
echo.
echo FINISHED: release
echo ****************************************
@@ -72,21 +73,37 @@ goto:eof
echo.
echo ****************************************
echo STARTING: all
- call:debug
call:release
+ call:debug
echo.
echo FINISHED: all
echo ****************************************
goto:eof
+:documentation
+ echo.
+ echo.
+ echo ****************************************
+ echo STARTING: documentation
+
+ cd ..
+ doxygen
+ rem TODO: cd back to previous directory. Maybe use: cd /D %~dp0
+ echo.
+ echo FINISHED: documentation
+ echo ****************************************
+ goto:eof
:clean
echo.
echo.
echo ****************************************
echo STARTING: clean
+ @echo on
if exist debug rmdir /S /Q debug
if exist release rmdir /S /Q release
if exist CMakeFiles rmdir /S /Q CMakeFiles
+ if exist CMakeCache.txt del CMakeCache.txt
+ @echo off
echo.
echo FINISHED: clean
echo ****************************************
@@ -102,4 +119,4 @@ goto:eof
echo ^ help shows this information
echo.
-ENDLOCAL \ No newline at end of file
+ENDLOCAL
diff --git a/fuzzylite/build.sh b/fuzzylite/build.sh
index 78343c4..da39905 100755
--- a/fuzzylite/build.sh
+++ b/fuzzylite/build.sh
@@ -1,19 +1,46 @@
#!/bin/bash
+if [ -z "$FL_USE_FLOAT" ]; then
+ FL_USE_FLOAT="OFF"
+fi
+
+if [ -z "$FL_CPP98" ]; then
+ FL_CPP98="OFF"
+fi
+
+if [ -z "$FL_BUILD_TESTS" ]; then
+ FL_BUILD_TESTS="OFF"
+fi
+
debug(){
+ set -e
mkdir -p debug
cd debug
- cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DFL_BACKTRACE=ON -DFL_USE_FLOAT=OFF -DFL_CPP11=OFF
- make
+ cmake .. -G"Unix Makefiles" -DFL_USE_FLOAT=${FL_USE_FLOAT} -DFL_CPP98=${FL_CPP98} -DCMAKE_BUILD_TYPE=Debug -DFL_BACKTRACE=ON -DFL_BUILD_TESTS=${FL_BUILD_TESTS}
+ make all
+ if [ "${FL_BUILD_TESTS}" == "ON" ]; then
+ (export CTEST_OUTPUT_ON_FAILURE=TRUE; make test)
+ fi
cd ..
}
release(){
+ set -e
mkdir -p release
cd release
- cmake .. -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DFL_BACKTRACE=ON -DFL_USE_FLOAT=OFF -DFL_CPP11=OFF
- make
+ cmake .. -G"Unix Makefiles" -DFL_USE_FLOAT=${FL_USE_FLOAT} -DFL_CPP98=${FL_CPP98} -DCMAKE_BUILD_TYPE=Release -DFL_BACKTRACE=ON -DFL_BUILD_TESTS=${FL_BUILD_TESTS}
+ make all
+ if [ "${FL_BUILD_TESTS}" == "ON" ]; then
+ (export CTEST_OUTPUT_ON_FAILURE=TRUE; make test)
+ fi
+ cd ..
+}
+
+documentation(){
+ set -e
cd ..
+ doxygen Doxyfile
+ cd -
}
all(){
@@ -37,20 +64,21 @@ usage(){
}
#############################
+echo "Parameters: $@"
-OPTIONS=( "all" "debug" "release" "clean" "help")
+OPTIONS=( "all" "release" "debug" "clean" "documentation" "help")
BUILD=( )
for arg in "$@"
do
if [[ "$arg" == "help" ]]; then usage && exit 0; fi
- if [[ "$arg" == "all" || "$arg" == "debug" || "$arg" == "release" || "$arg" == "clean" ]];
+ if [[ "$arg" == "all" || "$arg" == "debug" || "$arg" == "release" || "$arg" == "clean" || "$arg" == "documentation" ]];
then BUILD+=( $arg ); else echo "Invalid option: $arg" && usage && exit 2;
fi
done
-if [ ${#BUILD[@]} -eq 0 ]; then BUILD+=( "all" ); fi
+if [ ${#BUILD[@]} -eq 0 ]; then BUILD+=( "release" "debug" ); fi
echo "Building schedule: ${BUILD[@]}"
echo "Starting in 3 seconds..."
diff --git a/fuzzylite/fl/Benchmark.h b/fuzzylite/fl/Benchmark.h
new file mode 100644
index 0000000..9a212db
--- /dev/null
+++ b/fuzzylite/fl/Benchmark.h
@@ -0,0 +1,400 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_BENCHMARK_H
+#define FL_BENCHMARK_H
+
+#include "fl/fuzzylite.h"
+
+#include "fl/Complexity.h"
+#include "fl/imex/FldExporter.h"
+
+#include <string>
+#include <vector>
+
+namespace fl {
+
+ class Engine;
+
+ /**
+ The Benchmark class is designed to evaluate the performance of an Engine.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Engine
+ @since 6.0
+ */
+ class FL_API Benchmark {
+ private:
+ std::string _name;
+ Engine* _engine;
+ std::vector<std::vector<scalar> > _expected;
+ std::vector<std::vector<scalar> > _obtained;
+ std::vector<scalar> _times;
+ scalar _tolerance;
+
+ public:
+
+ /**
+ Unit of time to utilize in the results
+ */
+ enum TimeUnit {
+ NanoSeconds, MicroSeconds, MilliSeconds, Seconds, Minutes, Hours
+ };
+
+ /**
+ Shape of the table of results
+ */
+ enum TableShape {
+ Horizontal, Vertical
+ };
+
+ /**
+ Contents of the table of results
+ */
+ enum TableContents {
+ Header = 1, Body = 2, HeaderAndBody = (Header | Body)
+ };
+
+ /**
+ Type of error between expected and obtained values
+ */
+ enum ErrorType {
+ NonFinite, Accuracy, All
+ };
+
+ explicit Benchmark(const std::string& name = "", Engine* engine = fl::null,
+ scalar tolerance = fuzzylite::macheps());
+ virtual ~Benchmark();
+ FL_DEFAULT_COPY_AND_MOVE(Benchmark)
+
+ /**
+ Sets the name of the benchmark
+ @param name is the name of the benchmark
+ */
+ void setName(const std::string& name);
+ /**
+ Gets the name of the benchmark
+ @return name is the name of the benchmark
+ */
+ std::string getName() const;
+
+ /**
+ Sets the engine to benchmark
+ @param engine is the engine to benchmark
+ */
+ void setEngine(Engine* engine);
+ /**
+ Gets the engine to benchmark
+ @return the engine to benchmark
+ */
+ Engine* getEngine() const;
+
+ /**
+ Sets the set of expected values from the engine, where the inner vector
+ contains the input values and output values
+ @param expected is the set of expected values from the engine
+ */
+ void setExpected(const std::vector<std::vector<scalar> >& expected);
+ /**
+ Gets the set of expected values from the engine, where the inner vector
+ contains the input values and output values
+ @return the set of expected values from the engine
+ */
+ const std::vector<std::vector<scalar> >& getExpected() const;
+
+ /**
+ Sets the set of obtained values from the engine, where the inner vector
+ contains the input values and output values
+ @param obtained is the set of obtained values from the engine
+ */
+ void setObtained(const std::vector<std::vector<scalar> >& obtained);
+ /**
+ Gets the set of obtained values from the engine, where the inner vector
+ contains the input values and output values
+ @return the set of obtained values from the engine
+ */
+ const std::vector<std::vector<scalar> >& getObtained() const;
+
+ /**
+ Sets the vector of nanoseconds taken to produce the set of obtained values
+ from the set of expected input values
+ @param times is the vector of nanoseconds taken to produce the set of obtained values
+ from the set of expected input values
+ */
+ void setTimes(const std::vector<scalar> times);
+ /**
+ Gets the vector of nanoseconds taken to produce the set of obtained values
+ from the set of expected input values
+ @return the vector of nanoseconds taken to produce the set of obtained values
+ from the set of expected input values
+ */
+ const std::vector<scalar>& getTimes() const;
+
+ /**
+ Sets the tolerance above which the difference between an expected and
+ obtained value from the engine is considered an error
+ @param tolerance is the tolerance above which the difference between
+ an expected and obtained value from the engine is considered an error
+ */
+ void setTolerance(scalar tolerance);
+ /**
+ Gets the tolerance above which the difference between an expected and
+ obtained value from the engine is considered an error
+ @return the tolerance above which the difference between an expected
+ and obtained value from the engine is considered an error
+ */
+ scalar getTolerance() const;
+
+ /**
+ Produces and loads into memory the set of expected values from the
+ engine
+ @param values is the number of values to evaluate the engine upon
+ @param scope is the scope of the values to generate
+ @throws Exception if the engine is not set
+ */
+ virtual void prepare(int values, FldExporter::ScopeOfValues scope);
+ /**
+ Reads and loads into memory the set of expected values from the
+ engine
+ @param reader is the reader of a set of lines containing
+ space-separated values
+ @param numberOfLines is the maximum number of lines to read from the
+ reader, and a value $f@n=(\infty, -1]$f@ reads the entire file.
+ */
+ virtual void prepare(std::istream& reader, long numberOfLines = -1);
+
+ /**
+ Runs the benchmark on the engine only once
+ @return the time in nanoseconds required by the run, which is
+ also appended to the times stored in Benchmark::getTimes()
+ */
+ virtual scalar runOnce();
+ /**
+ Runs the benchmark on the engine multiple times
+ @param times is the number of times to run the benchmark on the engine
+ @return vector of the time in nanoseconds required by each run, which is
+ also appended to the times stored in Benchmark::getTimes()
+ */
+ virtual std::vector<scalar> run(int times);
+
+ /**
+ Resets the benchmark to be ready to run again
+ */
+ virtual void reset();
+
+ /**
+ Indicates whether errors can be computed based on the expected and
+ obtained values from the benchmark. If the benchmark was prepared from
+ a file reader and the file included columns of expected output values
+ and the benchmark has been run at least once, then the benchmark can
+ automatically compute the errors and will automatically include them in
+ the results.
+ @return whether errors can be computed based on the expected and
+ obtained values from the benchmark
+ */
+ virtual bool canComputeErrors() const;
+
+ /**
+ Computes the mean squared error over all output variables considering
+ only those cases where there is an accuracy error as defined in
+ Benchmark::accuracyErrors().
+ @return the mean squared error over all the output variables.
+ */
+ virtual scalar meanSquaredError() const;
+
+ /**
+ Computes the mean squared error of the given output variable
+ considering only those cases where there is an accuracy error
+ as defined in Benchmark::accuracyErrors().
+ @param outputVariable is the output variable to compute the errors for
+ @return the mean squared error over the given output variable.
+ */
+ virtual scalar meanSquaredError(const OutputVariable* outputVariable) const;
+
+ /**
+ Computes the number of errors over all the output variables caused by
+ non-finite differences or accuracy differences. An error is counted when
+ the difference between the expected and obtained values is not finite,
+ or the absolute difference between the expected and obtained values
+ is not smaller than the tolerance.
+ @return the number of errors over all the output variables caused by
+ non-finite differences or accuracy differences
+ */
+ virtual int allErrors() const;
+
+ /**
+ Computes the number of errors of the given output variable caused by
+ non-finite differences or accuracy differences. An error is counted when
+ the difference between the expected and obtained values is not finite,
+ or the absolute difference between the expected and obtained values
+ is not smaller than the tolerance.
+ @param outputVariable is the output variable to account the errors for
+ @return the number of errors of the given output variable caused by
+ non-finite differences or accuracy differences
+ */
+ virtual int allErrors(const OutputVariable* outputVariable) const;
+
+ /**
+ Computes the number of errors over all the output variables caused by
+ non-finite differences (ie, infinity and NaN). An error is counted when
+ the difference between the expected and obtained values is not finite.
+ @return the number of errors over all the output variables caused by
+ non-finite differences
+ */
+ virtual int nonFiniteErrors() const;
+
+ /**
+ Computes the number of errors of the given output variable caused by
+ non-finite differences (ie, infinity and NaN). An error is counted when
+ the difference between the expected and obtained values is not finite.
+ @param outputVariable is the output variable to account the errors for
+ @return the number of errors of the given output variable caused by
+ non-finite differences
+ */
+ virtual int nonFiniteErrors(const OutputVariable* outputVariable) const;
+
+ /**
+ Computes the number of errors over all the output variables caused by
+ a significant difference in accuracy. An error is counted when the
+ absolute difference between the expected and obtained values
+ is not smaller than the tolerance.
+
+ @f$\text{E} = \sum_y \sum_i \epsilon_i^y, \text{where } \epsilon_i^y =
+ \begin{cases}
+ 0 & \text{if} |e_i^y - o^y_i| < \theta\\
+ 1 & \text{otherwise}
+ \end{cases}
+ @f$,
+ @f$y@f$ is the set of output variables, @f$e@f$ is the set of
+ expected output values, @f$o@f$ is the set of obtained output values,
+ and @f$\theta@f$ is the tolerance
+
+ @return the number of errors over all the output variables caused by
+ a significant difference in accuracy
+ */
+ virtual int accuracyErrors() const;
+
+
+ /**
+ Computes the number of errors over the given output variable caused by
+ a significant difference in accuracy. An error is counted when the
+ absolute difference between the expected and obtained values
+ is not smaller than the tolerance.
+
+ @f$\text{E} = \sum_i \epsilon_i, \text{where } \epsilon_i =
+ \begin{cases}
+ 0 & \text{if} |e_i - o_i| < \theta\\
+ 1 & \text{otherwise}
+ \end{cases}
+ @f$,
+ @f$e@f$ is the set of expected output values,
+ @f$o@f$ is the set of obtained output values,
+ and @f$\theta@f$ is the tolerance
+
+ @param outputVariable is the output variable to account the errors for
+ @return the number of errors of the given output variable caused by
+ a significant difference in accuracy
+ */
+ virtual int accuracyErrors(const OutputVariable* outputVariable) const;
+
+ /**
+ Computes the number of errors of the given type over all the output
+ variables.
+ @param errorType is the type of error to account for
+ @return the number of errors over all the output variables
+ */
+ virtual int numberOfErrors(ErrorType errorType) const;
+
+ /**
+ Computes the number of errors of the given type over the given output
+ variable.
+ @param errorType is the type of error to account for
+ @param outputVariable is the output variable to account the errors for
+ @return the number of errors over the given output variable
+ */
+ virtual int numberOfErrors(ErrorType errorType,
+ const OutputVariable* outputVariable) const;
+
+ /**
+ Returns the name of the time unit
+ @param unit is the time unit
+ @return the name of the time unit
+ */
+ static std::string stringOf(TimeUnit unit);
+
+ /**
+ Returns the factor of the given unit from NanoSeconds
+ @param unit is the time unit
+ @return the factor of the given unit from NanoSeconds
+ */
+ static scalar factorOf(TimeUnit unit);
+ /**
+ Converts the time to different scales
+ @param time is the time to convert
+ @param from is the units of the time to convert from
+ @param to is the units of the time to convert to
+ @return the time in the units specified
+ */
+ static scalar convert(scalar time, TimeUnit from, TimeUnit to);
+
+ /**
+ Returns the header of a horizontal table of results
+ @param runs is the number of times the benchmark will be run, hence
+ producing the relevant number of columns for each run
+ @param includeErrors indicates whether to include columns for computing
+ the errors
+ @return the header of a horizontal table of results
+ */
+ virtual std::vector<std::string> header(int runs, bool includeErrors = true);
+
+ /**Result is a type definition for a pair of strings*/
+ typedef std::pair<std::string, std::string> Result;
+ /**
+ Computes and returns the results from the benchmark aggregating the
+ statistics of all the output variables
+ @param timeUnit is the unit of time of the results
+ @param includeTimes indicates whether to include the times of each run
+ @return the results from the benchmark
+ */
+ virtual std::vector<Result> results(TimeUnit timeUnit = NanoSeconds, bool includeTimes = true) const;
+
+ /**
+ Computes and returns the results from the benchmark for the given output
+ variable
+ @param outputVariable is the output variable to compute the statistics for
+ @param timeUnit is the unit of time of the results
+ @param includeTimes indicates whether to include the times of each run
+ @return the results from the benchmark
+ */
+ virtual std::vector<Result> results(const OutputVariable* outputVariable,
+ TimeUnit timeUnit = NanoSeconds, bool includeTimes = true) const;
+
+ /**
+ Formats the results
+ @param results is the vector of results
+ @param shape is the shape to present the table of results
+ @param contents indicates the information to include in the table of results
+ @param delimiter is the delimiter of the table of results
+ @return the formatted results from the benchmark
+ */
+ virtual std::string format(std::vector<Result> results, TableShape shape,
+ TableContents contents, const std::string& delimiter = "\t") const;
+ };
+
+}
+
+#endif /* FL_BENCHMARK_H */
+
diff --git a/fuzzylite/fl/Complexity.h b/fuzzylite/fl/Complexity.h
new file mode 100644
index 0000000..a63138f
--- /dev/null
+++ b/fuzzylite/fl/Complexity.h
@@ -0,0 +1,297 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_COMPLEXITY_H
+#define FL_COMPLEXITY_H
+
+#include "fl/fuzzylite.h"
+
+#include <vector>
+
+namespace fl {
+ class Engine;
+ class InputVariable;
+ class OutputVariable;
+ class Variable;
+ class RuleBlock;
+ class Rule;
+
+ /**
+ The Complexity class is used throughout the library to estimate the
+ computational cost of the different components of the library
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Engine
+ @see Variable
+ @see OutputVariable
+ @see RuleBlock
+ @see Activation
+ @see Rule
+ @see Antecedent
+ @see Consequent
+ @see Hedge
+ @see Norm
+ @since 6.0
+ */
+
+ class FL_API Complexity {
+ private:
+ scalar _comparison;
+ scalar _arithmetic;
+ scalar _function;
+
+ public:
+ explicit Complexity(scalar all = 0.0);
+ explicit Complexity(scalar comparison, scalar arithmetic, scalar function);
+ virtual ~Complexity();
+ FL_DEFAULT_COPY_AND_MOVE(Complexity)
+
+ Complexity& operator+=(const Complexity& other);
+ Complexity& operator-=(const Complexity& other);
+ Complexity& operator*=(const Complexity& other);
+ Complexity& operator/=(const Complexity& other);
+
+ Complexity operator+(const Complexity& rhs) const;
+ Complexity operator-(const Complexity& rhs) const;
+ Complexity operator*(const Complexity& rhs) const;
+ Complexity operator/(const Complexity& rhs) const;
+
+ bool operator==(const Complexity& rhs) const;
+ bool operator!=(const Complexity& rhs) const;
+ bool operator<(const Complexity& rhs) const;
+ bool operator<=(const Complexity& rhs) const;
+ bool operator>(const Complexity& rhs) const;
+ bool operator>=(const Complexity& rhs) const;
+
+ /**
+ Increases the comparison measure by the given amount
+ @param comparison is the amount to increase the comparison measure by
+ @return the reference to the Complexity object with the updated comparison
+ measure
+ */
+ virtual Complexity& comparison(scalar comparison);
+ virtual void setComparison(scalar comparison);
+ virtual scalar getComparison() const;
+
+ /**
+ Increases the arithmetic measure by the given amount
+ @param arithmetic is the amount to increase the comparison measure by
+ @return the reference to the Complexity object with the updated arithmetic
+ measure
+ */
+ virtual Complexity& arithmetic(scalar arithmetic);
+ virtual void setArithmetic(scalar arithmetic);
+ virtual scalar getArithmetic() const;
+
+ /**
+ Increases the function measure by the given amount
+ @param function is the amount to increase the function measure by
+ @return the reference to the Complexity object with the updated function
+ measure
+ */
+ virtual Complexity& function(scalar function);
+ virtual void setFunction(scalar function);
+ virtual scalar getFunction() const;
+
+ /**
+ Returns a vector containing the measures of complexity
+ @return a vector containing the measures of complexity
+ */
+ typedef std::pair<std::string, scalar> Measure;
+ virtual std::vector<Measure> measures() const;
+
+ /**
+ Increases the complexity by the given parameter
+ @param x is the addend
+ @return the reference to the updated complexity
+ */
+ virtual Complexity& plus(const Complexity& x);
+ /**
+ Reduces the complexity by the given parameter
+ @param x is the subtrahend
+ @return the reference to the updated complexity object
+ */
+ virtual Complexity& minus(const Complexity& x);
+ /**
+ Multiplies the complexity by the given parameter
+ @param x is the multiplicand
+ @return the reference to the updated complexity object
+ */
+ virtual Complexity& multiply(const Complexity& x);
+ /**
+ Divides the complexity by the given parameter
+ @param x is the divisor
+ @return the reference to the updated complexity object
+ */
+ virtual Complexity& divide(const Complexity& x);
+
+ /**
+ Increases each measure by the given parameter
+ @param x is the addend
+ @return the reference to the updated complexity
+ */
+ virtual Complexity& plus(scalar x);
+ /**
+ Reduces each measure by the given parameter
+ @param x is the subtrahend
+ @return the reference to the updated complexity
+ */
+ virtual Complexity& minus(scalar x);
+ /**
+ Multiplies each measure by the given parameter
+ @param x is the multiplicand
+ @return the reference to the updated complexity
+ */
+ virtual Complexity& multiply(scalar x);
+ /**
+ Divides each measure by the given parameter
+ @param x is the divisor
+ @return the reference to the updated complexity
+ */
+ virtual Complexity& divide(scalar x);
+
+ /**
+ Compares the complexity for equality to another with the given tolerance
+ @param x is the complexity to compare against
+ @param macheps is the tolerance to compare floating-point values
+ @return `true` if every measure in this satisfies Op::isEq(this, x, macheps),
+ and `false` otherwise
+ */
+ virtual bool equals(const Complexity& x, scalar macheps = fuzzylite::macheps()) const;
+ /**
+ Compares the complexity for strict inequality (less than) to another
+ with the given tolerance
+ @param x is the complexity to compare against
+ @param macheps is the tolerance to compare floating-point values
+ @return `true` if every measure in this satisfies Op::isLt(this, x, macheps),
+ and `false` otherwise
+ */
+ virtual bool lessThan(const Complexity& x, scalar macheps = fuzzylite::macheps()) const;
+ /**
+ Compares the complexity for inequality (less than or equal to) to another
+ with the given tolerance
+ @param x is the complexity to compare against
+ @param macheps is the tolerance to compare floating-point values
+ @return `true` if every measure in this satisfies Op::isLE(this, x, macheps),
+ and `false` otherwise
+ */
+ virtual bool lessThanOrEqualsTo(const Complexity& x, scalar macheps = fuzzylite::macheps()) const;
+ /**
+ Compares the complexity for strict inequality (greater than) to another
+ with the given tolerance
+ @param x is the complexity to compare against
+ @param macheps is the tolerance to compare floating-point values
+ @return `true` if every measure in this satisfies Op::isGt(this, x, macheps),
+ and `false` otherwise
+ */
+ virtual bool greaterThan(const Complexity& x, scalar macheps = fuzzylite::macheps()) const;
+ /**
+ Compares the complexity for inequality (greater than or equal to) to
+ another with the given tolerance
+ @param x is the complexity to compare against
+ @param macheps is the tolerance to compare floating-point values
+ @return `true` if every measure in this satisfies Op::isGE(this, x, macheps),
+ and `false` otherwise
+ */
+ virtual bool greaterThanOrEqualsTo(const Complexity& x, scalar macheps = fuzzylite::macheps()) const;
+
+ /**
+ Computes the sum of the measures
+ @return the sum of the measures
+ */
+ virtual scalar sum() const;
+
+ /**
+ Computes the norm of the complexity
+ @return the norm of the complexity
+ */
+ virtual scalar norm() const;
+
+ /**
+ Returns the measures of the complexity
+ @return the measures of the complexity
+ */
+ virtual std::string toString() const;
+
+ /**
+ Computes the complexity of the given engine as the sum of complexities
+ of the rule blocks
+ @param engine is the engine for which to compute the complexity
+ @return the complexity of the given engine as the sum of complexities
+ of the rule blocks
+ */
+ virtual Complexity compute(const Engine* engine) const;
+
+ /**
+ Computes the complexity of the given input variable
+ @param inputVariable is the input variable for which to compute the complexity
+ @return the complexity of the given input variable
+ */
+ virtual Complexity compute(const InputVariable* inputVariable) const;
+ /**
+ Computes the complexity of the given output variable
+ @param outputVariable is the output variable for which to compute the complexity
+ @return the complexity of the given output variable
+ */
+ virtual Complexity compute(const OutputVariable* outputVariable) const;
+
+ /**
+ Computes the complexity of the given input variables
+ @param inputVariables is the vector of input variables for which to
+ compute the complexity
+ @return the complexity of the given input variables
+ */
+ virtual Complexity compute(const std::vector<InputVariable*>& inputVariables) const;
+ /**
+ Computes the complexity of the given output variables
+ @param outputVariables is the vector of output variables for which to
+ compute the complexity
+ @param complexityOfDefuzzification indicates whether to compute the
+ complexity of the variable including the defuzzification process
+ @return the complexity of the given output variables
+ */
+ virtual Complexity compute(const std::vector<OutputVariable*>& outputVariables,
+ bool complexityOfDefuzzification = false) const;
+ /**
+ Computes the complexity of the given variables
+ @param variables is the vector of variables for which to compute the
+ complexity
+ @return the complexity of the given variables
+ */
+ virtual Complexity compute(const std::vector<Variable*>& variables) const;
+
+ /**
+ Computes the complexity of the given rule block
+ @param ruleBlock is the rule block for which to compute the complexity
+ @return the complexity of the given rule block
+ */
+ virtual Complexity compute(const RuleBlock* ruleBlock) const;
+
+ /**
+ Computes the complexity of the given rule blocks
+ @param ruleBlocks is the vector of rule blocks for which to compute the
+ complexity
+ @return Computes the complexity of the given rule blocks
+ */
+ virtual Complexity compute(const std::vector<RuleBlock*>& ruleBlocks) const;
+
+ };
+
+
+}
+
+#endif /* COMPLEXITY_H */
+
diff --git a/fuzzylite/fl/Console.h b/fuzzylite/fl/Console.h
index 59e818d..b96d677 100644
--- a/fuzzylite/fl/Console.h
+++ b/fuzzylite/fl/Console.h
@@ -1,32 +1,23 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_CONSOLE_H
#define FL_CONSOLE_H
#include "fl/fuzzylite.h"
-
#include <map>
#include <string>
#include <vector>
@@ -34,57 +25,131 @@
namespace fl {
class Engine;
+ /**
+ The Console class is a command-line tool that helps to utilize the
+ `fuzzylite` library.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @since 4.0
+ */
class FL_API Console {
public:
+ /**
+ A command-line option given by key, value and description
+ */
struct Option {
std::string key, value, description;
- explicit Option(const std::string& key = "", const std::string& value = "", const std::string& description = "") :
- key(key), value(value), description(description) {
- }
+ explicit Option(const std::string& key = "",
+ const std::string& value = "",
+ const std::string& description = "");
};
+ /**Keyword for input file*/
static const std::string KW_INPUT_FILE;
+ /**Keyword for input file format*/
static const std::string KW_INPUT_FORMAT;
+ /**Keyword for output file*/
static const std::string KW_OUTPUT_FILE;
+ /**Keyword for output file format*/
static const std::string KW_OUTPUT_FORMAT;
+ /**Keyword for built-in example*/
static const std::string KW_EXAMPLE;
+ /**Keyword for number of decimals*/
static const std::string KW_DECIMALS;
- static const std::string KW_DATA_INPUT;
- static const std::string KW_DATA_MAXIMUM;
+ /**Keyword for file containing input data*/
+ static const std::string KW_DATA_INPUT_FILE;
+ /**Keyword for number of values to generate*/
+ static const std::string KW_DATA_VALUES;
+ /**Keyword for the scope of the number of values to generate*/
+ static const std::string KW_DATA_VALUES_SCOPE;
+ /**Keyword for exporting headers in FLD*/
static const std::string KW_DATA_EXPORT_HEADER;
+ /**Keyword for exporting input values in FLD*/
static const std::string KW_DATA_EXPORT_INPUTS;
+ /**
+ Creates a new Mamdani Engine based on the SimpleDimmer example
+ @return a new Mamdani Engine based on the SimpleDimmer example
+ */
static Engine* mamdani();
+ /**
+ Creates a new TakagiSugeno Engine based on the Approximation example of @f$sin(x)/x@f$
+ @return a new TakagiSugeno Engine based on the Approximation example of @f$sin(x)/x@f$
+ */
static Engine* takagiSugeno();
+ /**
+ Creates a new Hybrid Engine based on the Tipper example using Mamdani
+ and TakagiSugeno outputs.
+ @return a new Hybrid Engine based on the Tipper example using Mamdani
+ and TakagiSugeno outputs.
+ */
+ static Engine* hybrid();
+
+
protected:
- static std::map<std::string, std::string> parse(int argc, char** argv);
- static void process(const std::map<std::string, std::string>& options);
+ virtual std::map<std::string, std::string> parse(int argc, const char* argv[]);
+ virtual void process(const std::map<std::string, std::string>& options);
- static void process(const std::string& input, std::ostream& writer,
+ virtual void process(const std::string& input, std::ostream& writer,
const std::string& inputFormat, const std::string& outputFormat,
const std::map<std::string, std::string>& options);
- static int readCharacter();
- static void interactive(std::ostream& writer, Engine* engine);
- static std::string interactiveHelp();
-
- static void exportAllExamples(const std::string& from, const std::string& to);
- static void exportAllExamples(const std::string& from, const std::string& to, const std::string& path);
-#ifdef FL_CPP11
- static void benchmarkExamples(const std::string& path, int runs);
-#endif
+ virtual int readCharacter();
+ virtual void interactive(std::ostream& writer, Engine* engine);
+ virtual std::string interactiveHelp();
+
+ virtual void exportAllExamples(const std::string& from, const std::string& to);
+ virtual void exportAllExamples(const std::string& from, const std::string& to,
+ const std::string& examplesPath, const std::string& outputPath);
+
+ /**
+ Benchmarks the engine described in the FLL file against the dataset
+ contained in the FLD file.
+
+ @param fllFile is the file describing the engine in FLL format
+ @param fldFile is the file containing the dataset in FLD format
+ @param runs is the number of runs to evaluate the benchmarks
+ @param writer is the output where the results will be written to
+ @throws Exception if something goes wrong reading the files, importing the
+ engines or evaluating the benchmark
+ */
+
+ virtual void benchmark(const std::string& fllFile, const std::string& fldFile,
+ int runs, std::ofstream* writer = fl::null) const;
+ /**
+ Benchmarks the list of engines against the list of datasets, both described
+ as absolute or relative paths
+
+ @param fllFileList is the file containing the list of paths of engines in
+ FLL format
+ @param fldFileList is the file containing the list of paths of datasets in
+ FLD format
+ @param runs is the number of runs to evaluate the benchmarks
+ @param writer is the output where the results will be written to
+ @throws Exception if something goes wrong reading the files, importing the
+ engines or evaluating the benchmark
+ */
+ virtual void benchmarks(const std::string& fllFileList, const std::string& fldFileList,
+ int runs, std::ofstream* writer = fl::null) const;
public:
- static std::string usage();
- static std::vector<Option> availableOptions();
-
- static int main(int argc, char** argv);
+ /**
+ Returns a string representation of the usage of the command-line tool
+ @return a string representation of the usage of the command-line tool
+ */
+ virtual std::string usage();
+
+ /**
+ Returns a vector of the options available from the command line
+ @return a vector of the options available from the command line
+ */
+ virtual std::vector<Option> availableOptions();
+
+ static int main(int argc, const char* argv[]);
};
-
}
-
#endif /* FL_CONSOLE_H */
diff --git a/fuzzylite/fl/Engine.h b/fuzzylite/fl/Engine.h
index 532c5e9..3a88478 100644
--- a/fuzzylite/fl/Engine.h
+++ b/fuzzylite/fl/Engine.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_ENGINE_H
@@ -27,7 +19,7 @@
#include "fl/fuzzylite.h"
-#include "fl/defuzzifier/IntegralDefuzzifier.h"
+#include "fl/Complexity.h"
#include <string>
#include <vector>
@@ -42,16 +34,29 @@ namespace fl {
class TNorm;
class SNorm;
class Defuzzifier;
-
+ class Activation;
+
+ /**
+ The Engine class is the core class of the library as it groups the
+ necessary components of a fuzzy logic controller.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see InputVariable
+ @see OutputVariable
+ @see RuleBlock
+ @since 4.0
+ */
class FL_API Engine {
private:
- void copyFrom(const Engine& source);
- protected:
std::string _name;
+ std::string _description;
std::vector<InputVariable*> _inputVariables;
std::vector<OutputVariable*> _outputVariables;
- std::vector<RuleBlock*> _ruleblocks;
+ std::vector<RuleBlock*> _ruleBlocks;
+
+ void copyFrom(const Engine& source);
+ protected:
void updateReferences() const;
public:
@@ -61,92 +66,413 @@ namespace fl {
virtual ~Engine();
FL_DEFAULT_MOVE(Engine)
- //TODO: remove int resolution in v6.0
- virtual void configure(const std::string& conjunctionT,
- const std::string& disjunctionS,
- const std::string& activationT,
- const std::string& accumulationS,
+ /**
+ Configures the engine with the given operators
+ @param conjunction is a TNorm registered in the TNormFactory
+ @param disjunction is an SNorm registered in the SNormFactory
+ @param implication is an TNorm registered in the TNormFactory
+ @param aggregation is an SNorm registered in the SNormFactory
+ @param defuzzifier is a defuzzifier registered in the DefuzzifierFactory
+ @param activation is an activation method registered in the ActivationFactory
+ */
+ virtual void configure(const std::string& conjunction,
+ const std::string& disjunction,
+ const std::string& implication,
+ const std::string& aggregation,
const std::string& defuzzifier,
- int resolution = IntegralDefuzzifier::defaultResolution());
+ const std::string& activation);
+ /**
+ Configures the engine with clones of the given object operators, taking
+ ownership of the objects.
+
+ @param conjunction is the operator to process the propositions joined
+ by `and` in the antecedent of the rules
+ @param disjunction is the operator to process the propositions
+ joined by `or` in the antecedent of the rules
+ @param implication is the operator to modify the consequents of the
+ rules based on the activation degree of the antecedents of the rules
+ @param aggregation is the operator to aggregate the resulting
+ implications of the rules
+ @param defuzzifier is the operator to transform the aggregated
+ implications into a single scalar value
+ @param activation is the activation method to activate and fire the
+ rule blocks
+ */
virtual void configure(TNorm* conjunction, SNorm* disjunction,
- TNorm* activation, SNorm* accumulation,
- Defuzzifier* defuzzifier);
+ TNorm* implication, SNorm* aggregation,
+ Defuzzifier* defuzzifier, Activation* activation);
+ /**
+ Indicates whether the engine has been configured correctly and is
+ ready for operation. In more advanced engines, the result of this
+ method should be taken as a suggestion and not as a prerequisite to
+ operate the engine.
+
+ @param status (if not null) contains the configuration errors of the engine
+ @return whether the engine is ready to operate
+ */
virtual bool isReady(std::string* status = fl::null) const;
+ /**
+ Computes the estimated complexity of operation of the engine
+ @return the estimated complexity of operation of the engine
+ */
+ virtual Complexity complexity() const;
+ /**
+ Processes the engine in its current state as follows: (a) Clears the
+ aggregated fuzzy output variables, (b) Activates the rule blocks, and
+ (c) Defuzzifies the output variables
+ @see Aggregated::clear()
+ @see RuleBlock::activate()
+ @see OutputVariable::defuzzify()
+ */
virtual void process();
+ /**
+ Restarts the engine by setting the values of the input variables to
+ fl::nan and clearing the output variables
+ @see Variable::setValue()
+ @see OutputVariable::clear()
+ */
virtual void restart();
+ /**
+ Sets the name of the engine
+ @param name is the name of the engine
+ */
virtual void setName(const std::string& name);
+ /**
+ Gets the name of the engine
+ @return the name of the engine
+ */
virtual std::string getName() const;
+ /**
+ Sets the description of the engine
+ @param description is the description of the engine
+ */
+ virtual void setDescription(const std::string& description);
+ /**
+ Gets the description of the engine
+ @return the description of the engine
+ */
+ virtual std::string getDescription() const;
+
+ /**
+ Sets the value of the given input variable.
+ The cost of this method is O(n), where n is the number of
+ input variables in the engine. For performance, please get the
+ variables by index.
+ @param name is the name of the input variable
+ @param value is the value for the input variable
+ */
virtual void setInputValue(const std::string& name, scalar value);
+ /**
+ Gets the value of the given output variable.
+ The cost of this method is O(n), where n is the number of
+ output variables in the engine. For performance, please get the
+ variables by index.
+ @param name is the name of the output variable
+ @return the value of the given output variable
+ */
virtual scalar getOutputValue(const std::string& name);
-
+ /**
+ Returns a string representation of the engine in the FuzzyLite
+ Language
+ @return a string representation of the engine in the FuzzyLite
+ Language
+ */
virtual std::string toString() const;
enum Type {
- Mamdani, Larsen, TakagiSugeno,
- Tsukamoto, InverseTsukamoto, Hybrid, Unknown
+ /**Mamdani: When the output variables have IntegralDefuzzifier%s*/
+ Mamdani,
+ /**Larsen: When Mamdani and AlgebraicProduct is the implication operator of
+ the rule blocks */
+ Larsen,
+ /**TakagiSugeno: When output variables have WeightedDefuzzifier%s of type
+ TakagiSugeno and the output variables have Constant, Linear, or
+ Function terms*/
+ TakagiSugeno,
+ /**Tsukamoto: When output variables have WeightedDefuzzifier%s of type
+ Tsukamoto and the output variables only have monotonic terms
+ (Concave, Ramp, Sigmoid, SShape, and ZShape)*/
+ Tsukamoto,
+ /**InverseTsukamoto: When output variables have WeightedDefuzzifier%s of type
+ TakagiSugeno and the output variables do not only have Constant,
+ Linear or Function terms*/
+ InverseTsukamoto,
+ /**Hybrid: When output variables have different defuzzifiers*/
+ Hybrid,
+ /**Unknown: When output variables have no defuzzifiers*/
+ Unknown
};
+ /**
+ Infers the type of the engine based on its current configuration
+
+ @param name stores a string representation of the engine type (if the
+ pointer passed is not `fl::null`)
+ @param reason stores a string representation explaining the reasons
+ for the inferred type (if the pointer passed is not `fl::null`)
+ @return the inferred type of the engine based on its current
+ configuration
+ */
virtual Type type(std::string* name = fl::null, std::string* reason = fl::null) const;
+ /**
+ Creates a clone of the engine
+ @return a clone of the engine
+ */
virtual Engine* clone() const;
+ /**
+ Returns a vector that contains the input variables followed by the
+ output variables in the order of insertion
+
+ @return a vector that contains the input variables followed by the
+ output variables in the order of insertion
+ */
virtual std::vector<Variable*> variables() const;
/**
- * Operations for iterable datatype _inputVariables
+ Adds the input variable
+ @param inputVariable is the input variable
*/
virtual void addInputVariable(InputVariable* inputVariable);
- virtual InputVariable* setInputVariable(InputVariable* inputVariable, int index);
- virtual void insertInputVariable(InputVariable* inputVariable, int index);
- virtual InputVariable* getInputVariable(int index) const;
+ /**
+ Sets the input variable at the given index
+ @param inputVariable is the input variable to set
+ @param index is the index at which the input variable is to be stored
+ @return the input variable previously stored at the given index
+ */
+ virtual InputVariable* setInputVariable(InputVariable* inputVariable, std::size_t index);
+ /**
+ Inserts the input variable at the given index, shifting other
+ variables one position to the right
+ @param inputVariable is the input variable to insert
+ @param index is the index at which the input variable is to be
+ inserted
+ */
+ virtual void insertInputVariable(InputVariable* inputVariable, std::size_t index);
+ /**
+ Gets the input variable at the given index
+ @param index is the given index
+ @return the input variable at the given index
+ */
+ virtual InputVariable* getInputVariable(std::size_t index) const;
+ /**
+ Gets the input variable of the given name after iterating the input
+ variables. The cost of this method is O(n), where n is the number of
+ input variables in the engine. For performance, please get the
+ variables by index.
+ @param name is the name of the input variable
+ @return input variable of the given name
+ @throws fl::Exception if there is no variable with the given name
+ */
virtual InputVariable* getInputVariable(const std::string& name) const;
- virtual InputVariable* removeInputVariable(int index);
+ /**
+ Removes the input variable at the given index (without deleting it)
+ and shifts the remaining input variables one position to the left
+ @param index is the given index
+ @return the input variable at the given index
+ */
+ virtual InputVariable* removeInputVariable(std::size_t index);
+ /**
+ Removes the input variable of the given name (without deleting it) and
+ shifts the remaining input variables one position to the left
+ @param name is the name of the input variable
+ @return the input variable of the given name
+ @throws fl::Exception if there is no variable with the given name
+ */
virtual InputVariable* removeInputVariable(const std::string& name);
+ /**
+ Indicates whether an input variable of the given name is in the input
+ variables
+ @param name is the name of the input variable
+ @return whether an input variable is registered with the given name
+ */
virtual bool hasInputVariable(const std::string& name) const;
- virtual int numberOfInputVariables() const;
+ /**
+ Returns the number of input variables added to the engine
+ @return the number of input variables added to the engine
+ */
+ virtual std::size_t numberOfInputVariables() const;
+ /**
+ Returns an immutable vector of input variables
+ @return an immutable vector of input variables
+ */
virtual const std::vector<InputVariable*>& inputVariables() const;
+ /**
+ Sets the vector of input variables
+ @param inputVariables is the vector of input variables
+ */
virtual void setInputVariables(const std::vector<InputVariable*>& inputVariables);
+ /**
+ Returns a mutable vector of input variables
+ @return a mutable vector of input variables
+ */
virtual std::vector<InputVariable*>& inputVariables();
/**
- * Operations for iterable datatype _outputVariables
+ Adds the output variable
+ @param outputVariable is the output variable
*/
virtual void addOutputVariable(OutputVariable* outputVariable);
- virtual OutputVariable* setOutputVariable(OutputVariable* outputVariable, int index);
- virtual void insertOutputVariable(OutputVariable* outputVariable, int index);
- virtual OutputVariable* getOutputVariable(int index) const;
+ /**
+ Sets the output variable at the given index
+ @param outputVariable is the output variable to set
+ @param index is the index at which the output variable is to be stored
+ @return the output variable previously stored at the given index
+ */
+ virtual OutputVariable* setOutputVariable(OutputVariable* outputVariable, std::size_t index);
+ /**
+ Inserts the output variable at the given index, shifting other
+ variables one position to the right
+ @param outputVariable is the output variable to insert
+ @param index is the index at which the output variable is to be inserted
+ */
+ virtual void insertOutputVariable(OutputVariable* outputVariable, std::size_t index);
+ /**
+ Gets the output variable at the given index
+ @param index is the given index
+ @return the output variable at the given index
+ */
+ virtual OutputVariable* getOutputVariable(std::size_t index) const;
+ /**
+ Gets the output variable of the given name after iterating the output
+ variables. The cost of this method is O(n), where n is the number of
+ output variables in the engine. For performance, please get the
+ variables by index.
+ @param name is the name of the output variable
+ @return output variable of the given name
+ @throws fl::Exception if there is no variable with the given name
+ */
virtual OutputVariable* getOutputVariable(const std::string& name) const;
+
+ /**
+ Indicates whether an output variable of the given name is in the
+ output variables
+ @param name is the name of the output variable
+ @return whether an output variable is registered with the given name
+ */
virtual bool hasOutputVariable(const std::string& name) const;
- virtual OutputVariable* removeOutputVariable(int index);
+ /**
+ Removes the output variable at the given index (without deleting it)
+ and shifts the remaining output variables one position to the left
+ @param index is the given index
+ @return the output variable at the given index
+ */
+ virtual OutputVariable* removeOutputVariable(std::size_t index);
+ /**
+ Removes the output variable of the given name (without deleting it)
+ and shifts the remaining output variables one position to the left
+ @param name is the name of the output variable
+ @return the output variable of the given name
+ @throws fl::Exception if there is no variable with the given name
+ */
virtual OutputVariable* removeOutputVariable(const std::string& name);
- virtual int numberOfOutputVariables() const;
+ /**
+ Returns the number of output variables added to the engine
+ @return the number of output variables added to the engine
+ */
+ virtual std::size_t numberOfOutputVariables() const;
+ /**
+ Returns an immutable vector of output variables
+ @return an immutable vector of output variables
+ */
virtual const std::vector<OutputVariable*>& outputVariables() const;
+ /**
+ Sets the vector of output variables
+ @param outputVariables is the vector of output variables
+ */
virtual void setOutputVariables(const std::vector<OutputVariable*>& outputVariables);
+ /**
+ Returns a mutable vector of output variables
+ @return a mutable vector of output variables
+ */
virtual std::vector<OutputVariable*>& outputVariables();
/**
- * Operations for iterable datatype _ruleblocks
+ Adds the rule block
+ @param ruleBlock is the rule block
+ */
+ virtual void addRuleBlock(RuleBlock* ruleBlock);
+ /**
+ Sets the rule block at the given index
+ @param ruleBlock is the rule block to set
+ @param index is the index at which the rule block is to be stored
+ @return the rule block previously stored at the given index
+ */
+ virtual RuleBlock* setRuleBlock(RuleBlock* ruleBlock, std::size_t index);
+ /**
+ Inserts the rule block at the given index, shifting other blocks one
+ position to the right
+ @param ruleBlock is the rule block to insert
+ @param index is the index at which the rule block is to be inserted
+ */
+ virtual void insertRuleBlock(RuleBlock* ruleBlock, std::size_t index);
+ /**
+ Gets the rule block at the given index
+ @param index is the given index
+ @return the rule block at the given index
+ */
+ virtual RuleBlock* getRuleBlock(std::size_t index) const;
+ /**
+ Gets the rule block of the given name after iterating the rule blocks.
+ The cost of this method is O(n), where n is the number of
+ rule blocks in the engine. For performance, please get the rule blocks
+ by index.
+ @param name is the name of the rule block
+ @return rule block of the given name
+ @throws fl::Exception if there is no block with the given name
*/
- virtual void addRuleBlock(RuleBlock* ruleblock);
- virtual RuleBlock* setRuleBlock(RuleBlock* ruleBlock, int index);
- virtual void insertRuleBlock(RuleBlock* ruleblock, int index);
- virtual RuleBlock* getRuleBlock(int index) const;
virtual RuleBlock* getRuleBlock(const std::string& name) const;
+ /**
+ Indicates whether an rule block of the given name is in the rule
+ blocks
+ @param name is the name of the rule block
+ @return whether an rule block of the given name is in the rule blocks
+
+ */
virtual bool hasRuleBlock(const std::string& name) const;
- virtual RuleBlock* removeRuleBlock(int index);
+ /**
+ Removes the rule block at the given index (without deleting it) and
+ shifts the remaining rule blocks one position to the left
+ @param index is the given index
+ @return the rule block at the given index
+ */
+ virtual RuleBlock* removeRuleBlock(std::size_t index);
+ /**
+ Removes the rule block of the given name (without deleting it) and
+ shifts the remaining rule blocks one position to the left
+ @param name is the name of the rule block
+ @return the rule block of the given name
+ @throws fl::Exception if there is no rule block with the given name
+ */
virtual RuleBlock* removeRuleBlock(const std::string& name);
- virtual int numberOfRuleBlocks() const;
+ /**
+ Returns the number of rule blocks added to the engine
+ @return the number of rule blocks added to the engine
+ */
+ virtual std::size_t numberOfRuleBlocks() const;
+ /**
+ Returns an immutable vector of rule blocks
+ @return an immutable vector of rule blocks
+ */
virtual const std::vector<RuleBlock*>& ruleBlocks() const;
+ /**
+ Sets the vector of rule blocks
+ @param ruleBlocks is the vector of rule blocks
+ */
virtual void setRuleBlocks(const std::vector<RuleBlock*>& ruleBlocks);
+ /**
+ Returns a mutable vector of rule blocks
+ @return a mutable vector of rule blocks
+ */
virtual std::vector<RuleBlock*>& ruleBlocks();
};
-
}
#endif /* FL_ENGINE_H */
diff --git a/fuzzylite/fl/Exception.h b/fuzzylite/fl/Exception.h
index f33fb13..60996f1 100644
--- a/fuzzylite/fl/Exception.h
+++ b/fuzzylite/fl/Exception.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_EXCEPTION_H
@@ -33,34 +25,116 @@
namespace fl {
+ /**
+
+ The Exception class is the only type of exception that is utilized
+ throughout the library. If the library is built with the compiling flag
+ `-DFL_BACKTRACE=ON`, the method Exception::btCallStack() will provide a
+ stack trace when an exception is thrown. Please, have in mind that
+ enabling the stack trace requires the external library `dbghelp` in
+ the Windows platform, which is generally available in the operating
+ system.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @since 4.0
+
+ */
+
+#ifdef FL_WINDOWS
+ //Disable warning for dllexport of std::exception in Windows
+#pragma warning (push)
+#pragma warning (disable:4275)
+#endif
+
class FL_API Exception : public std::exception {
- protected:
+#ifdef FL_WINDOWS
+#pragma warning (pop)
+#endif
+ private:
std::string _what;
public:
explicit Exception(const std::string& what);
- Exception(const std::string& what, const std::string& file, int line,
+ /**
+ Constructor to be used in conjunction with macro `FL_AT`
+ @param what is the message of the exception
+ @param file is the name of the file where the exception occurred
+ @param line is the line number in the file where the exception occurred
+ @param function is the name of the function where the exception occurred
+ */
+ explicit Exception(const std::string& what, const std::string& file, int line,
const std::string& function);
virtual ~Exception() FL_INOEXCEPT FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(Exception)
+ /**
+ Sets the message of the `std::exception`
+ @param what is the message of the `std::exception`
+ */
virtual void setWhat(const std::string& what);
+ /**
+ Gets the message of the `std::exception`
+ @return the message of the `std::exception`
+ */
virtual std::string getWhat() const;
+ /**
+ Gets the message of the `std::exception`
+ @return the message of the `std::exception`
+ */
virtual const char* what() const FL_INOEXCEPT FL_IOVERRIDE;
+ /**
+ Appends a message to the exception
+ @param whatElse is a message to the exception
+ */
virtual void append(const std::string& whatElse);
+ /**
+ Appends an error trace to the exception. The method can be called
+ utilizing the macro `FL_AT`
+ @param file is the name of the file where the exception occurred
+ @param line is the line number in the file where the exception occurred
+ @param function is the name of the function where the exception occurred
+ */
virtual void append(const std::string& file, int line, const std::string& function);
+ /**
+ Appends an error trace with a message to the exception. The method can be called
+ utilizing the macro `FL_AT`
+ @param whatElse is further information about the exception
+ @param file is the name of the file where the exception occurred
+ @param line is the line number in the file where the exception occurred
+ @param function is the name of the function where the exception occurred
+ */
virtual void append(const std::string& whatElse,
const std::string& file, int line, const std::string& function);
+ /**
+ Returns the stack trace (if enabled)
+ @return the stack trace (if enabled)
+ */
static std::string btCallStack();
+ /**
+ Provides a signal handler to catch signals
+ @param signal is the code of the signal
+ */
static void signalHandler(int signal);
+
+ /**
+ Converts a given signal into an Exception (does not work very well on Windows)
+ @param signal is the code of the signal
+ */
static void convertToException(int signal);
+
+ /**
+ Provides a handler for `terminate` and `unexpected` signals
+ */
static void terminate();
+ /**
+ Logs the exception to console and proceeds the regular execution of the library
+ @param exception is the exception thrown
+ */
static void catchException(const std::exception& exception);
};
-
}
#endif /* FL_EXCEPTION_H */
diff --git a/fuzzylite/fl/Headers.h b/fuzzylite/fl/Headers.h
index 9c2299a..1c41002 100644
--- a/fuzzylite/fl/Headers.h
+++ b/fuzzylite/fl/Headers.h
@@ -1,36 +1,46 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_HEADERS_H
#define FL_HEADERS_H
+/**
+ The Headers.h file contains the headers of all the classes in the
+ `fuzzylite` library, thereby encouraging the use of the directive `#include
+ "fl/Headers.h"` in projects using the library.
+ */
+
+
#include "fl/fuzzylite.h"
+#include "fl/Benchmark.h"
+#include "fl/Complexity.h"
#include "fl/Console.h"
#include "fl/Engine.h"
#include "fl/Exception.h"
+#include "fl/activation/Activation.h"
+#include "fl/activation/First.h"
+#include "fl/activation/General.h"
+#include "fl/activation/Highest.h"
+#include "fl/activation/Last.h"
+#include "fl/activation/Lowest.h"
+#include "fl/activation/Proportional.h"
+#include "fl/activation/Threshold.h"
+
#include "fl/defuzzifier/Bisector.h"
#include "fl/defuzzifier/Centroid.h"
#include "fl/defuzzifier/Defuzzifier.h"
@@ -42,6 +52,7 @@
#include "fl/defuzzifier/WeightedDefuzzifier.h"
#include "fl/defuzzifier/WeightedSum.h"
+#include "fl/factory/ActivationFactory.h"
#include "fl/factory/CloningFactory.h"
#include "fl/factory/ConstructionFactory.h"
#include "fl/factory/FactoryManager.h"
@@ -61,10 +72,12 @@
#include "fl/imex/FllImporter.h"
#include "fl/imex/FllExporter.h"
#include "fl/imex/JavaExporter.h"
+#include "fl/imex/RScriptExporter.h"
#include "fl/hedge/Any.h"
#include "fl/hedge/Extremely.h"
#include "fl/hedge/Hedge.h"
+#include "fl/hedge/HedgeFunction.h"
#include "fl/hedge/Not.h"
#include "fl/hedge/Seldom.h"
#include "fl/hedge/Somewhat.h"
@@ -84,6 +97,8 @@
#include "fl/norm/s/Maximum.h"
#include "fl/norm/s/NilpotentMaximum.h"
#include "fl/norm/s/NormalizedSum.h"
+#include "fl/norm/s/SNormFunction.h"
+#include "fl/norm/s/UnboundedSum.h"
#include "fl/norm/t/AlgebraicProduct.h"
#include "fl/norm/t/BoundedDifference.h"
@@ -92,6 +107,7 @@
#include "fl/norm/t/HamacherProduct.h"
#include "fl/norm/t/Minimum.h"
#include "fl/norm/t/NilpotentMinimum.h"
+#include "fl/norm/t/TNormFunction.h"
#include "fl/rule/Antecedent.h"
#include "fl/rule/Consequent.h"
@@ -99,8 +115,9 @@
#include "fl/rule/RuleBlock.h"
#include "fl/rule/Expression.h"
-#include "fl/term/Accumulated.h"
+#include "fl/term/Aggregated.h"
#include "fl/term/Bell.h"
+#include "fl/term/Binary.h"
#include "fl/term/Concave.h"
#include "fl/term/Constant.h"
#include "fl/term/Cosine.h"
diff --git a/fuzzylite/fl/Operation.h b/fuzzylite/fl/Operation.h
index d92e66c..8070116 100644
--- a/fuzzylite/fl/Operation.h
+++ b/fuzzylite/fl/Operation.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_OPERATION_H
@@ -34,111 +26,1044 @@
namespace fl {
- class FL_API Operation {
+ /**
+ The Operation class contains methods for numeric operations, string
+ manipulation, and other functions, all of which are also accessible via
+ fl::Op.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @since 4.0
+ */
+ class Operation {
public:
+ /**
+ Returns the minimum between the two parameters
+ @param a
+ @param b
+ @return @f$\min(a,b)@f$
+ */
template <typename T>
static T min(T a, T b);
+ /**
+ Returns the maximum between the two parameters
+ @param a
+ @param b
+ @return @f$\max(a,b)@f$
+ */
template <typename T>
static T max(T a, T b);
+ /**
+ Returns @f$x@f$ bounded in @f$[\min,\max]@f$
+ @param x is the value to be bounded
+ @param min is the minimum value of the range
+ @param max is the maximum value of the range
+ @return @f$
+ \begin{cases}
+ \min & \mbox{if $x < \min$} \cr
+ \max & \mbox{if $x > \max$} \cr
+ x & \mbox{otherwise}
+ \end{cases}
+ @f$
+ */
template <typename T>
static T bound(T x, T min, T max);
+ /**
+ Indicates whether @f$x@f$ is within the boundaries (open or closed)
+ @param x is the value
+ @param min is the minimum of the range
+ @param max is the maximum of the range
+ @param geq determines whether the maximum is a closed interval
+ @param leq determines whether the minimum is a closed interval
+ @return @f$
+ \begin{cases}
+ x \in [\min,\max] & \mbox{if $geq \wedge leq$} \cr
+ x \in (\min,\max] & \mbox{if $geq \wedge \bar{leq}$} \cr
+ x \in [\min, \max) & \mbox{if $\bar{geq} \wedge leq$} \cr
+ x \in (\min, \max) & \mbox{if $\bar{geq} \wedge \bar{leq}$} \cr
+ \end{cases}
+ @f$
+ */
template <typename T>
static bool in(T x, T min, T max, bool geq = true, bool leq = true);
+ /**
+ Indicates whether @f$x@f$ is infinity
+ @param x is the value
+ @return whether @f$x@f$ is infinity
+ */
template <typename T>
static bool isInf(T x);
+ /**
+ Indicates whether @f$x@f$ is not-a-number (NaN)
+ @param x is the value
+ @return whether @f$x@f$ is not-a-number (NaN)
+ */
template <typename T>
static bool isNaN(T x);
+ /**
+ Indicates whether @f$x@f$ is finite, that is, @f$x \not\in
+ \{\pm\infty, \mathrm{NaN}\}@f$
+ @param x is the value
+ @return whether @f$x@f$ is finite
+ */
template <typename T>
static bool isFinite(T x);
- //Is less than
+ /**
+ Returns whether @f$a@f$ is less than @f$b@f$ at the given tolerance
+ @param a
+ @param b
+ @param macheps is the minimum difference upon which two
+ floating-point values are considered equivalent
+ @return whether @f$a@f$ is less than @f$b@f$ at the given tolerance
+ */
+ static bool isLt(scalar a, scalar b, scalar macheps = fuzzylite::_macheps);
+ /**
+ Returns whether @f$a@f$ is less than or equal to @f$b@f$ at the given
+ tolerance
+ @param a
+ @param b
+ @param macheps is the minimum difference upon which two
+ floating-point values are considered equivalent
+ @return whether @f$a@f$ is less than or equal to @f$b@f$ at the given
+ tolerance
+ */
+ static bool isLE(scalar a, scalar b, scalar macheps = fuzzylite::_macheps);
+ /**
+ Returns whether @f$a@f$ is equal to @f$b@f$ at the given tolerance
+ @param a
+ @param b
+ @param macheps is the minimum difference upon which two
+ floating-point values are considered equivalent
+ @return whether @f$a@f$ is equal to @f$b@f$ at the given tolerance
+ */
+ static bool isEq(scalar a, scalar b, scalar macheps = fuzzylite::_macheps);
+ /**
+ Returns whether @f$a@f$ is greater than @f$b@f$ at the given tolerance
+ @param a
+ @param b
+ @param macheps is the minimum difference upon which two
+ floating-point values are considered equivalent
+ @return whether @f$a@f$ is greater than @f$b@f$ at the given tolerance
+ */
+ static bool isGt(scalar a, scalar b, scalar macheps = fuzzylite::_macheps);
+ /**
+ Returns whether @f$a@f$ is greater than or equal to @f$b@f$ at the
+ given tolerance
+ @param a
+ @param b
+ @param macheps is the minimum difference upon which two
+ floating-point values are considered equivalent
+ @return whether @f$a@f$ is greater than or equal to @f$b@f$ at the
+ given tolerance
+ */
+ static bool isGE(scalar a, scalar b, scalar macheps = fuzzylite::_macheps);
- static bool isLt(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps());
- static bool isLE(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps());
- static bool isEq(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps());
- static bool isGt(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps());
- static bool isGE(scalar a, scalar b, scalar macheps = fl::fuzzylite::macheps());
+ /**
+ Linearly interpolates the parameter @f$x@f$ in range
+ `[fromMin,fromMax]` to a new value in the range `[toMin,toMax]`
+ @param x is the source value to interpolate
+ @param fromMin is the minimum value of the source range
+ @param fromMax is the maximum value of the source range
+ @param toMin is the minimum value of the target range
+ @param toMax is the maximum value of the target range
+ @return the source value linearly interpolated to the target range:
+ @f$ y = y_a + (y_b - y_a) \dfrac{x-x_a}{x_b-x_a} @f$
+ */
+ static scalar scale(scalar x, scalar fromMin, scalar fromMax,
+ scalar toMin, scalar toMax);
+ /**
+ Linearly interpolates the parameter @f$x@f$ in range
+ `[fromMin,fromMax]` to a new value in the range `[toMin,toMax]`,
+ truncated to the range `[toMin,toMax]` if bounded is `true`.
+ @param x is the source value to interpolate
+ @param fromMin is the minimum value of the source range
+ @param fromMax is the maximum value of the source range
+ @param toMin is the minimum value of the target range
+ @param toMax is the maximum value of the target range
+ @param bounded determines whether the resulting value is bounded to
+ the range
+ @return the source value linearly interpolated to the target range:
+ @f$ y = y_a + (y_b - y_a) \dfrac{x-x_a}{x_b-x_a} @f$
+ */
static scalar scale(scalar x, scalar fromMin, scalar fromMax,
- scalar toMin, scalar toMax, bool bounded = false);
+ scalar toMin, scalar toMax, bool bounded);
+ /**
+ Adds two values
+ @param a
+ @param b
+ @return @f$a+b@f$
+ */
static scalar add(scalar a, scalar b);
+ /**
+ Subtracts two values
+ @param a
+ @param b
+ @return @f$a-b@f$
+ */
static scalar subtract(scalar a, scalar b);
+ /**
+ Multiplies two values
+ @param a
+ @param b
+ @return @f$a\times b@f$
+ */
static scalar multiply(scalar a, scalar b);
+ /**
+ Divides two values
+ @param a
+ @param b
+ @return @f$a/b@f$
+ */
static scalar divide(scalar a, scalar b);
+ /**
+ Computes the modulo
+ @param a
+ @param b
+ @return @f$a \mod b@f$
+ */
static scalar modulo(scalar a, scalar b);
+
+ /**
+ Computes the logical AND
+ @param a
+ @param b
+ @return @f$
+ \begin{cases}
+ 1.0 & \mbox{if $a=1 \wedge b=1$}\cr
+ 0.0 & \mbox{otherwise}
+ \end{cases}
+ @f$
+ */
static scalar logicalAnd(scalar a, scalar b);
+ /**
+ Computes the logical OR
+ @param a
+ @param b
+ @return @f$
+ \begin{cases}
+ 1.0 & \mbox{if $a=1 \vee b=1$}\cr
+ 0.0 & \mbox{otherwise}
+ \end{cases}
+ @f$
+ */
static scalar logicalOr(scalar a, scalar b);
+ /**
+ Returns the complement of the value
+ @param a
+ @return @f$
+ \begin{cases}
+ 0.0 & \mbox{if $a=1$}\cr
+ 1.0 & \mbox{otherwise}
+ \end{cases}
+ @f$
+ */
static scalar logicalNot(scalar a);
+ /**
+ Negates the value
+ @param a
+ @return -a
+ */
static scalar negate(scalar a);
+ /**
+ Rounds the value to the nearest integer
+ @param x
+ @return @f$
+ \begin{cases}
+ \lfloor x + 0.5 \rfloor & \mbox{if $x > 0$}\cr
+ \lceil x - 0.5 \rceil & \mbox{otherwise}
+ \end{cases}
+ @f$
+ */
static scalar round(scalar x);
- //greater than
+ /**
+ Returns whether @f$a@f$ is greater than or equal to @f$b@f$ at the
+ default tolerance
+ @param a
+ @param b
+ @return whether @f$a@f$ is greater than or equal to @f$b@f$ at the
+ default tolerance
+ */
static scalar gt(scalar a, scalar b);
- //greater than or equal to
+ /**
+ Returns whether @f$a@f$ is greater than or equal to @f$b@f$ at the
+ default tolerance
+ @param a
+ @param b
+ @return whether @f$a@f$ is greater than or equal to @f$b@f$ at the
+ default tolerance
+ */
static scalar ge(scalar a, scalar b);
- //equal to
+ /**
+ Returns whether @f$a@f$ is equal to @f$b@f$ at the default tolerance
+ @param a
+ @param b
+ @return whether @f$a@f$ is equal to @f$b@f$ at the default tolerance
+ */
static scalar eq(scalar a, scalar b);
- //not equal to
+ /**
+ Returns whether @f$a@f$ is different from @f$b@f$ at the default
+ tolerance
+ @param a
+ @param b
+ @return whether @f$a@f$ is different from @f$b@f$ at the default
+ tolerance
+ */
static scalar neq(scalar a, scalar b);
- //less than or equal to
+ /**
+ Returns whether @f$a@f$ is less than or equal to @f$b@f$ at the
+ default tolerance
+ @param a
+ @param b
+ @return whether @f$a@f$ is less than or equal to @f$b@f$ at the
+ default tolerance
+ */
static scalar le(scalar a, scalar b);
- //less than
+ /**
+ Returns whether @f$a@f$ is less than @f$b@f$ at the default tolerance
+ @param a
+ @param b
+ @return whether @f$a@f$ is less than @f$b@f$ at the default tolerance
+ */
static scalar lt(scalar a, scalar b);
+ /**
+ Returns a random number
+ */
+ static int random();
+
+ /**
+ Increments @f$x@f$ by the unit, treating the entire vector as a
+ number. For example, incrementing a few times @f$x_0=\{0,0\}@f$
+ within boundaries @f$[0,1]@f$ results in: @f$x_1=\{0,1\}@f$,
+ @f$x_2=\{1,0\}@f$, @f$x_3=\{1,1\}@f$, @f$x_4=\{0,0\}@f$.
+ @param x is the vector to increment
+ @param min is the minimum value of the dimension
+ @param max is the maximum value of the dimension
+ @return `true` if @f$x@f$ was incremented, `false` otherwise (e.g.,
+ incrementing @f$x_3@f$ returns `false`). In earlier versions to 6.0, the
+ result was the inverse and indicated whether the counter had overflown
+ (most sincere apologies for this change).
+ */
static bool increment(std::vector<int>& x, std::vector<int>& min, std::vector<int>& max);
+ /**
+ Increments @f$x@f$ by the unit at the given position, treating the
+ entire vector as a number. For example, incrementing
+ @f$x_0=\{0,0,0\}@f$ within boundaries @f$[0,1]@f$ at the second
+ position results in: @f$x_1=\{0,1,0\}@f$, @f$x_2=\{1,0,0\}@f$,
+ @f$x_3=\{1,1,0\}@f$, @f$x_4=\{0,0,0\}@f$.
+ @param x is the vector to increment
+ @param position is the position of the vector to increment, where
+ smaller values lead to higher significance digits
+ @param min is the minimum value of the dimension
+ @param max is the maximum value of the dimension
+ @return `true` if @f$x@f$ was incremented, `false` otherwise (e.g.,
+ incrementing @f$x_3@f$ returns `false`). In earlier versions to 6.0, the
+ result was the inverse and indicated whether the counter had overflown
+ (most sincere apologies for this change).
+ */
static bool increment(std::vector<int>& x, int position, std::vector<int>& min, std::vector<int>& max);
- static double mean(const std::vector<scalar>& x);
- static double variance(const std::vector<scalar>& x);
- static double variance(const std::vector<scalar>& x, scalar mean);
- static double standardDeviation(const std::vector<scalar>& x);
- static double standardDeviation(const std::vector<scalar>& x, scalar mean);
+ /**
+ Computes the sum of the vector
+ */
+ template <typename T>
+ static T sum(const std::vector<T>& x);
+ /**
+ Computes the mean of the vector
+ @param x is the vector
+ @return @f$\dfrac{\sum_i{x_i}}{|x|}@f$
+ */
+ template <typename T>
+ static scalar mean(const std::vector<T>& x);
+ /**
+ Computes the variance of the vector
+ @param x is the vector
+ @return @f$ \sum_i{ (x_i - \bar{x})^2 } / (|x| - 1) @f$
+ */
+ template <typename T>
+ static scalar variance(const std::vector<T>& x);
+ /**
+ Computes the variance of the vector using the given mean
+ @param x is the vector
+ @param mean is the mean value of the vector
+ @return @f$ \sum_i{ (x_i - \bar{x})^2 } / (|x| - 1) @f$
+ */
+ template <typename T>
+ static scalar variance(const std::vector<T>& x, scalar mean);
+ /**
+ Computes the standard deviation of the vector
+ @param x
+ @return @f$ \sqrt{\mbox{variance}(x, \bar{x})} @f$
+ */
+ template <typename T>
+ static scalar standardDeviation(const std::vector<T>& x);
+ /**
+ Computes the standard deviation of the vector using the given mean
+ @param x
+ @param mean is the mean value of x
+ @return @f$ \sqrt{\mbox{variance}(x, \bar{x})} @f$
+ */
+ template <typename T>
+ static scalar standardDeviation(const std::vector<T>& x, scalar mean);
+ /**
+ Returns a valid name for variables
+ @param name
+ @return an name whose characters are in `[a-zA-Z_0-9.]`
+ */
static std::string validName(const std::string& name);
- static int isValidForName(int character);
-
+ /**
+ Replaces the substrings that are equal to the given expression
+ @param str is the target string
+ @param find is the string to find
+ @param replace is the string to replace the findings
+ @param replaceAll whether all the substrings are to be replaced or
+ just the first string
+ @return the original string with replacements
+ */
static std::string findReplace(const std::string& str, const std::string& find,
const std::string& replace, bool replaceAll = true);
+ /**
+ Replaces the first substring that is equal to the given expression
+ @param str is the target string
+ @param find is the string to find
+ @param replace is the string to replace
+ @return the original string with the replacement
+ */
+ static std::string replaceFirst(const std::string& str, const std::string& find,
+ const std::string& replace);
+
+ /**
+ Replaces the every substring that is equal to the given expression
+ @param str is the target string
+ @param find is the string to find
+ @param replace is the string to replace
+ @return the original string with all of the replacements
+ */
+ static std::string replaceAll(const std::string& str, const std::string& find,
+ const std::string& replace);
+
+ /**
+ Splits the string around the given delimiter
+ @param str is the string to split
+ @param delimiter is the substrings on which the string will be split
+ @param ignoreEmpty whether the empty strings are discarded
+ @return the string split around the given delimiter
+ */
static std::vector<std::string> split(const std::string& str,
const std::string& delimiter = " ", bool ignoreEmpty = true);
+ /**
+ Removes whitespace at the beginning and end of the text
+ @param text
+ @return a space-trimmed string
+ */
static std::string trim(const std::string& text);
+ /**
+ Replaces every matching character in the text with the given
+ replacement
+ @param text is the string to have replacements
+ @param matchesChar is a pointer to a method that indicates whether
+ the given character is a match
+ @param replacement a string to replace a matching character
+ @return the string with every matching character replaced
+ */
static std::string format(const std::string& text, int matchesChar(int),
const std::string& replacement = "");
- //Intentionally results in a compiler error in C++11, or linker error in C++98
- //in order to avoid the deprecated usage of this method from version 4.0
- static scalar toScalar(const std::string& x, bool quiet,
- scalar alternative = fl::nan) FL_IDELETE;
+ /**
+ Parses the given string into a scalar value
+ @param x is the string to parse
+ @return the given string into a scalar value
+ @throws fl::Exception if the string does not contain a scalar value
+ */
+ static scalar toScalar(const std::string& x); //throws (fl::Exception)
- static scalar toScalar(const std::string& x); //throws fl::Exception
+ /**
+ Parses the given string into a scalar value without throwing an
+ exception
+ @param x is the string to parse
+ @param alternative is the value to return if the string does not
+ contain a scalar value
+ @param ok contains whether the operation was successful (optional)
+ @return the given string into a scalar value or the alternative value
+ if the string does not contain a scalar value
+ */
+ static scalar toScalar(const std::string& x, scalar alternative,
+ bool* ok = fl::null) FL_INOEXCEPT;
- static scalar toScalar(const std::string& x, scalar alternative) FL_INOEXCEPT;
+ /**
+ Parses the given string into a vector of scalar values
+ @param x is the string containing space-separated values to parse
+ @return the vector of scalar values
+ @throws fl::Exception if the string contains an invalid scalar value
+ */
+ static std::vector<scalar> toScalars(const std::string& x); //throws (fl::Exception)
+ /**
+ Parses the given string into a vector of scalar values
+ @param x is the string containing space-separated values to parse
+ @param alternative is the value to use if an invalid value is found
+ @param ok contains whether the operation was successful (optional)
+ @return the vector of scalar values
+ */
+ static std::vector<scalar> toScalars(const std::string& x, scalar alternative,
+ bool* ok = fl::null) FL_INOEXCEPT;
+
+ /**
+ Indicates whether the string can be converted to a numeric value.
+ @param x
+ @return whether the string can be converted to a numeric value
+ */
static bool isNumeric(const std::string& x);
+ /**
+ Returns a string representation of the given value
+ @param x is the value
+ @param decimals is the number of decimals to display
+ @param scalarFormat are the flags for the underlying std::ostringstream
+ @return a string representation of the given value
+ */
template <typename T>
- static std::string str(T x, int decimals = fuzzylite::decimals());
+ static std::string str(T x, int decimals = fuzzylite::_decimals,
+ std::ios_base::fmtflags scalarFormat = fuzzylite::_scalarFormat);
+ /**
+ Joins a vector of elements by the given separator into a single
+ string. The elements are represented as strings utilizing the
+ Operation::str() method on each element
+ @param x is the vector of elements
+ @param separator is the string to add between the elements
+ @return a single string joining the vector of elements by the given
+ separator
+ */
template <typename T>
static std::string join(const std::vector<T>& x, const std::string& separator);
+ /**
+ Joins a variadic number of elements by the given separator into a
+ single string. The elements are represented as strings utilizing the
+ Operation::str() method on each element
+ @param items is the number of elements to join
+ @param separator is the string to add between the elements
+ @param first is the first element, which defines the type of the
+ subsequent elements
+ @param ... are the remaining elements to join
+ @return a single string joining the variadic number of elements by
+ the given separator
+ */
template <typename T>
static std::string join(int items, const std::string& separator, T first, ...);
};
+ /**A shortened type to refer to Operation*/
typedef Operation Op;
}
+
+
+/**
+ Template implementation
+ */
+
+#include "fl/defuzzifier/Defuzzifier.h"
+#include "fl/norm/Norm.h"
+#include "fl/norm/SNorm.h"
+#include "fl/norm/TNorm.h"
+
+#include <algorithm>
+#include <iomanip>
+#include <cstdarg>
+#include <cctype>
+
+namespace fl {
+
+ template <typename T>
+ inline T Operation::min(T a, T b) {
+ if (Op::isNaN(a)) return b;
+ if (Op::isNaN(b)) return a;
+ return a < b ? a : b;
+ }
+
+ template <typename T>
+ inline T Operation::max(T a, T b) {
+ if (Op::isNaN(a)) return b;
+ if (Op::isNaN(b)) return a;
+ return a > b ? a : b;
+ }
+
+ template <typename T>
+ inline T Operation::bound(T x, T min, T max) {
+ if (x > max) return max;
+ if (x < min) return min;
+ return x;
+ }
+
+ template <typename T>
+ inline bool Operation::in(T x, T min, T max, bool geq, bool leq) {
+ bool left = geq ? Op::isGE(x, min) : Op::isGt(x, min);
+ bool right = leq ? Op::isLE(x, max) : Op::isLt(x, max);
+ return (left and right);
+ }
+
+ template <typename T>
+ inline bool Operation::isInf(T x) {
+ return x == fl::inf or x == -fl::inf;
+ }
+
+ template <typename T>
+ inline bool Operation::isNaN(T x) {
+ return (x != x);
+ }
+
+ template<typename T>
+ inline bool Operation::isFinite(T x) {
+ return not (x != x or x == fl::inf or x == -fl::inf);
+ }
+
+ inline bool Operation::isLt(scalar a, scalar b, scalar macheps) {
+ return not (a == b or std::abs(a - b) < macheps or (a != a and b != b)) and a < b;
+ }
+
+ inline bool Operation::isLE(scalar a, scalar b, scalar macheps) {
+ return a == b or std::abs(a - b) < macheps or (a != a and b != b) or a < b;
+ }
+
+ inline bool Operation::isEq(scalar a, scalar b, scalar macheps) {
+ return a == b or std::abs(a - b) < macheps or (a != a and b != b);
+ }
+
+ inline bool Operation::isGt(scalar a, scalar b, scalar macheps) {
+ return not (a == b or std::abs(a - b) < macheps or (a != a and b != b)) and a > b;
+ }
+
+ inline bool Operation::isGE(scalar a, scalar b, scalar macheps) {
+ return a == b or std::abs(a - b) < macheps or (a != a and b != b) or a > b;
+ }
+
+ inline scalar Operation::scale(scalar x, scalar fromMin, scalar fromMax, scalar toMin, scalar toMax) {
+ return (toMax - toMin) / (fromMax - fromMin) * (x - fromMin) + toMin;
+ }
+
+ inline scalar Operation::scale(scalar x, scalar fromMin, scalar fromMax, scalar toMin, scalar toMax, bool bounded) {
+ scalar result = (toMax - toMin) / (fromMax - fromMin) * (x - fromMin) + toMin;
+ return bounded ? Op::bound(result, toMin, toMax) : result;
+ }
+
+ inline scalar Operation::add(scalar a, scalar b) {
+ return a + b;
+ }
+
+ inline scalar Operation::subtract(scalar a, scalar b) {
+ return a - b;
+ }
+
+ inline scalar Operation::multiply(scalar a, scalar b) {
+ return a * b;
+ }
+
+ inline scalar Operation::divide(scalar a, scalar b) {
+ return a / b;
+ }
+
+ inline scalar Operation::modulo(scalar a, scalar b) {
+ return fmod(a, b);
+ }
+
+ inline scalar Operation::logicalAnd(scalar a, scalar b) {
+ return (isEq(a, 1.0) and isEq(b, 1.0)) ? 1.0 : 0.0;
+ }
+
+ inline scalar Operation::logicalOr(scalar a, scalar b) {
+ return (isEq(a, 1.0) or isEq(b, 1.0)) ? 1.0 : 0.0;
+ }
+
+ inline scalar Operation::logicalNot(scalar a) {
+ return isEq(a, 1.0) ? 0.0 : 1.0;
+ }
+
+ inline scalar Operation::negate(scalar a) {
+ return -a;
+ }
+
+ inline scalar Operation::round(scalar x) {
+ return (x > 0.0) ? std::floor(x + 0.5) : std::ceil(x - 0.5);
+ }
+
+ inline scalar Operation::gt(scalar a, scalar b) {
+ return isGt(a, b);
+ }
+
+ inline scalar Operation::ge(scalar a, scalar b) {
+ return isGE(a, b);
+ }
+
+ inline scalar Operation::eq(scalar a, scalar b) {
+ return isEq(a, b);
+ }
+
+ inline scalar Operation::neq(scalar a, scalar b) {
+ return not isEq(a, b);
+ }
+
+ inline scalar Operation::le(scalar a, scalar b) {
+ return isLE(a, b);
+ }
+
+ inline scalar Operation::lt(scalar a, scalar b) {
+ return isLt(a, b);
+ }
+
+ inline int Operation::random() {
+ return std::rand();
+ }
+
+ inline bool Operation::increment(std::vector<int>& x, std::vector<int>& min, std::vector<int>& max) {
+ return increment(x, -1 + int(x.size()), min, max);
+ }
+
+ inline bool Operation::increment(std::vector<int>& x, int position, std::vector<int>& min, std::vector<int>& max) {
+ if (x.empty() or position < 0) return false;
+
+ bool incremented = true;
+ if (x.at(position) < max.at(position)) {
+ ++x.at(position);
+ } else {
+ incremented = !(position == 0);
+ x.at(position) = min.at(position);
+ --position;
+ if (position >= 0) {
+ incremented = increment(x, position, min, max);
+ }
+ }
+ return incremented;
+ }
+
+ template<typename T>
+ inline T Operation::sum(const std::vector<T>& x) {
+ T result = T(0);
+ for (std::size_t i = 0; i < x.size(); ++i) {
+ result += x.at(i);
+ }
+ return result;
+ }
+
+ template<typename T>
+ inline scalar Operation::mean(const std::vector<T>& x) {
+ return scalar(sum(x)) / x.size();
+ }
+
+ template<typename T>
+ inline scalar Operation::standardDeviation(const std::vector<T>& x) {
+ return standardDeviation(x, mean(x));
+ }
+
+ template<typename T>
+ inline scalar Operation::standardDeviation(const std::vector<T>& x, scalar mean) {
+ if (x.empty()) return fl::nan;
+ if (x.size() == 1) return scalar(0.0);
+ return std::sqrt(variance(x, mean));
+ }
+
+ template<typename T>
+ inline scalar Operation::variance(const std::vector<T>& x) {
+ return variance(x, mean(x));
+ }
+
+ template<typename T>
+ inline scalar Operation::variance(const std::vector<T>& x, scalar mean) {
+ if (x.empty()) return fl::nan;
+ if (x.size() == 1) return scalar(0.0);
+ scalar result = 0.0;
+ for (std::size_t i = 0; i < x.size(); ++i) {
+ result += (x.at(i) - mean) * (x.at(i) - mean);
+ }
+ result /= -1 + x.size();
+ return result;
+ }
+
+
+
+ //Text Operations:
+
+ inline std::string Operation::validName(const std::string& name) {
+ if (trim(name).empty()) return "unnamed";
+ std::ostringstream ss;
+ for (std::size_t i = 0; i < name.length(); ++i) {
+ char c = name[i];
+ if (c == '_' or c == '.' or isalnum(c)) {
+ ss << c;
+ }
+ }
+ return ss.str();
+ }
+
+ inline std::string Operation::findReplace(const std::string& str, const std::string& find,
+ const std::string& replace, bool replaceAll) {
+ std::ostringstream result;
+ std::size_t fromIndex = 0, nextIndex;
+ do {
+ nextIndex = str.find(find, fromIndex);
+ result << str.substr(fromIndex, nextIndex - fromIndex);
+ if (nextIndex != std::string::npos)
+ result << replace;
+ fromIndex = nextIndex + find.size();
+ } while (replaceAll and nextIndex != std::string::npos);
+ return result.str();
+ }
+
+ inline std::string Operation::replaceFirst(const std::string& str,
+ const std::string& find, const std::string& replace) {
+ return findReplace(str, find, replace, false);
+ }
+
+ inline std::string Operation::replaceAll(const std::string& str,
+ const std::string& find, const std::string& replace) {
+ return findReplace(str, find, replace, true);
+ }
+
+ inline std::vector<std::string> Operation::split(const std::string& str,
+ const std::string& delimiter, bool ignoreEmpty) {
+ std::vector<std::string> result;
+ if (str.empty() or delimiter.empty()) {
+ result.push_back(str);
+ return result;
+ }
+ std::string::const_iterator position = str.begin(), next = str.begin();
+ while (next != str.end()) {
+ next = std::search(position, str.end(), delimiter.begin(), delimiter.end());
+ std::string token(position, next);
+ if (not (token.empty() and ignoreEmpty)) {
+ result.push_back(token);
+ }
+ if (next != str.end()) {
+ position = next + delimiter.size();
+ }
+ }
+ return result;
+ }
+
+ inline std::string Operation::trim(const std::string& text) {
+ if (text.empty()) return text;
+ if (not (std::isspace(text.at(0)) or std::isspace(text.at(text.size() - 1))))
+ return text;
+ std::size_t start = 0, end = text.size() - 1;
+ while (start <= end and std::isspace(text.at(start))) {
+ ++start;
+ }
+ while (end >= start and std::isspace(text.at(end))) {
+ --end;
+ }
+ std::size_t length = end - start + 1;
+ if (length <= 0) return "";
+ return text.substr(start, length);
+ }
+
+ inline std::string Operation::format(const std::string& text, int matchesChar(int),
+ const std::string& replacement) {
+ std::ostringstream ss;
+ std::string::const_iterator it = text.begin();
+ while (it != text.end()) {
+ if (matchesChar(*it)) {
+ ss << *it;
+ } else {
+ ss << replacement;
+ }
+ ++it;
+ }
+ return ss.str();
+ }
+
+ inline scalar Operation::toScalar(const std::string& x) {
+ std::istringstream iss(x);
+ scalar result;
+ iss >> result;
+ char strict;
+ if (not (iss.fail() or iss.get(strict))) return result;
+
+ std::ostringstream _nan;
+ _nan << fl::nan;
+ if (x == _nan.str() or x == "nan")
+ return fl::nan;
+
+ std::ostringstream pInf;
+ pInf << fl::inf;
+ if (x == pInf.str() or x == "inf")
+ return fl::inf;
+
+ std::ostringstream nInf;
+ nInf << (-fl::inf);
+ if (x == nInf.str() or x == "-inf")
+ return -fl::inf;
+
+ throw Exception("[conversion error] from <" + x + "> to scalar", FL_AT);
+ }
+
+ inline scalar Operation::toScalar(const std::string& x, scalar alternative, bool* ok) FL_INOEXCEPT {
+ if (ok) *ok = true;
+ std::istringstream iss(x);
+ scalar result;
+ iss >> result;
+ char strict;
+ if (not (iss.fail() or iss.get(strict))) return result;
+
+ std::ostringstream _nan;
+ _nan << fl::nan;
+ if (x == _nan.str() or x == "nan")
+ return fl::nan;
+
+ std::ostringstream pInf;
+ pInf << fl::inf;
+ if (x == pInf.str() or x == "inf")
+ return fl::inf;
+
+ std::ostringstream nInf;
+ nInf << (-fl::inf);
+ if (x == nInf.str() or x == "-inf")
+ return -fl::inf;
+
+ if (ok) *ok = false;
+ return alternative;
+ }
+
+ inline std::vector<scalar> Operation::toScalars(const std::string& x) {
+ std::vector<scalar> result;
+ std::istringstream tokenizer(x);
+ std::string token;
+ while (tokenizer >> token) {
+ result.push_back(Op::toScalar(token));
+ }
+ return result;
+ }
+
+ inline std::vector<scalar> Operation::toScalars(const std::string& x,
+ scalar alternative, bool* ok) FL_INOEXCEPT {
+ std::vector<scalar> result;
+ std::istringstream tokenizer(x);
+ std::string token;
+ bool allOK = true;
+ while (tokenizer >> token) {
+ bool good;
+ result.push_back(Op::toScalar(token, alternative, &good));
+ allOK &= good;
+ }
+ if (ok) *ok = allOK;
+ return result;
+ }
+
+ inline bool Operation::isNumeric(const std::string& x) {
+ try {
+ Op::toScalar(x);
+ return true;
+ } catch (...) {
+ return false;
+ }
+ }
+
+ template <typename T>
+ inline std::string Operation::str(T x, int decimals,
+ std::ios_base::fmtflags scalarFormat) {
+ std::ostringstream ss;
+ if (scalarFormat != std::ios_base::fmtflags(0x0)) ss.flags(scalarFormat);
+ if (decimals >= 0) ss.precision(decimals);
+ if (Op::isNaN(x)) {
+ ss << "nan";
+ } else if (Op::isInf(x)) {
+ ss << (x < T(0) ? "-inf" : "inf");
+ } else if (decimals >= 0 //print x considering the given decimals regardless of macheps
+ and Op::isEq(scalar(x), 0.0, std::pow(10.0, -decimals))) {
+ ss << T(0);
+ } else ss << x;
+ return ss.str();
+ }
+
+ template <> FL_API
+ inline std::string Operation::str(const std::string& x, int decimals,
+ std::ios_base::fmtflags scalarFormat) {
+ FL_IUNUSED(decimals);
+ FL_IUNUSED(scalarFormat);
+ return x;
+ }
+
+ template <typename T>
+ inline std::string Operation::join(const std::vector<T>& x,
+ const std::string& separator) {
+ std::ostringstream ss;
+ for (std::size_t i = 0; i < x.size(); ++i) {
+ ss << str(x.at(i));
+ if (i + 1 < x.size()) ss << separator;
+ }
+ return ss.str();
+ }
+
+ template <> FL_API
+ inline std::string Operation::join(const std::vector<std::string>& x,
+ const std::string& separator) {
+ std::ostringstream ss;
+ for (std::size_t i = 0; i < x.size(); ++i) {
+ ss << x.at(i);
+ if (i + 1 < x.size()) ss << separator;
+ }
+ return ss.str();
+ }
+
+ template <typename T>
+ inline std::string Operation::join(int items, const std::string& separator, T first, ...) {
+ std::ostringstream ss;
+ ss << str(first);
+ if (items > 1) ss << separator;
+ va_list args;
+ va_start(args, first);
+ for (int i = 0; i < items - 1; ++i) {
+ ss << str(va_arg(args, T));
+ if (i + 1 < items - 1) ss << separator;
+ }
+ va_end(args);
+ return ss.str();
+ }
+
+ template <> FL_API
+ inline std::string Operation::join(int items, const std::string& separator,
+ float first, ...) {
+ std::ostringstream ss;
+ ss << str(first);
+ if (items > 1) ss << separator;
+ va_list args;
+ va_start(args, first);
+ for (int i = 0; i < items - 1; ++i) {
+ ss << str(va_arg(args, double)); //automatic promotion
+ if (i + 1 < items - 1) ss << separator;
+ }
+ va_end(args);
+ return ss.str();
+ }
+
+ template <> FL_API
+ inline std::string Operation::join(int items, const std::string& separator, const char* first, ...) {
+ std::ostringstream ss;
+ ss << first;
+ if (items > 1) ss << separator;
+ va_list args;
+ va_start(args, first);
+ for (int i = 0; i < items - 1; ++i) {
+ ss << va_arg(args, const char*);
+ if (i + 1 < items - 1) ss << separator;
+ }
+ va_end(args);
+ return ss.str();
+ }
+}
#endif /* FL_OPERATION_H */
diff --git a/fuzzylite/fl/activation/Activation.h b/fuzzylite/fl/activation/Activation.h
new file mode 100644
index 0000000..562d53e
--- /dev/null
+++ b/fuzzylite/fl/activation/Activation.h
@@ -0,0 +1,95 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_ACTIVATION_H
+#define FL_ACTIVATION_H
+
+#include "fl/fuzzylite.h"
+
+#include "fl/Complexity.h"
+
+namespace fl {
+ class RuleBlock;
+
+ /**
+ The Activation class is the abstract class for RuleBlock activation
+ methods. An activation method implements the criteria to activate the
+ rules within a given rule block. An activation method needs to process
+ every rule and determine whether the rule is to be activated or
+ deactivated. The activation methods were first introduced in version 6.0,
+ but in earlier versions the term `activation` referred to the TNorm that
+ modulated the consequent of a rule, which is now referred to as the
+ `implication` operator.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Rule
+ @see RuleBlock
+ @see ActivationFactory
+ @since 6.0
+ */
+
+ class FL_API Activation {
+ public:
+
+ Activation() { }
+
+ virtual ~Activation() { }
+
+ FL_DEFAULT_COPY_AND_MOVE(Activation)
+
+ /**
+ Returns the name of the activation method, which is also utilized to
+ register the activation method in the ActivationFactory.
+ @return the name of the activation method
+ @see ActivationFactory
+ */
+ virtual std::string className() const = 0;
+
+ /**
+ Returns the parameters of the activation method, which can be used to
+ configure other instances of the activation method.
+ @return the parameters of the activation method
+ */
+ virtual std::string parameters() const = 0;
+
+ /**
+ Configures the activation method with the given parameters.
+ @param parameters contains a list of space-separated parameter values
+ */
+ virtual void configure(const std::string& parameters) = 0;
+
+ /**
+ Computes the estimated complexity of activating the given rule block
+ @return the estimated complexity of activating the given rule block
+ */
+ virtual Complexity complexity(const RuleBlock* ruleBlock) const = 0;
+
+ /**
+ Activates the rule block
+ @param ruleBlock is the rule block to activate
+ */
+ virtual void activate(RuleBlock* ruleBlock) = 0;
+
+ /**
+ Clones the activation method.
+ @return a clone of the activation method
+ */
+ virtual Activation* clone() const = 0;
+ };
+
+}
+
+#endif /* FL_ACTIVATION_H */
diff --git a/fuzzylite/fl/activation/First.h b/fuzzylite/fl/activation/First.h
new file mode 100644
index 0000000..355b1a9
--- /dev/null
+++ b/fuzzylite/fl/activation/First.h
@@ -0,0 +1,104 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_FIRST_H
+#define FL_FIRST_H
+
+#include "fl/activation/Activation.h"
+
+namespace fl {
+
+ /**
+ The First class is a RuleBlock Activation method that activates the first
+ @f$n@f$ rules whose activation degrees are greater than or equal to the given
+ threshold. The rules are iterated in the order they were added to the rule block.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Last
+ @see Rule
+ @see RuleBlock
+ @see ActivationFactory
+ @since 6.0
+ */
+
+ class FL_API First : public Activation {
+ private:
+ int _numberOfRules;
+ scalar _threshold;
+ public:
+
+ explicit First(int numberOfRules = 1, scalar threshold = 0.0);
+ virtual ~First();
+ FL_DEFAULT_COPY_AND_MOVE(First)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ /**
+ Returns the number of rules and the threshold of the activation method
+ @return "numberOfRules threshold"
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+
+ /**
+ Configures the activation method with the given number of rules and
+ threshold
+ @param parameters as "numberOfRules threshold"
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ /**
+ Sets the number of rules for the activation degree
+ @param numberOfRules is the number of rules for the activation degree
+ */
+ virtual void setNumberOfRules(int numberOfRules);
+
+ /**
+ Gets the number of rules for the activation degree
+ @return the number of rules for the activation degree
+ */
+ virtual int getNumberOfRules() const;
+
+ /**
+ Sets the threshold for the activation degree
+ @param threshold is the threshold for the activation degree
+ */
+ virtual void setThreshold(scalar threshold);
+
+ /**
+ Gets the threshold for the activation degree
+ @return the threshold for the activation degree
+ */
+ virtual scalar getThreshold() const;
+
+ virtual Complexity complexity(const RuleBlock* ruleBlock) const FL_IOVERRIDE;
+
+ /**
+ Activates the first @f$n@f$ rules whose activation degrees are greater than or
+ equal to the given threshold. The rules are iterated in the order the
+ rules were added to the rule block.
+ @param ruleBlock is the rule block to activate
+ */
+ virtual void activate(RuleBlock* ruleBlock) FL_IOVERRIDE;
+
+ virtual First* clone() const FL_IOVERRIDE;
+
+ static Activation* constructor();
+ };
+
+}
+
+
+#endif /* FL_FIRST_H */
diff --git a/fuzzylite/fl/activation/General.h b/fuzzylite/fl/activation/General.h
new file mode 100644
index 0000000..8b057e9
--- /dev/null
+++ b/fuzzylite/fl/activation/General.h
@@ -0,0 +1,73 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_GENERAL_H
+#define FL_GENERAL_H
+
+#include "fl/fuzzylite.h"
+
+#include "fl/activation/Activation.h"
+
+namespace fl {
+
+ /**
+ The General class is a RuleBlock Activation method that activates every
+ rule following the order in which the rules were added to the rule block.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Rule
+ @see RuleBlock
+ @see ActivationFactory
+ @since 6.0
+ */
+
+ class FL_API General : public Activation {
+ public:
+
+ General();
+ virtual ~General();
+ FL_DEFAULT_COPY_AND_MOVE(General)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ /**
+ No parameters are required to configure the activation method.
+ @return an empty string
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+
+ /**
+ No parameters are required to configure the activation method.
+ @param parameters is an empty string
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ virtual Complexity complexity(const RuleBlock* ruleBlock) const FL_IOVERRIDE;
+
+ /**
+ Activates every rule in the given rule block following the order in
+ which the rules were added.
+ @param ruleBlock is the rule block to activate
+ */
+ virtual void activate(RuleBlock* ruleBlock) FL_IOVERRIDE;
+
+ virtual General* clone() const FL_IOVERRIDE;
+
+ static Activation* constructor();
+ };
+}
+
+#endif /* FL_GENERAL_H */
diff --git a/fuzzylite/fl/activation/Highest.h b/fuzzylite/fl/activation/Highest.h
new file mode 100644
index 0000000..d3abc72
--- /dev/null
+++ b/fuzzylite/fl/activation/Highest.h
@@ -0,0 +1,86 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_HIGHEST_H
+#define FL_HIGHEST_H
+
+#include "fl/fuzzylite.h"
+
+#include "fl/activation/Activation.h"
+
+namespace fl {
+
+ /**
+ The Highest class is a RuleBlock Activation method that activates a given
+ number of rules with highest activation degrees in descending order.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Lowest
+ @see Rule
+ @see RuleBlock
+ @see ActivationFactory
+ @since 6.0
+ */
+ class FL_API Highest : public Activation {
+ private:
+ int _numberOfRules;
+ public:
+ explicit Highest(int numberOfRules = 1);
+ virtual ~Highest();
+ FL_DEFAULT_COPY_AND_MOVE(Highest)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ /**
+ Returns the number of rules to activate.
+ @return number of rules to activate
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+
+ /**
+ Configures the activation method with the number of rules to activate.
+ @param parameters contains the number of rules to activate
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ /**
+ Sets the number of rules to activate
+ @param numberOfRules is the number of rules to activate
+ */
+ virtual void setNumberOfRules(int numberOfRules);
+
+ /**
+ Returns the number of rules to activate
+ @return the number of rules to activate
+ */
+ virtual int getNumberOfRules() const;
+
+ virtual Complexity complexity(const RuleBlock* ruleBlock) const FL_IOVERRIDE;
+
+ /**
+ Activates the given number of rules with the highest activation
+ degrees
+ @param ruleBlock is the rule block to activate.
+ */
+ virtual void activate(RuleBlock* ruleBlock) FL_IOVERRIDE;
+
+ virtual Highest* clone() const FL_IOVERRIDE;
+
+ static Activation* constructor();
+ };
+}
+
+#endif /* FL_HIGHEST_H */
diff --git a/fuzzylite/fl/activation/Last.h b/fuzzylite/fl/activation/Last.h
new file mode 100644
index 0000000..9dadede
--- /dev/null
+++ b/fuzzylite/fl/activation/Last.h
@@ -0,0 +1,103 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_LAST_H
+#define FL_LAST_H
+
+
+#include "fl/activation/Activation.h"
+
+namespace fl {
+
+ /**
+ The Last class is a RuleBlock Activation method that activates the last
+ @f$n@f$ rules whose activation degrees are greater than or equal to the given
+ threshold. The rules are iterated in the reverse order in which they were
+ added to the rule block.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see First
+ @see Rule
+ @see RuleBlock
+ @see ActivationFactory
+ @since 6.0
+ */
+
+ class FL_API Last : public Activation {
+ private:
+ int _numberOfRules;
+ scalar _threshold;
+ public:
+ explicit Last(int numberOfRules = 1, scalar threshold = 0.0);
+ virtual ~Last();
+ FL_DEFAULT_COPY_AND_MOVE(Last)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ /**
+ Returns the number of rules and the threshold of the activation method
+ @return "numberOfRules threshold"
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+
+ /**
+ Configures the activation method with the given number of rules and
+ threshold
+ @param parameters as "numberOfRules threshold"
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ /**
+ Sets the number of rules for the activation degree
+ @param numberOfRules is the number of rules for the activation degree
+ */
+ virtual void setNumberOfRules(int numberOfRules);
+
+ /**
+ Gets the number of rules for the activation degree
+ @return the number of rules for the activation degree
+ */
+ virtual int getNumberOfRules() const;
+ /**
+ Sets the threshold for the activation degree
+ @param threshold is the threshold for the activation degree
+ */
+ virtual void setThreshold(scalar threshold);
+
+ /**
+ Gets the threshold for the activation degree
+ @return the threshold for the activation degree
+ */
+ virtual scalar getThreshold() const;
+
+
+ virtual Complexity complexity(const RuleBlock* ruleBlock) const FL_IOVERRIDE;
+
+ /**
+ Activates the last @f$n@f$ rules whose activation degrees are greater
+ than the given threshold. The rules are iterated in the reverse order
+ that the rules were added to the rule block.
+ @param ruleBlock is the rule block to activate
+ */
+ virtual void activate(RuleBlock* ruleBlock) FL_IOVERRIDE;
+
+ virtual Last* clone() const FL_IOVERRIDE;
+
+ static Activation* constructor();
+ };
+}
+
+#endif /* FL_LAST_H */
diff --git a/fuzzylite/fl/activation/Lowest.h b/fuzzylite/fl/activation/Lowest.h
new file mode 100644
index 0000000..dab8419
--- /dev/null
+++ b/fuzzylite/fl/activation/Lowest.h
@@ -0,0 +1,87 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_LOWEST_H
+#define FL_LOWEST_H
+
+#include "fl/fuzzylite.h"
+
+#include "fl/activation/Activation.h"
+
+namespace fl {
+
+ /**
+ The Lowest class is a RuleBlock Activation method that activates a given
+ number of rules with lowest activation degrees in ascending order
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Highest
+ @see Rule
+ @see RuleBlock
+ @see ActivationFactory
+ @since 6.0
+ */
+ class FL_API Lowest : public Activation {
+ private:
+ int _numberOfRules;
+ public:
+ explicit Lowest(int numberOfRules = 1);
+ virtual ~Lowest();
+ FL_DEFAULT_COPY_AND_MOVE(Lowest)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ /**
+ Returns the number of rules to activate
+ @return number of rules to activate
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+
+ /**
+ Configures the activation method with the number of rules to activate
+ @param parameters contains the number of rules to activate
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ /**
+ Sets the number of rules to activate
+ @param numberOfRules is the number of rules to activate
+ */
+ virtual void setNumberOfRules(int numberOfRules);
+
+ /**
+ Returns the number of rules to activate
+ @return the number of rules to activate
+ */
+ virtual int getNumberOfRules() const;
+
+
+ virtual Complexity complexity(const RuleBlock* ruleBlock) const FL_IOVERRIDE;
+
+ /**
+ Activates the rules with the lowest activation degrees in the given
+ rule block
+ @param ruleBlock is the rule block to activate
+ */
+ virtual void activate(RuleBlock* ruleBlock) FL_IOVERRIDE;
+
+ virtual Lowest* clone() const FL_IOVERRIDE;
+
+ static Activation* constructor();
+ };
+}
+
+#endif /* FL_LOWEST_H */
diff --git a/fuzzylite/fl/activation/Proportional.h b/fuzzylite/fl/activation/Proportional.h
new file mode 100644
index 0000000..09e51a7
--- /dev/null
+++ b/fuzzylite/fl/activation/Proportional.h
@@ -0,0 +1,71 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_PROPORTIONAL_H
+#define FL_PROPORTIONAL_H
+
+#include "fl/activation/Activation.h"
+
+namespace fl {
+
+ /**
+ The Proportional class is a RuleBlock Activation method that activates
+ the rules utilizing activation degrees proportional to the activation
+ degrees of the other rules, thus the sum of the activation degrees is
+ equal to one.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Rule
+ @see RuleBlock
+ @see ActivationFactory
+ @since 6.0
+ */
+ class FL_API Proportional : public Activation {
+ public:
+ Proportional();
+ virtual ~Proportional();
+ FL_DEFAULT_COPY_AND_MOVE(Proportional)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ /**
+ No parameters are required to configure the activation method
+ @return an empty string
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+
+ /**
+ No parameters are required to configure the activation method
+ @param parameters is an empty string
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ virtual Complexity complexity(const RuleBlock* ruleBlock) const FL_IOVERRIDE;
+
+ /**
+ Activates the rules utilizing activation degrees proportional to
+ the activation degrees of the other rules in the rule block.
+ @param ruleBlock is the rule block to activate.
+ */
+ virtual void activate(RuleBlock* ruleBlock) FL_IOVERRIDE;
+
+ virtual Proportional* clone() const FL_IOVERRIDE;
+
+ static Activation* constructor();
+ };
+}
+
+#endif /* FL_PROPORTIONAL_H */
diff --git a/fuzzylite/fl/activation/Threshold.h b/fuzzylite/fl/activation/Threshold.h
new file mode 100644
index 0000000..0baadfa
--- /dev/null
+++ b/fuzzylite/fl/activation/Threshold.h
@@ -0,0 +1,183 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_THRESHOLD_H
+#define FL_THRESHOLD_H
+
+#include "fl/fuzzylite.h"
+
+#include "fl/activation/Activation.h"
+
+#include <vector>
+
+namespace fl {
+
+ /**
+ The Threshold class is a RuleBlock Activation method that activates the
+ rules whose activation degrees satisfy the equation given by the
+ comparison operator and the threshold, and deactivates the rules which do
+ not satisfy the equation.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Rule
+ @see RuleBlock
+ @see ActivationFactory
+ @since 6.0
+ */
+
+ class FL_API Threshold : public Activation {
+ public:
+
+ /**
+ Comparison is an enumerator that provides six comparison operators
+ between the activation degree @f$a@f$ and the threshold @f$\theta@f$.
+ */
+ enum Comparison {
+ /**@f$a < \theta@f$*/
+ LessThan,
+ /**@f$a \leq \theta@f$*/
+ LessThanOrEqualTo,
+ /**@f$a = \theta@f$*/
+ EqualTo,
+ /**@f$a \neq \theta@f$*/
+ NotEqualTo,
+ /**@f$a \geq \theta@f$*/
+ GreaterThanOrEqualTo,
+ /**@f$a > \theta@f$*/
+ GreaterThan
+ };
+ private:
+ Comparison _comparison;
+ scalar _value;
+ public:
+ explicit Threshold(Comparison comparison = GreaterThanOrEqualTo, scalar threshold = 0.0);
+ explicit Threshold(const std::string& comparison, scalar threshold);
+ virtual ~Threshold();
+ FL_DEFAULT_COPY_AND_MOVE(Threshold)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ /**
+ Returns the comparison operator followed by the threshold.
+ @return comparison operator and threshold
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+
+ /**
+ Configures the activation method with the comparison operator and the
+ threshold.
+ @param parameters is the comparison operator and threshold
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ /**
+ Sets the comparison operator for the activation method
+ @param comparison is the operator for the activation method
+ */
+ virtual void setComparison(Comparison comparison);
+
+ /**
+ Gets the comparison operator for the activation method
+ @return comparison operator for the activation method
+ */
+ virtual Comparison getComparison() const;
+
+ /**
+ Returns the comparison operator of the activation method
+ @return the comparison operator in (`==`, `!=`, `<`, `>`, `<=`, `>=`)
+ */
+ virtual std::string comparisonOperator() const;
+
+ /**
+ Returns the given comparison operator of the activation method
+ @param comparison is a valid enum value
+ @return the comparison operator for the given enum value
+ @throws fl::Exception if the given comparison operator is not valid
+ */
+ virtual std::string comparisonOperator(Comparison comparison) const;
+
+ /**
+ Returns the list of available comparison operators of the activation
+ method
+ @return (`==`, `!=`, `<`, `>`, `<=`, `>=`)
+ */
+ virtual std::vector<std::string> availableComparisonOperators() const;
+
+
+ /**
+ Parses the comparison operator, or throws an
+ exception if the parameter does not correspond to a valid operator
+ @param comparisonOperator is an operator in (`==`, `!=`, `<`, `>`,
+ `<=`, `>=`)
+ */
+ virtual Comparison parseComparison(const std::string& comparisonOperator) const;
+
+ /**
+ Sets the threshold value of the activation method
+ @param value is the threshold value for activation degrees
+ */
+ virtual void setValue(scalar value);
+
+ /**
+ Gets the threshold value of the activation method
+ @return the threshold value of the activation method
+ */
+ virtual scalar getValue() const;
+
+ /**
+ Sets the comparison operator and the threshold for the activation
+ method
+ @param comparison is the comparison enumerator
+ @param value is the threshold of the activation method
+ */
+ virtual void setThreshold(Comparison comparison, scalar value);
+
+ /**
+ Sets the comparison operator and the threshold for the activation method
+ @param comparison is a valid comparison operator
+ @param value is the threshold for activation degrees
+ @throws fl::Exception if the comparison operator is not valid
+ */
+ virtual void setThreshold(const std::string& comparison, scalar value);
+
+ /**
+ Returns whether the activation method will activate a rule with
+ the given activation degree
+ @param activationDegree an activation degree
+ @return whether the comparison equation is satisfied with the
+ activation degree and the threshold
+ */
+ virtual bool activatesWith(scalar activationDegree) const;
+
+
+ virtual Complexity complexity(const RuleBlock* ruleBlock) const FL_IOVERRIDE;
+
+ /**
+ Activates the rules whose activation degrees satisfy the comparison
+ equation with the given threshold, and deactivate the rules which do
+ not.
+ @param ruleBlock is the rule block to activate
+ */
+ virtual void activate(RuleBlock* ruleBlock) FL_IOVERRIDE;
+
+ virtual Threshold* clone() const FL_IOVERRIDE;
+
+ static Activation* constructor();
+ };
+
+}
+
+#endif /* FL_THRESHOLD_H */
diff --git a/fuzzylite/fl/defuzzifier/Bisector.h b/fuzzylite/fl/defuzzifier/Bisector.h
index 7ba8db2..046b185 100644
--- a/fuzzylite/fl/defuzzifier/Bisector.h
+++ b/fuzzylite/fl/defuzzifier/Bisector.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_BISECTOR_H
@@ -29,6 +21,16 @@
namespace fl {
+ /**
+ The Bisector class is an IntegralDefuzzifier that computes the bisector
+ of a fuzzy set represented in a Term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Centroid
+ @see IntegralDefuzzifier
+ @see Defuzzifier
+ @since 4.0
+ */
class FL_API Bisector : public IntegralDefuzzifier {
public:
explicit Bisector(int resolution = defaultResolution());
@@ -36,13 +38,26 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Bisector)
virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the bisector of a fuzzy set. The defuzzification process
+ integrates over the fuzzy set utilizing the boundaries given as
+ parameters. The integration algorithm is the midpoint rectangle
+ method (https://en.wikipedia.org/wiki/Rectangle_method).
+
+ @param term is the fuzzy set
+ @param minimum is the minimum value of the fuzzy set
+ @param maximum is the maximum value of the fuzzy set
+ @return the @f$x@f$-coordinate of the bisector of the fuzzy set
+ */
virtual scalar defuzzify(const Term* term,
scalar minimum, scalar maximum) const FL_IOVERRIDE;
virtual Bisector* clone() const FL_IOVERRIDE;
static Defuzzifier* constructor();
};
-
}
#endif /* FL_BISECTOR_H */
diff --git a/fuzzylite/fl/defuzzifier/Centroid.h b/fuzzylite/fl/defuzzifier/Centroid.h
index 7510673..b056eac 100644
--- a/fuzzylite/fl/defuzzifier/Centroid.h
+++ b/fuzzylite/fl/defuzzifier/Centroid.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_CENTROID_H
@@ -29,6 +21,16 @@
namespace fl {
+ /**
+ The Centroid class is an IntegralDefuzzifier that computes the centroid
+ of a fuzzy set represented in a Term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see BiSector
+ @see IntegralDefuzzifier
+ @see Defuzzifier
+ @since 4.0
+ */
class FL_API Centroid : public IntegralDefuzzifier {
public:
explicit Centroid(int resolution = defaultResolution());
@@ -36,12 +38,26 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Centroid)
virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the centroid of a fuzzy set. The defuzzification process
+ integrates over the fuzzy set utilizing the boundaries given as
+ parameters. The integration algorithm is the midpoint rectangle
+ method (https://en.wikipedia.org/wiki/Rectangle_method).
+
+ @param term is the fuzzy set
+ @param minimum is the minimum value of the fuzzy set
+ @param maximum is the maximum value of the fuzzy set
+ @return the @f$x@f$-coordinate of the centroid of the fuzzy set
+ */
virtual scalar defuzzify(const Term* term,
scalar minimum, scalar maximum) const FL_IOVERRIDE;
virtual Centroid* clone() const FL_IOVERRIDE;
static Defuzzifier* constructor();
};
-
}
+
#endif /* FL_CENTROID_H */
diff --git a/fuzzylite/fl/defuzzifier/Defuzzifier.h b/fuzzylite/fl/defuzzifier/Defuzzifier.h
index 3598113..25749eb 100644
--- a/fuzzylite/fl/defuzzifier/Defuzzifier.h
+++ b/fuzzylite/fl/defuzzifier/Defuzzifier.h
@@ -1,38 +1,39 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
-//TODO Check http://en.wikipedia.org/wiki/Defuzzification for other defuzzifiers.
-
#ifndef FL_DEFUZZIFIER_H
#define FL_DEFUZZIFIER_H
#include "fl/fuzzylite.h"
+
+#include "fl/Complexity.h"
+
#include <string>
namespace fl {
class Term;
+ /**
+ The Defuzzifier class is the abstract class for defuzzifiers.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see IntegralDefuzzifier
+ @see WeightedDefuzzifier
+ @since 4.0
+ */
class FL_API Defuzzifier {
public:
@@ -43,11 +44,33 @@ namespace fl {
}
FL_DEFAULT_COPY_AND_MOVE(Defuzzifier)
+ /**
+ Returns the name of the class of the defuzzifier
+ @return the name of the class of the defuzzifier
+ */
virtual std::string className() const = 0;
+ /**
+ Creates a clone of the defuzzifier
+ @return a clone of the defuzzifier
+ */
virtual Defuzzifier* clone() const = 0;
+
+ /**
+ Computes the complexity of defuzzifying the given term
+ @param term is the term to defuzzify
+ @return the complexity of defuzzifying the given term
+ */
+ virtual Complexity complexity(const Term* term) const = 0;
+ /**
+ Defuzzifies the given fuzzy term utilizing the range `[minimum,maximum]`
+ @param term is the term to defuzzify, typically an Aggregated term
+ @param minimum is the minimum value of the range
+ @param maximum is the maximum value of the range
+ @return the defuzzified value of the given fuzzy term
+ */
virtual scalar defuzzify(const Term* term, scalar minimum, scalar maximum) const = 0;
};
-
}
+
#endif /* FL_DEFUZZIFIER_H */
diff --git a/fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h b/fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h
index 61aaf8a..9cfd132 100644
--- a/fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h
+++ b/fuzzylite/fl/defuzzifier/IntegralDefuzzifier.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_INTEGRALDEFUZZIFIER_H
@@ -28,24 +20,52 @@
#include "fl/defuzzifier/Defuzzifier.h"
namespace fl {
- //TODO: check http://en.wikipedia.org/wiki/Adaptive_quadrature
+ /**
+ The IntegralDefuzzifier class is the base class for defuzzifiers which integrate
+ over the fuzzy set.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @since 4.0
+ */
class FL_API IntegralDefuzzifier : public Defuzzifier {
- protected:
+ private:
static int _defaultResolution;
int _resolution;
public:
-
- static void setDefaultResolution(int defaultResolution);
- static int defaultResolution();
-
explicit IntegralDefuzzifier(int resolution = defaultResolution());
virtual ~IntegralDefuzzifier() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(IntegralDefuzzifier)
+ /**
+ Sets the resolution of the defuzzifier. The resolution refers to the
+ number of divisions in which the range `[minimum,maximum]` is divided
+ in order to integrate the area under the curve
+
+ @param resolution is the resolution of the defuzzifier
+ */
virtual void setResolution(int resolution);
+ /**
+ Gets the resolution of the defuzzifier. The resolution refers to the
+ number of divisions in which the range `[minimum,maximum]` is divided
+ in order to integrate the area under the curve
+
+ @return the resolution of the defuzzifier
+ */
virtual int getResolution() const;
+
+ /**
+ Sets the default resolution for integral-based defuzzifiers
+ @param defaultResolution is the default resolution for integral-based defuzzifiers
+ */
+ static void setDefaultResolution(int defaultResolution);
+ /**
+ Gets the default resolution for integral-based defuzzifiers
+ @return the default resolution for integral-based defuzzifiers
+ */
+ static int defaultResolution();
+
};
}
diff --git a/fuzzylite/fl/defuzzifier/LargestOfMaximum.h b/fuzzylite/fl/defuzzifier/LargestOfMaximum.h
index 8f1d3c8..e325db5 100644
--- a/fuzzylite/fl/defuzzifier/LargestOfMaximum.h
+++ b/fuzzylite/fl/defuzzifier/LargestOfMaximum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_LARGESTOFMAXIMUM_H
@@ -29,6 +21,18 @@
namespace fl {
+ /**
+ The LargestOfMaximum class is an IntegralDefuzzifier that computes the
+ largest value of the maximum membership function of a fuzzy set
+ represented in a Term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see SmallestOfMaximum
+ @see MeanOfMaximum
+ @see IntegralDefuzzifier
+ @see Defuzzifier
+ @since 4.0
+ */
class FL_API LargestOfMaximum : public IntegralDefuzzifier {
public:
explicit LargestOfMaximum(int resolution = defaultResolution());
@@ -36,6 +40,21 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(LargestOfMaximum)
virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the largest value of the maximum membership function of a
+ fuzzy set. The largest value is computed by integrating over the
+ fuzzy set. The integration algorithm is the midpoint rectangle method
+ (https://en.wikipedia.org/wiki/Rectangle_method).
+
+ @param term is the fuzzy set
+ @param minimum is the minimum value of the fuzzy set
+ @param maximum is the maximum value of the fuzzy set
+ @return the largest @f$x@f$-coordinate of the maximum membership
+ function value in the fuzzy set
+ */
virtual scalar defuzzify(const Term* term,
scalar minimum, scalar maximum) const FL_IOVERRIDE;
virtual LargestOfMaximum* clone() const FL_IOVERRIDE;
@@ -43,5 +62,6 @@ namespace fl {
static Defuzzifier* constructor();
};
}
+
#endif /* FL_LARGESTOFMAXIMUM_H */
diff --git a/fuzzylite/fl/defuzzifier/MeanOfMaximum.h b/fuzzylite/fl/defuzzifier/MeanOfMaximum.h
index 2c09759..027f43b 100644
--- a/fuzzylite/fl/defuzzifier/MeanOfMaximum.h
+++ b/fuzzylite/fl/defuzzifier/MeanOfMaximum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_MEANOFMAXIMUM_H
@@ -29,6 +21,18 @@
namespace fl {
+ /**
+ The MeanOfMaximum class is an IntegralDefuzzifier that computes the mean
+ value of the maximum membership function of a fuzzy set represented in a
+ Term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see SmallestOfMaximum
+ @see MeanOfMaximum
+ @see IntegralDefuzzifier
+ @see Defuzzifier
+ @since 4.0
+ */
class FL_API MeanOfMaximum : public IntegralDefuzzifier {
public:
explicit MeanOfMaximum(int resolution = defaultResolution());
@@ -36,6 +40,21 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(MeanOfMaximum)
virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the mean value of the maximum membership function
+ of a fuzzy set. The mean value is computed while integrating
+ over the fuzzy set. The integration algorithm is the midpoint
+ rectangle method (https://en.wikipedia.org/wiki/Rectangle_method).
+
+ @param term is the fuzzy set
+ @param minimum is the minimum value of the fuzzy set
+ @param maximum is the maximum value of the fuzzy set
+ @return the mean @f$x@f$-coordinate of the maximum membership
+ function value in the fuzzy set
+ */
virtual scalar defuzzify(const Term* term,
scalar minimum, scalar maximum) const FL_IOVERRIDE;
virtual MeanOfMaximum* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/defuzzifier/SmallestOfMaximum.h b/fuzzylite/fl/defuzzifier/SmallestOfMaximum.h
index 289e2a9..94f8a7a 100644
--- a/fuzzylite/fl/defuzzifier/SmallestOfMaximum.h
+++ b/fuzzylite/fl/defuzzifier/SmallestOfMaximum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SMALLESTOFMAXIMUM_H
@@ -29,6 +21,18 @@
namespace fl {
+ /**
+ The SmallestOfMaximum class is an IntegralDefuzzifier that computes the
+ smallest value of the maximum membership function of a fuzzy set
+ represented in a Term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see LargestOfMaximum
+ @see MeanOfMaximum
+ @see IntegralDefuzzifier
+ @see Defuzzifier
+ @since 4.0
+ */
class FL_API SmallestOfMaximum : public IntegralDefuzzifier {
public:
explicit SmallestOfMaximum(int resolution = defaultResolution());
@@ -36,6 +40,21 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(SmallestOfMaximum)
virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the smallest value of the maximum membership function in the
+ fuzzy set. The smallest value is computed while integrating over the
+ fuzzy set. The integration algorithm is the midpoint rectangle method
+ (https://en.wikipedia.org/wiki/Rectangle_method).
+
+ @param term is the fuzzy set
+ @param minimum is the minimum value of the fuzzy set
+ @param maximum is the maximum value of the fuzzy set
+ @return the smallest @f$x@f$-coordinate of the maximum membership
+ function value in the fuzzy set
+ */
virtual scalar defuzzify(const Term* term,
scalar minimum, scalar maximum) const FL_IOVERRIDE;
virtual SmallestOfMaximum* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/defuzzifier/WeightedAverage.h b/fuzzylite/fl/defuzzifier/WeightedAverage.h
index 3fbbd38..7f8e9f6 100644
--- a/fuzzylite/fl/defuzzifier/WeightedAverage.h
+++ b/fuzzylite/fl/defuzzifier/WeightedAverage.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_WEIGHTEDAVERAGE_H
@@ -30,6 +22,18 @@
namespace fl {
class Activated;
+ /**
+ The WeightedAverage class is a WeightedDefuzzifier that computes the
+ weighted average of a fuzzy set represented in an Aggregated Term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see WeightedAverageCustom
+ @see WeightedSum
+ @see WeightedSumCustom
+ @see WeightedDefuzzifier
+ @see Defuzzifier
+ @since 4.0
+ */
class FL_API WeightedAverage : public WeightedDefuzzifier {
public:
explicit WeightedAverage(Type type = Automatic);
@@ -38,6 +42,23 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(WeightedAverage)
virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the weighted average of the given fuzzy set represented in
+ an Aggregated term as @f$y = \dfrac{\sum_i w_iz_i}{\sum_i w_i} @f$,
+ where @f$w_i@f$ is the activation degree of term @f$i@f$, and
+ @f$z_i = \mu_i(w_i) @f$.
+
+ From version 6.0, the implication and aggregation operators are not
+ utilized for defuzzification.
+
+ @param term is the fuzzy set represented as an Aggregated Term
+ @param minimum is the minimum value of the range (only used for Tsukamoto)
+ @param maximum is the maximum value of the range (only used for Tsukamoto)
+ @return the weighted average of the given fuzzy set
+ */
virtual scalar defuzzify(const Term* term,
scalar minimum, scalar maximum) const FL_IOVERRIDE;
virtual WeightedAverage* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/defuzzifier/WeightedAverageCustom.h b/fuzzylite/fl/defuzzifier/WeightedAverageCustom.h
new file mode 100644
index 0000000..5597f97
--- /dev/null
+++ b/fuzzylite/fl/defuzzifier/WeightedAverageCustom.h
@@ -0,0 +1,77 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_WEIGHTEDAVERAGECUSTOM_H
+#define FL_WEIGHTEDAVERAGECUSTOM_H
+
+#include "fl/defuzzifier/WeightedDefuzzifier.h"
+
+namespace fl {
+ class Activated;
+
+ /**
+ The (experimental) WeightedAverageCustom class is a WeightedDefuzzifier that computes the
+ weighted average of a fuzzy set represented in an Aggregated Term utilizing
+ the fuzzy operators for implication and aggregation to compute the weighted
+ average. This is an experimental approach to take advantage of customization
+ thanks to the object-oriented design.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see WeightedAverage
+ @see WeightedSum
+ @see WeightedSumCustom
+ @see WeightedDefuzzifier
+ @see Defuzzifier
+ @since 6.0
+ */
+ class FL_API WeightedAverageCustom : public WeightedDefuzzifier {
+ public:
+ explicit WeightedAverageCustom(Type type = Automatic);
+ explicit WeightedAverageCustom(const std::string& type);
+ virtual ~WeightedAverageCustom() FL_IOVERRIDE;
+ FL_DEFAULT_COPY_AND_MOVE(WeightedAverageCustom)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the weighted average of the given fuzzy set represented as
+ an AggregatedTerm as @f$y = \dfrac{\sum_i w_iz_i}{\sum_i w_i} @f$,
+ where @f$w_i@f$ is the activation degree of term @f$i@f$, and
+ @f$z_i = \mu_i(w_i) @f$.
+
+ If the implication and aggregation operators are set to fl::null (or
+ set to AlgebraicProduct and UnboundedSum, respectively), then the
+ operation of WeightedAverageCustom is the same as the WeightedAverage.
+ Otherwise, the implication and aggregation operators are utilized to
+ compute the multiplications and sums in @f$y@f$, respectively.
+
+ @param term is the fuzzy set represented as an Aggregated Term
+ @param minimum is the minimum value of the range (only used for Tsukamoto)
+ @param maximum is the maximum value of the range (only used for Tsukamoto)
+ @return the weighted average of the given fuzzy set
+ */
+ virtual scalar defuzzify(const Term* term,
+ scalar minimum, scalar maximum) const FL_IOVERRIDE;
+ virtual WeightedAverageCustom* clone() const FL_IOVERRIDE;
+
+ static Defuzzifier* constructor();
+ };
+}
+
+#endif /* FL_WEIGHTEDAVERAGECUSTOM_H */
+
diff --git a/fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h b/fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h
index 2bf0495..2045772 100644
--- a/fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h
+++ b/fuzzylite/fl/defuzzifier/WeightedDefuzzifier.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_WEIGHTEDDEFUZZIFIER_H
@@ -30,33 +22,68 @@
namespace fl {
class Activated;
+ /**
+ The WeightedDefuzzifier class is the base class for defuzzifiers which
+ compute a weighted function on the fuzzy set without requiring to
+ integrate over the fuzzy set.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @since 5.0
+ */
class FL_API WeightedDefuzzifier : public Defuzzifier {
public:
+ /**The Type enum indicates the type of the WeightedDefuzzifier based
+ the terms included in the fuzzy set.*/
enum Type {
- Automatic, TakagiSugeno, Tsukamoto
+ /**Automatic: Automatically inferred from the terms */
+ Automatic,
+ /**TakagiSugeno: Manually set to TakagiSugeno (or Inverse Tsukamoto)*/
+ TakagiSugeno,
+ /**Tsukamoto: Manually set to Tsukamoto*/
+ Tsukamoto
};
- static std::string typeName(Type);
+ /**
+ Returns a string representation of the given type
+ @param type is the type of a defuzzifier
+ @return a string representation of the given type
+ */
+ static std::string typeName(Type type);
+ private:
+ Type _type;
+ public:
explicit WeightedDefuzzifier(Type type = Automatic);
explicit WeightedDefuzzifier(const std::string& type);
virtual ~WeightedDefuzzifier() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(WeightedDefuzzifier)
- virtual void setType(Type type);
- virtual Type getType() const;
+ /**
+ Sets the type of the weighted defuzzifier
+ @param type is the type of the weighted defuzzifier
+ */
+ void setType(Type type);
+ /**
+ Gets the type of the weighted defuzzifier
+ @return the type of the weighted defuzzifier
+ */
+ Type getType() const;
+ /**
+ Returns a string representation of the type of the defuzzifier
+ @return a string representation of the type of the defuzzifier
+ */
virtual std::string getTypeName() const;
+ /**
+ Infers the type of the defuzzifier based on the given term. If the
+ given term is Constant, Linear or Function, then the type is
+ TakagiSugeno; otherwise, the type is Tsukamoto
+
+ @param term is the given term
+ @return the inferred type of the defuzzifier based on the given term
+ */
virtual Type inferType(const Term* term) const;
- virtual bool isMonotonic(const Term* term) const;
-
- virtual scalar tsukamoto(const Term* monotonic, scalar activationDegree,
- scalar minimum, scalar maximum) const;
-
- protected:
- Type _type;
};
-
}
#endif /* FL_WEIGHTEDDEFUZZIFIER_H */
diff --git a/fuzzylite/fl/defuzzifier/WeightedSum.h b/fuzzylite/fl/defuzzifier/WeightedSum.h
index a754023..fb61ef3 100644
--- a/fuzzylite/fl/defuzzifier/WeightedSum.h
+++ b/fuzzylite/fl/defuzzifier/WeightedSum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_WEIGHTEDSUM_H
@@ -30,6 +22,18 @@
namespace fl {
+ /**
+ The WeightedSum class is a WeightedDefuzzifier that computes the
+ weighted sum of a fuzzy set represented in an Aggregated Term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see WeightedSumCustom
+ @see WeightedAverage
+ @see WeightedAverageCustom
+ @see WeightedDefuzzifier
+ @see Defuzzifier
+ @since 4.0
+ */
class FL_API WeightedSum : public WeightedDefuzzifier {
public:
explicit WeightedSum(Type type = Automatic);
@@ -38,6 +42,23 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(WeightedSum)
virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the weighted sum of the given fuzzy set represented as an
+ Aggregated Term as @f$y = \sum_i{w_iz_i} @f$,
+ where @f$w_i@f$ is the activation degree of term @f$i@f$, and @f$z_i
+ = \mu_i(w_i) @f$.
+
+ From version 6.0, the implication and aggregation operators are not
+ utilized for defuzzification.
+
+ @param term is the fuzzy set represented as an AggregatedTerm
+ @param minimum is the minimum value of the range (only used for Tsukamoto)
+ @param maximum is the maximum value of the range (only used for Tsukamoto)
+ @return the weighted sum of the given fuzzy set
+ */
virtual scalar defuzzify(const Term* term,
scalar minimum, scalar maximum) const FL_IOVERRIDE;
virtual WeightedSum* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/defuzzifier/WeightedSumCustom.h b/fuzzylite/fl/defuzzifier/WeightedSumCustom.h
new file mode 100644
index 0000000..c055d1e
--- /dev/null
+++ b/fuzzylite/fl/defuzzifier/WeightedSumCustom.h
@@ -0,0 +1,78 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_WEIGHTEDSUMCUSTOM_H
+#define FL_WEIGHTEDSUMCUSTOM_H
+
+
+#include "fl/defuzzifier/WeightedDefuzzifier.h"
+
+namespace fl {
+
+ /**
+ The (experimental) WeightedSumCustom class is a WeightedDefuzzifier that computes the
+ weighted sum of a fuzzy set represented in an Aggregated Term utilizing
+ the fuzzy operators for implication and aggregation to compute the weighted
+ sum. This is an experimental approach to take advantage of customization
+ thanks to the object-oriented design.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see WeightedSum
+ @see WeightedAverage
+ @see WeightedAverageCustom
+ @see WeightedDefuzzifier
+ @see Defuzzifier
+ @since 6.0
+ @experimental
+ */
+ class FL_API WeightedSumCustom : public WeightedDefuzzifier {
+ public:
+ explicit WeightedSumCustom(Type type = Automatic);
+ explicit WeightedSumCustom(const std::string& type);
+ virtual ~WeightedSumCustom() FL_IOVERRIDE;
+ FL_DEFAULT_COPY_AND_MOVE(WeightedSumCustom)
+
+ virtual std::string className() const FL_IOVERRIDE;
+
+ virtual Complexity complexity(const Term* term) const FL_IOVERRIDE;
+
+ /**
+ Computes the weighted sum of the given fuzzy set represented in an
+ Aggregated Term as @f$y = \sum_i{w_iz_i} @f$,
+ where @f$w_i@f$ is the activation degree of term @f$i@f$, and @f$z_i
+ = \mu_i(w_i) @f$.
+
+ If the implication and aggregation operators are set to fl::null (or
+ set to AlgebraicProduct and UnboundedSum, respectively), then the
+ operation of WeightedAverageCustom is the same as the WeightedAverage.
+ Otherwise, the implication and aggregation operators are utilized to
+ compute the multiplications and sums in @f$y@f$, respectively.
+
+ @param term is the fuzzy set represented as an AggregatedTerm
+ @param minimum is the minimum value of the range (only used for Tsukamoto)
+ @param maximum is the maximum value of the range (only used for Tsukamoto)
+ @return the weighted sum of the given fuzzy set
+ */
+ virtual scalar defuzzify(const Term* term,
+ scalar minimum, scalar maximum) const FL_IOVERRIDE;
+ virtual WeightedSumCustom* clone() const FL_IOVERRIDE;
+
+ static Defuzzifier* constructor();
+ };
+}
+
+#endif /* FL_WEIGHTEDSUMCUSTOM_H */
+
diff --git a/fuzzylite/fl/factory/ActivationFactory.h b/fuzzylite/fl/factory/ActivationFactory.h
new file mode 100644
index 0000000..6ebfc73
--- /dev/null
+++ b/fuzzylite/fl/factory/ActivationFactory.h
@@ -0,0 +1,46 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_ACTIVATIONFACTORY_H
+#define FL_ACTIVATIONFACTORY_H
+
+#include "fl/fuzzylite.h"
+
+#include "fl/factory/ConstructionFactory.h"
+#include "fl/activation/Activation.h"
+
+namespace fl {
+
+ /**
+ The ActivationFactory class is a ConstructionFactory of Activation
+ methods for RuleBlock%s.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Activation
+ @see RuleBlock
+ @see ConstructionFactory
+ @see FactoryManager
+ @since 6.0
+ */
+ class FL_API ActivationFactory : public ConstructionFactory<Activation*> {
+ public:
+ ActivationFactory();
+ virtual ~ActivationFactory() FL_IOVERRIDE;
+ FL_DEFAULT_COPY_AND_MOVE(ActivationFactory)
+ };
+}
+
+#endif /* FL_ACTIVATIONFACTORY_H */
diff --git a/fuzzylite/fl/factory/CloningFactory.h b/fuzzylite/fl/factory/CloningFactory.h
index 3262721..a21e1d2 100644
--- a/fuzzylite/fl/factory/CloningFactory.h
+++ b/fuzzylite/fl/factory/CloningFactory.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_CLONINGFACTORY_H
@@ -33,9 +25,20 @@
namespace fl {
+ /**
+ The CloningFactory class is the base class for a factory whose objects
+ are created from a registered object by calling the `clone()` method.
+
+ @param <T> is the class of the object to be cloned
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FactoryManager
+ @since 5.0
+ */
+
template <typename T>
- class FL_API CloningFactory {
- protected:
+ class CloningFactory {
+ private:
std::string _name;
std::map<std::string, T> _objects;
@@ -46,17 +49,178 @@ namespace fl {
virtual ~CloningFactory();
FL_DEFAULT_MOVE(CloningFactory)
+ /**
+ Returns the name of the factory
+ @return the name of the factory
+ */
virtual std::string name() const;
+ /**
+ Registers the object in the factory and assumes its ownership
+ @param key is the unique name by which objects are registered
+ @param object is the object to be cloned via a `clone` method
+ */
virtual void registerObject(const std::string& key, T object);
+ /**
+ Deregisters the given object from the factory and deletes it
+ @param key is the unique name by which objects are registered
+ */
virtual void deregisterObject(const std::string& key);
+ /**
+ Checks whether the factory has the given object registered
+ @param key is the unique name by which objects are registered
+ @return whether the factory has the given object registered
+ */
virtual bool hasObject(const std::string& key) const;
+ /**
+ Gets the object registered by the given key, not a clone of the object
+ @param key is the unique name by which objects are registered
+ @return the object registered by the given key
+ */
virtual T getObject(const std::string& key) const;
+ /**
+ Creates a cloned object by executing the clone method on the registered object
+ @param key is the unique name by which objects are registered
+ @return a cloned object by executing the clone method on the registered object
+ */
virtual T cloneObject(const std::string& key) const;
+ /**
+ Returns a vector of the available objects
+ @return a vector of the available objects
+ */
virtual std::vector<std::string> available() const;
+ /**
+ Gets the map of registered keys and objects
+ @return the map of registered keys and objects
+ */
+ virtual std::map<std::string, T>& objects();
+ /**
+ Gets an immutable map of registered keys and objects
+ @return an immutable map of registered keys and objects
+ */
+ virtual const std::map<std::string, T>& objects() const;
};
}
+/**
+ Template implementation
+ */
+
+#include "fl/Exception.h"
+
+namespace fl {
+
+ template<typename T>
+ inline CloningFactory<T>::CloningFactory(const std::string& name) : _name(name) {
+
+ }
+
+ template<typename T>
+ inline CloningFactory<T>::CloningFactory(const CloningFactory& other) {
+ typename std::map<std::string, T>::const_iterator it = other._objects.begin();
+ while (it != other._objects.end()) {
+ T clone = fl::null;
+ if (it->second) clone = it->second->clone();
+ this->_objects[it->first] = clone;
+ ++it;
+ }
+ }
+
+ template<typename T>
+ inline CloningFactory<T>& CloningFactory<T>::operator=(const CloningFactory& other) {
+ if (this != &other) {
+ typename std::map<std::string, T>::const_iterator it = this->_objects.begin();
+ while (it != this->_objects.end()) {
+ if (it->second) delete it->second;
+ ++it;
+ }
+ this->_objects.clear();
+
+ it = other._objects.begin();
+ while (it != other._objects.end()) {
+ T clone = fl::null;
+ if (it->second) clone = it->second->clone();
+ this->_objects[it->first] = clone;
+ ++it;
+ }
+ }
+ return *this;
+ }
+
+ template<typename T>
+ inline CloningFactory<T>::~CloningFactory() {
+ typename std::map<std::string, T>::const_iterator it = this->_objects.begin();
+ while (it != this->_objects.end()) {
+ if (it->second) delete it->second;
+ ++it;
+ }
+ }
+
+ template<typename T>
+ inline std::string CloningFactory<T>::name() const {
+ return this->_name;
+ }
+
+ template<typename T>
+ inline void CloningFactory<T>::registerObject(const std::string& key, T object) {
+ this->_objects[key] = object;
+ }
+
+ template<typename T>
+ inline void CloningFactory<T>::deregisterObject(const std::string& key) {
+ typename std::map<std::string, T>::iterator it = this->_objects.find(key);
+ if (it != this->_objects.end()) {
+ this->_objects.erase(it);
+ delete it->second;
+ }
+ }
+
+ template<typename T>
+ inline bool CloningFactory<T>::hasObject(const std::string& key) const {
+ typename std::map<std::string, T>::const_iterator it = this->_objects.find(key);
+ return (it != this->_objects.end());
+ }
+
+ template<typename T>
+ inline T CloningFactory<T>::getObject(const std::string& key) const {
+ typename std::map<std::string, T>::const_iterator it = this->_objects.find(key);
+ if (it != this->_objects.end()) {
+ if (it->second) return it->second;
+ }
+ return fl::null;
+ }
+
+ template<typename T>
+ inline T CloningFactory<T>::cloneObject(const std::string& key) const {
+ typename std::map<std::string, T>::const_iterator it = this->_objects.find(key);
+ if (it != this->_objects.end()) {
+ if (it->second) return it->second->clone();
+ return fl::null;
+ }
+ throw Exception("[cloning error] " + _name + " object by name <" + key + "> not registered", FL_AT);
+ }
+
+ template<typename T>
+ inline std::vector<std::string> CloningFactory<T>::available() const {
+ std::vector<std::string> result;
+ typename std::map<std::string, T>::const_iterator it = this->_objects.begin();
+ while (it != this->_objects.end()) {
+ result.push_back(it->first);
+ }
+ return result;
+ }
+
+ template<typename T>
+ inline std::map<std::string, T>& CloningFactory<T>::objects() {
+ return this->_objects;
+ }
+
+ template<typename T>
+ inline const std::map<std::string, T>& CloningFactory<T>::objects() const {
+ return this->_objects;
+ }
+}
+
#endif /* FL_CLONINGFACTORY_H */
diff --git a/fuzzylite/fl/factory/ConstructionFactory.h b/fuzzylite/fl/factory/ConstructionFactory.h
index d01ca7d..2558d7f 100644
--- a/fuzzylite/fl/factory/ConstructionFactory.h
+++ b/fuzzylite/fl/factory/ConstructionFactory.h
@@ -1,29 +1,21 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
-#ifndef FL_FACTORY_H
-#define FL_FACTORY_H
+#ifndef FL_CONSTRUCTIONFACTORY_H
+#define FL_CONSTRUCTIONFACTORY_H
#include "fl/fuzzylite.h"
@@ -33,12 +25,25 @@
namespace fl {
+ /**
+ The ConstructionFactory class is the base class for a factory whose
+ objects are created from a registered ConstructionFactory::Constructor.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FactoryManager
+ @since 5.0
+ */
+
template <typename T>
- class FL_API ConstructionFactory {
+ class ConstructionFactory {
public:
+ /**
+ The Constructor type definition refers to a zero-parameter method
+ which returns an instance of T
+ */
typedef T(*Constructor)();
- protected:
+ private:
std::string _name;
std::map<std::string, Constructor> _constructors;
@@ -47,18 +52,151 @@ namespace fl {
virtual ~ConstructionFactory();
FL_DEFAULT_COPY_AND_MOVE(ConstructionFactory)
+ /**
+ Returns the name of the factory
+ @return the name of the factory
+ */
virtual std::string name() const;
+ /**
+ Registers the constructor in the factory
+ @param key is the unique name by which constructors are registered
+ @param constructor is the pointer to the constructor of the object
+ */
virtual void registerConstructor(const std::string& key, Constructor constructor);
+ /**
+ Deregisters from the factory the constructor associated to the given key
+ @param key is the unique name by which constructors are registered
+ */
virtual void deregisterConstructor(const std::string& key);
+ /**
+ Checks whether the factory has a constructor registered by the given key
+ @param key is the unique name by which constructors are registered
+ @return whether the factory has the given constructor registered
+ */
virtual bool hasConstructor(const std::string& key) const;
+ /**
+ Gets the constructor registered by the given key
+ @param key is the unique name by which constructors are registered
+ @return the pointer to the given constructor
+ */
virtual Constructor getConstructor(const std::string& key) const;
+ /**
+ Creates an object by executing the constructor associated to the given key
+ @param key is the unique name by which constructors are registered
+ @return an object by executing the constructor associated to the given key
+ */
virtual T constructObject(const std::string& key) const;
+ /**
+ Returns a vector of keys for the constructors available
+ @return a vector of keys for the constructors available
+ */
virtual std::vector<std::string> available() const;
-
+ /**
+ Gets the map of registered keys and constructors
+ @return the map of registered keys and constructors
+ */
+ virtual std::map<std::string, Constructor>& constructors();
+ /**
+ Gets an immutable map of registered keys and constructors
+ @return an immutable map of registered keys and constructors
+ */
+ virtual const std::map<std::string, Constructor>& constructors() const;
};
}
-#endif /* FL_FACTORY_H */
+/**
+ * Template implementation
+ */
+
+
+#include "fl/Exception.h"
+#include "fl/defuzzifier/Defuzzifier.h"
+#include "fl/hedge/Hedge.h"
+#include "fl/norm/SNorm.h"
+#include "fl/norm/TNorm.h"
+#include "fl/term/Term.h"
+
+namespace fl {
+
+ template <typename T>
+ inline ConstructionFactory<T>::ConstructionFactory(const std::string& name) : _name(name) {
+
+ }
+
+ template <typename T>
+ inline ConstructionFactory<T>::~ConstructionFactory() {
+ }
+
+ template<typename T>
+ inline std::string ConstructionFactory<T>::name() const {
+ return this->_name;
+ }
+
+ template <typename T>
+ inline void ConstructionFactory<T>::registerConstructor(const std::string& key, Constructor constructor) {
+ this->_constructors[key] = constructor;
+ }
+
+ template <typename T>
+ inline void ConstructionFactory<T>::deregisterConstructor(const std::string& key) {
+ typename std::map<std::string, Constructor>::iterator it = this->_constructors.find(key);
+ if (it != this->_constructors.end()) {
+ this->_constructors.erase(it);
+ }
+ }
+
+ template <typename T>
+ inline bool ConstructionFactory<T>::hasConstructor(const std::string& key) const {
+ typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key);
+ return (it != this->_constructors.end());
+ }
+
+ template <typename T>
+ inline typename ConstructionFactory<T>::Constructor ConstructionFactory<T>::getConstructor(const std::string& key) const {
+ typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key);
+ if (it != this->_constructors.end()) {
+ return it->second;
+ }
+ return fl::null;
+ }
+
+ template <typename T>
+ inline T ConstructionFactory<T>::constructObject(const std::string& key) const {
+ typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key);
+ if (it != this->_constructors.end()) {
+ if (it->second) {
+ return it->second();
+ }
+ return fl::null;
+ }
+ std::ostringstream ss;
+ ss << "[factory error] constructor of " + _name + " <" << key << "> not registered";
+ throw Exception(ss.str(), FL_AT);
+ }
+
+ template <typename T>
+ inline std::vector<std::string> ConstructionFactory<T>::available() const {
+ std::vector<std::string> result;
+ typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.begin();
+ while (it != this->_constructors.end()) {
+ result.push_back(it->first);
+ ++it;
+ }
+ return result;
+ }
+
+ template<typename T>
+ inline std::map<std::string, typename ConstructionFactory<T>::Constructor>& ConstructionFactory<T>::constructors() {
+ return this->_constructors;
+ }
+
+ template<typename T>
+ inline const std::map<std::string, typename ConstructionFactory<T>::Constructor>& ConstructionFactory<T>::constructors() const {
+ return this->_constructors;
+ }
+}
+
+#endif /* FL_CONSTRUCTIONFACTORY_H */
diff --git a/fuzzylite/fl/factory/DefuzzifierFactory.h b/fuzzylite/fl/factory/DefuzzifierFactory.h
index 32d3ee7..8fa4c1b 100644
--- a/fuzzylite/fl/factory/DefuzzifierFactory.h
+++ b/fuzzylite/fl/factory/DefuzzifierFactory.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_DEFUZZIFIERFACTORY_H
@@ -33,19 +25,51 @@
namespace fl {
+ /**
+ The DefuzzifierFactory class is a ConstructionFactory of Defuzzifier%s.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Defuzzifier
+ @see ConstructionFactory
+ @see FactoryManager
+ @since 4.0
+ */
class FL_API DefuzzifierFactory : public ConstructionFactory<Defuzzifier*> {
public:
DefuzzifierFactory();
virtual ~DefuzzifierFactory() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(DefuzzifierFactory)
+ /**
+ Creates a Defuzzifier by executing the registered constructor
+ @param key is the unique name by which constructors are registered
+ @param resolution is the resolution of an IntegralDefuzzifier
+ @param type is the type of a WeightedDefuzzifier
+ @return a Defuzzifier by executing the registered constructor and
+ setting its resolution or type accordingly
+ */
virtual Defuzzifier* constructDefuzzifier(const std::string& key,
- int resolution, WeightedDefuzzifier::Type) const;
+ int resolution, WeightedDefuzzifier::Type type) const;
+ /**
+ Creates a Defuzzifier by executing the registered constructor
+ @param key is the unique name by which constructors are registered
+ @param resolution is the resolution of an IntegralDefuzzifier
+ @return a Defuzzifier by executing the registered constructor and
+ setting its resolution
+ */
virtual Defuzzifier* constructDefuzzifier(const std::string& key, int resolution) const;
+ /**
+ Creates a Defuzzifier by executing the registered constructor
+ @param key is the unique name by which constructors are registered
+ @param type is the type of a WeightedDefuzzifier
+ @return a Defuzzifier by executing the registered constructor and
+ setting its type
+ */
virtual Defuzzifier* constructDefuzzifier(const std::string& key, WeightedDefuzzifier::Type type);
};
}
+
#endif /* DEFUZZIFIERFACTORY_H */
diff --git a/fuzzylite/fl/factory/FactoryManager.h b/fuzzylite/fl/factory/FactoryManager.h
index d853d93..79f7996 100644
--- a/fuzzylite/fl/factory/FactoryManager.h
+++ b/fuzzylite/fl/factory/FactoryManager.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FACTORYMANAGER_H
@@ -27,55 +19,136 @@
#include "fl/fuzzylite.h"
+#include "fl/factory/TNormFactory.h"
+#include "fl/factory/SNormFactory.h"
+#include "fl/factory/ActivationFactory.h"
+#include "fl/factory/DefuzzifierFactory.h"
+#include "fl/factory/TermFactory.h"
+#include "fl/factory/HedgeFactory.h"
+#include "fl/factory/FunctionFactory.h"
+
namespace fl {
- class TNormFactory;
- class SNormFactory;
- class DefuzzifierFactory;
- class TermFactory;
- class HedgeFactory;
- class FunctionFactory;
+ /**
+ The FactoryManager class is a central class grouping different factories
+ of objects, together with a singleton instance to access each of the
+ factories throughout the library.
+
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see TermFactory
+ @see TNormFactory
+ @see SNormFactory
+ @see HedgeFactory
+ @see ActivationFactory
+ @see DefuzzifierFactory
+ @see FunctionFactory
+ @since 4.0
+ */
class FL_API FactoryManager {
- protected:
- static FactoryManager _instance;
-
+ private:
FL_unique_ptr<TNormFactory> _tnorm;
FL_unique_ptr<SNormFactory> _snorm;
+ FL_unique_ptr<ActivationFactory> _activation;
FL_unique_ptr<DefuzzifierFactory> _defuzzifier;
FL_unique_ptr<TermFactory> _term;
FL_unique_ptr<HedgeFactory> _hedge;
FL_unique_ptr<FunctionFactory> _function;
+ public:
FactoryManager();
- FactoryManager(TNormFactory* tnorm, SNormFactory* snorm,
- DefuzzifierFactory* defuzzifier, TermFactory* term,
- HedgeFactory* hedge, FunctionFactory* function);
- FactoryManager(const FactoryManager& other);
+ explicit FactoryManager(TNormFactory* tnorm, SNormFactory* snorm,
+ ActivationFactory* activation, DefuzzifierFactory* defuzzifier,
+ TermFactory* term, HedgeFactory* hedge, FunctionFactory* function);
+ explicit FactoryManager(const FactoryManager& other);
FactoryManager& operator=(const FactoryManager& other);
FL_DEFAULT_MOVE(FactoryManager)
virtual ~FactoryManager();
- public:
+ /**
+ Gets the static instance of the manager
+ @return the static instance of the manager
+ */
static FactoryManager* instance();
+ /**
+ Sets the factory of TNorm%s
+ @param tnorm is the factory of TNorm%s
+ */
virtual void setTnorm(TNormFactory* tnorm);
+ /**
+ Gets the factory of TNorm%s
+ @return the factory of TNorm%s
+ */
virtual TNormFactory* tnorm() const;
+ /**
+ Sets the factory of SNorm%s
+ @param snorm is the factory of SNorm%s
+ */
virtual void setSnorm(SNormFactory* snorm);
+ /**
+ Gets the factory of SNorm%s
+ @return the factory of SNorm%s
+ */
virtual SNormFactory* snorm() const;
+ /**
+ Sets the factory of Activation methods
+ @param activation is the factory of Activation methods
+ */
+ virtual void setActivation(ActivationFactory* activation);
+ /**
+ Gets the factory of Activation methods
+ @return the factory of Activation methods
+ */
+ virtual ActivationFactory* activation() const;
+
+ /**
+ Sets the factory of Defuzzifier%s
+ @param defuzzifier is the factory of Defuzzifier%s
+ */
virtual void setDefuzzifier(DefuzzifierFactory* defuzzifier);
+ /**
+ Gets the factory of Defuzzifier%s
+ @return the factory of Defuzzifier%s
+ */
virtual DefuzzifierFactory* defuzzifier() const;
+ /**
+ Sets the factory of Term%s
+ @param term is the factory of Term%s
+ */
virtual void setTerm(TermFactory* term);
+ /**
+ Gets the factory of Term%s
+ @return the factory of Term%s
+ */
virtual TermFactory* term() const;
+ /**
+ Sets the factory of Hedge%s
+ @param hedge is the factory of Hedge%s
+ */
virtual void setHedge(HedgeFactory* hedge);
+ /**
+ Gets the factory of Hedge%s
+ @return the factory of Hedge%s
+ */
virtual HedgeFactory* hedge() const;
+ /**
+ Sets the factory of Function Element%s
+ @param function is the factory of Function Element%s
+ */
virtual void setFunction(FunctionFactory* function);
+ /**
+ Gets the factory of Function Element%s
+ @return the factory of Function Element%s
+ */
virtual FunctionFactory* function() const;
};
}
+
#endif /* FL_FACTORYMANAGER_H */
diff --git a/fuzzylite/fl/factory/FunctionFactory.h b/fuzzylite/fl/factory/FunctionFactory.h
index c1ea9f1..84e0104 100644
--- a/fuzzylite/fl/factory/FunctionFactory.h
+++ b/fuzzylite/fl/factory/FunctionFactory.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FUNCTIONFACTORY_H
@@ -31,7 +23,18 @@
namespace fl {
- class FunctionFactory : public CloningFactory<Function::Element*> {
+ /**
+ The FunctionFactory class is a CloningFactory of operators and functions
+ utilized by the Function term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Function
+ @see Element
+ @see CloningFactory
+ @see FactoryManager
+ @since 5.0
+ */
+ class FL_API FunctionFactory : public CloningFactory<Function::Element*> {
private:
void registerOperators();
void registerFunctions();
@@ -40,11 +43,18 @@ namespace fl {
virtual ~FunctionFactory() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(FunctionFactory)
+ /**
+ Returns a vector of the operators available
+ @return a vector of the operators available
+ */
virtual std::vector<std::string> availableOperators() const;
+ /**
+ Returns a vector of the functions available
+ @return a vector of the functions available
+ */
virtual std::vector<std::string> availableFunctions() const;
};
-
}
#endif /* FL_FUNCTIONFACTORY_H */
diff --git a/fuzzylite/fl/factory/HedgeFactory.h b/fuzzylite/fl/factory/HedgeFactory.h
index aca5d3a..e4733b2 100644
--- a/fuzzylite/fl/factory/HedgeFactory.h
+++ b/fuzzylite/fl/factory/HedgeFactory.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_HEDGEFACTORY_H
@@ -31,6 +23,15 @@
namespace fl {
+ /**
+ The HedgeFactory class is a ConstructionFactory of Hedge%s.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Hedge
+ @see ConstructionFactory
+ @see FactoryManager
+ @since 4.0
+ */
class FL_API HedgeFactory : public ConstructionFactory<Hedge*> {
public:
HedgeFactory();
@@ -38,5 +39,6 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(HedgeFactory)
};
}
+
#endif /* FL_HEDGEFACTORY_H */
diff --git a/fuzzylite/fl/factory/SNormFactory.h b/fuzzylite/fl/factory/SNormFactory.h
index ca8bf1a..111664a 100644
--- a/fuzzylite/fl/factory/SNormFactory.h
+++ b/fuzzylite/fl/factory/SNormFactory.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SNORMFACTORY_H
@@ -31,6 +23,15 @@
namespace fl {
+ /**
+ The SNormFactory class is a ConstructionFactory of SNorm%s.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see SNorm
+ @see ConstructionFactory
+ @see FactoryManager
+ @since 4.0
+ */
class FL_API SNormFactory : public ConstructionFactory<SNorm*> {
public:
SNormFactory();
@@ -38,5 +39,6 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(SNormFactory)
};
}
+
#endif /* FL_SNORMFACTORY_H */
diff --git a/fuzzylite/fl/factory/TNormFactory.h b/fuzzylite/fl/factory/TNormFactory.h
index 6af2249..5093fa7 100644
--- a/fuzzylite/fl/factory/TNormFactory.h
+++ b/fuzzylite/fl/factory/TNormFactory.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_TNORMFACTORY_H
@@ -31,6 +23,15 @@
namespace fl {
+ /**
+ The TNormFactory class is a ConstructionFactory of TNorm%s.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see TNorm
+ @see ConstructionFactory
+ @see FactoryManager
+ @since 4.0
+ */
class FL_API TNormFactory : public ConstructionFactory<TNorm*> {
public:
TNormFactory();
@@ -38,5 +39,6 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(TNormFactory)
};
}
+
#endif /* FL_TNORMFACTORY_H */
diff --git a/fuzzylite/fl/factory/TermFactory.h b/fuzzylite/fl/factory/TermFactory.h
index 6fd0656..f6a5d60 100644
--- a/fuzzylite/fl/factory/TermFactory.h
+++ b/fuzzylite/fl/factory/TermFactory.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_TERMFACTORY_H
@@ -32,6 +24,15 @@
namespace fl {
+ /**
+ The TermFactory class is a ConstructionFactory of Term%s.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see ConstructionFactory
+ @see FactoryManager
+ @since 4.0
+ */
class FL_API TermFactory : public ConstructionFactory<Term*> {
public:
TermFactory();
@@ -39,5 +40,6 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(TermFactory)
};
}
+
#endif /* FL_TERMFACTORY_H */
diff --git a/fuzzylite/fl/fuzzylite.h b/fuzzylite/fl/fuzzylite.h
index 18c8dfa..3cca94b 100644
--- a/fuzzylite/fl/fuzzylite.h
+++ b/fuzzylite/fl/fuzzylite.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FUZZYLITE_H
@@ -31,14 +23,7 @@
#include <sstream>
#include <limits>
#include <memory>
-
-#ifndef FL_VERSION
-#define FL_VERSION "?"
-#endif
-
-#ifndef FL_DATE
-#define FL_DATE "?"
-#endif
+#include <cstddef>
#ifndef FL_BUILD_PATH
#define FL_BUILD_PATH ""
@@ -54,19 +39,21 @@
#ifdef __APPLE__
#define FL_APPLE
+#ifndef FL_UNIX
+#define FL_UNIX
+#endif
#endif
#define FL__FILE__ std::string(__FILE__).substr(std::string(FL_BUILD_PATH).size())
-#define FL_LOG_PREFIX FL__FILE__ << " [" << __LINE__ << "]:"
+#define FL_LOG_PREFIX FL__FILE__ << " (" << __LINE__ << "):"
#define FL_AT FL__FILE__, __LINE__, __FUNCTION__
+#define FL_LOG(message) {if (fl::fuzzylite::isLogging()){std::cout << FL_LOG_PREFIX << message << std::endl;}}
+#define FL_LOGP(message) {if (fl::fuzzylite::isLogging()){std::cout << message << std::endl;}}
-#define FL_LOG(message) {if (fl::fuzzylite::logging()){std::cout << FL_LOG_PREFIX << message << std::endl;}}
-#define FL_LOGP(message) {if (fl::fuzzylite::logging()){std::cout << message << std::endl;}}
-
-#define FL_DEBUG_BEGIN if (fl::fuzzylite::debug()){
+#define FL_DEBUG_BEGIN if (fl::fuzzylite::isDebugging()){
#define FL_DEBUG_END }
#define FL_DBG(message) FL_DEBUG_BEGIN\
@@ -83,7 +70,7 @@
//#define bitand &
//#define bitor |
-//TODO: Address warning 4251 by exporting members?
+//@todo: Address warning 4251 by exporting members?
//http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html
#ifdef _MSC_VER
#pragma warning (disable:4251)
@@ -107,21 +94,80 @@
#define FL_API
#endif
+/**
+ The fl namespace is the namespace where all the classes of the `fuzzylite`
+ library are contained in.
+ @author Juan Rada-Vilela, Ph.D.
+ @since 4.0
+ */
namespace fl {
+ /**
+ Represents floating-point values (typedef to float or double).
+ */
#ifdef FL_USE_FLOAT
typedef float scalar;
#else
+ /**
+ Represents floating-point values as doubles.
+ */
typedef double scalar;
#endif
- const scalar nan = std::numeric_limits<scalar>::quiet_NaN();
- const scalar inf = std::numeric_limits<scalar>::infinity();
+#define FL_IUNUSED(x) (void) (x)
+
+#ifdef __GNUC__
+#define FL_IUNUSED_DECL __attribute__((unused))
+#else
+#define FL_IUNUSED_DECL
+#endif
-#ifdef FL_CPP11
+ /**
+ Represents the Not-A-Number scalar value
+ */
+ const scalar nan FL_IUNUSED_DECL = std::numeric_limits<scalar>::quiet_NaN();
+ /**
+ Represents the infinity scalar value
+ */
+ const scalar inf FL_IUNUSED_DECL = std::numeric_limits<scalar>::infinity();
+
+#ifdef FL_CPP98
+ //C++98 defines
+
+ //Pointers
+ /**
+ Represents the `C++11` or `C++98` null pointer depending on whether the
+ compilation flag `-DFL_CPP98` is set
+ */
+ const long null = 0L;
+#define FL_unique_ptr std::auto_ptr
+#define FL_move_ptr(x) x
+
+ //Identifiers
+#define FL_IOVERRIDE
+#define FL_IFINAL
+#define FL_IDEFAULT
+#define FL_IDELETE
+#define FL_INOEXCEPT throw()
+#define FL_ITHREAD_LOCAL
+
+ //Constructors
+#define FL_DEFAULT_COPY(Class)
+#define FL_DEFAULT_MOVE(Class)
+#define FL_DEFAULT_COPY_AND_MOVE(Class)
+
+#define FL_DISABLE_COPY(Class) \
+ Class(const Class &);\
+ Class &operator=(const Class &);
+
+#else
//C++11 defines
//Pointers
+ /**
+ Represents the `C++11` or `C++98` null pointer depending on whether the
+ compilation flag `-DFL_CPP98` is set
+ */
const std::nullptr_t null = nullptr;
#define FL_unique_ptr std::unique_ptr
#define FL_move_ptr(x) std::move(x)
@@ -132,6 +178,7 @@ namespace fl {
#define FL_IDEFAULT = default
#define FL_IDELETE = delete
#define FL_INOEXCEPT noexcept
+#define FL_ITHREAD_LOCAL /*thread_local (commented for performance)*/
//Constructors
#define FL_DEFAULT_COPY(Class) \
@@ -150,73 +197,231 @@ namespace fl {
Class(const Class &) = delete;\
Class &operator=(const Class &) = delete;
-#else
- //C++98 defines
+#endif
- //Pointers
- const long null = 0L;
-#define FL_unique_ptr std::auto_ptr
-#define FL_move_ptr(x) x
+}
- //Identifiers
-#define FL_IOVERRIDE
-#define FL_IFINAL
-#define FL_IDEFAULT
-#define FL_IDELETE
-#define FL_INOEXCEPT throw()
- //Constructors
-#define FL_DEFAULT_COPY(Class)
-#define FL_DEFAULT_MOVE(Class)
-#define FL_DEFAULT_COPY_AND_MOVE(Class)
+namespace fl {
-#define FL_DISABLE_COPY(Class) \
- Class(const Class &);\
- Class &operator=(const Class &);
+ /**
-#endif
-}
+ The fuzzylite class contains global settings and information about the
+ library.
+ @author Juan Rada-Vilela, Ph.D.
+ @since 4.0
-namespace fl {
+ */
class FL_API fuzzylite {
- protected:
+ friend class Operation;
+ private:
static int _decimals;
static scalar _macheps;
- static bool _debug;
+ static std::ios_base::fmtflags _scalarFormat;
static bool _logging;
-
+ static bool _debugging;
public:
+ /**
+ Returns the name of the `fuzzylite` library
+ @return the name of the `fuzzylite` library
+ */
static std::string name();
- static std::string fullname();
+ /**
+ Returns the version of the `fuzzylite` library
+ @return the version of the `fuzzylite` library
+ */
static std::string version();
- static std::string longVersion();
+ /**
+ Returns the name of the `fuzzylite` library including the version
+ @return the name of the `fuzzylite` library including the version
+ */
+ static std::string library();
+
+ /**
+ Returns the license under which the `fuzzylite` library is released
+ @return the license under which the `fuzzylite` library is released
+ */
static std::string license();
- static std::string author();
- static std::string company();
- static std::string website();
- static std::string date();
- static std::string platform();
+ /**
+ Returns the name of the author of the `fuzzylite` library
+ @return "Juan Rada-Vilela, Ph.D."
+ */
+ static std::string author();
- static std::string floatingPoint();
+ /**
+ Returns the name of the company that owns the `fuzzylite` library
+ @return "FuzzyLite Limited"
+ */
+ static std::string company();
- static bool debug();
- static void setDebug(bool debug);
+ /**
+ Returns the website of the `fuzzylite` library
+ @return "http://www.fuzzylite.com/"
+ */
+ static std::string website();
+ /**
+ Returns the number of decimals utilized when formatting scalar values
+ @return the number of decimals utilized when formatting scalar values
+ (default is 3)
+ */
static int decimals();
+
+ /**
+ Sets the number of decimals utilized when formatting scalar values
+ @param decimals is the number of decimals utilized when formatting
+ scalar values
+ */
static void setDecimals(int decimals);
+ /**
+ Returns the minimum difference at which two floating-point values
+ are considered equivalent
+ @return the minimum difference at which two floating-point values
+ are considered equivalent (default is 1e-6)
+ */
static scalar macheps();
+
+ /**
+ Sets the minimum difference at which two floating-point values are
+ considered equivalent
+ @param macheps is the minimum difference at which two floating-point
+ values are considered equivalent (default is 1e-6)
+ */
static void setMachEps(scalar macheps);
- static bool logging();
+ /**
+ Sets the default format to be utilized for every fl::scalar passed to
+ Op::str()
+ @param scalarFormat is the format to be utilized for every fl::scalar
+ passed to Op::str()
+ */
+ static void setScalarFormat(std::ios_base::fmtflags scalarFormat);
+
+ /**
+ Gets the default format to be utilized for every fl::scalar passed to
+ Op::str()
+ @return the format to be utilized for every fl::scalar passed to Op::str()
+ */
+ static std::ios_base::fmtflags scalarFormat();
+
+ /**
+ Returns whether the library is logging information via the `FL_LOG`
+ macro
+ @return whether the library is logging information via the `FL_LOG`
+ macro
+ */
+ static bool isLogging();
+
+ /**
+ Sets whether the library is set to log information using the macro
+ `FL_LOG`
+ @param logging indicates whether the library is set to log
+ information via the `FL_LOG` macro
+ */
static void setLogging(bool logging);
+ /**
+ Indicates whether the library is running in debug mode
+ @return `true` if the library is running in debug mode, and `false`
+ if it is running in release mode
+ */
+ static bool isDebugging();
+
+ /**
+ Sets whether the library is set to run in debug mode
+ @param debugging indicates whether the library is set to run in debug mode
+ */
+ static void setDebugging(bool debugging);
+
+ /**
+ Returns the platform under which the `fuzzylite` library was built
+ @return `Unix` or `Windows`
+ */
+ static std::string platform();
+
+ /**
+ Returns the name of the type of the floating-point variables
+ @return `double` or `float`
+ */
+ static std::string floatingPoint();
};
}
+namespace fl {
+
+ inline std::string fuzzylite::name() {
+ return "fuzzylite";
+ }
+
+ inline std::string fuzzylite::library() {
+ return name() + " " + version();
+ }
+
+ inline std::string fuzzylite::version() {
+ return "6.0";
+ }
+
+ inline std::string fuzzylite::license() {
+ return "FuzzyLite License";
+ }
+
+ inline std::string fuzzylite::author() {
+ return "Juan Rada-Vilela, Ph.D.";
+ }
+
+ inline std::string fuzzylite::company() {
+ return "FuzzyLite Limited";
+ }
+
+ inline std::string fuzzylite::website() {
+ return "http://www.fuzzylite.com/";
+ }
+
+ inline void fuzzylite::setDebugging(bool debugging) {
+ _debugging = debugging;
+ }
+
+ inline bool fuzzylite::isDebugging() {
+ return _debugging;
+ }
+
+ inline void fuzzylite::setDecimals(int decimals) {
+ _decimals = decimals;
+ }
+
+ inline int fuzzylite::decimals() {
+ return _decimals;
+ }
+
+ inline void fuzzylite::setScalarFormat(std::ios_base::fmtflags scalarFormat) {
+ _scalarFormat = scalarFormat;
+ }
+
+ inline std::ios_base::fmtflags fuzzylite::scalarFormat() {
+ return _scalarFormat;
+ }
+
+ inline void fuzzylite::setMachEps(scalar macheps) {
+ _macheps = macheps;
+ }
+
+ inline scalar fuzzylite::macheps() {
+ return _macheps;
+ }
+
+ inline void fuzzylite::setLogging(bool logging) {
+ _logging = logging;
+ }
+
+ inline bool fuzzylite::isLogging() {
+ return _logging;
+ }
+}
+
#endif /* FL_FUZZYLITE_H */
diff --git a/fuzzylite/fl/hedge/Any.h b/fuzzylite/fl/hedge/Any.h
index c30b4c7..bf71842 100644
--- a/fuzzylite/fl/hedge/Any.h
+++ b/fuzzylite/fl/hedge/Any.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_ANY_H
@@ -28,8 +20,20 @@
#include "fl/hedge/Hedge.h"
namespace fl {
- //Only this hedge has virtual methods due to its special case use.
+ /**
+ The Any class is a special Hedge that always returns `1.0`. Its
+ position with respect to the other hedges is last in the ordered set
+ (Not, Seldom, Somewhat, Very, Extremely, Any). The Antecedent of a Rule
+ considers Any to be a syntactically special hedge because it is not
+ followed by a Term (e.g., `if Variable is any then...`). Amongst hedges,
+ only Any has virtual methods to be overriden due to its particular case.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Hedge
+ @see HedgeFactory
+ @since 4.0
+ */
class FL_API Any : public Hedge {
public:
Any();
@@ -37,11 +41,20 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Any)
virtual std::string name() const FL_IOVERRIDE;
+
+
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the hedge for the given value
+ @param x is irrelevant
+ @return `1.0`
+ */
virtual scalar hedge(scalar x) const FL_IOVERRIDE;
virtual Any* clone() const FL_IOVERRIDE;
static Hedge* constructor();
};
-
}
+
#endif /* FL_ANY_H */
diff --git a/fuzzylite/fl/hedge/Extremely.h b/fuzzylite/fl/hedge/Extremely.h
index 7ecda66..fbd617a 100644
--- a/fuzzylite/fl/hedge/Extremely.h
+++ b/fuzzylite/fl/hedge/Extremely.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_EXTREMELY_H
@@ -29,14 +21,35 @@
namespace fl {
- class FL_API Extremely : public Hedge {
+ /**
+ The Extremely class is a Hedge located fifth in the ordered set
+ (Not, Seldom, Somewhat, Very, Extremely, Any).
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Hedge
+ @see HedgeFactory
+ @since 4.0
+ */
+ class FL_API Extremely FL_IFINAL : public Hedge {
public:
- std::string name() const;
- scalar hedge(scalar x) const;
- Extremely* clone() const;
+ std::string name() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the hedge for the membership function value @f$x@f$
+ @param x is a membership function value
+ @return @f$
+ \begin{cases}
+ 2x^2 & \mbox{if $x \le 0.5$} \cr
+ 1-2(1-x)^2 & \mbox{otherwise} \cr
+ \end{cases}@f$
+ */
+ scalar hedge(scalar x) const FL_IOVERRIDE;
+ Extremely* clone() const FL_IOVERRIDE;
static Hedge* constructor();
};
-
}
+
#endif /* FL_EXTREMELY_H */
diff --git a/fuzzylite/fl/hedge/Hedge.h b/fuzzylite/fl/hedge/Hedge.h
index 011c745..9dac17c 100644
--- a/fuzzylite/fl/hedge/Hedge.h
+++ b/fuzzylite/fl/hedge/Hedge.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_HEDGE_H
@@ -27,10 +19,24 @@
#include "fl/fuzzylite.h"
+#include "fl/Complexity.h"
+
#include <string>
namespace fl {
+ /**
+ The Hedge class is the abstract class for hedges. Hedges are utilized
+ within the Antecedent and Consequent of a Rule in order to modify the
+ membership function of a linguistic Term.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Antecedent
+ @see Consequent
+ @see Rule
+ @see HedgeFactory
+ @since 4.0
+ */
class FL_API Hedge {
public:
@@ -41,8 +47,28 @@ namespace fl {
}
FL_DEFAULT_COPY_AND_MOVE(Hedge)
+ /**
+ Returns the name of the hedge
+ @return the name of the hedge
+ */
virtual std::string name() const = 0;
+
+ /**
+ Computes the estimated complexity of applying the hedge
+ @return the estimated complexity of applying the hedge
+ */
+ virtual Complexity complexity() const = 0;
+ /**
+ Computes the hedge for the membership function value @f$x@f$
+ @param x is a membership function value
+ @return the hedge of @f$x@f$
+ */
virtual scalar hedge(scalar x) const = 0;
+
+ /**
+ Creates a clone of the hedge
+ @return a clone of the hedge.
+ */
virtual Hedge* clone() const = 0;
};
diff --git a/fuzzylite/fl/hedge/HedgeFunction.h b/fuzzylite/fl/hedge/HedgeFunction.h
new file mode 100644
index 0000000..bc8930d
--- /dev/null
+++ b/fuzzylite/fl/hedge/HedgeFunction.h
@@ -0,0 +1,82 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_HEDGEFUNCTION_H
+#define FL_HEDGEFUNCTION_H
+
+#include "fl/hedge/Hedge.h"
+
+#include "fl/term/Function.h"
+
+namespace fl {
+
+ /**
+ The HedgeFunction class is a customizable Hedge via Function, which
+ computes any function based on the @f$x@f$ value. This hedge is not
+ registered with the HedgeFactory due to issues configuring the formula
+ within. To register the hedge, a static method with the
+ constructor needs to be manually created and registered. Please, check the
+ file `test/hedge/HedgeFunction.cpp` for further details.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Function
+ @see Hedge
+ @see HedgeFactory
+ @since 6.0
+ */
+
+ class FL_API HedgeFunction FL_IFINAL : public Hedge {
+ private:
+ Function _function;
+ public:
+ explicit HedgeFunction(const std::string& formula = "");
+
+ std::string name() const FL_IOVERRIDE;
+
+ /**
+ Returns the reference to the Function
+ @return the reference to the Function
+ */
+ Function& function();
+
+ /**
+ Loads the function with the given formula
+ @param formula is a valid formula in infix notation
+ */
+ void setFormula(const std::string& formula);
+ /**
+ Returns the formula loaded into the function
+ @return the formula loaded into the function
+ */
+ std::string getFormula() const;
+
+ Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the hedge for the membership function value @f$x@f$ utilizing
+ the given function via HedgeFunction::setFormula()
+ @param x is a membership function value
+ @return the evaluation of the function
+ */
+ scalar hedge(scalar x) const FL_IOVERRIDE;
+ HedgeFunction* clone() const FL_IOVERRIDE;
+
+ static Hedge* constructor();
+ };
+}
+
+#endif /* FL_HEDGEFUNCTION_H */
+
diff --git a/fuzzylite/fl/hedge/Not.h b/fuzzylite/fl/hedge/Not.h
index 161fefd..e981ac9 100644
--- a/fuzzylite/fl/hedge/Not.h
+++ b/fuzzylite/fl/hedge/Not.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_NOT_H
@@ -29,14 +21,31 @@
namespace fl {
- class FL_API Not : public Hedge {
+ /**
+ The Not class is a Hedge located first in the ordered set
+ (Not, Seldom, Somewhat, Very, Extremely, Any).
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Hedge
+ @see HedgeFactory
+ @since 4.0
+ */
+ class FL_API Not FL_IFINAL : public Hedge {
public:
std::string name() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the hedge for the membership function value @f$x@f$
+ @param x is a membership function value
+ @return @f$1-x@f$
+ */
scalar hedge(scalar x) const FL_IOVERRIDE;
Not* clone() const FL_IOVERRIDE;
static Hedge* constructor();
};
-
}
+
#endif /* FL_NOT_H */
diff --git a/fuzzylite/fl/hedge/Seldom.h b/fuzzylite/fl/hedge/Seldom.h
index a2a96c2..0bbedbf 100644
--- a/fuzzylite/fl/hedge/Seldom.h
+++ b/fuzzylite/fl/hedge/Seldom.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SELDOM_H
@@ -29,14 +21,36 @@
namespace fl {
- class FL_API Seldom : public Hedge {
+ /**
+ The Seldom class is a Hedge located second in the ordered set
+ (Not, Seldom, Somewhat, Very, Extremely, Any).
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Hedge
+ @see HedgeFactory
+ @since 4.0
+ */
+ class FL_API Seldom FL_IFINAL : public Hedge {
public:
std::string name() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the hedge for the membership function value @f$x@f$
+ @param x is a membership function value
+ @return @f$
+ \begin{cases}
+ \sqrt{0.5x} & \mbox{if $x \le 0.5$} \cr
+ 1-\sqrt{0.5(1-x)} & \mbox{otherwise}\cr
+ \end{cases}
+ @f$
+ */
scalar hedge(scalar x) const FL_IOVERRIDE;
Seldom* clone() const FL_IOVERRIDE;
static Hedge* constructor();
};
-
}
+
#endif /* FL_SELDOM_H */
diff --git a/fuzzylite/fl/hedge/Somewhat.h b/fuzzylite/fl/hedge/Somewhat.h
index 89a14a6..ccd21ec 100644
--- a/fuzzylite/fl/hedge/Somewhat.h
+++ b/fuzzylite/fl/hedge/Somewhat.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SOMEWHAT_H
@@ -29,14 +21,32 @@
namespace fl {
- class FL_API Somewhat : public Hedge {
+ /**
+ The Somewhat class is a Hedge located third in the ordered set
+ (Not, Seldom, Somewhat, Very, Extremely, Any).
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Hedge
+ @see HedgeFactory
+ @since 4.0
+ */
+ class FL_API Somewhat FL_IFINAL : public Hedge {
public:
std::string name() const FL_IOVERRIDE;
+
+
+ Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the hedge for the membership function value @f$x@f$
+ @param x is a membership function value
+ @return @f$\sqrt{x}@f$
+ */
scalar hedge(scalar x) const FL_IOVERRIDE;
Somewhat* clone() const FL_IOVERRIDE;
static Hedge* constructor();
};
-
}
+
#endif /* FL_SOMEWHAT_H */
diff --git a/fuzzylite/fl/hedge/Very.h b/fuzzylite/fl/hedge/Very.h
index bcfe5e4..b80c994 100644
--- a/fuzzylite/fl/hedge/Very.h
+++ b/fuzzylite/fl/hedge/Very.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_VERY_H
@@ -29,14 +21,30 @@
namespace fl {
- class FL_API Very : public Hedge {
+ /**
+ The Very class is a Hedge located fourth in the ordered set
+ (Not, Seldom, Somewhat, Very, Extremely, Any).
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Hedge
+ @see HedgeFactory
+ @since 4.0
+ */
+ class FL_API Very FL_IFINAL : public Hedge {
public:
std::string name() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the hedge for the membership function value @f$x@f$
+ @param x is a membership function value
+ @return @f$x^2@f$
+ */
scalar hedge(scalar x) const FL_IOVERRIDE;
Very* clone() const FL_IOVERRIDE;
static Hedge* constructor();
};
-
}
#endif /* FL_VERY_H */
diff --git a/fuzzylite/fl/imex/CppExporter.h b/fuzzylite/fl/imex/CppExporter.h
index e53cf15..1c48225 100644
--- a/fuzzylite/fl/imex/CppExporter.h
+++ b/fuzzylite/fl/imex/CppExporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_CPPEXPORTER_H
@@ -36,30 +28,129 @@ namespace fl {
class Norm;
class Defuzzifier;
class Hedge;
-
+ class Activation;
+
+ /**
+ The CppExporter class is an Exporter that translates an Engine and its
+ components to the `C++` programming language using the `fuzzylite`
+ library.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see JavaExporter
+ @see Exporter
+ @since 4.0
+ */
class FL_API CppExporter : public Exporter {
- protected:
- bool _prefixNamespace;
- virtual std::string fl(const std::string& clazz) const;
+ private:
+ bool _usingNamespace;
+ bool _usingVariableNames;
public:
- explicit CppExporter(bool prefixNamespace = false);
+ explicit CppExporter(bool usingNamespace = false, bool usingVariableNames = true);
virtual ~CppExporter() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(CppExporter)
virtual std::string name() const FL_IOVERRIDE;
virtual std::string toString(const Engine* engine) const FL_IOVERRIDE;
- virtual void setPrefixNamespace(bool prefixNamespace);
- virtual bool isPrefixNamespace() const;
-
+ /**
+ Sets whether the fl namespace of the library is prepended to types
+ (e.g., fl::Engine)
+
+ @param usingNamespace whether the fl namespace of the library is
+ prepended to types (e.g., fl::Engine)
+ */
+ virtual void setUsingNamespace(bool usingNamespace);
+ /**
+ Gets whether the fl namespace of the library is prepended to types
+ (e.g., fl::Engine)
+ @return whether the fl namespace of the library is prepended to types
+ */
+ virtual bool isUsingNamespace() const;
+
+ /**
+ Returns the given text prepended with the `fl` namespace if
+ CppExporter::isUsingNamespace is `true`, or the text otherwise
+
+ @param clazz is the text to be prepended the `fl::`.
+ @return the given text prepended with the `fl` namespace if
+ CppExporter::isUsingNamespace is `true`, or the text otherwise
+ */
+ virtual std::string fl(const std::string& clazz) const;
+ /**
+ Sets whether variables are exported using their names
+ (e.g., `power->setValue(fl::nan)`) instead of numbered identifiers
+ (e.g., `inputVariable1->setValue(fl::nan)`)
+ @param usingVariableNames indicates whether variables are exported using
+ their names
+ */
+ virtual void setUsingVariableNames(bool usingVariableNames);
+ /**
+ Gets whether variables are exported using their names
+ (e.g., `power->setValue(fl::nan)`) instead of numbered identifiers
+ (e.g., `inputVariable1->setValue(fl::nan)`)
+ @return whether variables are exported using their names
+ */
+ virtual bool isUsingVariableNames() const;
+
+ /**
+ Returns a string representation of InputVariable in the `C++` programming language
+ @param inputVariable is the input variable
+ @param engine is the engine in which the input variable is registered
+ @return a string representation of the input variable in the `C++` programming language
+ */
virtual std::string toString(const InputVariable* inputVariable, const Engine* engine) const;
+ /**
+ Returns a string representation of the OutputVariable in the `C++` programming language
+ @param outputVariable is the output variable
+ @param engine is the engine in which the output variable is registered
+ @return a string representation of the output variable in the `C++` programming language
+ */
virtual std::string toString(const OutputVariable* outputVariable, const Engine* engine) const;
+ /**
+ Returns a string representation of the RuleBlock in the `C++` programming language
+ @param ruleBlock is the rule block
+ @param engine is the engine in which the rule block is registered
+ @return a string representation of the rule block in the `C++` programming language
+ */
virtual std::string toString(const RuleBlock* ruleBlock, const Engine* engine) const;
+
+ /**
+ Returns a string representation of the Activation method in the `C++` programming language
+ @param activation is the activation method
+ @return a string representation of the activation method in the `C++` programming language
+ */
+ virtual std::string toString(const Activation* activation) const;
+
+ /**
+ Returns a string representation of the scalar value in the `C++` programming language
+ @param value is the scalar value
+ @return a string representation of the scalar value in the `C++` programming language
+ */
virtual std::string toString(scalar value) const;
+ /**
+ Returns a string representation of the Hedge in the `C++` programming language
+ @param hedge is the hedge
+ @return a string representation of the hedge in the `C++` programming language
+ */
virtual std::string toString(const Hedge* hedge) const;
+ /**
+ Returns a string representation of the Term in the `C++` programming language
+ @param term is the term
+ @return a string representation of the term in the `C++` programming language
+ */
virtual std::string toString(const Term* term) const;
- virtual std::string toString(const Norm* op) const;
+ /**
+ Returns a string representation of the Norm in the `C++` programming language
+ @param norm is the norm
+ @return a string representation of the norm in the `C++` programming language
+ */
+ virtual std::string toString(const Norm* norm) const;
+ /**
+ Returns a string representation of the Defuzzifier in the `C++` programming language
+ @param defuzzifier is the defuzzifier
+ @return a string representation of the defuzzifier in the `C++` programming language
+ */
virtual std::string toString(const Defuzzifier* defuzzifier) const;
virtual CppExporter* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/imex/Exporter.h b/fuzzylite/fl/imex/Exporter.h
index 8b55c21..b883edf 100644
--- a/fuzzylite/fl/imex/Exporter.h
+++ b/fuzzylite/fl/imex/Exporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_EXPORTER_H
@@ -32,6 +24,16 @@
namespace fl {
class Engine;
+ /**
+ The Exporter class is the abstract class for exporters to translate an
+ Engine into different formats.
+
+ @todo declare methods for exporting other components (e.g., Variable)
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Importer
+ @since 4.0
+ */
class FL_API Exporter {
public:
@@ -39,10 +41,30 @@ namespace fl {
virtual ~Exporter();
FL_DEFAULT_COPY_AND_MOVE(Exporter)
+ /**
+ Returns a string representation of the engine
+ @param engine is the engine to export
+ @return a string representation of the engine
+ */
virtual std::string toString(const Engine* engine) const = 0;
+ /**
+ Stores the string representation of the engine into the specified file
+ @param path is the full path of the file to export the engine to
+ @param engine is the engine to export
+ @throws fl::Exception if the file cannot be created
+ */
virtual void toFile(const std::string& path, const Engine* engine) const;
+ /**
+ Returns the name of the exporter
+ @return the name of the exporter
+ */
virtual std::string name() const = 0;
+
+ /**
+ Creates a clone of the exporter
+ @return a clone of the exporter
+ */
virtual Exporter* clone() const = 0;
};
diff --git a/fuzzylite/fl/imex/FclExporter.h b/fuzzylite/fl/imex/FclExporter.h
index 9bfa3ed..efec3c4 100644
--- a/fuzzylite/fl/imex/FclExporter.h
+++ b/fuzzylite/fl/imex/FclExporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FCLEXPORTER_H
@@ -37,8 +29,17 @@ namespace fl {
class Defuzzifier;
class Term;
+ /**
+ The FclExporter class is an Exporter that translates an Engine and its
+ components to the Fuzzy Control Language specification.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FclImporter
+ @see Exporter
+ @since 4.0
+ */
class FL_API FclExporter : public Exporter {
- protected:
+ private:
std::string _indent;
public:
@@ -46,25 +47,59 @@ namespace fl {
virtual ~FclExporter() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(FclExporter)
+ /**
+ Sets the indentation string within blocks
+ @param indent is the indentation string within blocks
+ */
virtual void setIndent(const std::string& indent);
+ /**
+ Gets the indentation string within blocks
+ @return the indentation string within blocks
+ */
virtual std::string getIndent() const;
virtual std::string name() const FL_IOVERRIDE;
virtual std::string toString(const Engine* engine) const FL_IOVERRIDE;
-
+
+ /**
+ Returns a string representation of the InputVariable according to the Fuzzy Control Language specification
+ @param variable is the input variable
+ @return a string representation of the input variable according to the Fuzzy Control Language specification
+ */
virtual std::string toString(const InputVariable* variable) const;
+ /**
+ Returns a string representation of the OutputVariable according to the Fuzzy Control Language specification
+ @param variable is the output variable
+ @return a string representation of the output variable according to the Fuzzy Control Language specification
+ */
virtual std::string toString(const OutputVariable* variable) const;
+ /**
+ Returns a string representation of the RuleBlock according to the Fuzzy Control Language specification
+ @param ruleBlock is the rule block
+ @return a string representation of the rule block according to the Fuzzy Control Language specification
+ */
virtual std::string toString(const RuleBlock* ruleBlock) const;
-
+ /**
+ Returns a string representation of the Norm according to the Fuzzy Control Language specification
+ @param norm is the norm
+ @return a string representation of the norm according to the Fuzzy Control Language specification
+ */
virtual std::string toString(const Norm* norm) const;
-
- virtual std::string toString(const TNorm* tnorm) const; //TODO: Delete in v6.0
- virtual std::string toString(const SNorm* snorm) const; //TODO: Delete in v6.0
+ /**
+ Returns a string representation of the Defuzzifier according to the Fuzzy Control Language specification
+ @param defuzzifier is the defuzzifier
+ @return a string representation of the defuzzifier according to the Fuzzy Control Language specification
+ */
virtual std::string toString(const Defuzzifier* defuzzifier) const;
+ /**
+ Returns a string representation of the Term according to the Fuzzy Control Language specification
+ @param term is the term
+ @return a string representation of the term according to the Fuzzy Control Language specification
+ */
virtual std::string toString(const Term* term) const;
virtual FclExporter* clone() const FL_IOVERRIDE;
};
-
}
+
#endif /* FL_FCLEXPORTER_H */
diff --git a/fuzzylite/fl/imex/FclImporter.h b/fuzzylite/fl/imex/FclImporter.h
index b219717..2e75432 100644
--- a/fuzzylite/fl/imex/FclImporter.h
+++ b/fuzzylite/fl/imex/FclImporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FCLIMPORTER_H
@@ -39,6 +31,15 @@ namespace fl {
class Term;
class Defuzzifier;
+ /**
+ The FclImporter class is an Importer that configures an Engine and its
+ components utilizing the Fuzzy Control Language specification.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FclExporter
+ @see Importer
+ @since 4.0
+ */
class FL_API FclImporter : public Importer {
public:
FclImporter();
@@ -69,6 +70,5 @@ namespace fl {
virtual bool parseEnabled(const std::string& line) const;
};
-
}
#endif /* FL_FCLIMPORTER_H */
diff --git a/fuzzylite/fl/imex/FisExporter.h b/fuzzylite/fl/imex/FisExporter.h
index 05d6a22..a7f5d8c 100644
--- a/fuzzylite/fl/imex/FisExporter.h
+++ b/fuzzylite/fl/imex/FisExporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FISEXPORTER_H
@@ -39,6 +31,15 @@ namespace fl {
class Proposition;
class Variable;
+ /**
+ The FisExporter class is an Exporter that translates an Engine and its
+ components into the Fuzzy Inference System format for Matlab or Octave.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FisImporter
+ @see Exporter
+ @since 4.0
+ */
class FL_API FisExporter : public Exporter {
protected:
@@ -52,22 +53,68 @@ namespace fl {
virtual std::string name() const FL_IOVERRIDE;
virtual std::string toString(const Engine* engine) const FL_IOVERRIDE;
-
- virtual std::string toString(const Norm* norm) const;
- virtual std::string toString(const TNorm* tnorm) const; //TODO: delete in v6.0
- virtual std::string toString(const SNorm* snorm) const; //TODO: delete in v6.0
+
+ /**
+ Returns a string representation of the TNorm in the Fuzzy Inference System format
+ @param tnorm is the TNorm
+ @return a string representation of the TNorm in the Fuzzy Inference System format
+ */
+ virtual std::string toString(const TNorm* tnorm) const;
+
+ /**
+ Returns a string representation of the SNorm in the Fuzzy Inference System format
+ @param snorm is the SNorm
+ @return a string representation of the SNorm in the Fuzzy Inference System format
+ */
+ virtual std::string toString(const SNorm* snorm) const;
+
+ /**
+ Returns a string representation of the Defuzzifier in the Fuzzy Inference System format
+ @param defuzzifier is the defuzzifier
+ @return a string representation of the Defuzzifier in the Fuzzy Inference System format
+ */
virtual std::string toString(const Defuzzifier* defuzzifier) const;
+ /**
+ Returns a string representation of the Term in the Fuzzy Inference System format
+ @param term is the term
+ @return a string representation of the term in the Fuzzy Inference System format
+ */
virtual std::string toString(const Term* term) const;
+ /**
+ Returns a string representation of the `[System]` configuration
+ @param engine is the engine
+ @return a string representation of the `[System]` configuration
+ */
virtual std::string exportSystem(const Engine* engine) const;
+ /**
+ Returns a string representation of the `[Input]` configuration
+ @param engine is the engine
+ @return a string representation of the `[Input]` configuration
+ */
virtual std::string exportInputs(const Engine* engine) const;
+ /**
+ Returns a string representation of the `[Output]` configuration
+ @param engine is the engine
+ @return a string representation of the `[Output]` configuration
+ */
virtual std::string exportOutputs(const Engine* engine) const;
+ /**
+ Returns a string representation of the `[Rules]` configuration
+ @param engine is the engine
+ @return a string representation of the `[Rules]` configuration
+ */
virtual std::string exportRules(const Engine* engine) const;
+ /**
+ Returns a string representation for the Rule in the Fuzzy Inference System format
+ @param rule is the rule
+ @param engine is the engine in which the rule is registered
+ @return a string representation for the rule in the Fuzzy Inference System format
+ */
virtual std::string exportRule(const Rule* rule, const Engine* engine) const;
virtual FisExporter* clone() const FL_IOVERRIDE;
};
-
}
#endif /* FL_FISEXPORTER_H */
diff --git a/fuzzylite/fl/imex/FisImporter.h b/fuzzylite/fl/imex/FisImporter.h
index b631a48..2c9ce36 100644
--- a/fuzzylite/fl/imex/FisImporter.h
+++ b/fuzzylite/fl/imex/FisImporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FISIMPORTER_H
@@ -39,6 +31,16 @@ namespace fl {
class Defuzzifier;
class Variable;
+ /**
+ The FisImporter class is an Importer that configures an Engine and its
+ components from utilizing the Fuzzy Inference System format for Matlab or
+ Octave.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FisExporter
+ @see Importer
+ @since 4.0
+ */
class FL_API FisImporter : public Importer {
public:
FisImporter();
@@ -60,20 +62,19 @@ namespace fl {
virtual void importOutput(const std::string& section, Engine* engine) const;
virtual void importRules(const std::string& section, Engine* engine) const;
virtual std::string translateProposition(scalar code, Variable* variable) const;
-
- //TODO: rename extract to translate in v6.0
- virtual std::string extractTNorm(const std::string& tnorm) const;
- virtual std::string extractSNorm(const std::string& tnorm) const;
- virtual std::string extractDefuzzifier(const std::string& defuzzifier) const;
+
+ virtual std::string translateTNorm(const std::string& tnorm) const;
+ virtual std::string translateSNorm(const std::string& tnorm) const;
+ virtual std::string translateDefuzzifier(const std::string& defuzzifier) const;
virtual Term* parseTerm(const std::string& line, const Engine* engine) const;
virtual Term* createInstance(const std::string& termClass, const std::string& name,
const std::vector<std::string>& params, const Engine* engine) const;
- //TODO: rename to parseRange in v6.0
- virtual std::pair<scalar, scalar> range(const std::string& range) const;
- };
+ virtual std::pair<scalar, scalar> parseRange(const std::string& range) const;
+ };
}
+
#endif /* FL_FISIMPORTER_H */
diff --git a/fuzzylite/fl/imex/FldExporter.h b/fuzzylite/fl/imex/FldExporter.h
index 71679a6..98a14c9 100644
--- a/fuzzylite/fl/imex/FldExporter.h
+++ b/fuzzylite/fl/imex/FldExporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FLDEXPORTER_H
@@ -34,47 +26,219 @@ namespace fl {
class InputVariable;
class OutputVariable;
+ /**
+ The FldExporter class is an Exporter that evaluates an Engine and exports
+ its input values and output values to the FuzzyLite Dataset (FLD) format,
+ see [http://www.fuzzylite.com/fll-fld](http://www.fuzzylite.com/fll-fld)
+ for more information.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FllExporter
+ @see Exporter
+ @since 4.0
+ */
class FL_API FldExporter : public Exporter {
- protected:
+ private:
std::string _separator;
bool _exportHeaders;
bool _exportInputValues;
bool _exportOutputValues;
public:
+
+ /**
+ The ScopeOfValues refers to the scope of the equally-distributed values
+ to generate.
+ */
+ enum ScopeOfValues {
+ /**Generates @f$n@f$ values for each variable*/
+ EachVariable,
+ /**Generates @f$n@f$ values for all variables*/
+ AllVariables
+ };
explicit FldExporter(const std::string& separator = " ");
virtual ~FldExporter() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(FldExporter)
virtual std::string name() const FL_IOVERRIDE;
+ /**
+ Sets the separator of the dataset columns
+ @param separator is the separator of the dataset columns
+ */
virtual void setSeparator(const std::string& separator);
+ /**
+ Gets the separator of the dataset columns
+ @return the separator of the dataset columns
+ */
virtual std::string getSeparator() const;
+ /**
+ Sets whether the header of the dataset is to be exported
+ @param exportHeaders indicates whether the header of the dataset is
+ to be exported
+ */
virtual void setExportHeader(bool exportHeaders);
+ /**
+ Gets whether the header of the dataset is to be exported
+ @return whether the header of the dataset is to be exported
+ */
virtual bool exportsHeader() const;
+ /**
+ Sets whether the values of the input variables are to be exported
+ @param exportInputValues indicates whether the values of the input
+ variables are to be exported
+ */
virtual void setExportInputValues(bool exportInputValues);
+ /**
+ Gets whether the values of the input variables are to be exported
+ @return whether the values of the input variables are to be exported
+ */
virtual bool exportsInputValues() const;
+ /**
+ Sets whether the values of the output variables are to be exported
+ @param exportOutputValues indicates whether the values of the output
+ variables are to be exported
+ */
virtual void setExportOutputValues(bool exportOutputValues);
+ /**
+ Gets whether the values of the output variables are to be exported
+ @return whether the values of the output variables are to be exported
+ */
virtual bool exportsOutputValues() const;
+ /**
+ Gets the header of the dataset for the given engine
+ @param engine is the engine to be exported
+ @return the header of the dataset for the given engine
+ */
virtual std::string header(const Engine* engine) const;
- //WARNING: The engine will be const_casted in order to be processed!
+ /**
+ Returns a FuzzyLite Dataset from the engine. Please consider that the
+ engine will be `const_cast`ed to achieve so; that is, despite being
+ marked as `const`, the engine will be modified in order to compute
+ the output values based on the input values.
+ @param engine is the engine to export
+ @return a FuzzyLite Dataset from the engine
+ */
virtual std::string toString(const Engine* engine) const FL_IOVERRIDE;
- virtual std::string toString(Engine* engine, int maximumNumberOfResults) const;
- virtual std::string toString(Engine* engine, const std::string& inputData) const;
+ /**
+ Returns a FuzzyLite Dataset from the engine.
+ @param engine is the engine to export
+ @param values is the number of values to export
+ @param scope indicates the scope of the values
+ @return a FuzzyLite Dataset from the engine
+ */
+ virtual std::string toString(Engine* engine, int values, ScopeOfValues scope = AllVariables) const;
+
+ /**
+ Returns a FuzzyLite Dataset from the engine.
+ @param engine is the engine to export
+ @param values is the number of values to export
+ @param scope indicates the scope of the values
+ @param activeVariables contains the input variables to generate values for.
+ The input variables must be in the same order as in the engine. A value of
+ fl::null indicates the variable is not active.
+ @return a FuzzyLite Dataset from the engine
+ */
+ virtual std::string toString(Engine* engine, int values, ScopeOfValues scope,
+ const std::vector<InputVariable*>& activeVariables) const;
+ /**
+ Returns a FuzzyLite Dataset from the engine.
+ @param engine is the engine to export
+ @param reader is the reader of a set of lines containing space-separated
+ input values
+ @return a FuzzyLite Dataset from the engine
+ */
+ virtual std::string toString(Engine* engine, std::istream& reader) const;
- using Exporter::toFile;
- virtual void toFile(const std::string& path, Engine* engine, int maximumNumberOfResults) const;
- virtual void toFile(const std::string& path, Engine* engine, const std::string& inputData) const;
-
- virtual std::vector<scalar> parse(const std::string& x) const;
- void write(Engine* engine, std::ostream& writer, int maximumNumberOfResults) const;
- void write(Engine* engine, std::ostream& writer, std::istream& reader) const;
- void write(Engine* engine, std::ostream& writer, const std::vector<scalar>& inputValues) const;
+ using Exporter::toFile;
+ /**
+ Saves the engine as a FuzzyLite Dataset into the specified file
+ @param path is the full path of the file
+ @param engine is the engine to export
+ @param values is the number of values to export
+ @param scope indicates the scope of the values
+ */
+ virtual void toFile(const std::string& path, Engine* engine,
+ int values, ScopeOfValues scope = AllVariables) const;
+ /**
+ Saves the engine as a FuzzyLite Dataset into the specified file
+ @param path is the full path of the file
+ @param engine is the engine to export
+ @param values is the number of values to export
+ @param scope indicates the scope of the values
+ @param activeVariables contains the input variables to generate values for.
+ The input variables must be in the same order as in the engine. A value of
+ fl::null indicates the variable is not active.
+ */
+ virtual void toFile(const std::string& path, Engine* engine,
+ int values, ScopeOfValues scope,
+ const std::vector<InputVariable*>& activeVariables) const;
+ /**
+ Saves the engine as a FuzzyLite Dataset into the specified file
+ @param path is the full path of the file
+ @param engine is the engine to export
+ @param reader is the reader of a set of lines containing space-separated input values
+ */
+ virtual void toFile(const std::string& path, Engine* engine, std::istream& reader) const;
+
+ /**
+ Parses the string into a vector of values unless the string starts with `#`
+ @param values is a space-separated set of values
+ @return a vector of values
+ */
+ virtual std::vector<scalar> parse(const std::string& values) const;
+
+ /**
+ Writes the engine into the given writer
+ @param engine is the engine to export
+ @param writer is the output where the engine will be written to
+ @param values is the number of values to export
+ @param scope indicates the scope of the values
+ */
+ virtual void write(Engine* engine, std::ostream& writer, int values,
+ ScopeOfValues scope = AllVariables) const;
+ /**
+ Writes the engine into the given writer
+ @param engine is the engine to export
+ @param writer is the output where the engine will be written to
+ @param values is the number of values to export
+ @param scope indicates the scope of the values
+ @param activeVariables contains the input variables to generate values for.
+ The input variables must be in the same order as in the engine. A value of
+ fl::null indicates the variable is not active.
+ */
+ virtual void write(Engine* engine, std::ostream& writer, int values, ScopeOfValues scope,
+ const std::vector<InputVariable*>& activeVariables) const;
+ /**
+ Writes the engine into the given writer
+ @param engine is the engine to export
+ @param writer is the output where the engine will be written to
+ @param reader is the reader of a set of lines containing space-separated input values
+ */
+ virtual void write(Engine* engine, std::ostream& writer, std::istream& reader) const;
+ /**
+ Writes the engine into the given writer
+ @param engine is the engine to export
+ @param writer is the output where the engine will be written to
+ @param inputValues is the vector of input values
+ */
+ virtual void write(Engine* engine, std::ostream& writer, const std::vector<scalar>& inputValues) const;
+ /**
+ Writes the engine into the given writer
+ @param engine is the engine to export
+ @param writer is the output where the engine will be written to
+ @param inputValues is the vector of input values
+ @param activeVariables contains the input variables to generate values for.
+ The input variables must be in the same order as in the engine. A value of
+ fl::null indicates the variable is not active.
+ */
+ virtual void write(Engine* engine, std::ostream& writer, const std::vector<scalar>& inputValues,
+ const std::vector<InputVariable*>& activeVariables) const;
virtual FldExporter* clone() const FL_IOVERRIDE;
};
diff --git a/fuzzylite/fl/imex/FllExporter.h b/fuzzylite/fl/imex/FllExporter.h
index e6a89f5..5a222e4 100644
--- a/fuzzylite/fl/imex/FllExporter.h
+++ b/fuzzylite/fl/imex/FllExporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FLLEXPORTER_H
@@ -36,11 +28,23 @@ namespace fl {
class RuleBlock;
class Rule;
class Norm;
+ class Activation;
class Defuzzifier;
class Term;
+ /**
+ The FllExporter class is an Exporter that translates an Engine and its
+ components to the FuzzyLite Language (FLL), see
+ [http://www.fuzzylite.com/fll-fld](http://www.fuzzylite.com/fll-fld) for
+ more information.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FllImporter
+ @see Exporter
+ @since 4.0
+ */
class FL_API FllExporter : public Exporter {
- protected:
+ private:
std::string _indent;
std::string _separator;
public:
@@ -50,33 +54,114 @@ namespace fl {
virtual std::string name() const FL_IOVERRIDE;
+ /**
+ Sets the indent string of the FuzzyLite Language
+ @param indent is the indent string of the FuzzyLite Language
+ */
virtual void setIndent(const std::string& indent);
+ /**
+ Gets the indent string of the FuzzyLite Language
+ @return the indent string of the FuzzyLite Language
+ */
virtual std::string getIndent() const;
+ /**
+ Gets the separator of the FuzzyLite Language
+ @param separator of the FuzzyLite Language
+ */
virtual void setSeparator(const std::string& separator);
+ /**
+ Gets the separator of the FuzzyLite Language
+ @return the separator of the FuzzyLite Language
+ */
virtual std::string getSeparator() const;
virtual std::string toString(const Engine* engine) const FL_IOVERRIDE;
+ /**
+ Returns a string representation of the vector of variables in the FuzzyLite Language
+ @param variables is the vector of variables
+ @return a string representation of the vector of variables in the FuzzyLite Language
+ */
virtual std::string toString(const std::vector<Variable*>& variables) const;
+ /**
+ Returns a string representation of the vector of input variables in the FuzzyLite Language
+ @param inputVariables is the vector of input variables
+ @return a string representation of the vector of input variables in the FuzzyLite Language
+ */
virtual std::string toString(const std::vector<InputVariable*>& inputVariables) const;
+ /**
+ Returns a string representation of the vector of output variables in the FuzzyLite Language
+ @param outputVariables is a vector of output variables
+ @return a string representation of the vector of output variables in the FuzzyLite Language
+ */
virtual std::string toString(const std::vector<OutputVariable*>& outputVariables) const;
+ /**
+ Returns a string representation of the vector of rule blocks in the FuzzyLite Language
+ @param ruleBlocks is the vector of rule blocks
+ @return a string representation of the vector of rule blocks in the FuzzyLite Language
+ */
virtual std::string toString(const std::vector<RuleBlock*>& ruleBlocks) const;
+ /**
+ Returns a string representation of the Variable in the FuzzyLite Language
+ @param variable is the variable
+ @return a string representation of the variable in the FuzzyLite Language
+ */
virtual std::string toString(const Variable* variable) const;
+ /**
+ Returns a string representation of the InputVariable in the FuzzyLite Language
+ @param inputVariable is the input variable to export
+ @return a string representation of the input variable in the FuzzyLite Language
+ */
virtual std::string toString(const InputVariable* inputVariable) const;
+ /**
+ Returns a string representation of the OutputVariable in the FuzzyLite Language
+ @param outputVariable is the output variable
+ @return a string representation of the output variable in the FuzzyLite Language
+ */
virtual std::string toString(const OutputVariable* outputVariable) const;
+ /**
+ Returns a string representation of the RuleBlock in the FuzzyLite Language
+ @param ruleBlock is the rule block
+ @return a string representation of the rule block in the FuzzyLite Language
+ */
virtual std::string toString(const RuleBlock* ruleBlock) const;
+ /**
+ Returns a string representation of the Rule in the FuzzyLite Language
+ @param rule is the rule
+ @return a string representation of the rule in the FuzzyLite Language
+ */
virtual std::string toString(const Rule* rule) const;
+ /**
+ Returns a string representation of the Norm in the FuzzyLite Language
+ @param norm is the norm
+ @return a string representation of the norm in the FuzzyLite Language
+ */
virtual std::string toString(const Norm* norm) const;
+ /**
+ Returns a string representation of the Activation method in the FuzzyLite Language
+ @param activation is the activation method
+ @return a string representation of the activation method in the FuzzyLite Language
+ */
+ virtual std::string toString(const Activation* activation) const;
+ /**
+ Returns a string representation of the Defuzzifier in the FuzzyLite Language
+ @param defuzzifier is the defuzzifier
+ @return a string representation of the defuzzifier in the FuzzyLite Language
+ */
virtual std::string toString(const Defuzzifier* defuzzifier) const;
+ /**
+ Returns a string representation of the Term in the FuzzyLite Language
+ @param term is the term
+ @return a string representation of the term in the FuzzyLite Language
+ */
virtual std::string toString(const Term* term) const;
virtual FllExporter* clone() const FL_IOVERRIDE;
};
-
}
#endif /* FL_FLLEXPORTER_H */
diff --git a/fuzzylite/fl/imex/FllImporter.h b/fuzzylite/fl/imex/FllImporter.h
index 5be41c7..055bb88 100644
--- a/fuzzylite/fl/imex/FllImporter.h
+++ b/fuzzylite/fl/imex/FllImporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FLLIMPORTER_H
@@ -32,18 +24,39 @@
namespace fl {
class TNorm;
class SNorm;
+ class Activation;
class Term;
class Defuzzifier;
+ /**
+ The FllImporter class is an Importer that configures an Engine and its
+ components utilizing the FuzzyLite Language (FLL), see
+ [http://www.fuzzylite.com/fll-fld](http://www.fuzzylite.com/fll-fld) for
+ more information.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FllExporter
+ @see Importer
+ @since 4.0
+ @todo parse methods returning respective instances from blocks of text
+ */
class FL_API FllImporter : public Importer {
- protected:
+ private:
std::string _separator;
public:
explicit FllImporter(const std::string& separator = "\n");
virtual ~FllImporter() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(FllImporter)
+ /**
+ Sets the separator of the language (default separator is a new line '\n')
+ @param separator is the separator of the language
+ */
virtual void setSeparator(const std::string& separator);
+ /**
+ Gets the separator of the language (default separator is a new line '\n')
+ @return the separator of the language
+ */
virtual std::string getSeparator() const;
virtual std::string name() const FL_IOVERRIDE;
@@ -52,6 +65,7 @@ namespace fl {
virtual FllImporter* clone() const FL_IOVERRIDE;
protected:
+
virtual void process(const std::string& tag, const std::string& block, Engine* engine) const;
virtual void processInputVariable(const std::string& block, Engine* engine) const;
virtual void processOutputVariable(const std::string& block, Engine* engine) const;
@@ -59,6 +73,7 @@ namespace fl {
virtual TNorm* parseTNorm(const std::string& name) const;
virtual SNorm* parseSNorm(const std::string& name) const;
+ virtual Activation* parseActivation(const std::string& name) const;
virtual Term* parseTerm(const std::string& text, Engine* engine) const;
@@ -68,7 +83,6 @@ namespace fl {
virtual std::pair<std::string, std::string> parseKeyValue(const std::string& text,
char separator = ':') const;
- virtual std::string clean(const std::string& line) const;
};
}
diff --git a/fuzzylite/fl/imex/Importer.h b/fuzzylite/fl/imex/Importer.h
index 28d2b36..1250e66 100644
--- a/fuzzylite/fl/imex/Importer.h
+++ b/fuzzylite/fl/imex/Importer.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_IMPORTER_H
@@ -32,6 +24,16 @@
namespace fl {
class Engine;
+ /**
+ The Importer class is the abstract class for importers to configure an
+ Engine and its components from different text formats.
+
+ @todo declare methods to import specific components
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Exporter
+ @since 4.0
+ */
class FL_API Importer {
public:
@@ -39,13 +41,30 @@ namespace fl {
virtual ~Importer();
FL_DEFAULT_COPY_AND_MOVE(Importer)
- virtual Engine* fromString(const std::string& s) const = 0;
+ /**
+ Imports the engine from the given text
+ @param text is the string representation of the engine to import from
+ @return the engine represented by the text
+ */
+ virtual Engine* fromString(const std::string& text) const = 0;
+ /**
+ Imports the engine from the given file
+ @param path is the full path of the file containing the engine to import from
+ @return the engine represented by the file
+ */
virtual Engine* fromFile(const std::string& path) const;
+ /**
+ Returns the name of the importer
+ @return the name of the importer
+ */
virtual std::string name() const = 0;
+ /**
+ Creates a clone of the importer
+ @return a clone of the importer
+ */
virtual Importer* clone() const = 0;
};
-
}
#endif /* IMPORTER_H */
diff --git a/fuzzylite/fl/imex/JavaExporter.h b/fuzzylite/fl/imex/JavaExporter.h
index e882d4a..a1817f6 100644
--- a/fuzzylite/fl/imex/JavaExporter.h
+++ b/fuzzylite/fl/imex/JavaExporter.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_JAVAEXPORTER_H
@@ -38,30 +30,122 @@ namespace fl {
class Norm;
class SNorm;
class TNorm;
-
+ class Activation;
+
+ /**
+ The JavaExporter class is an Exporter that translates an Engine and its
+ components to the `Java` programming language using the `jfuzzylite`
+ library.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see CppExporter
+ @see Exporter
+ @since 4.0
+ */
class FL_API JavaExporter : public Exporter {
+ private:
+ bool _usingVariableNames;
public:
- JavaExporter();
+ explicit JavaExporter(bool usingVariableNames = true);
virtual ~JavaExporter() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(JavaExporter)
virtual std::string name() const FL_IOVERRIDE;
+ /**
+ Sets whether variables are exported using their names
+ (e.g., `power.setValue(Double.NaN)`) instead of numbered identifiers
+ (e.g., `inputVariable1.setValue(Double.NaN)`)
+ @param usingVariableNames indicates whether variables are exported using
+ their names
+ */
+ virtual void setUsingVariableNames(bool usingVariableNames);
+
+ /**
+ Gets whether variables are exported using their names
+ (e.g., `power.setValue(Double.NaN)`) instead of numbered identifiers
+ (e.g., `inputVariable1.setValue(Double.NaN)`)
+ @return whether variables are exported using their names
+ */
+ virtual bool isUsingVariableNames() const;
+
virtual std::string toString(const Engine* engine) const FL_IOVERRIDE;
+ /**
+ Returns a string representation of the InputVariable in the Java
+ programming language
+ @param inputVariable is the input variable
+ @param engine is the engine in which the input variable is registered
+ @return a string representation of the input variable in the Java
+ programming language
+ */
virtual std::string toString(const InputVariable* inputVariable, const Engine* engine) const;
+ /**
+ Returns a string representation of the OutputVariable in the Java
+ programming language
+ @param outputVariable is the output variable
+ @param engine is the engine in which the output variable is registered
+ @return a string representation of the output variable in the Java
+ programming language
+ */
virtual std::string toString(const OutputVariable* outputVariable, const Engine* engine) const;
+ /**
+ Returns a string representation of the RuleBlock in the Java
+ programming language
+ @param ruleBlock is the rule block
+ @param engine is the engine in which the rule block is registered
+ @return a string representation of the rule block in the Java
+ programming language
+ */
virtual std::string toString(const RuleBlock* ruleBlock, const Engine* engine) const;
+
+ /**
+ Returns a string representation of the Term in the Java programming
+ language
+ @param term is the term
+ @return a string representation of the term in the Java programming
+ language
+ */
virtual std::string toString(const Term* term) const;
+
+ /**
+ Returns a string representation of the Activation method in the Java
+ programming language
+ @param activation is the activation method
+ @return a string representation of the activation method in the Java
+ programming language
+ */
+ virtual std::string toString(const Activation* activation) const;
+
+ /**
+ Returns a string representation of the Defuzzifier in the Java
+ programming language
+ @param defuzzifier is the defuzzifier
+ @return a string representation of the defuzzifier in the Java
+ programming language
+ */
virtual std::string toString(const Defuzzifier* defuzzifier) const;
+
+ /**
+ Returns a string representation of the Norm in the Java programming
+ language
+ @param norm is the norm
+ @return a string representation of the norm in the Java programming
+ language
+ */
virtual std::string toString(const Norm* norm) const;
- virtual std::string toString(const SNorm* norm) const;//TODO: delete in v6.0
- virtual std::string toString(const TNorm* norm) const;//TODO: delete in v6.0
+
+ /**
+ Returns a string representation of the scalar value in the Java
+ programming language
+ @param value is the scalar value
+ @return a string representation of the scalar value in the Java
+ programming language
+ */
virtual std::string toString(scalar value) const;
virtual JavaExporter* clone() const FL_IOVERRIDE;
};
-
}
#endif /* FL_JAVAEXPORTER_H */
diff --git a/fuzzylite/fl/imex/RScriptExporter.h b/fuzzylite/fl/imex/RScriptExporter.h
new file mode 100644
index 0000000..c53c751
--- /dev/null
+++ b/fuzzylite/fl/imex/RScriptExporter.h
@@ -0,0 +1,246 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_RSCRIPTEXPORTER_H
+#define FL_RSCRIPTEXPORTER_H
+
+#include "fl/imex/Exporter.h"
+#include "fl/imex/FldExporter.h"
+
+#include <vector>
+
+namespace fl {
+ class Engine;
+ class InputVariable;
+ class OutputVariable;
+
+ /**
+ The RScriptExporter class is an Exporter that creates an R script to plot one or
+ more surfaces of an engine for two input variables and any number of output
+ variables.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see FldExporter
+ @see Exporter
+ @since 6.0
+ */
+ class FL_API RScriptExporter : public Exporter {
+ private:
+ std::string _minimumColor;
+ std::string _maximumColor;
+ std::string _contourColor;
+
+ public:
+ RScriptExporter();
+ virtual ~RScriptExporter() FL_IOVERRIDE;
+ FL_DEFAULT_COPY_AND_MOVE(RScriptExporter)
+
+ virtual std::string name() const FL_IOVERRIDE;
+
+ /**
+ Sets the color to represent the minimum values.
+ @param minimumColor is the color to represent the minimum values
+ */
+ void setMinimumColor(const std::string& minimumColor);
+ /**
+ Gets the color to represent the minimum values.
+ @return the color to represent the minimum values
+ */
+ std::string getMinimumColor() const;
+
+ /**
+ Sets the color to represent the maximum values.
+ @param maximumColor is the color to represent the maximum values
+ */
+ void setMaximumColor(const std::string& maximumColor);
+ /**
+ Gets the color to represent the maximum values.
+ @return maximumColor is the color to represent the maximum values
+ */
+ std::string getMaximumColor() const;
+
+ /**
+ Sets the color to draw the contour lines
+ @param contourColor is the color to draw the contour lines
+ */
+ void setContourColor(const std::string& contourColor);
+ /**
+ Gets the color to draw the contour lines
+ @return the color to draw the contour lines
+ */
+ std::string getContourColor() const;
+
+ /**
+ Returns an R script plotting multiple surfaces based on a data frame
+ generated with 1024 values in the scope of FldExporter::AllVariables
+ for the first two input variables.
+ @param engine is the engine to export
+ @return an R script plotting multiple surfaces for the first two input
+ variables in the engine.
+ */
+ virtual std::string toString(const Engine* engine) const FL_IOVERRIDE;
+
+ /**
+ Returns an R script plotting multiple surfaces based on a data frame
+ generated with the given number of values and scope for the two input
+ variables.
+ @param engine is the engine to export
+ @param a is the first input variable
+ @param b is the second input variable
+ @param values is the number of values to evaluate the engine
+ @param scope is the scope of the number of values to evaluate the engine
+ @param outputVariables are the output variables to create the surface for
+ @return an R script plotting multiple surfaces for the two input
+ variables on the output variables.
+ */
+ virtual std::string toString(Engine* engine, InputVariable* a, InputVariable* b,
+ int values, FldExporter::ScopeOfValues scope,
+ const std::vector<OutputVariable*>& outputVariables) const;
+
+ /**
+ Returns an R script plotting multiple surfaces based on the input stream
+ of values for the two input variables.
+ @param engine is the engine to export
+ @param a is the first input variable
+ @param b is the second input variable
+ @param reader is an input stream of data whose lines contain space-separated
+ input values
+ @param outputVariables are the output variables to create the surface for
+ @return an R script plotting multiple surfaces for the two input
+ variables on the output variables
+ */
+ virtual std::string toString(Engine* engine, InputVariable* a, InputVariable* b,
+ std::istream& reader, const std::vector<OutputVariable*>& outputVariables) const;
+
+ /**
+ Creates an R script file plotting multiple surfaces based on a data frame
+ generated with 1024 values in the scope of FldExporter::AllVariables
+ for the two input variables
+ @param filePath is the full path of the R script file
+ @param engine is the engine to export
+ */
+ virtual void toFile(const std::string& filePath, const Engine* engine) const FL_IOVERRIDE;
+
+ /**
+ Creates an R script file plotting multiple surfaces based on a data frame
+ generated with the given number of values and scope for the two input
+ variables
+ @param filePath is the full path of the R script file
+ @param engine is the engine to export
+ @param a is the first input variable
+ @param b is the second input variable
+ @param values is the number of values to evaluate the engine
+ @param scope is the scope of the number of values to evaluate the engine
+ @param outputVariables are the output variables to create the surface for
+ */
+ virtual void toFile(const std::string& filePath, Engine* engine,
+ InputVariable* a, InputVariable* b,
+ int values, FldExporter::ScopeOfValues scope,
+ const std::vector<OutputVariable*>& outputVariables) const;
+
+ /**
+ Creates an R script file plotting multiple surfaces based on the input stream
+ of values for the two input variables.
+ @param filePath is the full path of the R script file
+ @param engine is the engine to export
+ @param a is the first input variable
+ @param b is the second input variable
+ @param reader is an input stream of data whose lines contain space-separated
+ input values
+ @param outputVariables are the output variables to create the surface for
+ */
+ virtual void toFile(const std::string& filePath, Engine* engine,
+ InputVariable* a, InputVariable* b, std::istream& reader,
+ const std::vector<OutputVariable*>& outputVariables) const;
+
+
+ /**
+ Writes an R script plotting multiple surfaces based on a manually
+ imported data frame containing the data for the two input variables
+ on the output variables.
+ @param engine is the engine to export
+ @param writer is the output where the engine will be written to
+ @param a is the first input variable
+ @param b is the second input variable
+ @param dataFramePath is the path where the data frame should be located
+ (the path will not be accessed, it will only be written to script)
+ @param outputVariables are the output variables to create the surface for
+ */
+ virtual void writeScriptImportingDataFrame(const Engine* engine, std::ostream& writer,
+ InputVariable* a, InputVariable* b, const std::string& dataFramePath,
+ const std::vector<OutputVariable*>& outputVariables) const;
+
+ /**
+ Writes an R script plotting multiple surfaces based on a data frame
+ generated with the given number of values and scope for the two input
+ variables on the output variables.
+ @param engine is the engine to export
+ @param writer is the output where the engine will be written to
+ @param a is the first input variable
+ @param b is the second input variable
+ @param values is the number of values to evaluate the engine
+ @param scope is the scope of the number of values to evaluate the engine
+ @param outputVariables are the output variables to create the surface for
+ */
+ virtual void writeScriptExportingDataFrame(Engine* engine, std::ostream& writer,
+ InputVariable* a, InputVariable* b, int values, FldExporter::ScopeOfValues scope,
+ const std::vector<OutputVariable*>& outputVariables) const;
+
+ /**
+ Writes an R script plotting multiple surfaces based on a data frame
+ generated with the given number of values and scope for the two input
+ variables on the output variables.
+ @param engine is the engine to export
+ @param writer is the output where the engine will be written to
+ @param a is the first input variable
+ @param b is the second input variable
+ @param reader is an input stream of data whose lines contain space-separated
+ input values
+ @param outputVariables are the output variables to create the surface for
+ */
+ virtual void writeScriptExportingDataFrame(Engine* engine, std::ostream& writer,
+ InputVariable* a, InputVariable* b, std::istream& reader,
+ const std::vector<OutputVariable*>& outputVariables) const;
+
+ protected:
+ /**
+ Writes the header of the R script (e.g., import libraries)
+ @param writer is the output where the header will be written to
+ @param engine is the engine to export
+ */
+ virtual void writeScriptHeader(std::ostream& writer, const Engine* engine) const;
+
+ /**
+ Writes the code to generate the surface plots for the input variables
+ on the output variables.
+ @param writer is the output where the engine will be written to
+ @param a is the first input variable
+ @param b is the second input variable
+ @param outputVariables are the output variables to create the surface for
+ */
+ virtual void writeScriptPlots(std::ostream& writer,
+ InputVariable* a, InputVariable* b,
+ const std::vector<OutputVariable*>& outputVariables) const;
+
+
+ virtual RScriptExporter* clone() const FL_IOVERRIDE;
+
+ };
+
+}
+
+#endif /* FL_RSCRIPTEXPORTER_H */
+
diff --git a/fuzzylite/fl/norm/Norm.h b/fuzzylite/fl/norm/Norm.h
index 5f1b578..682d2ad 100644
--- a/fuzzylite/fl/norm/Norm.h
+++ b/fuzzylite/fl/norm/Norm.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_NORM_H
@@ -27,12 +19,22 @@
#include "fl/fuzzylite.h"
-#include "fl/Operation.h"
+#include "fl/Complexity.h"
#include <string>
namespace fl {
+ /**
+ The Norm class is the abstract class for norms.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see TNorm
+ @see SNorm
+ @see TNormFactory
+ @see SNormFactory
+ @since 4.0
+ */
class FL_API Norm {
public:
@@ -43,13 +45,31 @@ namespace fl {
}
FL_DEFAULT_COPY_AND_MOVE(Norm)
-
+ /**
+ Returns the name of the class of the norm
+ @return the name of the class of the norm
+ */
virtual std::string className() const = 0;
+
+ /**
+ Computes the estimated complexity of computing the hedge
+ @return the complexity of computing the hedge
+ */
+ virtual Complexity complexity() const = 0;
+ /**
+ Computes the norm for @f$a@f$ and @f$b@f$
+ @param a is a membership function value
+ @param b is a membership function value
+ @return the norm between @f$a@f$ and @f$b@f$
+ */
virtual scalar compute(scalar a, scalar b) const = 0;
+ /**
+ Creates a clone of the norm
+ @return a clone of the norm
+ */
virtual Norm* clone() const = 0;
};
}
#endif /* FL_NORM_H */
-
diff --git a/fuzzylite/fl/norm/SNorm.h b/fuzzylite/fl/norm/SNorm.h
index a281f52..a68081c 100644
--- a/fuzzylite/fl/norm/SNorm.h
+++ b/fuzzylite/fl/norm/SNorm.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SNORM_H
@@ -29,6 +21,19 @@
namespace fl {
+ /**
+ The SNorm class is the base class for all S-Norms, and it is utilized as
+ the disjunction fuzzy logic operator and as the aggregation (or
+ `accumulation` in versions 5.0 and earlier) fuzzy logic operator.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see RuleBlock::getDisjunction()
+ @see OutputVariable::fuzzyOutput()
+ @see Aggregated::getAggregation()
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
class FL_API SNorm : public Norm {
public:
@@ -44,4 +49,3 @@ namespace fl {
};
}
#endif /* FL_SNORM_H */
-
diff --git a/fuzzylite/fl/norm/TNorm.h b/fuzzylite/fl/norm/TNorm.h
index 8ba8538..b1f7cb7 100644
--- a/fuzzylite/fl/norm/TNorm.h
+++ b/fuzzylite/fl/norm/TNorm.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_TNORM_H
@@ -29,6 +21,18 @@
namespace fl {
+ /**
+ The TNorm class is the base class for T-Norms, and it is utilized as the
+ conjunction fuzzy logic operator and as the implication (or `activation`
+ in versions 5.0 and earlier) fuzzy logic operator.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see RuleBlock::getConjunction()
+ @see RuleBlock::getImplication()
+ @see TNormFactory
+ @see Norm
+ @since 4.0
+ */
class FL_API TNorm : public Norm {
public:
@@ -44,4 +48,3 @@ namespace fl {
};
}
#endif /* TNORM_H */
-
diff --git a/fuzzylite/fl/norm/s/AlgebraicSum.h b/fuzzylite/fl/norm/s/AlgebraicSum.h
index 786bcbd..2fbf4c1 100644
--- a/fuzzylite/fl/norm/s/AlgebraicSum.h
+++ b/fuzzylite/fl/norm/s/AlgebraicSum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_ALGEBRAICSUM_H
@@ -27,20 +19,35 @@
#include "fl/norm/SNorm.h"
-
namespace fl {
- class FL_API AlgebraicSum : public SNorm {
+ /**
+ The AlgebraicSum class is an SNorm that computes the algebraic sum of
+ values any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see AlgebraicProduct
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API AlgebraicSum FL_IFINAL : public SNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the algebraic sum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$a+b-(a \times b)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
AlgebraicSum* clone() const FL_IOVERRIDE;
static SNorm* constructor();
};
-
-
}
-
#endif /* FL_ALGEBRAICSUM_H */
-
diff --git a/fuzzylite/fl/norm/s/BoundedSum.h b/fuzzylite/fl/norm/s/BoundedSum.h
index 5231856..cd9438e 100644
--- a/fuzzylite/fl/norm/s/BoundedSum.h
+++ b/fuzzylite/fl/norm/s/BoundedSum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_BOUNDEDSUM_H
@@ -29,15 +21,34 @@
namespace fl {
- class FL_API BoundedSum : public SNorm {
+ /**
+ The BoundedSum class is an SNorm that computes the bounded sum of any two
+ values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see BoundedDifference
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API BoundedSum FL_IFINAL : public SNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the bounded sum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\min(1, a+b)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
BoundedSum* clone() const FL_IOVERRIDE;
static SNorm* constructor();
};
+
}
#endif /* FL_BOUNDEDSUM_H */
-
diff --git a/fuzzylite/fl/norm/s/DrasticSum.h b/fuzzylite/fl/norm/s/DrasticSum.h
index 65d4d4c..a1e33fe 100644
--- a/fuzzylite/fl/norm/s/DrasticSum.h
+++ b/fuzzylite/fl/norm/s/DrasticSum.h
@@ -1,43 +1,55 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_DRASTICSUM_H
#define FL_DRASTICSUM_H
#include "fl/norm/SNorm.h"
+
namespace fl {
- class FL_API DrasticSum : public SNorm {
+ /**
+ The DrasticSum class is an SNorm that computes the drastic sum of any two
+ values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see DrasticProduct
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API DrasticSum FL_IFINAL : public SNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the drastic sum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\begin{cases}
+ \max(a,b) & \mbox{if $\min(a,b)=0$} \cr
+ 1 & \mbox{otherwise}
+ \end{cases}@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
DrasticSum* clone() const FL_IOVERRIDE;
static SNorm* constructor();
};
-
}
-
#endif /* FL_DRASTICSUM_H */
-
diff --git a/fuzzylite/fl/norm/s/EinsteinSum.h b/fuzzylite/fl/norm/s/EinsteinSum.h
index 8114c68..7450330 100644
--- a/fuzzylite/fl/norm/s/EinsteinSum.h
+++ b/fuzzylite/fl/norm/s/EinsteinSum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_EINSTEINSUM_H
@@ -29,16 +21,32 @@
namespace fl {
- class FL_API EinsteinSum : public SNorm {
+ /**
+ The EinsteinSum class is an SNorm that computes the einstein sum of any
+ two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see EinsteinProduct
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API EinsteinSum FL_IFINAL : public SNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the Einstein sum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$a+b/(1+a \times b)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
EinsteinSum* clone() const FL_IOVERRIDE;
static SNorm* constructor();
};
-
}
-
#endif /* FL_EINSTEINSUM_H */
-
diff --git a/fuzzylite/fl/norm/s/HamacherSum.h b/fuzzylite/fl/norm/s/HamacherSum.h
index 3daf852..0242512 100644
--- a/fuzzylite/fl/norm/s/HamacherSum.h
+++ b/fuzzylite/fl/norm/s/HamacherSum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_HAMACHERSUM_H
@@ -29,16 +21,32 @@
namespace fl {
- class FL_API HamacherSum : public SNorm {
+ /**
+ The HamacherSum class is an SNorm that computes the Hamacher sum of any
+ two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see HamacherProduct
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API HamacherSum FL_IFINAL : public SNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the Hamacher sum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$a+b-(2\times a \times b)/(1-a\times b)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
HamacherSum* clone() const FL_IOVERRIDE;
static SNorm* constructor();
};
-
}
-
#endif /* FL_HAMACHERSUM_H */
-
diff --git a/fuzzylite/fl/norm/s/Maximum.h b/fuzzylite/fl/norm/s/Maximum.h
index 28a3b6d..c8ce488 100644
--- a/fuzzylite/fl/norm/s/Maximum.h
+++ b/fuzzylite/fl/norm/s/Maximum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_MAXIMUM_H
@@ -29,17 +21,31 @@
namespace fl {
- class FL_API Maximum : public SNorm {
+ /**
+ The Maximum class is an SNorm that computes the maximum of any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Minimum
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API Maximum FL_IFINAL : public SNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the maximum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\max(a,b)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
Maximum* clone() const FL_IOVERRIDE;
static SNorm* constructor();
};
-
-
}
-
#endif /* FL_MAXIMUM_H */
-
diff --git a/fuzzylite/fl/norm/s/NilpotentMaximum.h b/fuzzylite/fl/norm/s/NilpotentMaximum.h
index 151d92d..13e9793 100644
--- a/fuzzylite/fl/norm/s/NilpotentMaximum.h
+++ b/fuzzylite/fl/norm/s/NilpotentMaximum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_NILPOTENTMAXIMUM_H
@@ -29,9 +21,31 @@
namespace fl {
- class FL_API NilpotentMaximum : public SNorm {
+ /**
+ The NilpotentMaximum class is an SNorm that computes the nilpotent
+ maximum of any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see NilpotentMinimum
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 5.0
+ */
+ class FL_API NilpotentMaximum FL_IFINAL : public SNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the nilpotent maximum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\begin{cases}
+ \max(a,b) & \mbox{if $a+b<0$} \cr
+ 1 & \mbox{otherwise}
+ \end{cases}@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
NilpotentMaximum* clone() const FL_IOVERRIDE;
@@ -40,4 +54,3 @@ namespace fl {
}
#endif /* FL_NILPOTENTMAXIMUM_H */
-
diff --git a/fuzzylite/fl/norm/s/NormalizedSum.h b/fuzzylite/fl/norm/s/NormalizedSum.h
index 59063a6..e2e757b 100644
--- a/fuzzylite/fl/norm/s/NormalizedSum.h
+++ b/fuzzylite/fl/norm/s/NormalizedSum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_NORMALIZEDSUM_H
@@ -29,16 +21,32 @@
namespace fl {
- class FL_API NormalizedSum : public SNorm {
+ /**
+ The NormalizedSum class is an SNorm that computes the normalized sum of
+ any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API NormalizedSum FL_IFINAL : public SNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the normalized sum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$(a+b)/\max(1, a + b)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
NormalizedSum* clone() const FL_IOVERRIDE;
static SNorm* constructor();
};
-
}
#endif /* FL_NORMALIZEDSUM_H */
-
diff --git a/fuzzylite/fl/norm/s/SNormFunction.h b/fuzzylite/fl/norm/s/SNormFunction.h
new file mode 100644
index 0000000..a78b1aa
--- /dev/null
+++ b/fuzzylite/fl/norm/s/SNormFunction.h
@@ -0,0 +1,81 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_SNORMFUNCTION_H
+#define FL_SNORMFUNCTION_H
+
+#include "fl/norm/SNorm.h"
+
+#include "fl/term/Function.h"
+
+namespace fl {
+
+ /**
+ The SNormFunction class is a customizable SNorm via Function, which
+ computes any function based on the @f$a@f$ and @f$b@f$ values.
+ This SNorm is not registered with the SNormFactory.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Function
+ @see SNorm
+ @see Norm
+ @see SNormFactory
+ @since 6.0
+ */
+
+ class FL_API SNormFunction FL_IFINAL : public SNorm {
+ private:
+ Function _function;
+ public:
+ explicit SNormFunction(const std::string& formula = "");
+
+ /**
+ Returns the reference to the Function
+ @return the reference to the Function
+ */
+ Function& function();
+
+ /**
+ Loads the function with the given formula
+ @param formula is a valid formula in infix notation
+ */
+ void setFormula(const std::string& formula);
+ /**
+ Returns the formula loaded into the function
+ @return the formula loaded into the function
+ */
+ std::string getFormula() const;
+
+ std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the S-Norm utilizing the given function via
+ SNormFunction::setFormula(), which automatically assigns the values
+ of @f$a@f$ and @f$b@f$.
+
+ @param a is a membership function value
+ @param b is a membership function value
+ @return the evaluation of the function
+ */
+ scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
+ SNormFunction* clone() const FL_IOVERRIDE;
+
+ static SNorm* constructor();
+ };
+}
+#endif /* FL_SNORMFUNCTION_H */
+
diff --git a/fuzzylite/fl/norm/s/UnboundedSum.h b/fuzzylite/fl/norm/s/UnboundedSum.h
new file mode 100644
index 0000000..695fdfd
--- /dev/null
+++ b/fuzzylite/fl/norm/s/UnboundedSum.h
@@ -0,0 +1,52 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_UNBOUNDEDSUM_H
+#define FL_UNBOUNDEDSUM_H
+
+#include "fl/norm/SNorm.h"
+
+namespace fl {
+
+ /**
+ The UnboundedSum class is an SNorm that computes the sum of any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see BoundedSum
+ @see SNorm
+ @see SNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API UnboundedSum FL_IFINAL : public SNorm {
+ public:
+ std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the bounded sum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\min(1, a+b)@f$
+ */
+ scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
+ UnboundedSum* clone() const FL_IOVERRIDE;
+
+ static SNorm* constructor();
+ };
+}
+
+#endif /* FL_BOUNDEDSUM_H */
diff --git a/fuzzylite/fl/norm/t/AlgebraicProduct.h b/fuzzylite/fl/norm/t/AlgebraicProduct.h
index e4b0865..d19cb64 100644
--- a/fuzzylite/fl/norm/t/AlgebraicProduct.h
+++ b/fuzzylite/fl/norm/t/AlgebraicProduct.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_ALGEBRAICPRODUCT_H
@@ -29,17 +21,32 @@
namespace fl {
- class FL_API AlgebraicProduct : public TNorm {
+ /**
+ The AlgebraicProduct class is a TNorm that computes the algebraic product
+ of any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see AlgebraicSum
+ @see TNorm
+ @see TNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API AlgebraicProduct FL_IFINAL : public TNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the algebraic product of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$a\times b@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
AlgebraicProduct* clone() const FL_IOVERRIDE;
static TNorm* constructor();
};
-
-
}
-
#endif /* FL_ALGEBRAICPRODUCT_H */
-
diff --git a/fuzzylite/fl/norm/t/BoundedDifference.h b/fuzzylite/fl/norm/t/BoundedDifference.h
index 3dc9d3a..250512b 100644
--- a/fuzzylite/fl/norm/t/BoundedDifference.h
+++ b/fuzzylite/fl/norm/t/BoundedDifference.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_BOUNDEDDIFFERENCE_H
@@ -29,16 +21,32 @@
namespace fl {
- class FL_API BoundedDifference : public TNorm {
+ /**
+ The BoundedDifference class is a TNorm that computes the bounded
+ difference between any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see BoundedSum
+ @see TNorm
+ @see TNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API BoundedDifference FL_IFINAL : public TNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the bounded difference between two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\max(0, a+b - 1)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
BoundedDifference* clone() const FL_IOVERRIDE;
static TNorm* constructor();
};
-
}
-
#endif /* FL_BOUNDEDDIFFERENCE_H */
-
diff --git a/fuzzylite/fl/norm/t/DrasticProduct.h b/fuzzylite/fl/norm/t/DrasticProduct.h
index efd589d..d0d490e 100644
--- a/fuzzylite/fl/norm/t/DrasticProduct.h
+++ b/fuzzylite/fl/norm/t/DrasticProduct.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_DRASTICPRODUCT_H
@@ -29,17 +21,35 @@
namespace fl {
- class FL_API DrasticProduct : public TNorm {
+ /**
+ The DrasticProduct class is a TNorm that computes the drastic product of
+ any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see DrasticSum
+ @see TNorm
+ @see TNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API DrasticProduct FL_IFINAL : public TNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the drastic product of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\begin{cases}
+ \min(a,b) & \mbox{if $\max(a,b)=1$} \cr
+ 0 & \mbox{otherwise}
+ \end{cases}@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
DrasticProduct* clone() const FL_IOVERRIDE;
static TNorm* constructor();
};
-
-
}
-
#endif /* FL_DRASTICPRODUCT_H */
-
diff --git a/fuzzylite/fl/norm/t/EinsteinProduct.h b/fuzzylite/fl/norm/t/EinsteinProduct.h
index a4c1141..9d3a71b 100644
--- a/fuzzylite/fl/norm/t/EinsteinProduct.h
+++ b/fuzzylite/fl/norm/t/EinsteinProduct.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_EINSTEINPRODUCT_H
@@ -29,17 +21,32 @@
namespace fl {
- class FL_API EinsteinProduct : public TNorm {
+ /**
+ The EinsteinProduct class is a TNorm that computes the Einstein product
+ of any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see EinsteinSum
+ @see TNorm
+ @see TNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API EinsteinProduct FL_IFINAL : public TNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the Einstein product of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$(a\times b)/(2-(a+b-a\times b))@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
EinsteinProduct* clone() const FL_IOVERRIDE;
static TNorm* constructor();
};
-
-
}
-
#endif /* FL_EINSTEINPRODUCT_H */
-
diff --git a/fuzzylite/fl/norm/t/HamacherProduct.h b/fuzzylite/fl/norm/t/HamacherProduct.h
index 9bc6b40..79c56ee 100644
--- a/fuzzylite/fl/norm/t/HamacherProduct.h
+++ b/fuzzylite/fl/norm/t/HamacherProduct.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_HAMACHERPRODUCT_H
@@ -29,16 +21,32 @@
namespace fl {
- class FL_API HamacherProduct : public TNorm {
+ /**
+ The HamacherProduct class is a TNorm that computes the Hamacher product
+ of any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see HamacherSum
+ @see TNorm
+ @see TNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API HamacherProduct FL_IFINAL : public TNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the Hamacher product of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$(a \times b) / (a+b- a \times b)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
HamacherProduct* clone() const FL_IOVERRIDE;
static TNorm* constructor();
};
-
}
-
#endif /* FL_HAMACHERPRODUCT_H */
-
diff --git a/fuzzylite/fl/norm/t/Minimum.h b/fuzzylite/fl/norm/t/Minimum.h
index 3590e42..5df1ae2 100644
--- a/fuzzylite/fl/norm/t/Minimum.h
+++ b/fuzzylite/fl/norm/t/Minimum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_MINIMUM_H
@@ -29,16 +21,31 @@
namespace fl {
- class FL_API Minimum : public TNorm {
+ /**
+ The Minimum class is a TNorm that computes the minimum of any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Maximum
+ @see TNorm
+ @see TNormFactory
+ @see Norm
+ @since 4.0
+ */
+ class FL_API Minimum FL_IFINAL : public TNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the minimum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\min(a,b)@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
Minimum* clone() const FL_IOVERRIDE;
static TNorm* constructor();
};
-
}
-
#endif /* FL_MINIMUM_H */
-
diff --git a/fuzzylite/fl/norm/t/NilpotentMinimum.h b/fuzzylite/fl/norm/t/NilpotentMinimum.h
index b3c11e0..2ea7f3c 100644
--- a/fuzzylite/fl/norm/t/NilpotentMinimum.h
+++ b/fuzzylite/fl/norm/t/NilpotentMinimum.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_NILPOTENTMINIMUM_H
@@ -29,15 +21,35 @@
namespace fl {
- class FL_API NilpotentMinimum : public TNorm {
+ /**
+ The NilpotentMinimum class is a TNorm that computes the nilpotent minimum
+ of any two values.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see NilpotentMaximum
+ @see TNorm
+ @see TNormFactory
+ @see Norm
+ @since 5.0
+ */
+ class FL_API NilpotentMinimum FL_IFINAL : public TNorm {
public:
std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the nilpotent minimum of two membership function values
+ @param a is a membership function value
+ @param b is a membership function value
+ @return @f$\begin{cases}
+ \min(a,b) & \mbox{if $a+b>1$} \cr
+ 0 & \mbox{otherwise}
+ \end{cases}@f$
+ */
scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
NilpotentMinimum* clone() const FL_IOVERRIDE;
static TNorm* constructor();
};
}
-
#endif /* FL_NILPOTENTMINIMUM_H */
-
diff --git a/fuzzylite/fl/norm/t/TNormFunction.h b/fuzzylite/fl/norm/t/TNormFunction.h
new file mode 100644
index 0000000..1193a40
--- /dev/null
+++ b/fuzzylite/fl/norm/t/TNormFunction.h
@@ -0,0 +1,81 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_TNORMFUNCTION_H
+#define FL_TNORMFUNCTION_H
+
+#include "fl/norm/TNorm.h"
+
+#include "fl/term/Function.h"
+
+namespace fl {
+
+ /**
+ The TNormFunction class is a customizable TNorm via Function, which
+ computes any function based on the @f$a@f$ and @f$b@f$ values.
+ This TNorm is not registered with the TNormFactory.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Function
+ @see TNorm
+ @see Norm
+ @see TNormFactory
+ @since 6.0
+ */
+
+ class FL_API TNormFunction FL_IFINAL : public TNorm {
+ private:
+ Function _function;
+ public:
+ explicit TNormFunction(const std::string& formula = "");
+
+ /**
+ Returns the reference to the Function
+ @return the reference to the Function
+ */
+ Function& function();
+
+ /**
+ Loads the function with the given formula
+ @param formula is a valid formula in infix notation
+ */
+ void setFormula(const std::string& formula);
+ /**
+ Returns the formula loaded into the function
+ @return the formula loaded into the function
+ */
+ std::string getFormula() const;
+
+ std::string className() const FL_IOVERRIDE;
+
+ Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the S-Norm utilizing the given function via
+ SNormFunction::setFormula(), which automatically assigns the values
+ of @f$a@f$ and @f$b@f$.
+
+ @param a is a membership function value
+ @param b is a membership function value
+ @return the evaluation of the function
+ */
+ scalar compute(scalar a, scalar b) const FL_IOVERRIDE;
+ TNormFunction* clone() const FL_IOVERRIDE;
+
+ static TNorm* constructor();
+ };
+}
+#endif /* FL_TNORMFUNCTION_H */
+
diff --git a/fuzzylite/fl/rule/Antecedent.h b/fuzzylite/fl/rule/Antecedent.h
index 02724e5..a424d95 100644
--- a/fuzzylite/fl/rule/Antecedent.h
+++ b/fuzzylite/fl/rule/Antecedent.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_ANTECEDENT_H
@@ -27,6 +19,8 @@
#include "fl/fuzzylite.h"
+#include "fl/Complexity.h"
+
#include <string>
namespace fl {
@@ -36,42 +30,156 @@ namespace fl {
class SNorm;
class Expression;
+ /**
+ The Antecedent class is an expression tree that represents and evaluates
+ the antecedent of a Rule. The structure of a rule is: `if (antecedent)
+ then (consequent)`. The structure of the antecedent of a rule is:
+
+ `if variable is [hedge]* term [(and|or) variable is [hedge]* term]*`
+
+ where `*`-marked elements may appear zero or more times, elements in
+ brackets are optional, and elements in parentheses are compulsory.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Consequent
+ @see Rule
+ @since 4.0
+ */
class FL_API Antecedent {
- protected:
+ private:
std::string _text;
- Expression* _expression;
+ FL_unique_ptr<Expression> _expression;
public:
Antecedent();
virtual ~Antecedent();
+ /**
+ Sets the antecedent in text
+ @param text is the antecedent in text
+ */
virtual void setText(const std::string& text);
+ /**
+ Gets the antecedent in text
+ @return the antecedent in text
+ */
virtual std::string getText() const;
+ /**
+ Gets the expression tree of the antecedent
+ @return the expression tree of the antecedent
+ */
virtual Expression* getExpression() const;
+ /**
+ Sets the expression tree of the antecedent
+ @param expression is the expression tree of the antecedent
+ */
+ virtual void setExpression(Expression* expression);
+
+ /**
+ Indicates whether the antecedent is loaded
+ @return whether the antecedent is loaded
+ */
virtual bool isLoaded() const;
+ /**
+ Unloads the antecedent
+ */
virtual void unload();
- virtual void load(Rule* rule, const Engine* engine);
- virtual void load(const std::string& antecedent, Rule* rule, const Engine* engine);
+ /**
+ Loads the antecedent with the text obtained from
+ Antecedent::getText() and uses the engine to identify and retrieve
+ references to the input variables and output variables as required
+
+ @param engine is the engine from which the rules are part of
+ */
+ virtual void load(const Engine* engine);
+ /**
+ Loads the antecedent with the given text and uses the engine to
+ identify and retrieve references to the input variables and output
+ variables as required
+
+ @param antecedent is the antecedent of the rule in text
+ @param engine is the engine from which the rules are part of
+ */
+ virtual void load(const std::string& antecedent, const Engine* engine);
+
+ /**
+ Computes the estimated complexity of calculating the activation degree
+ @return the estimated complexity of calculating the activation degree
+ */
+ virtual Complexity complexity(const TNorm* conjunction, const SNorm* disjunction) const;
+ /**
+ Computes the estimated complexity of recursively calculating the
+ activation degree from the given node
+ @return the estimated complexity of recursively calculating the
+ activation degree from the given node
+ */
+ virtual Complexity complexity(const TNorm* conjunction, const SNorm* disjunction,
+ const Expression* node) const;
+
+
+ /**
+ Computes the activation degree of the antecedent on the expression
+ tree from the given node
+
+ @param conjunction is the conjunction operator from the RuleBlock
+ @param disjunction is the disjunction operator from the RuleBlock
+ @param node is a node in the expression tree of the antecedent
+ @return the activation degree of the antecedent
+ */
virtual scalar activationDegree(const TNorm* conjunction, const SNorm* disjunction,
const Expression* node) const;
+ /**
+ Computes the activation degree of the antecedent on the expression
+ tree from the root node
+
+ @param conjunction is the conjunction operator from the RuleBlock
+ @param disjunction is the disjunction operator from the RuleBlock
+ @return the activation degree of the antecedent on the expression tree
+ */
virtual scalar activationDegree(const TNorm* conjunction, const SNorm* disjunction) const;
+ /**
+ Returns a string representation of the expression tree in infix
+ notation
+
+ @return a string representation of the expression tree in infix
+ notation
+ */
virtual std::string toString() const;
+ /**
+ Returns a string represention of the given expression tree utilizing
+ prefix notation
+ @param node is a node in the expression tree of the antecedent
+ @return a string represention of the given expression tree utilizing
+ prefix notation
+ */
virtual std::string toPrefix(const Expression* node = fl::null) const;
+ /**
+ Returns a string represention of the given expression tree utilizing
+ infix notation
+ @param node is a node in the expression tree of the antecedent
+ @return a string represention of the given expression tree utilizing
+ infix notation
+ */
virtual std::string toInfix(const Expression* node = fl::null) const;
+ /**
+ Returns a string represention of the given expression tree utilizing
+ postfix notation
+ @param node is a node in the expression tree of the antecedent
+ @return a string represention of the given expression tree utilizing
+ postfix notation
+ */
virtual std::string toPostfix(const Expression* node = fl::null) const;
private:
FL_DISABLE_COPY(Antecedent)
};
-
}
-
#endif /* FL_ANTECEDENT_H */
diff --git a/fuzzylite/fl/rule/Consequent.h b/fuzzylite/fl/rule/Consequent.h
index 5394dc0..275d1e7 100644
--- a/fuzzylite/fl/rule/Consequent.h
+++ b/fuzzylite/fl/rule/Consequent.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_CONSEQUENT_H
@@ -27,6 +19,8 @@
#include "fl/fuzzylite.h"
+#include "fl/Complexity.h"
+
#include <string>
#include <vector>
@@ -36,8 +30,26 @@ namespace fl {
class Proposition;
class TNorm;
+ /**
+ The Consequent class is a proposition set that represents and evaluates
+ the consequent of a Rule.. The structure of a rule is: `if (antecedent)
+ then (consequent)`. The structure of the consequent of a rule is:
+
+ `then variable is [hedge]* term [and variable is [hedge]* term]* [with
+ w]?`
+
+ where `*`-marked elements may appear zero or more times, elements in
+ brackets are optional, elements in parentheses are compulsory, and
+ `?`-marked elements may appear once or not at all.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Antecedent
+ @see Rule
+ @since 4.0
+ */
+
class FL_API Consequent {
- protected:
+ private:
std::string _text;
std::vector<Proposition*> _conclusions;
@@ -45,24 +57,82 @@ namespace fl {
Consequent();
virtual ~Consequent();
+ /**
+ Sets the text of the consequent
+ @param text is the text of the consequent
+ */
virtual void setText(const std::string& text);
+ /**
+ Gets the text of the consequent
+ @return the text of the consequent
+ */
virtual std::string getText() const;
+ /**
+ Computes the estimated complexity of modifying the consequents
+ @return the estimated complexity of modifying the consequents
+ */
+ virtual Complexity complexity(const TNorm* implication) const;
+ /**
+ Returns an immutable vector of the propositions that represent the
+ Consequent of a Rule
+ @return an immutable vector of the set of propositions that represent
+ the Consequent of a Rule
+ */
virtual const std::vector<Proposition*>& conclusions() const;
+ /**
+ Returns the vector of propositions that represent the Consequent of a
+ Rule
+ @return the vector of propositions that represent the Consequent of a
+ Rule
+ */
+ virtual std::vector<Proposition*>& conclusions();
+
+ /**
+ Indicates whether the consequent is loaded
+ @return whether the consequent is loaded
+ */
virtual bool isLoaded();
+ /**
+ Unloads the consequent
+ */
virtual void unload();
- virtual void load(Rule* rule, const Engine* engine);
- virtual void load(const std::string& consequent, Rule* rule, const Engine* engine);
-
- virtual void modify(scalar activationDegree, const TNorm* activation);
-
+ /**
+ Loads the consequent with text given from Consequent::getText() and
+ uses the engine to identify and retrieve references to the input
+ variables and output variables as required
+ @param engine is the engine from which the rules are part of
+ */
+ virtual void load(const Engine* engine);
+ /**
+ Loads the consequent with the given text and uses the engine to
+ identify and retrieve references to the input variables and output
+ variables as required
+ @param consequent is the consequent of the rule in text
+ @param engine is the engine from which the rules are part of
+ */
+ virtual void load(const std::string& consequent, const Engine* engine);
+
+ /**
+ Modifies the proposition set according to the activation degree
+ (computed in the Antecedent of the Rule) and the implication operator
+ (given in the RuleBlock)
+ @param activationDegree is the activation degree computed in the
+ Antecedent of the Rule
+ @param implication is the implication operator configured in the
+ RuleBlock
+ */
+ virtual void modify(scalar activationDegree, const TNorm* implication);
+
+ /**
+ Returns a string representation of the Consequent
+ @return a string representation of the Consequent
+ */
virtual std::string toString() const;
private:
FL_DISABLE_COPY(Consequent)
};
-
}
-
#endif /* FL_CONSEQUENT_H */
diff --git a/fuzzylite/fl/rule/Expression.h b/fuzzylite/fl/rule/Expression.h
index cb48355..dbacc60 100644
--- a/fuzzylite/fl/rule/Expression.h
+++ b/fuzzylite/fl/rule/Expression.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_EXPRESSION_H
@@ -37,48 +29,105 @@ namespace fl {
class Hedge;
class Term;
+ /**
+ The Expression class is the base class to build an expression tree.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Antecedent
+ @see Consequent
+ @see Rule
+ @since 4.0
+ */
class FL_API Expression {
public:
+ enum Type {
+ Proposition, Operator
+ };
Expression();
virtual ~Expression();
+ /**
+ Returns the type of the expression
+ @return the type of the expression
+ */
+ virtual Type type() const = 0;
virtual std::string toString() const = 0;
private:
FL_DISABLE_COPY(Expression)
};
- class FL_API Proposition : public Expression {
+ /**
+ The Proposition class is an Expression that represents a terminal node in
+ the expression tree as `variable is [hedge]* term`.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Antecedent
+ @see Consequent
+ @see Rule
+ @since 4.0
+ */
+ class FL_API Proposition FL_IFINAL : public Expression {
public:
+ /**Variable in `variable is [hedge]* term`*/
Variable* variable;
+ /**Hedge%s in `variable is [hedge]* term`, owned by the object,
+ destroyed on destructor*/
std::vector<Hedge*> hedges;
+ /**Term in `variable is [hedge]* term`*/
Term* term;
Proposition();
- virtual ~Proposition() FL_IOVERRIDE;
+ ~Proposition() FL_IOVERRIDE;
+
+ Expression::Type type() const FL_IOVERRIDE;
+
+ /**
+ Returns a string representation of the proposition
+ @return a string representation of the proposition
+ */
+ std::string toString() const FL_IOVERRIDE;
- virtual std::string toString() const FL_IOVERRIDE;
private:
FL_DISABLE_COPY(Proposition)
};
- class FL_API Operator : public Expression {
+ /**
+ The Operator class is an Expression that represents a non-terminal node
+ in the expression tree as a binary operator (i.e., `and` or `or`) on two
+ Expression nodes.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Antecedent
+ @see Consequent
+ @see Rule
+ @since 4.0
+ */
+ class FL_API Operator FL_IFINAL : public Expression {
public:
+ /**Name of the operator*/
std::string name;
+ /**Left expression in the binary tree*/
Expression* left;
+ /**Right expression in the binary tree*/
Expression* right;
Operator();
- virtual ~Operator() FL_IOVERRIDE;
+ ~Operator() FL_IOVERRIDE;
+
+ Expression::Type type() const FL_IOVERRIDE;
- virtual std::string toString() const FL_IOVERRIDE;
+ /**
+ Returns the name of the operator
+ @return the name of the operator
+ */
+ std::string toString() const FL_IOVERRIDE;
private:
FL_DISABLE_COPY(Operator)
};
-
}
#endif /* FL_FUZZYEXPRESSION_H */
diff --git a/fuzzylite/fl/rule/Rule.h b/fuzzylite/fl/rule/Rule.h
index 20d39fb..b123d15 100644
--- a/fuzzylite/fl/rule/Rule.h
+++ b/fuzzylite/fl/rule/Rule.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_RULE_H
@@ -27,25 +19,59 @@
#include "fl/fuzzylite.h"
+#include "fl/rule/Consequent.h"
+#include "fl/rule/Antecedent.h"
+
#include <map>
#include <string>
namespace fl {
class Engine;
- class Antecedent;
- class Consequent;
class Hedge;
class TNorm;
class SNorm;
+ /**
+ The Rule class is a conditional statement that contributes to the control
+ of an Engine. Each rule consists of an Antecedent and a Consequent, each
+ of which comprises propositions in the form `variable is term`. The
+ propositions in the Antecedent can be connected by the conjunctive `and`
+ or the disjunctive `or`, both of which are fuzzy logic operators (TNorm
+ and SNorm, respectively). Differently, the propositions in the Consequent
+ are independent from each other and are separated with a symbolic `and`.
+ The Term in any proposition can be preceded by a Hedge that modifies its
+ membership function to model cases such as Very, Somewhat, Seldom and
+ Not. Additionally, the contribution of a rule to the control of the
+ engine can be determined by its weight @f$w \in [0.0, 1.0]@f$, which is
+ equal to 1.0 if omitted. The structure of a rule is the following: `if
+ (antecedent) then (consequent) [with weight]`. The structures of
+ the antecedent and the consequent are:
+
+ `if variable is [hedge]* term [(and|or) variable is [hedge]* term]*`
+
+ `then variable is [hedge]* term [and variable is [hedge]* term]* [with w]?`
+
+ where elements in brackets are optional, elements in parentheses are
+ compulsory, `*`-marked elements may appear zero or more times, and
+ `?`-marked elements may appear once or not at all.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Antecedent
+ @see Consequent
+ @see Hedge
+ @see RuleBlock
+ @since 4.0
+ */
class FL_API Rule {
- protected:
+ private:
+ bool _enabled;
std::string _text;
scalar _weight;
+ scalar _activationDegree;
+ bool _triggered;
FL_unique_ptr<Antecedent> _antecedent;
FL_unique_ptr<Consequent> _consequent;
- std::map<std::string, Hedge*> _hedges;
public:
explicit Rule(const std::string& text = "", scalar weight = 1.0);
@@ -54,68 +80,226 @@ namespace fl {
virtual ~Rule();
FL_DEFAULT_MOVE(Rule)
+ /**
+ Sets whether the rule is enabled. An enabled rule will be fired, whereas
+ a disabled rule will not.
+ @param enabled determines whether the rule is enabled
+ */
+ virtual void setEnabled(bool enabled);
+
+ /**
+ Gets whether the rule is enabled. An enabled rule will be fired, whereas
+ a disabled rule will not.
+ @return whether the rule is enabled
+ */
+ virtual bool isEnabled() const;
+
+ /**
+ Sets the text of the rule
+ @param text is the text of the rule
+ */
virtual void setText(const std::string& text);
+ /**
+ Gets the text of the rule
+ @return the text of the rule
+ */
virtual std::string getText() const;
+ /**
+ Sets the weight of the rule
+ @param weight is the weight of the rule
+ */
virtual void setWeight(scalar weight);
+ /**
+ Gets the weight of the rule
+ @return the weight of the rule
+ */
virtual scalar getWeight() const;
+ /**
+ Sets the antecedent of the rule
+ @param antecedent is the antecedent of the rule
+ */
virtual void setAntecedent(Antecedent* antecedent);
+ /**
+ Gets the antecedent of the rule
+ @return the antecedent of the rule
+ */
virtual Antecedent* getAntecedent() const;
+ /**
+ Sets the consequent of the rule
+ @param consequent the consequent of the rule
+ */
virtual void setConsequent(Consequent* consequent);
+ /**
+ Gets the consequent of the rule
+ @return the consequent of the rule
+ */
virtual Consequent* getConsequent() const;
- virtual void addHedge(Hedge* hedge);
- virtual Hedge* getHedge(const std::string& name) const;
- virtual Hedge* removeHedge(const std::string& hedge);
- virtual bool hasHedge(const std::string& name) const;
- virtual int numberOfHedges() const;
- virtual void setHedges(const std::map<std::string, Hedge*>& hedges);
- virtual const std::map<std::string, Hedge*>& hedges() const;
- virtual std::map<std::string, Hedge*>& hedges();
-
- virtual scalar activationDegree(const TNorm* conjunction, const SNorm* disjunction) const;
- virtual void activate(scalar degree, const TNorm* activation) const;
-
+ /**
+ Sets the activation degree of the rule
+ @param activationDegree is the activation degree of the rule
+ */
+ virtual void setActivationDegree(scalar activationDegree);
+
+ /**
+ Gets the activation degree of the rule
+ @return the activation degree of the rule
+ */
+ virtual scalar getActivationDegree() const;
+
+ /**
+ Activates the rule by computing its activation degree using the given
+ conjunction and disjunction operators
+ @param conjunction is the conjunction operator
+ @param disjunction is the disjunction operator
+ @return the activation degree of the rule
+ */
+ virtual scalar activateWith(const TNorm* conjunction, const SNorm* disjunction);
+
+ /**
+ Deactivates the rule
+ */
+ virtual void deactivate();
+
+ /**
+ Triggers the rule's implication (if the rule is enabled) using the
+ given implication operator and the underlying activation degree
+ @param implication is the implication operator
+ */
+ virtual void trigger(const TNorm* implication);
+
+ /**
+ Indicates whether the rule's implication was triggered
+ @return whether the rule's implication was triggered
+ */
+ virtual bool isTriggered() const;
+
+ /**
+ Returns a string representation of the rule in the FuzzyLite Language
+ @return a string representation of the rule in the FuzzyLite Language
+ */
virtual std::string toString() const;
+ /**
+ Indicates whether the rule is loaded
+ @return whether the rule is loaded
+ */
virtual bool isLoaded() const;
+ /**
+ Unloads the rule
+ */
virtual void unload();
+ /**
+ Loads the rule with the text from Rule::getText(), and uses the
+ engine to identify and retrieve references to the input variables and
+ output variables as required
+ @param engine is the engine from which the rule is part of
+ */
virtual void load(const Engine* engine);
+ /**
+ Loads the rule with the given text, and uses the engine to identify
+ and retrieve references to the input variables and output variables
+ as required
+
+ @param rule is the rule in text
+ @param engine is the engine from which the rule is part of
+ */
virtual void load(const std::string& rule, const Engine* engine);
-
+
+ /**
+ Creates a clone of the rule without the rule being loaded
+ @return a clone of the rule without the rule being loaded
+ */
virtual Rule* clone() const;
+ /**
+ Parses and creates a new rule based on the text passed
+ @param rule is the rule in text
+ @param engine is the engine from which the rule is part of
+ @return a new rule parsed from the given text
+ */
static Rule* parse(const std::string& rule, const Engine* engine);
- static std::string ifKeyword() {
+ /**
+ Returns a string representation of the `if` keyword in rules
+ @return a string representation of the `if` keyword in rules
+ */
+ inline static std::string ifKeyword() {
return "if";
}
- static std::string isKeyword() {
+ /**
+ Returns a string representation of the `is` keyword in rules
+ @return a string representation of the `is` keyword in rules
+ */
+ inline static std::string isKeyword() {
return "is";
}
- static std::string thenKeyword() {
+ /**
+ Returns a string representation of the `then` keyword in rules
+ @return a string representation of the `then` keyword in rules
+ */
+ inline static std::string thenKeyword() {
return "then";
}
- static std::string andKeyword() {
+ /**
+ Returns a string representation of the `and` keyword in rules
+ @return a string representation of the `and` keyword in rules
+ */
+ inline static std::string andKeyword() {
return "and";
}
- static std::string orKeyword() {
+ /**
+ Returns a string representation of the `or` keyword in rules
+ @return a string representation of the `or` keyword in rules
+ */
+ inline static std::string orKeyword() {
return "or";
}
- static std::string withKeyword() {
+ /**
+ Returns a string representation of the `with` keyword in rules
+ @return a string representation of the `with` keyword in rules
+ */
+ inline static std::string withKeyword() {
return "with";
}
- };
+ /**
+ Computes the estimated complexity of calculating the activation degree
+ of the rule
+ @param conjunction is the conjunction operator
+ @param disjunction is the disjunction operator
+ @return the estimated complexity of calculating the activation degree
+ of the rule
+ */
+ virtual Complexity complexityOfActivation(const TNorm* conjunction,
+ const SNorm* disjunction) const;
+
+ /**
+ Computes the estimated complexity of firing the rule
+ @param implication is the implication operator
+ @return the estimated complexity of firing the rule
+ */
+ virtual Complexity complexityOfFiring(const TNorm* implication) const;
+
+ /**
+ Returns the estimated complexity of activating and firing the rule
+ @param conjunction is the conjunction operator
+ @param disjunction is the disjunction operator
+ @param implication is the implication operator
+ @return the estimated complexity of activating and firing the rule
+ */
+ virtual Complexity complexity(const TNorm* conjunction,
+ const SNorm* disjunction, const TNorm* implication) const;
+ };
}
-
#endif /* FL_RULE_H */
diff --git a/fuzzylite/fl/rule/RuleBlock.h b/fuzzylite/fl/rule/RuleBlock.h
index 35fe62e..d4ccace 100644
--- a/fuzzylite/fl/rule/RuleBlock.h
+++ b/fuzzylite/fl/rule/RuleBlock.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_RULEBLOCK_H
@@ -27,6 +19,9 @@
#include "fl/fuzzylite.h"
+#include "fl/activation/Activation.h"
+#include "fl/Complexity.h"
+
#include <string>
#include <vector>
@@ -38,16 +33,29 @@ namespace fl {
class TNorm;
class SNorm;
+ /**
+ The RuleBlock class contains a set of Rule%s and fuzzy logic
+ operators required to control an Engine.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Engine
+ @see Rule
+ @see Antecedent
+ @see Consequent
+ @since 4.0
+ */
class FL_API RuleBlock {
private:
- void copyFrom(const RuleBlock& source);
- protected:
+ bool _enabled;
std::string _name;
+ std::string _description;
std::vector<Rule*> _rules;
FL_unique_ptr<TNorm> _conjunction;
FL_unique_ptr<SNorm> _disjunction;
- FL_unique_ptr<TNorm> _activation;
- bool _enabled;
+ FL_unique_ptr<TNorm> _implication;
+ FL_unique_ptr<Activation> _activation;
+
+ void copyFrom(const RuleBlock& source);
public:
explicit RuleBlock(const std::string& name = "");
@@ -56,42 +64,170 @@ namespace fl {
virtual ~RuleBlock();
FL_DEFAULT_MOVE(RuleBlock)
+ /**
+ Enables the rule block
+ @param enabled whether the rule block is enabled
+ */
+ virtual void setEnabled(bool enabled);
+ /**
+ Indicates whether the rule block is enabled
+ @return whether the rule block is enabled
+ */
+ virtual bool isEnabled() const;
+
+ /**
+ Activates the rule block
+ */
virtual void activate();
+ /**
+ Sets the name of the rule block
+ @param name is the name of the rule block
+ */
virtual void setName(std::string name);
+ /**
+ Gets the name of the rule block
+ @return the name of the rule block
+ */
virtual std::string getName() const;
+ /**
+ Gets the description of the rule block
+ @return the description of the rule block
+ */
+ virtual std::string getDescription() const;
+
+ /**
+ Sets the description of the rule block
+ @param description is the description of the rule block
+ */
+ virtual void setDescription(const std::string& description);
+ /**
+ Sets the conjunction operator
+ @param conjunction is the conjunction operator
+ */
virtual void setConjunction(TNorm* conjunction);
+ /**
+ Gets the conjunction operator
+ @return the conjunction operator
+ */
virtual TNorm* getConjunction() const;
+ /**
+ Sets the disjunction operator
+ @param disjunction is the disjunction operator
+ */
virtual void setDisjunction(SNorm* disjunction);
+ /**
+ Gets the disjunction operator
+ @return the disjunction operator
+ */
virtual SNorm* getDisjunction() const;
- virtual void setActivation(TNorm* activation);
- virtual TNorm* getActivation() const;
+ /**
+ Sets the implication operator
+ @param implication is the implication operator
+ */
+ virtual void setImplication(TNorm* implication);
+ /**
+ Gets the implication operator
+ @return the implication operator
+ */
+ virtual TNorm* getImplication() const;
- virtual void setEnabled(bool enabled);
- virtual bool isEnabled() const;
+ /**
+ Sets the activation method
+ @param activation is the activation method
+ */
+ virtual void setActivation(Activation* activation);
+ /**
+ Gets the activation method
+ @return the activation method
+ */
+ virtual Activation* getActivation() const;
+ /**
+ Unloads all the rules in the rule block
+ */
virtual void unloadRules() const;
+ /**
+ Loads all the rules into the rule block
+ @param engine is the engine where this rule block is registered
+ */
virtual void loadRules(const Engine* engine);
+
+ /**
+ Unloads all the rules in the rule block and then loads each rule again
+ @param engine is the engine where this rule block is registered
+ */
virtual void reloadRules(const Engine* engine);
+ /**
+ Returns a string representation of the rule block in the FuzzyLite
+ Language
+ @return a string representation of the rule block in the FuzzyLite
+ Language
+ */
virtual std::string toString() const;
/**
- * Operations for iterable datatype _rules
+ Returns the estimated complexity of activating the rule block
+ @return the estimated complexity of activating the rule block
+ */
+ virtual Complexity complexity() const;
+
+ /**
+ Adds the given rule to the rule block
+ @param rule is the rule to add
*/
virtual void addRule(Rule* rule);
- virtual void insertRule(Rule* rule, int index);
- virtual Rule* getRule(int index) const;
- virtual Rule* removeRule(int index);
- virtual int numberOfRules() const;
+ /**
+ Inserts the rule at the specified index, shifting other rules to
+ the right
+ @param rule is the rule to insert
+ @param index is the index at which to insert the rule
+ */
+ virtual void insertRule(Rule* rule, std::size_t index);
+ /**
+ Gets the rule at the specified index
+ @param index is the index at which the rule is retrieved
+ @return the rule at the specified index
+ */
+ virtual Rule* getRule(std::size_t index) const;
+ /**
+ Removes the rule at the specified index
+ @param index is the index at which the rule will be removed,
+ shifting other rules to the left
+ @return the rule at the specified index
+ */
+ virtual Rule* removeRule(std::size_t index);
+ /**
+ Returns the number of rules added to the rule block
+ @return the number of rules added to the rule block
+ */
+ virtual std::size_t numberOfRules() const;
+ /**
+ Sets the rules of the rule block
+ @param rules is a vector of rules
+ */
virtual void setRules(const std::vector<Rule*>& rules);
+ /**
+ Returns an immutable vector of the rules added to the rule block
+ @return an immutable vector of the rules added to the rule block
+ */
virtual const std::vector<Rule*>& rules() const;
+ /**
+ Returns a mutable vector of the rules added to the rule block
+ @return a mutable vector of the rules added to the rule block
+ */
virtual std::vector<Rule*>& rules();
- };
+ /**
+ Creates a clone of the rule block without the rules being loaded
+ @return a clone of the rule block without the rules being loaded
+ */
+ virtual RuleBlock* clone() const;
+ };
}
#endif /* RULEBLOCK_H */
diff --git a/fuzzylite/fl/term/Accumulated.h b/fuzzylite/fl/term/Accumulated.h
deleted file mode 100644
index 51625d0..0000000
--- a/fuzzylite/fl/term/Accumulated.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
-
- This file is part of fuzzylite.
-
- fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
-
- */
-
-#ifndef FL_ACCUMULATED_H
-#define FL_ACCUMULATED_H
-
-#include "fl/term/Term.h"
-
-#include <vector>
-
-namespace fl {
-
- class Activated;
- class SNorm;
- class TNorm;
-
- class FL_API Accumulated : public Term {
- private:
- void copyFrom(const Accumulated& source);
- protected:
- std::vector<Activated*> _terms;
- scalar _minimum, _maximum;
- FL_unique_ptr<SNorm> _accumulation;
- public:
- explicit Accumulated(const std::string& name = "",
- scalar minimum = fl::nan,
- scalar maximum = fl::nan,
- SNorm* accumulation = fl::null);
- Accumulated(const Accumulated& other);
- Accumulated& operator=(const Accumulated& other);
- virtual ~Accumulated() FL_IOVERRIDE;
- FL_DEFAULT_MOVE(Accumulated)
-
- virtual std::string className() const FL_IOVERRIDE;
- virtual std::string parameters() const FL_IOVERRIDE;
- virtual void configure(const std::string& parameters) FL_IOVERRIDE;
-
- virtual Accumulated* clone() const FL_IOVERRIDE;
-
- virtual scalar membership(scalar x) const FL_IOVERRIDE;
- virtual scalar activationDegree(const Term* forTerm) const;
-
- virtual std::string toString() const FL_IOVERRIDE;
-
-
- virtual void setMinimum(scalar minimum);
- virtual scalar getMinimum() const;
-
- virtual void setMaximum(scalar maximum);
- virtual scalar getMaximum() const;
-
- virtual void setRange(scalar minimum, scalar maximum);
- virtual scalar range() const;
-
- virtual void setAccumulation(SNorm* accumulation);
- virtual SNorm* getAccumulation() const;
-
- /**
- * Operations for std::vector _terms
- */
- virtual void addTerm(const Term* term, scalar degree, const TNorm* activation);
- virtual void addTerm(Activated* term);
- virtual Activated* getTerm(int index) const;
- virtual Activated* removeTerm(int index);
- virtual int numberOfTerms() const;
- virtual const std::vector<Activated*>& terms() const;
- virtual std::vector<Activated*>& terms();
- virtual bool isEmpty() const;
- virtual void clear();
- };
-
-}
-#endif /* FL_ACCUMULATED_H */
diff --git a/fuzzylite/fl/term/Activated.h b/fuzzylite/fl/term/Activated.h
index 10c1b40..f122a25 100644
--- a/fuzzylite/fl/term/Activated.h
+++ b/fuzzylite/fl/term/Activated.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_ACTIVATED_H
@@ -30,36 +22,86 @@
namespace fl {
class TNorm;
+ /**
+ The Activated class is a special Term that contains pointers to the
+ necessary information of a term that has been activated as part of the
+ Antecedent of a Rule. The ownership of the pointers is not transferred to
+ objects of this class. The Activated class was named
+ `Thresholded` in versions 4.0 and earlier.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see OutputVariable
+ @see Term
+ @since 5.0
+ */
class FL_API Activated : public Term {
- protected:
+ private:
const Term* _term;
scalar _degree;
- const TNorm* _activation;
+ const TNorm* _implication;
public:
explicit Activated(const Term* term = fl::null, scalar degree = 1.0,
- const TNorm* activationOperator = fl::null);
+ const TNorm* implication = fl::null);
virtual ~Activated() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(Activated)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"degree implication term"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Does nothing.
+ @param parameters are irrelevant
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the implication of the activation degree and the membership
+ function value of @f$x@f$
+ @param x is a value
+ @return @f$d \otimes \mu(x)@f$, where @f$d@f$ is the activation degree
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
virtual std::string toString() const FL_IOVERRIDE;
+ /**
+ Sets the activated term
+ @param term is the activated term
+ */
virtual void setTerm(const Term* term);
+ /**
+ Gets the activated term
+ @return the activated term
+ */
virtual const Term* getTerm() const;
+ /**
+ Sets the activation degree of the term
+ @param degree is the activation degree of the term
+ */
virtual void setDegree(scalar degree);
+ /**
+ Gets the activation degree of the term
+ @return the activation degree of the term
+ */
virtual scalar getDegree() const;
- virtual void setActivation(const TNorm* activation);
- virtual const TNorm* getActivation() const;
+ /**
+ Sets the implication operator
+ @param implication is the implication operator
+ */
+ virtual void setImplication(const TNorm* implication);
+ /**
+ Gets the implication operator
+ @return the implication operator
+ */
+ virtual const TNorm* getImplication() const;
virtual Activated* clone() const FL_IOVERRIDE;
};
-
}
#endif /* FL_ACTIVATED_H */
diff --git a/fuzzylite/fl/term/Aggregated.h b/fuzzylite/fl/term/Aggregated.h
new file mode 100644
index 0000000..af08c75
--- /dev/null
+++ b/fuzzylite/fl/term/Aggregated.h
@@ -0,0 +1,212 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_AGGREGATED_H
+#define FL_AGGREGATED_H
+
+#include "fl/term/Term.h"
+
+#include "fl/term/Activated.h"
+
+#include <vector>
+
+namespace fl {
+
+ class SNorm;
+ class TNorm;
+
+ /**
+ The Aggregated class is a special Term that stores a fuzzy set with the
+ Activated terms from the Antecedent%s of a Rule, thereby serving mainly
+ as the fuzzy output value of the OutputVariable%s. The ownership of the
+ activated terms will be transfered to objects of this class, and
+ therefore their destructors will be called upon destruction of this term
+ (or calling Aggregated::clear()).
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Antecedent
+ @see Rule
+ @see OutputVariable
+ @see Activated
+ @see Term
+ @since 6.0
+ */
+ class FL_API Aggregated : public Term {
+ private:
+ std::vector<Activated> _terms;
+ scalar _minimum, _maximum;
+ FL_unique_ptr<SNorm> _aggregation;
+
+ void copyFrom(const Aggregated& source);
+ public:
+ explicit Aggregated(const std::string& name = "",
+ scalar minimum = fl::nan,
+ scalar maximum = fl::nan,
+ SNorm* aggregation = fl::null);
+ Aggregated(const Aggregated& other);
+ Aggregated& operator=(const Aggregated& other);
+ virtual ~Aggregated() FL_IOVERRIDE;
+ FL_DEFAULT_MOVE(Aggregated)
+
+ virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"aggregation minimum maximum terms"`
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Does nothing
+ @param parameters are irrelevant
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ virtual Aggregated* clone() const FL_IOVERRIDE;
+
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ virtual Complexity complexityOfMembership() const;
+ virtual Complexity complexityOfActivationDegree() const;
+
+ /**
+ Aggregates the membership function values of @f$x@f$ utilizing the
+ aggregation operator
+ @param x is a value
+ @return @f$\sum_i{\mu_i(x)}, i \in \mbox{terms}@f$
+ */
+ virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Computes the aggregated activation degree for the given term.
+ If the same term is present multiple times, the aggregation operator
+ is utilized to sum the activation degrees of the term. If the
+ aggregation operator is fl::null, a regular sum is performed.
+ @param forTerm is the term for which to compute the aggregated
+ activation degree
+ @return the aggregated activation degree for the given term
+ */
+ virtual scalar activationDegree(const Term* forTerm) const;
+
+ /**
+ Iterates over the Activated terms to find the term with the maximum
+ activation degree
+ @return the term with the maximum activation degree
+ */
+ virtual const Activated* highestActivatedTerm() const;
+
+ virtual std::string toString() const FL_IOVERRIDE;
+
+ /**
+ Sets the minimum of the range of the fuzzy set
+ @param minimum is the minimum of the range of the fuzzy set
+ */
+ virtual void setMinimum(scalar minimum);
+ /**
+ Gets the minimum of the range of the fuzzy set
+ @return the minimum of the range of the fuzzy set
+ */
+ virtual scalar getMinimum() const;
+
+ /**
+ Sets the maximum of the range of the fuzzy set
+ @param maximum is the maximum of the range of the fuzzy set
+ */
+ virtual void setMaximum(scalar maximum);
+ /**
+ Gets the maximum of the range of the fuzzy set
+ @return the maximum of the range of the fuzzy set
+ */
+ virtual scalar getMaximum() const;
+
+ /**
+ Sets the range of the fuzzy set to `[minimum, maximum]`
+ @param minimum is the minimum of the range of the fuzzy set
+ @param maximum is the maximum of the range of the fuzzy set
+ */
+ virtual void setRange(scalar minimum, scalar maximum);
+ /**
+ Returns the magnitude of the range of the fuzzy set,
+ @return the magnitude of the range of the fuzzy set,
+ i.e., `maximum - minimum`
+ */
+ virtual scalar range() const;
+
+ /**
+ Sets the aggregation operator
+ @param aggregation is the aggregation operator
+ */
+ virtual void setAggregation(SNorm* aggregation);
+ /**
+ Gets the aggregation operator
+ @return the aggregation operator
+ */
+ virtual SNorm* getAggregation() const;
+
+ /**
+ Adds a new Activated term (from the parameters) to the fuzzy set
+ @param term is the activated term
+ @param degree is the activation degree
+ @param implication is the implication operator
+ */
+ virtual void addTerm(const Term* term, scalar degree, const TNorm* implication);
+ /**
+ Adds the activated term to the fuzzy set. The activated term
+ will be deleted when Aggregated::clear()
+ @param term is the activated term
+ */
+ virtual void addTerm(const Activated& term);
+ /**
+ Gets the term at the given index
+ @param index is the index of the term
+ @return the activated term at the given index
+ */
+ virtual const Activated& getTerm(std::size_t index) const;
+ /**
+ Removes the term at the given index without deleting the term
+ @param index is the index of the term
+ @return the removed term
+ */
+ virtual const Activated& removeTerm(std::size_t index);
+ /**
+ Returns the number of activated terms
+ @return the number of activated terms
+ */
+ virtual std::size_t numberOfTerms() const;
+
+ /**
+ Sets the activated terms
+ @param terms is the activated terms
+ */
+ virtual void setTerms(const std::vector<Activated>& terms);
+ /**
+ Returns an immutable vector of activated terms
+ @return an immutable vector of activated terms
+ */
+ virtual const std::vector<Activated>& terms() const;
+ /**
+ Returns a mutable vector of activated terms
+ @return a mutable vector of activated terms
+ */
+ virtual std::vector<Activated>& terms();
+ /**
+ Indicates whether the vector of activated terms is empty
+ @return whether the vector of activated terms is empty
+ */
+ virtual bool isEmpty() const;
+ /**
+ Clears and deletes the activated terms
+ */
+ virtual void clear();
+ };
+}
+#endif /* FL_AGGREGATED_H */
diff --git a/fuzzylite/fl/term/Bell.h b/fuzzylite/fl/term/Bell.h
index 115479c..e27d9c9 100644
--- a/fuzzylite/fl/term/Bell.h
+++ b/fuzzylite/fl/term/Bell.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_BELL_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The Bell class is an extended Term that represents the generalized bell
+ curve membership function.
+
+ @image html bell.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Bell : public Term {
- protected:
+ private:
scalar _center;
scalar _width;
scalar _slope;
@@ -44,18 +47,62 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Bell)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"center width slope [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"center width slope [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$h / (1 + \left(|x-c|/w\right)^{2s}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$c@f$ is the center of the Bell,
+ @f$w@f$ is the width of the Bell,
+ @f$s@f$ is the slope of the Bell
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the center of the bell curve
+ @param center is the center of the bell curve
+ */
virtual void setCenter(scalar center);
+ /**
+ Gets the center of the bell curve
+ @return the center of the bell curve
+ */
virtual scalar getCenter() const;
+ /**
+ Sets the width of the bell curve
+ @param width is the width of the bell curve
+ */
virtual void setWidth(scalar width);
+ /**
+ Gets the width of the bell curve
+ @return the width of the bell curve
+ */
virtual scalar getWidth() const;
+ /**
+ Sets the slope of the bell curve
+ @param slope is the slope of the bell curve
+ */
virtual void setSlope(scalar slope);
+ /**
+ Gets the slope of the bell curve
+ @return the slope of the bell curve
+ */
virtual scalar getSlope() const;
virtual Bell* clone() const FL_IOVERRIDE;
@@ -63,6 +110,5 @@ namespace fl {
static Term* constructor();
};
-
}
#endif /* FL_BELL_H */
diff --git a/fuzzylite/fl/term/Binary.h b/fuzzylite/fl/term/Binary.h
new file mode 100644
index 0000000..c22a9e1
--- /dev/null
+++ b/fuzzylite/fl/term/Binary.h
@@ -0,0 +1,132 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#ifndef FL_BINARY_H
+#define FL_BINARY_H
+
+#include "fl/term/Term.h"
+
+namespace fl {
+
+ /**
+ The Binary class is an edge Term that represents the binary membership
+ function.
+
+ @image html binary.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 6.0
+ */
+ class FL_API Binary : public Term {
+ private:
+ scalar _start;
+ scalar _direction;
+ public:
+
+ /**
+ Direction is an enumerator that indicates the direction of the
+ edge.
+ */
+ enum Direction {
+ /** `(_|)` increases to the right (infinity)*/
+ Positive,
+ /** `(--)` direction is NaN */
+ Undefined,
+ /** `(|_)` increases to the left (-infinity)*/
+ Negative
+ };
+
+ explicit Binary(const std::string& name = "", scalar start = fl::nan,
+ scalar direction = fl::nan, scalar height = 1.0);
+ virtual ~Binary() FL_IOVERRIDE;
+ FL_DEFAULT_COPY_AND_MOVE(Binary)
+
+ virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"start direction [height]"`
+ */
+ virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"start direction [height]"`
+ */
+ virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$\begin{cases}
+ 1h & \mbox{if $ \left(s < d \vedge x \in [s, d)\right) \wedge
+ \left( s > d \vedge x \in (d, s] \right) $} \cr
+ 0h & \mbox{otherwise}
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$s@f$ is the start of the Binary edge,
+ @f$d@f$ is the direction of the Binary edge.
+ */
+ virtual scalar membership(scalar x) const FL_IOVERRIDE;
+
+ /**
+ Sets the start of the binary edge
+ @param start is the start of the binary edge
+ */
+ virtual void setStart(scalar start);
+ /**
+ Gets the start of the binary edge
+ @return the start of the binary edge
+ */
+ virtual scalar getStart() const;
+
+ /**
+ Sets the direction of the binary edge.
+
+ @f$\begin{cases}
+ \text{Positive} & \mbox{if $ d > s $}\cr
+ \text{Negative} & \mbox{if $ d < s $}\cr
+ \mbox{\tt NaN} & \mbox{otherwise}
+ \end{cases}
+ @f$
+
+ where @f$d@f$ is the given direction, and
+ @f$s@f$ is the start of the Binary edge
+
+ @param direction is the direction of the binary edge
+ */
+ virtual void setDirection(scalar direction);
+ /**
+ Gets the direction of the binary edge
+ @return the direction of the binary edge
+ */
+ virtual scalar getDirection() const;
+
+ /**
+ Gets the Direction of the binary edge as an enumerator
+ @return the Direction of the binary edge as an enumerator
+ */
+ virtual Direction direction() const;
+
+ virtual Binary* clone() const FL_IOVERRIDE;
+
+ static Term* constructor();
+ };
+}
+#endif /* FL_BINARY_H */
diff --git a/fuzzylite/fl/term/Concave.h b/fuzzylite/fl/term/Concave.h
index b3aabe6..12d7160 100644
--- a/fuzzylite/fl/term/Concave.h
+++ b/fuzzylite/fl/term/Concave.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_CONCAVE_H
@@ -27,11 +19,21 @@
#include "fl/term/Term.h"
-
namespace fl {
+ /**
+ The Concave class is an edge Term that represents the concave membership
+ function.
+
+ @image html concave.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 5.0
+ */
class FL_API Concave : public Term {
- protected:
+ private:
scalar _inflection, _end;
public:
explicit Concave(const std::string& name = "",
@@ -42,15 +44,61 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Concave)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term as
+ @return `"inflection end [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters given
+ @param parameters as `"inflection end [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$\begin{cases}
+ h \times (e - i) / (2e - i - x) & \mbox{if $i \leq e \wedge x < e$
+ (increasing concave)} \cr
+ h \times (i - e) / (-2e + i + x) & \mbox{if $i > e \wedge x > e$
+ (decreasing concave)} \cr
+ h & \mbox{otherwise} \cr
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$i@f$ is the inflection of the Concave,
+ @f$e@f$ is the end of the Concave
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ virtual scalar tsukamoto(scalar activationDegree,
+ scalar minimum, scalar maximum) const FL_IOVERRIDE;
+
+ virtual bool isMonotonic() const FL_IOVERRIDE;
+
+ /**
+ Sets the inflection of the curve
+ @param inflection is the inflection of the curve
+ */
virtual void setInflection(scalar inflection);
+ /**
+ Gets the inflection of the curve
+ @return the inflection of the curve
+ */
virtual scalar getInflection() const;
+ /**
+ Sets the end of the curve
+ @param end is the end of the curve
+ */
virtual void setEnd(scalar end);
+ /**
+ Gets the end of the curve
+ @return the end of the curve
+ */
virtual scalar getEnd() const;
virtual Concave* clone() const FL_IOVERRIDE;
@@ -58,7 +106,5 @@ namespace fl {
static Term* constructor();
};
}
-
-
#endif /* FL_CONCAVE_H */
diff --git a/fuzzylite/fl/term/Constant.h b/fuzzylite/fl/term/Constant.h
index c4ed17d..40ba77b 100644
--- a/fuzzylite/fl/term/Constant.h
+++ b/fuzzylite/fl/term/Constant.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_CONSTANT_H
@@ -29,8 +21,17 @@
namespace fl {
+ /**
+ The Constant class is a (zero) polynomial Term that represents a constant
+ value @f$ f(x) = k @f$
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Constant : public Term {
- protected:
+ private:
scalar _value;
public:
@@ -40,12 +41,35 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Constant)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"value"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"value"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x is irrelevant
+ @return @f$c@f$, where @f$c@f$ is the constant value
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the constant value
+ @param value is the constant value
+ */
virtual void setValue(scalar value);
+ /**
+ Gets the constant value
+ @return the constant value
+ */
virtual scalar getValue() const;
virtual Constant* clone() const FL_IOVERRIDE;
@@ -53,6 +77,5 @@ namespace fl {
static Term* constructor();
};
}
-
#endif /* FL_CONSTANT_H */
diff --git a/fuzzylite/fl/term/Cosine.h b/fuzzylite/fl/term/Cosine.h
index 510669f..b45ab85 100644
--- a/fuzzylite/fl/term/Cosine.h
+++ b/fuzzylite/fl/term/Cosine.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_COSINE_H
@@ -29,8 +21,20 @@
namespace fl {
+ /**
+ The Cosine class is an extended Term that represents the cosine
+ membership function.
+
+ @image html cosine.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 5.0
+ */
+
class FL_API Cosine : public Term {
- protected:
+ private:
scalar _center, _width;
public:
explicit Cosine(const std::string& name = "",
@@ -41,15 +45,51 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Cosine)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"center width [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"center width [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$\begin{cases}
+ 0h & \mbox{if $x < c - 0.5w \vee x > c + 0.5w$} \cr
+ 0.5h \times ( 1 + \cos(2.0 / w\pi(x-c))) & \mbox{otherwise}
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$c@f$ is the center of the Cosine,
+ @f$w@f$ is the width of the Cosine
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
-
+ /**
+ Sets the center of the cosine
+ @param center is the center of the cosine
+ */
virtual void setCenter(scalar center);
+ /**
+ Gets the center of the cosine
+ @return the center of the cosine
+ */
virtual scalar getCenter() const;
+ /**
+ Sets the width of the cosine
+ @param width is the width of the cosine
+ */
virtual void setWidth(scalar width);
+ /**
+ Gets the width of the cosine
+ @return the width of the cosine
+ */
virtual scalar getWidth() const;
virtual Cosine* clone() const FL_IOVERRIDE;
@@ -57,6 +97,5 @@ namespace fl {
static Term* constructor();
};
}
-
#endif /* FL_COSINE_H */
diff --git a/fuzzylite/fl/term/Discrete.h b/fuzzylite/fl/term/Discrete.h
index fc554b3..ba5ae70 100644
--- a/fuzzylite/fl/term/Discrete.h
+++ b/fuzzylite/fl/term/Discrete.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_DISCRETE_H
@@ -27,15 +19,30 @@
#include "fl/term/Term.h"
+#include "fl/defuzzifier/IntegralDefuzzifier.h"
+
#include <vector>
#include <utility>
namespace fl {
+ /**
+ The Discrete class is a basic Term that represents a discrete membership
+ function. The pairs of values in any Discrete term **must** be sorted
+ ascendently because the membership function is computed using binary search
+ to find the lower and upper bounds of @f$x@f$.
+
+ @image html discrete.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Discrete : public Term {
public:
typedef std::pair<scalar, scalar> Pair;
- protected:
+ private:
std::vector<Pair> _xy;
public:
explicit Discrete(const std::string& name = "",
@@ -45,37 +52,229 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Discrete)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term as `x1 y1 xn yn [height]`
+ @return `x1 y1 xn yn [height]`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters given as `x1 y1 xn yn [height]`
+ @param parameters as `x1 y1 xn yn [height]`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
- //Warning: this method is unsafe. Make sure you use it correctly.
- template <typename T>
- static Discrete* create(const std::string& name, int argc,
- T x1, T y1, ...); // throw (fl::Exception);
+ /**
+ Ascendantly sorts the given pairs of values by the @f$x@f$-value,
+ as it is required by the Discrete term.
+ @param pairs is a vector of pairs of values in the form @f$(x,y)@f$
+ */
+ static void sort(std::vector<Pair>& pairs);
+
+ /**
+ Ascendantly sorts the pairs of values in this Discrete term by the
+ @f$x@f$-coordinate
+ */
+ virtual void sort();
+
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$ by using binary
+ search to find the lower and upper bounds of @f$x@f$ and then linearly
+ interpolating the membership function between the bounds.
+ @param x
+ @return @f$ \dfrac{h (y_{\max} - y_{\min})}{(x_{\max}- x_{\min})} (x - x_{\min}) + y_{\min}@f$
+ where @f$h@f$ is the height of the Term,
+ @f$x_{\min}@f$ and @f$x_{\max}@f$is are the lower and upper limits
+ of @f$x@f$ in `xy` (respectively),
+ @f$y_{\min}@f$ and @f$y_{\max}@f$is are the membership functions
+ of @f$\mu(x_{\min})@f$ and @f$\mu(x_{\max})@f$ (respectively)
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the vector of pairs defining the discrete membership function
+ @param pairs is the vector of pairs defining the discrete membership function
+ */
virtual void setXY(const std::vector<Pair>& pairs);
+ /**
+ Gets an immutable vector of pairs defining the discrete membership function
+ @return an immutable vector of pairs defining the discrete membership function
+ */
virtual const std::vector<Pair>& xy() const;
+ /**
+ Gets a mutable vector of pairs defining the discrete membership function
+ @return a mutable vector of pairs defining the discrete membership function
+ */
virtual std::vector<Pair>& xy();
- virtual const Pair& xy(int index) const;
- virtual Pair& xy(int index);
+ /**
+ Gets the immutable pair @f$(x_i,y_i)@f$ at index @f$i@f$
+ @param index is the index @f$i@f$
+ @return the immutable pair @f$(x_i,y_i)@f$
+ */
+ virtual const Pair& xy(std::size_t index) const;
+ /**
+ Gets the mutable pair @f$(x_i,y_i)@f$ at index @f$i@f$
+ @param index is the index @f$i@f$
+ @return a mutable pair @f$(x_i,y_i)@f$
+ */
+ virtual Pair& xy(std::size_t index);
+
+ /**
+ Creates, fills and returns a vector containing the @f$x@f$ values
+ @return a vector containing the @f$x@f$ values
+ */
+ virtual std::vector<scalar> x() const;
+
+ /**
+ Gets the @f$x@f$ value at the given index
+ @return the @f$x@f$ value at the given index
+ */
+ virtual scalar x(std::size_t index) const;
+ /**
+ Gets the reference to the @f$x@f$ value at the given index
+ @return the reference to the @f$x@f$ value at the given index
+ */
+ virtual scalar& x(std::size_t index);
+ /**
+ Creates, fills and returns a vector containing the @f$y@f$ values
+ @return a vector containing the @f$y@f$ values
+ */
+ virtual std::vector<scalar> y() const;
+
+ /**
+ Gets the @f$y@f$ value at the given index
+ @param index is the index
+ @return the @f$y@f$ value at the given index
+ */
+ virtual scalar y(std::size_t index) const;
+
+ /**
+ Gets the reference to the @f$y@f$ value at the given index
+ @param index is the index
+ @return the reference to the @f$y@f$ value at the given index
+ */
+ virtual scalar& y(std::size_t index);
+ /**
+ Creates a vector of fl::scalar from a vector of Pair given in the
+ form @f$\left(\{x_1,y_1\},...,\{x_n,y_n\}\right)@f$
+ @param xy is the vector of Pair
+ @return a vector of fl::scalar as @f$(x_1,y_1,...,x_n,y_n)@f$
+ */
static std::vector<scalar> toVector(const std::vector<Pair>& xy);
+ /**
+ Creates a vector of Pair from a vector of fl::scalar given in the
+ form @f$(x_1,y_1,...,x_n,y_n)@f$
+ @param xy is a vector of fl::scalar given as
+ @f$(x_1,y_1,...,x_n,y_n)@f$
+ @return a vector of Pair in the form
+ @f$\left(\{x_1,y_1\},...,\{x_n,y_n\}\right)@f$
+ @throws fl::Exception if a value is missing, that is, if the length
+ of @f$xy@f$ is odd: @f$|xy|\mod 2 = 1@f$
+ */
static std::vector<Pair> toPairs(const std::vector<scalar>& xy);
+ /**
+ Creates a vector of Pair from a vector of fl::scalar given in the
+ form @f$(x_1,y_1,...,x_n,y_n)@f$
+ @param xy is a vector of fl::scalar given as
+ @f$(x_1,y_1,...,x_n,y_n)@f$ possibly missing a value
+ @param missingValue is the replacement in the case a value is missing
+ from @f$xy@f$
+ @return a vector of Pair in the form
+ @f$\left(\{x_1,y_1\},...,\{x_n,y_n\}\right)@f$
+ */
static std::vector<Pair> toPairs(const std::vector<scalar>& xy,
scalar missingValue) FL_INOEXCEPT;
+ /**
+ Formats a vector of Pair into a std::string in the form
+ @f$(x_1,y_1) ... (x_n,y_n)@f$
+ @param xy is the vector of Pair
+ @param prefix indicates the prefix of a Pair, e.g., `(` results in
+ @f$(x_i@f$
+ @param innerSeparator indicates the separator between
+ @f$x@f$ and @f$y@f$, e.g., `,` results in @f$x_i,y_i@f$
+ @param suffix indicates the postfix of a Pair, e.g., `]` results in
+ @f$y_i]@f$
+ @param outerSeparator indicates the separator between Pair, e.g.,
+ `;` results in @f$(x_i,y_i);(x_j,y_j)@f$
+ @return a formatted string containing the pairs of @f$(x,y)@f$ values
+ */
static std::string formatXY(const std::vector<Pair>& xy,
const std::string& prefix = "(", const std::string& innerSeparator = ",",
- const std::string& postfix = ")", const std::string& outerSeparator = " ");
+ const std::string& suffix = ")", const std::string& outerSeparator = " ");
+
+ /**
+ Discretizes the given term
+ @param term is the term to discretize
+ @param start is the value from which discretization starts
+ @param end is the value at which discretization ends
+ @param resolution is the number of equally-distributed samples to
+ perform between start and end
+ @param boundedMembershipFunction indicates whether to ensure that
+ @f$\mu(x)\in[0.0,1.0]@f$
+ @return a Discrete term that approximates the given term
+ */
+ static Discrete* discretize(const Term* term, scalar start, scalar end,
+ int resolution = IntegralDefuzzifier::defaultResolution(),
+ bool boundedMembershipFunction = true);
virtual Discrete* clone() const FL_IOVERRIDE;
static Term* constructor();
+ /**
+ Creates a Discrete term from a variadic set of values.
+ Beware: this method is unsafe and must be used with care by
+ ensuring:
+ - the value `argc` correctly and exactly determines the number of
+ values passed,
+ - the data type of each variadic arguments is the same, e.g.,
+ @f$(1.0, 2.0, 3.0)@f$ are all fl::scalar, whereas in
+ @f$(1.0, 2, 3.0)@f$ the second term is an integer, which will cause
+ memory access issues due to the difference in size between
+ `int` and `fl::scalar`.
+ @param name is the name of the resulting term
+ @param argc is the number of values passed
+ @param x1 is the @f$x@f$ value of the first Pair
+ @param y1 is the @f$y@f$ value of the first Pair
+ @param ... are the remaining pairs of values @f$x_i@f$ and @f$y_i@f$
+ @return a new Discrete term with the given parameters
+ */
+ template <typename T>
+ static Discrete* create(const std::string& name, int argc,
+ T x1, T y1, ...);
};
+}
+
+/**
+ Template implementation
+ */
+
+namespace fl {
+
+ template <typename T>
+ inline Discrete* Discrete::create(const std::string& name, int argc,
+ T x1, T y1, ...) {
+ std::vector<scalar> xy(argc);
+ xy.at(0) = x1;
+ xy.at(1) = y1;
+ va_list args;
+ va_start(args, y1);
+ for (int i = 2; i < argc; ++i) {
+ xy.at(i) = (scalar) va_arg(args, T);
+ }
+ va_end(args);
+ FL_unique_ptr<Discrete> result(new Discrete(name));
+ if (xy.size() % 2 != 0) {
+ result->setHeight(xy.back());
+ xy.pop_back();
+ }
+ result->setXY(toPairs(xy));
+ return result.release();
+ }
}
#endif /* FL_DISCRETE_H */
diff --git a/fuzzylite/fl/term/Function.h b/fuzzylite/fl/term/Function.h
index 99580b7..14e3427 100644
--- a/fuzzylite/fl/term/Function.h
+++ b/fuzzylite/fl/term/Function.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_FUNCTION_H
@@ -34,27 +26,77 @@ namespace fl {
class Engine;
+ /**
+ The Function class is a polynomial Term that represents a generic
+ function @f$ f : x \mapsto f(x) @f$. Every Function object has a public
+ key-value map, namely Function::variables, that links variable names to
+ fl::scalar values, which are utilized to replace the variable names for
+ their respective values in the given formula whenever the function
+ @f$f@f$ is evaluated. Specifically, when the method
+ Function::membership() is called, the name and value of the variable
+ @f$x@f$ are automatically loaded into the map. Furthermore, if an Engine
+ is given, the names of its InputVariable%s and OutputVariable%s will also
+ be automatically loaded into the map linking to their respective input
+ values and (previously defuzzified) output values. The
+ Function::variables need to be manually loaded whenever variables other
+ than @f$x@f$, input variables, and output variables, are expressed in the
+ given formula, always having in mind that (a) the map replaces existing
+ keys, and (b) the variable @f$x@f$, and input variables and output
+ variables of an engine will automatically be replaced and will also take
+ precedence over previously loaded variables.
+
+ Besides the use of Function as a linguistic Term, it is also utilized to
+ convert the text of the Antecedent of a Rule, expressed in infix
+ notation, into postfix notation.
+
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @see FunctionFactory
+ @see Antecedent::load()
+ @since 4.0
+ */
class FL_API Function : public Term {
- /****************************
- * Parsing Elements
- ****************************/
-
public:
typedef scalar(*Unary)(scalar);
typedef scalar(*Binary)(scalar, scalar);
+ /**
+ The Element class represents a single element in a formula, be that
+ either a function or an operator. If the Element represents a
+ function, the function can be Unary or Binary, that is, the function
+ take one or two parameters (respectively). Else, if the Element
+ represents an operator, the parameters to be defined are its `arity`,
+ its `precedence`, and its `associativity`.
+ */
struct FL_API Element {
+ /**
+ Determines the type of the element
+ */
enum Type {
- OPERATOR, FUNCTION
+ Operator, Function
};
+ /**Name of the element*/
std::string name;
+ /**Description of the element*/
std::string description;
+ /**Type of the element*/
Type type;
+ /**Pointer to unary method*/
Unary unary;
+ /**Pointer to binary method*/
Binary binary;
+ /**Number of operands required*/
int arity;
- int precedence; //Operator
+ /**Precedence of the element: clarifies which procedures should be
+ performed first in a given mathematical expression
+ (https://en.wikipedia.org/wiki/Order_of_operations)*/
+ int precedence;
+ /**Associativity of the element: determines how operators of the
+ same precedence are grouped in the absence of parentheses
+ (https://en.wikipedia.org/wiki/Operator_associativity)*/
int associativity;
Element(const std::string& name, const std::string& description, Type type);
Element(const std::string& name, const std::string& description,
@@ -64,24 +106,46 @@ namespace fl {
virtual ~Element();
FL_DEFAULT_COPY_AND_MOVE(Element)
+ /**
+ Indicates whether the element is a Type::Operator
+ @return whether the element is a Type::Operator
+ */
virtual bool isOperator() const;
+ /**
+ Indicates whether the element is a Type::Function
+ @return whether the element is a Type::Function
+ */
virtual bool isFunction() const;
-
+ /**
+ Clones the element
+ @return a clone of the element
+ */
virtual Element* clone() const;
+ /**
+ Returns a description of the element and its members
+ @return a description of the element and its members
+ */
virtual std::string toString() const;
};
- /**************************
- * Tree elements, wrap Elements into Nodes.
- **************************/
-
+ /**
+ The Node class structures a binary tree by storing pointers to a left
+ Node and a right Node, and storing its content as a
+ Function::Element, the name of an InputVariable or OutputVariable, or
+ a constant value.
+ */
struct FL_API Node {
+ /**The node takes an operation or a function*/
FL_unique_ptr<Element> element;
+ /**The node can have an expression tree on the left*/
FL_unique_ptr<Node> left;
+ /**The node can have an expression tree on the right*/
FL_unique_ptr<Node> right;
+ /**The node can refer to a variable by name*/
std::string variable;
+ /**The node can take an arbitrary floating-point value*/
scalar value;
explicit Node(Element* element, Node* left = fl::null, Node* right = fl::null);
@@ -92,14 +156,79 @@ namespace fl {
virtual ~Node();
FL_DEFAULT_MOVE(Node)
+ /**
+ Evaluates the node and substitutes the variables therein for the
+ values passed in the map. The expression tree is evaluated
+ recursively.
+
+ @param variables is a map of substitutions of variable names for
+ fl::scalar%s
+
+ @return a fl::scalar indicating the result of the evaluation of
+ the node
+ */
virtual scalar evaluate(const std::map<std::string, scalar>*
variables = fl::null) const;
+ /**
+ Computes the size of the subtree under the given node. The complexity
+ of calling this method is O(n).
+ @param node is the root of the subtree, which is this node if
+ fl::null is given
+ @return the size of the subtree under the given node
+ */
+ virtual std::size_t treeSize(const Node* node = fl::null) const;
+
+ /**
+ Computes the size of the subtree under the given node whose elements
+ are of the given type. The complexity of calling this method is O(n).
+ @param type is the type of elements to account for
+ @param node is the root of the subtree, which is this node if
+ fl::null is given
+ @return
+ */
+ virtual std::size_t treeSize(Element::Type type,
+ const Node* node = fl::null) const;
+
+ /**
+ Creates a clone of the node.
+ @return a clone of the node
+ */
virtual Node* clone() const;
+ /**
+ Returns a string with the name of the element, the name of the
+ variable, or the constant value, accordingly.
+ @return a string with the name of the element, the name of the
+ variable, or the constant value, accordingly.
+ */
virtual std::string toString() const;
+ /**
+ Returns a prefix representation of the expression tree under the
+ given node
+ @param node is the node to start the prefix representation from.
+ If the node is `fl::null`, then the starting point is `this` node
+ @return a prefix representation of the expression tree under the
+ given node
+ */
virtual std::string toPrefix(const Node* node = fl::null) const;
+ /**
+ Returns an infix representation of the expression tree under the
+ given node
+ @param node is the node to start the infix representation from.
+ If the node is `fl::null`, then the starting point is `this` node
+ @return an infix representation of the expression tree under the
+ given node
+ */
virtual std::string toInfix(const Node* node = fl::null) const;
+ /**
+ Returns a postfix representation of the expression tree under the
+ given node
+ @param node is the node to start the postfix representation from.
+ If the node is `fl::null`, then the starting point is `this` node
+ @return a postfix representation of the expression tree under the
+ given node
+ */
virtual std::string toPostfix(const Node* node = fl::null) const;
private:
void copyFrom(const Node& source);
@@ -112,11 +241,12 @@ namespace fl {
* Term
******************************/
- protected:
+ private:
FL_unique_ptr<Node> _root;
std::string _formula;
const Engine* _engine;
public:
+ /**A map of variables and substitution values**/
mutable std::map<std::string, scalar> variables;
explicit Function(const std::string& name = "",
const std::string& formula = "", const Engine* engine = fl::null);
@@ -125,47 +255,145 @@ namespace fl {
virtual ~Function() FL_IOVERRIDE;
FL_DEFAULT_MOVE(Function)
+ /**
+ Creates a Function term with the given parameters
+ @param name is the name of the term
+ @param formula is the formula defining the membership function
+ @param engine is the engine to which the Function can have access
+ @return a Function term configured with the given parameters
+ @throws fl::Exception if the formula has a syntax error
+ */
static Function* create(const std::string& name,
const std::string& formula,
- const Engine* engine = fl::null); // throw (fl::Exception);
-
+ const Engine* engine = fl::null);
+
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function value of @f$x@f$ at the root node.
+ If the engine has been set, the current values of the input variables
+ and output variables are added to the map of Function::variables. In
+ addition, the variable @f$x@f$ will also be added to the map.
+ @param x
+ @return the membership function value of @f$x@f$ at the root node
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
- virtual scalar evaluate(const std::map<std::string, scalar>* variables) const;
+ /**
+ Computes the function value of this term using the given map of
+ variable substitutions.
+ @param variables is a map of substitution variables
+ @return the function value of this term using the given map of
+ variable substitutions.
+ */
+ virtual scalar evaluate(const std::map<std::string, scalar>* variables = fl::null) const;
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term as `formula`
+ @return `formula`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters given as `formula`
+ @param parameters as `formula`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ /**
+ Sets the formula of the function
+ @param formula is the formula of the function
+ */
virtual void setFormula(const std::string& formula);
+ /**
+ Gets the formula of the function
+ @return the formula of the function
+ */
virtual std::string getFormula() const;
+ /**
+ Sets the engine to which the formula can refer
+ @param engine is the engine to which the formula can refer
+ */
virtual void setEngine(const Engine* engine);
+ /**
+ Gets the engine to which the formula can refer
+ @return the engine to which the formula can refer
+ */
virtual const Engine* getEngine() const;
+ /**
+ Gets the root node of the expression tree defining the Function. The
+ root is `fl::null` if the formula has not been loaded.
+ @return the root node of the expression tree defining the Function,
+ or `fl::null` if the formula has not been loaded
+ */
virtual Node* root() const;
+ /**
+ Indicates whether the formula is loaded
+ @return whether the formula is loaded
+ */
virtual bool isLoaded() const;
+ /**
+ Unloads the formula and resets the map of substitution variables.
+ */
virtual void unload();
- virtual void load(); // throw (fl::Exception);
- virtual void load(const std::string& formula); // throw (fl::Exception);
- virtual void load(const std::string& formula, const Engine* engine); // throw (fl::Exception);
-
- virtual Node* parse(const std::string& formula); // throw (fl::Exception);
-
- virtual std::string toPostfix(const std::string& formula) const; //throw (fl::Exception);
-
+ /**
+ Loads the current formula expressed in infix notation
+ */
+ virtual void load();
+ /**
+ Loads the given formula expressed in infix notation
+ @param formula is the right-hand side of a mathematical equation
+ @throws fl::Exception if the formula has syntax errors
+ */
+ virtual void load(const std::string& formula);
+ /**
+ Loads the given formula expressed in infix notation, and sets the
+ engine holding the variables to which the formula refers.
+ @param formula is the right-hand side of a mathematical equation
+ expressed in infix notation
+ @param engine is the engine to which the formula can refer
+ @throws fl::Exception if the formula has syntax errors
+ */
+ virtual void load(const std::string& formula, const Engine* engine);
+ /**
+ Creates a node representing a binary expression tree from the given formula
+ @param formula is the right-hand side of a mathematical equation
+ expressed in infix notation
+ @return a node representing a binary expression tree from the given formula
+ @throws fl::Exception if the formula has syntax errors
+ */
+ virtual Node* parse(const std::string& formula);
+
+ /**
+ Translates the given formula to postfix notation
+ @param formula is the right-hand side of a mathematical equation
+ expressed in infix notation
+ @return the formula represented in postfix notation
+ @throws fl::Exception if the formula has syntax errors
+ */
+ virtual std::string toPostfix(const std::string& formula) const;
+
+ /**
+ Adds spaces to the formula to separate parentheses, commas and
+ function operators such that these are treated as tokens when parsing
+ the function.
+ @param formula is the right-hand side of a mathematical equation
+ expressed in infix notation
+ @return the formula with spaces before and after parentheses, commas
+ and function operators
+ */
virtual std::string space(const std::string& formula) const;
+ virtual void updateReference(const Engine* engine) FL_IOVERRIDE;
+
virtual Function* clone() const FL_IOVERRIDE;
static Term* constructor();
- static void main();
-
};
-
}
-
#endif /* FL_FUNCTION_H */
diff --git a/fuzzylite/fl/term/Gaussian.h b/fuzzylite/fl/term/Gaussian.h
index a5b8055..9a7475d 100644
--- a/fuzzylite/fl/term/Gaussian.h
+++ b/fuzzylite/fl/term/Gaussian.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_GAUSSIAN_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The Gaussian class is an extended Term that represents the %Gaussian
+ curve membership function.
+
+ @image html gaussian.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Gaussian : public Term {
- protected:
+ private:
scalar _mean;
scalar _standardDeviation;
@@ -43,21 +46,54 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Gaussian)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"mean standardDeviation [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"mean standardDeviation [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$ h \times \exp(-(x-\mu)^2/(2\sigma^2))@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$\mu@f$ is the mean of the Gaussian,
+ @f$\sigma@f$ is the standard deviation of the Gaussian
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
- virtual void setMean(scalar c);
+ /**
+ Sets the mean of the Gaussian curve
+ @param mean is the mean of the Gaussian curve
+ */
+ virtual void setMean(scalar mean);
+ /**
+ Gets the mean of the Gaussian curve
+ @return the mean of the Gaussian curve
+ */
virtual scalar getMean() const;
- virtual void setStandardDeviation(scalar sigma);
+ /**
+ Sets the standard deviation of the Gaussian curve
+ @param standardDeviation is the standard deviation of the Gaussian curve
+ */
+ virtual void setStandardDeviation(scalar standardDeviation);
+ /**
+ Gets the standard deviation of the Gaussian curve
+ @return the standard deviation of the Gaussian curve
+ */
virtual scalar getStandardDeviation() const;
virtual Gaussian* clone() const FL_IOVERRIDE;
static Term* constructor();
};
-
}
#endif /* FL_GAUSSIAN_H */
diff --git a/fuzzylite/fl/term/GaussianProduct.h b/fuzzylite/fl/term/GaussianProduct.h
index bd1eaaa..e4a500c 100644
--- a/fuzzylite/fl/term/GaussianProduct.h
+++ b/fuzzylite/fl/term/GaussianProduct.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_GAUSSIANPRODUCT_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The GaussianProduct class is an extended Term that represents the
+ two-sided %Gaussian membership function.
+
+ @image html gaussianProduct.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API GaussianProduct : public Term {
- protected:
+ private:
scalar _meanA;
scalar _standardDeviationA;
scalar _meanB;
@@ -47,21 +50,83 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(GaussianProduct)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Provides the parameters of the term
+ @return `"meanA standardDeviationA meanB standardDeviationB [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"meanA standardDeviationA meanB
+ standardDeviationB [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$ h \left((1 - i) + i \times \exp(-(x - \mu_a)^2 /
+ (2\sigma_a^2))\right)
+ \left((1 - j) + j \times \exp(-(x - \mu_b)^2 / (2 \sigma_b)^2)\right)
+ @f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$\mu_a@f$ is the mean of the first GaussianProduct,
+ @f$\sigma_a@f$ is the standard deviation of the first
+ GaussianProduct,
+ @f$\mu_b@f$ is the mean of the second GaussianProduct,
+ @f$\sigma_b@f$ is the standard deviation of the second
+ GaussianProduct,
+ @f$i=\begin{cases}1 & \mbox{if $x \leq \mu_a$} \cr 0
+ &\mbox{otherwise}\end{cases}@f$,
+ @f$j=\begin{cases}1 & \mbox{if $x \geq \mu_b$} \cr 0
+ &\mbox{otherwise}\end{cases}@f$
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the mean of the first %Gaussian curve
+ @param meanA is the mean of the first %Gaussian curve
+ */
virtual void setMeanA(scalar meanA);
+ /**
+ Gets the mean of the first %Gaussian curve
+ @return the mean of the first %Gaussian curve
+ */
virtual scalar getMeanA() const;
- virtual void setStandardDeviationA(scalar sigmaA);
+ /**
+ Sets the standard deviation of the first %Gaussian curve
+ @param standardDeviationA is the standard deviation of the first %Gaussian curve
+ */
+ virtual void setStandardDeviationA(scalar standardDeviationA);
+ /**
+ Gets the standard deviation of the first %Gaussian curve
+ @return the standard deviation of the first %Gaussian curve
+ */
virtual scalar getStandardDeviationA() const;
+ /**
+ Sets the mean of the second %Gaussian curve
+ @param meanB is the mean of the second %Gaussian curve
+ */
virtual void setMeanB(scalar meanB);
+ /**
+ Gets the mean of the second %Gaussian curve
+ @return the mean of the second %Gaussian curve
+ */
virtual scalar getMeanB() const;
- virtual void setStandardDeviationB(scalar sigmaB);
+ /**
+ Sets the standard deviation of the second %Gaussian curve
+ @param standardDeviationB is the standard deviation of the second %Gaussian curve
+ */
+ virtual void setStandardDeviationB(scalar standardDeviationB);
+ /**
+ Gets the standard deviation of the second %Gaussian curve
+ @return the standard deviation of the second %Gaussian curve
+ */
virtual scalar getStandardDeviationB() const;
virtual GaussianProduct* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/term/Linear.h b/fuzzylite/fl/term/Linear.h
index 67ede04..1105a1d 100644
--- a/fuzzylite/fl/term/Linear.h
+++ b/fuzzylite/fl/term/Linear.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_LINEAR_H
@@ -30,8 +22,23 @@
namespace fl {
class Engine;
+ /**
+ The Linear class is a linear polynomial Term expressed as @f$f(x)=
+ \mathbf{c}\mathbf{v}+k = \sum_i c_iv_i + k@f$, where variable @f$x@f$ is
+ not utilized, @f$\mathbf{v}@f$ is a vector of values from the input
+ variables, @f$\mathbf{c}@f$ is a vector of coefficients, and @f$k@f$ is a
+ constant. Hereinafter, the vector @f$\mathbf{c}^\star=\{c_1, \ldots, c_i,
+ \ldots, c_n, k\}@f$ refers to a vector containing the coefficients of
+ @f$\mathbf{c}@f$ and the constant @f$k@f$.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Linear : public Term {
- protected:
+ private:
+ /**Contains the coefficients @f$c_i@f$ and the constant @f$k@f$*/
std::vector<scalar> _coefficients;
const Engine* _engine;
public:
@@ -42,31 +49,131 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Linear)
virtual std::string className() const FL_IOVERRIDE;
+
+ /**
+ Returns the vector @f$\mathbf{c}^\star@f$
+ @return `"c1 ... ci ... cn k"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the values of @f$\mathbf{c}^\star@f$
+ @param parameters as `"c1 ... ci ... cn k"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
- virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
- virtual void set(const std::vector<scalar>& coeffs, const Engine* engine);
+ /**
+ Computes the linear function @f$f(x)=\sum_i c_iv_i +k@f$,
+ where @f$v_i@f$ is the value of the input variable @f$i@f$ registered
+ in the Linear::getEngine()
+ @param x is not utilized
+ @return @f$\sum_i c_ix_i +k@f$
+ */
+ virtual scalar membership(scalar x) const FL_IOVERRIDE;
- virtual void setCoefficients(const std::vector<scalar>& coeffs);
+ /**
+ Sets the vector @f$\mathbf{c}^\star@f$ and the Engine from which
+ vector @f$\mathbf{v}@f$ will be retrieved when necessary
+ @param coefficients is the vector @f$\mathbf{c}^\star@f$
+ @param engine is the engine from which @f$\mathbf{v}@f$ will be
+ retrieved when necessary
+ */
+ virtual void set(const std::vector<scalar>& coefficients, const Engine* engine);
+
+ /**
+ Sets the vector @f$\mathbf{c}^\star@f$ of the linear function
+ @param coefficients is the vector @f$\mathbf{c}^\star@f$
+ */
+ virtual void setCoefficients(const std::vector<scalar>& coefficients);
+ /**
+ Gets the immutable vector @f$\mathbf{c}^\star@f$
+ @return the immutable vector @f$\mathbf{c}^\star@f$
+ */
virtual const std::vector<scalar>& coefficients() const;
+ /**
+ Gets the mutable vector @f$\mathbf{c}^\star@f$
+ @return the mutable vector @f$\mathbf{c}^\star@f$
+ */
virtual std::vector<scalar>& coefficients();
+ /**
+ Sets the engine from which the vector @f$\mathbf{v}@f$ will be
+ obtained upon computing the Linear::membership()
+ @param engine is the engine from which the vector @f$\mathbf{v}@f$
+ will be obtained
+ */
virtual void setEngine(const Engine* engine);
+ /**
+ Gets the engine from which the vector @f$\mathbf{v}@f$ will be
+ obtained upon computing the Linear::membership()
+ @return the engine from which the vector @f$\mathbf{v}@f$ will be
+ obtained
+ */
virtual const Engine* getEngine() const;
virtual Linear* clone() const FL_IOVERRIDE;
+ virtual void updateReference(const Engine* engine) FL_IOVERRIDE;
+
static Term* constructor();
- //Warning: this method is unsafe, make sure you use it correctly.
+ /**
+ Creates a Linear term from a variadic set of coefficients.
+ Beware: this method is unsafe and must be used with care by
+ ensuring:
+
+ - the data type of each variadic arguments is the same, e.g.,
+ @f$(1.0, 2.0, 3.0)@f$ are all fl::scalar%s. You *need* to avoid the
+ case of @f$(1.0, 2, 3.0)@f$, where the second term will be
+ considered as an `int` (different from the others) and cause memory
+ issues due to the difference in size between an `int` and
+ `fl::scalar`; and
+
+ - the number of variadic arguments is exactly the same as the number
+ of input variables in the engine plus one in order to match the
+ size of the vector @f$\mathbf{c}^\star@f$
+
+ @param name is the name of the term
+ @param engine is the engine from which the vector @f$\mathbf{v}@f$
+ will be obtained
+ @param firstCoefficient is the coefficient for the first input
+ variable, namely @f$c_1@f$
+ @param ... is a variadic number of coefficients whose type need to be
+ the same as the first coefficient
+ @return a new Linear term with the given parameters
+ */
template <typename T>
static Linear* create(const std::string& name, const Engine* engine,
- T firstCoefficient, ...); // throw (fl::Exception);
+ T firstCoefficient, ...);
};
-
}
+/**
+ Template implementation
+ */
+
+#include "fl/Engine.h"
+
+namespace fl {
+
+ template <typename T>
+ inline Linear* Linear::create(const std::string& name,
+ const Engine* engine, T firstCoefficient, ...) {
+ if (not engine) throw Exception("[linear error] cannot create term <" + name + "> "
+ "without a reference to the engine", FL_AT);
+ std::vector<scalar> coefficients;
+ coefficients.push_back((scalar) firstCoefficient);
+
+ va_list args;
+ va_start(args, firstCoefficient);
+ for (std::size_t i = 0; i < engine->inputVariables().size(); ++i) {
+ coefficients.push_back((scalar) va_arg(args, T));
+ }
+ va_end(args);
+
+ return new Linear(name, coefficients, engine);
+ }
+}
#endif /* FL_LINEAR_H */
diff --git a/fuzzylite/fl/term/PiShape.h b/fuzzylite/fl/term/PiShape.h
index a0c2f78..24e98ed 100644
--- a/fuzzylite/fl/term/PiShape.h
+++ b/fuzzylite/fl/term/PiShape.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_PISHAPE_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The PiShape class is an extended Term that represents the Pi-shaped curve
+ membership function.
+
+ @image html piShape.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API PiShape : public Term {
- protected:
+ private:
scalar _bottomLeft;
scalar _topLeft;
scalar _topRight;
@@ -47,21 +50,82 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(PiShape)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"bottomLeft topLeft topRight bottomRight [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"bottomLeft topLeft topRight bottomRight
+ [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$\begin{cases}
+ 0h & \mbox{if $x \leq b_l$}\cr
+ 2h \left((x - b_l) / (t_l-b_l)\right)^2 & \mbox{if $x \leq 0.5(a+b)$}\cr
+ h (1 - 2 \left((x - t_l) / (t_l-b_l)\right)^2) & \mbox{if $ x < t_l$}\cr
+ h & \mbox{if $x \leq t_r$}\cr
+ h (1 - 2\left((x - t_r) / (b_r - t_r)\right)^2) & \mbox{if $x \leq 0.5(t_r + b_r)$}\cr
+ 2h \left((x - b_r) / (b_r-t_r)\right)^2 & \mbox{if $x < b_r$} \cr
+ 0h & \mbox{otherwise}
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$b_l@f$ is the bottom left of the PiShape,
+ @f$t_l@f$ is the top left of the PiShape,
+ @f$t_r@f$ is the top right of the PiShape
+ @f$b_r@f$ is the bottom right of the PiShape,
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
- virtual void setBottomLeft(scalar a);
+ /**
+ Sets the bottom-left value of the curve
+ @param bottomLeft is the bottom-left value of the curve
+ */
+ virtual void setBottomLeft(scalar bottomLeft);
+ /**
+ Gets the bottom-left value of the curve
+ @return the bottom-left value of the curve
+ */
virtual scalar getBottomLeft() const;
- virtual void setTopLeft(scalar b);
+ /**
+ Sets the top-left value of the curve
+ @param topLeft is the top-left value of the curve
+ */
+ virtual void setTopLeft(scalar topLeft);
+ /**
+ Gets the top-left value of the curve
+ @return the top-left value of the curve
+ */
virtual scalar getTopLeft() const;
- virtual void setTopRight(scalar d);
+ /**
+ Sets the top-right value of the curve
+ @param topRight is the top-right value of the curve
+ */
+ virtual void setTopRight(scalar topRight);
+ /**
+ Gets the top-right value of the curve
+ @return the top-right value of the curve
+ */
virtual scalar getTopRight() const;
- virtual void setBottomRight(scalar c);
+ /**
+ Sets the bottom-right value of the curve
+ @param bottomRight is the bottom-right value of the curve
+ */
+ virtual void setBottomRight(scalar bottomRight);
+ /**
+ Gets the bottom-right value of the curve
+ @return the bottom-right value of the curve
+ */
virtual scalar getBottomRight() const;
virtual PiShape* clone() const FL_IOVERRIDE;
@@ -69,6 +133,5 @@ namespace fl {
static Term* constructor();
};
}
-
#endif /* FL_PISHAPE_H */
diff --git a/fuzzylite/fl/term/Ramp.h b/fuzzylite/fl/term/Ramp.h
index 63a683c..dc49301 100644
--- a/fuzzylite/fl/term/Ramp.h
+++ b/fuzzylite/fl/term/Ramp.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_RAMP_H
@@ -29,14 +21,30 @@
namespace fl {
+ /**
+ The Ramp class is an edge Term that represents the ramp membership
+ function.
+
+ @image html ramp.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Ramp : public Term {
- protected:
+ private:
scalar _start, _end;
public:
+ /**
+ Direction is an enumerator that indicates the direction of the ramp.
+ */
enum Direction {
- POSITIVE, ZERO, NEGATIVE
+ /** `(_/)` increases to the right */ Positive,
+ /** `(--)` slope is zero */ Zero,
+ /** `(\\_)` increases to the left */ Negative
};
explicit Ramp(const std::string& name = "",
scalar start = fl::nan,
@@ -46,17 +54,76 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Ramp)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"start end [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"start end [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return
+ @f$\begin{cases}
+
+ 0h & \mbox{if $x = e$}\cr
+
+ \begin{cases}
+ 0h & \mbox{if $x \leq s$}\cr
+ 1h & \mbox{if $x \geq e$}\cr
+ h (x - s) / (e - s) & \mbox{otherwise}\cr
+ \end{cases} & \mbox{if $s < e$}\cr
+
+ \begin{cases}
+ 0h & \mbox{if $x \geq s$}\cr
+ 1h & \mbox{if $x \leq e$}\cr
+ h (s - x) / (s - e) & \mbox{otherwise}
+ \end{cases} & \mbox{if $s > e$}\cr
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$s@f$ is the start of the Ramp,
+ @f$e@f$ is the end of the Ramp
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ virtual scalar tsukamoto(scalar activationDegree,
+ scalar minimum, scalar maximum) const FL_IOVERRIDE;
+
+ virtual bool isMonotonic() const FL_IOVERRIDE;
+
+ /**
+ Sets the start of the ramp
+ @param start is the start of the ramp
+ */
virtual void setStart(scalar start);
+ /**
+ Gets the start of the ramp
+ @return the start of the ramp
+ */
virtual scalar getStart() const;
+ /**
+ Sets the end of the ramp
+ @param end is the end of the ramp
+ */
virtual void setEnd(scalar end);
+ /**
+ Gets the end of the ramp
+ @return the end of the ramp
+ */
virtual scalar getEnd() const;
+ /**
+ Returns the direction of the ramp
+ @return the direction of the ramp
+ */
virtual Direction direction() const;
virtual Ramp* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/term/Rectangle.h b/fuzzylite/fl/term/Rectangle.h
index 23b5eda..0e29cd2 100644
--- a/fuzzylite/fl/term/Rectangle.h
+++ b/fuzzylite/fl/term/Rectangle.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_RECTANGLE_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The Rectangle class is a basic Term that represents the rectangle
+ membership function.
+
+ @image html rectangle.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Rectangle : public Term {
- protected:
+ private:
scalar _start, _end;
public:
@@ -42,21 +45,58 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Rectangle)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"start end [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"start end [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$\begin{cases}
+ 1h & \mbox{if $x \in [s, e]$} \cr
+ 0h & \mbox{otherwise}
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$s@f$ is the start of the Rectangle,
+ @f$e@f$ is the end of the Rectangle.
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the start of the rectangle
+ @param start is the start of the rectangle
+ */
virtual void setStart(scalar start);
+ /**
+ Gets the start of the rectangle
+ @return the start of the rectangle
+ */
virtual scalar getStart() const;
+ /**
+ Sets the end of the rectangle
+ @param end is the end of the rectangle
+ */
virtual void setEnd(scalar end);
+ /**
+ Gets the end of the rectangle
+ @return the end of the rectangle
+ */
virtual scalar getEnd() const;
virtual Rectangle* clone() const FL_IOVERRIDE;
static Term* constructor();
};
-
}
#endif /* FL_RECTANGLE_H */
diff --git a/fuzzylite/fl/term/SShape.h b/fuzzylite/fl/term/SShape.h
index 0891357..1d107a5 100644
--- a/fuzzylite/fl/term/SShape.h
+++ b/fuzzylite/fl/term/SShape.h
@@ -1,28 +1,19 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
-
#ifndef FL_SSHAPE_H
#define FL_SSHAPE_H
@@ -30,8 +21,19 @@
namespace fl {
+ /**
+ The SShape class is an edge Term that represents the S-shaped membership
+ function.
+
+ @image html sShape.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API SShape : public Term {
- protected:
+ private:
scalar _start, _end;
public:
@@ -43,15 +45,59 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(SShape)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"start end [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"start end [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$\begin{cases}
+ 0h & \mbox{if $x \leq s$} \cr
+ h(2 \left((x - s) / (e-s)\right)^2) & \mbox{if $x \leq 0.5(s+e)$}\cr
+ h(1 - 2\left((x - e) / (e-s)\right)^2) & \mbox{if $x < e$}\cr
+ 1h & \mbox{otherwise}
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$s@f$ is the start of the SShape,
+ @f$e@f$ is the end of the SShape.
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ virtual scalar tsukamoto(scalar activationDegree,
+ scalar minimum, scalar maximum) const FL_IOVERRIDE;
+
+ virtual bool isMonotonic() const FL_IOVERRIDE;
+
+ /**
+ Sets the start of the edge
+ @param start is the start of the edge
+ */
virtual void setStart(scalar start);
+ /**
+ Gets the start of the edge
+ @return the start of the edge
+ */
virtual scalar getStart() const;
+ /**
+ Sets the end of the edge
+ @param end is the end of the edge
+ */
virtual void setEnd(scalar end);
+ /**
+ Gets the end of the edge
+ @return the end of the edge
+ */
virtual scalar getEnd() const;
virtual SShape* clone() const FL_IOVERRIDE;
@@ -59,6 +105,5 @@ namespace fl {
static Term* constructor();
};
}
-
#endif /* FL_SSHAPE_H */
diff --git a/fuzzylite/fl/term/Sigmoid.h b/fuzzylite/fl/term/Sigmoid.h
index b37b1be..bde9c2f 100644
--- a/fuzzylite/fl/term/Sigmoid.h
+++ b/fuzzylite/fl/term/Sigmoid.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SIGMOID_H
@@ -29,14 +21,31 @@
namespace fl {
+ /**
+ The Sigmoid class is an edge Term that represents the sigmoid membership
+ function.
+
+ @image html sigmoid.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Sigmoid : public Term {
- protected:
+ private:
scalar _inflection;
scalar _slope;
public:
+ /**
+ Direction is an enumerator that indicates the direction of the
+ sigmoid.
+ */
enum Direction {
- POSITIVE, ZERO, NEGATIVE
+ /** `(_/)` increases to the right */ Positive,
+ /** `(--)` slope is zero */ Zero,
+ /** `(\\_)` increases to the left */ Negative
};
explicit Sigmoid(const std::string& name = "",
scalar inflection = fl::nan,
@@ -46,23 +55,66 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Sigmoid)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"inflection slope [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"inflection slope [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$ h / (1 + \exp(-s(x-i)))@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$s@f$ is the slope of the Sigmoid,
+ @f$i@f$ is the inflection of the Sigmoid
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ virtual scalar tsukamoto(scalar activationDegree,
+ scalar minimum, scalar maximum) const FL_IOVERRIDE;
+
+ virtual bool isMonotonic() const FL_IOVERRIDE;
+
+ /**
+ Sets the inflection of the sigmoid
+ @param inflection is the inflection of the sigmoid
+ */
virtual void setInflection(scalar inflection);
+ /**
+ Gets the inflection of the sigmoid
+ @return the inflection of the sigmoid
+ */
virtual scalar getInflection() const;
+ /**
+ Sets the slope of the sigmoid
+ @param slope is the slope of the sigmoid
+ */
virtual void setSlope(scalar slope);
+ /**
+ Gets the slope of the sigmoid
+ @return the slope of the sigmoid
+ */
virtual scalar getSlope() const;
+ /**
+ Returns the direction of the sigmoid
+ @return the direction of the sigmoid
+ */
virtual Direction direction() const;
virtual Sigmoid* clone() const FL_IOVERRIDE;
static Term* constructor();
};
-
}
#endif /* FL_SIGMOID_H */
diff --git a/fuzzylite/fl/term/SigmoidDifference.h b/fuzzylite/fl/term/SigmoidDifference.h
index 020f164..4861584 100644
--- a/fuzzylite/fl/term/SigmoidDifference.h
+++ b/fuzzylite/fl/term/SigmoidDifference.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SIGMOIDDIFFERENCE_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The SigmoidDifference class is an extended Term that represents the
+ difference between two sigmoidal membership functions.
+
+ @image html sigmoidDifference.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API SigmoidDifference : public Term {
- protected:
+ private:
scalar _left;
scalar _rising;
scalar _falling;
@@ -47,21 +50,76 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(SigmoidDifference)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"left rising falling right [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"left rising falling right [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$ h (a-b)@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$a= 1 / (1 + \exp(-s_l \times (x - i_l))) @f$,
+ @f$b = 1 / (1 + \exp(-s_r \times (x - i_r)))@f$,
+ @f$i_l@f$ is the left inflection of the SigmoidDifference,
+ @f$s_l@f$ is the left slope of the SigmoidDifference,
+ @f$i_r@f$ is the right inflection of the SigmoidDifference,
+ @f$s_r@f$ is the right slope of the SigmoidDifference
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the inflection of the left sigmoidal curve
+ @param leftInflection is the inflection of the left sigmoidal curve
+ */
virtual void setLeft(scalar leftInflection);
+ /**
+ Gets the inflection of the left sigmoidal curve
+ @return the inflection of the left sigmoidal curve
+ */
virtual scalar getLeft() const;
+ /**
+ Sets the slope of the left sigmoidal curve
+ @param risingSlope is the slope of the left sigmoidal curve
+ */
virtual void setRising(scalar risingSlope);
+ /**
+ Gets the slope of the left sigmoidal curve
+ @return the slope of the left sigmoidal curve
+ */
virtual scalar getRising() const;
+ /**
+ Sets the slope of the right sigmoidal curve
+ @param fallingSlope is the slope of the right sigmoidal curve
+ */
virtual void setFalling(scalar fallingSlope);
+ /**
+ Gets the slope of the right sigmoidal curve
+ @return the slope of the right sigmoidal curve
+ */
virtual scalar getFalling() const;
+ /**
+ Sets the inflection of the right sigmoidal curve
+ @param rightInflection is the inflection of the right sigmoidal curve
+ */
virtual void setRight(scalar rightInflection);
+ /**
+ Gets the inflection of the right sigmoidal curve
+ @return the inflection of the right sigmoidal curve
+ */
virtual scalar getRight() const;
virtual SigmoidDifference* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/term/SigmoidProduct.h b/fuzzylite/fl/term/SigmoidProduct.h
index cb83f30..19cd4d7 100644
--- a/fuzzylite/fl/term/SigmoidProduct.h
+++ b/fuzzylite/fl/term/SigmoidProduct.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SIGMOIDPRODUCT_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The SigmoidProduct class is an extended Term that represents the product
+ of two sigmoidal membership functions.
+
+ @image html sigmoidProduct.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API SigmoidProduct : public Term {
- protected:
+ private:
scalar _left;
scalar _rising;
scalar _falling;
@@ -47,23 +50,79 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(SigmoidProduct)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"left rising falling right [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"left rising falling right [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$ h (a \times b)@f$
+
+ where @f$h@f$ is the height,
+ @f$a= 1 / (1 + \exp(-s_l *\times (x - i_l))) @f$,
+ @f$b = 1 / (1 + \exp(-s_r \times (x - i_r)))@f$,
+ @f$i_l@f$ is the left inflection of the SigmoidProduct,
+ @f$s_l@f$ is the left slope of the SigmoidProduct,
+ @f$i_r@f$ is the right inflection of the SigmoidProduct,
+ @f$s_r@f$ is the right slope of the SigmoidProduct
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the inflection of the left sigmoidal curve
+ @param leftInflection is the inflection of the left sigmoidal curve
+ */
virtual void setLeft(scalar leftInflection);
+ /**
+ Gets the inflection of the left sigmoidal curve
+ @return the inflection of the left sigmoidal curve
+ */
virtual scalar getLeft() const;
+ /**
+ Sets the slope of the left sigmoidal curve
+ @param risingSlope is the slope of the left sigmoidal curve
+ */
virtual void setRising(scalar risingSlope);
+ /**
+ Gets the slope of the left sigmoidal curve
+ @return the slope of the left sigmoidal curve
+ */
virtual scalar getRising() const;
+ /**
+ Sets the slope of the right sigmoidal curve
+ @param fallingSlope is the slope of the right sigmoidal curve
+ */
virtual void setFalling(scalar fallingSlope);
+ /**
+ Gets the slope of the right sigmoidal curve
+ @return the slope of the right sigmoidal curve
+ */
virtual scalar getFalling() const;
+ /**
+ Sets the inflection of the right sigmoidal curve
+ @param rightInflection is the inflection of the right sigmoidal curve
+ */
virtual void setRight(scalar rightInflection);
+ /**
+ Gets the inflection of the right sigmoidal curve
+ @return the inflection of the right sigmoidal curve
+ */
virtual scalar getRight() const;
+
virtual SigmoidProduct* clone() const FL_IOVERRIDE;
static Term* constructor();
diff --git a/fuzzylite/fl/term/Spike.h b/fuzzylite/fl/term/Spike.h
index 7e520c9..7349307 100644
--- a/fuzzylite/fl/term/Spike.h
+++ b/fuzzylite/fl/term/Spike.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_SPIKE_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The Spike class is an extended Term that represents the spike membership
+ function.
+
+ @image html spike.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 5.0
+ */
class FL_API Spike : public Term {
- protected:
+ private:
scalar _center, _width;
public:
explicit Spike(const std::string& name = "",
@@ -41,15 +44,49 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Spike)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"center width [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"center width [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$h \times \exp(-|10 / w (x - c)|)@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$w@f$ is the width of the Spike,
+ @f$c@f$ is the center of the Spike
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the center of the spike
+ @param center is the center of the spike
+ */
virtual void setCenter(scalar center);
+ /**
+ Gets the center of the spike
+ @return the center of the spike
+ */
virtual scalar getCenter() const;
+ /**
+ Sets the width of the spike
+ @param width is the width of the spike
+ */
virtual void setWidth(scalar width);
+ /**
+ Gets the width of the spike
+ @return the width of the spike
+ */
virtual scalar getWidth() const;
virtual Spike* clone() const FL_IOVERRIDE;
@@ -57,6 +94,5 @@ namespace fl {
static Term* constructor();
};
}
-
#endif /* FL_SPIKE_H */
diff --git a/fuzzylite/fl/term/Term.h b/fuzzylite/fl/term/Term.h
index 6c2b2b1..31dcabd 100644
--- a/fuzzylite/fl/term/Term.h
+++ b/fuzzylite/fl/term/Term.h
@@ -1,34 +1,26 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
-
#ifndef FL_TERM_H
#define FL_TERM_H
#include "fl/fuzzylite.h"
#include "fl/Operation.h"
+#include "fl/Complexity.h"
#include <cmath>
#include <string>
@@ -37,9 +29,33 @@
namespace fl {
class Engine;
+ /**
+ The Term class is the abstract class for linguistic terms. The linguistic
+ terms in this library can be divided in four groups as: `basic`,
+ `extended`, `edge`, and `function`. The `basic` terms are Triangle,
+ Trapezoid, Rectangle, and Discrete. The `extended` terms are Bell,
+ Binary, Cosine, Gaussian, GaussianProduct, PiShape, SigmoidDifference,
+ SigmoidProduct, and Spike. The `edge` terms are Concave, Ramp, Sigmoid,
+ SShape, and ZShape. The `function` terms are Constant, Linear, and
+ Function.
+
+ In the figure below, the `basic` terms are represented in the first
+ column, and the `extended` terms in the second and third columns. The
+ `edge` terms are represented in the fifth and sixth rows, and the
+ `function` terms in the last row.
+
+ @image html terms.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Variable
+ @see InputVariable
+ @see OutputVariable
+ @since 4.0
+ */
class FL_API Term {
- protected:
+ private:
std::string _name;
+ protected:
scalar _height;
public:
@@ -47,25 +63,103 @@ namespace fl {
virtual ~Term();
FL_DEFAULT_COPY_AND_MOVE(Term)
+ /**
+ Sets the name of the term
+ @param name is the name of term
+ */
virtual void setName(const std::string& name);
+ /**
+ Gets the name of the term
+ @return the name of the term
+ */
virtual std::string getName() const;
+ /**
+ Sets the height of the term
+ @param height is the height of the term
+ */
virtual void setHeight(scalar height);
+ /**
+ Gets the height of the term
+ @return the height of the term
+ */
virtual scalar getHeight() const;
+ /**
+ Returns the representation of the term in the FuzzyLite Language
+ @return the representation of the term in FuzzyLite Language
+ @see FllExporter
+ */
virtual std::string toString() const;
+ /**
+ Returns the name of the class of the term
+ @return the name of the class of the term
+ */
virtual std::string className() const = 0;
+ /**
+ Returns the parameters to configure the term. The parameters are
+ separated by spaces. If there is one additional parameter, the
+ parameter will be considered as the height of the term; otherwise,
+ the height will be set to @f$1.0@f$
+ @return the parameters to configure the term (@see Term::configure())
+ */
virtual std::string parameters() const = 0;
+ /**
+ Configures the term with the given parameters. The parameters are
+ separated by spaces. If there is one additional parameter, the
+ parameter will be considered as the height of the term; otherwise,
+ the height will be set to @f$1.0@f$
+ @param parameters is the parameters to configure the term
+ */
virtual void configure(const std::string& parameters) = 0;
+ /**
+ Computes the estimated complexity of evaluating the membership function
+ @return the estimated complexity of evaluating the membership function
+ */
+ virtual Complexity complexity() const = 0;
+
+ /**
+ Computes the membership function value at @f$x@f$
+ @param x
+ @return the membership function value @f$\mu(x)@f$
+ */
virtual scalar membership(scalar x) const = 0;
+ /**
+ Creates a clone of the term
+ @return a clone of the term
+ */
virtual Term* clone() const = 0;
-
- //FIXME: This should not be static, and may not be here either.
- static void updateReference(Term* term, const Engine* engine);
- };
+ /**
+ Updates the references (if any) to point to the current engine (useful
+ when cloning engines or creating terms within Importer objects
+ @param engine is the engine to which this term belongs to
+ */
+ virtual void updateReference(const Engine* engine);
+
+ /**
+ For monotonic terms, computes the tsukamoto value of the term for the
+ given activation degree @f$\alpha@f$, that is,
+ @f$ g_j(\alpha) = \{ z \in\mathbb{R} : \mu_j(z) = \alpha \} $@f. If
+ the term is not monotonic (or does not override this method) the
+ method computes the membership function @f$\mu(\alpha)@f$.
+ @param activationDegree is the activationDegree
+ @param minimum is the minimum value of the range of the term
+ @param maximum is the maximum value of the range of the term
+ @return the tsukamoto value of the term for the given activation degree
+ if the term is monotonic (or overrides this method), or
+ the membership function for the activation degree otherwise.
+ */
+ virtual scalar tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const;
+
+ /**
+ Indicates whether the term is monotonic.
+ @return whether the term is monotonic.
+ */
+ virtual bool isMonotonic() const;
+ };
}
#endif /* FL_TERM_H */
diff --git a/fuzzylite/fl/term/Trapezoid.h b/fuzzylite/fl/term/Trapezoid.h
index f896997..ebf5ed8 100644
--- a/fuzzylite/fl/term/Trapezoid.h
+++ b/fuzzylite/fl/term/Trapezoid.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_TRAPEZOID_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The Trapezoid class is a basic Term that represents the trapezoidal
+ membership function.
+
+ @image html trapezoid.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Trapezoid : public Term {
- protected:
+ private:
scalar _vertexA, _vertexB, _vertexC, _vertexD;
public:
explicit Trapezoid(const std::string& name = "",
@@ -43,27 +46,84 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Trapezoid)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"vertexA vertexB vertexC vertexD [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"vertexA vertexB vertexC vertexD [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$\begin{cases}
+ 0h & \mbox{if $x \not\in[a,d]$}\cr
+ h \times \min(1, (x - a) / (b - a)) & \mbox{if $x < b$}\cr
+ 1h & \mbox{if $x \leq c$}\cr
+ h (d - x) / (d - c) & \mbox{if $x < d$}\cr
+ 0h & \mbox{otherwise}
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$a@f$ is the first vertex of the Trapezoid,
+ @f$b@f$ is the second vertex of the Trapezoid,
+ @f$c@f$ is the third vertex of the Trapezoid,
+ @f$d@f$ is the fourth vertex of the Trapezoid
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the first vertex of the trapezoid
+ @param a is the first vertex of the trapezoid
+ */
virtual void setVertexA(scalar a);
+ /**
+ Gets the first vertex of the trapezoid
+ @return the first vertex of the trapezoid
+ */
virtual scalar getVertexA() const;
+ /**
+ Sets the second vertex of the trapezoid
+ @param b is the second vertex of the trapezoid
+ */
virtual void setVertexB(scalar b);
+ /**
+ Gets the second vertex of the trapezoid
+ @return the second vertex of the trapezoid
+ */
virtual scalar getVertexB() const;
+ /**
+ Sets the third vertex of the trapezoid
+ @param c is the third vertex of the trapezoid
+ */
virtual void setVertexC(scalar c);
+ /**
+ Gets the third vertex of the trapezoid
+ @return the third vertex of the trapezoid
+ */
virtual scalar getVertexC() const;
+ /**
+ Sets the fourth vertex of the trapezoid
+ @param d is the fourth vertex of the trapezoid
+ */
virtual void setVertexD(scalar d);
+ /**
+ Gets the fourth vertex of the trapezoid
+ @return the fourth vertex of the trapezoid
+ */
virtual scalar getVertexD() const;
virtual Trapezoid* clone() const FL_IOVERRIDE;
static Term* constructor();
};
-
}
#endif /* FL_TRAPEZOID_H */
diff --git a/fuzzylite/fl/term/Triangle.h b/fuzzylite/fl/term/Triangle.h
index 9311687..8b16fa9 100644
--- a/fuzzylite/fl/term/Triangle.h
+++ b/fuzzylite/fl/term/Triangle.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_TRIANGLE_H
@@ -29,8 +21,19 @@
namespace fl {
+ /**
+ The Triangle class is a basic Term that represents the triangular
+ membership function.
+
+ @image html triangle.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
class FL_API Triangle : public Term {
- protected:
+ private:
scalar _vertexA;
scalar _vertexB;
scalar _vertexC;
@@ -44,18 +47,66 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(Triangle)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"vertexA vertexB vertexC [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"vertexA vertexB vertexC [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$\begin{cases}
+ 0h & \mbox{if $x \not\in [a,c]$}\cr
+ 1h & \mbox{if $x = b$}\cr
+ h (x - a) / (b - a) & \mbox{if $x < b$} \cr
+ h (c - x) / (c - b) & \mbox{otherwise}
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$a@f$ is the first vertex of the Triangle,
+ @f$b@f$ is the second vertex of the Triangle,
+ @f$c@f$ is the third vertex of the Triangle
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ /**
+ Sets the first vertex of the triangle
+ @param a is the first vertex of the triangle
+ */
virtual void setVertexA(scalar a);
+ /**
+ Gets the first vertex of the triangle
+ @return the first vertex of the triangle
+ */
virtual scalar getVertexA() const;
+ /**
+ Sets the second vertex of the triangle
+ @param b is the second vertex of the triangle
+ */
virtual void setVertexB(scalar b);
+ /**
+ Gets the second vertex of the triangle
+ @return the second vertex of the triangle
+ */
virtual scalar getVertexB() const;
+ /**
+ Sets the third vertex of the triangle
+ @param c is the third vertex of the triangle
+ */
virtual void setVertexC(scalar c);
+ /**
+ Gets the third vertex of the triangle
+ @return the third vertex of the triangle
+ */
virtual scalar getVertexC() const;
virtual Triangle* clone() const FL_IOVERRIDE;
@@ -63,6 +114,5 @@ namespace fl {
static Term* constructor();
};
-
}
#endif /* FL_TRIANGLE_H */
diff --git a/fuzzylite/fl/term/ZShape.h b/fuzzylite/fl/term/ZShape.h
index b53906e..1737891 100644
--- a/fuzzylite/fl/term/ZShape.h
+++ b/fuzzylite/fl/term/ZShape.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_ZSHAPE_H
@@ -29,8 +21,20 @@
namespace fl {
+ /**
+ The ZShape class is an edge Term that represents the Z-shaped membership
+ function.
+
+ @image html zShape.svg
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Term
+ @see Variable
+ @since 4.0
+ */
+
class FL_API ZShape : public Term {
- protected:
+ private:
scalar _start, _end;
public:
@@ -42,15 +46,59 @@ namespace fl {
FL_DEFAULT_COPY_AND_MOVE(ZShape)
virtual std::string className() const FL_IOVERRIDE;
+ /**
+ Returns the parameters of the term
+ @return `"start end [height]"`
+ */
virtual std::string parameters() const FL_IOVERRIDE;
+ /**
+ Configures the term with the parameters
+ @param parameters as `"start end [height]"`
+ */
virtual void configure(const std::string& parameters) FL_IOVERRIDE;
+ virtual Complexity complexity() const FL_IOVERRIDE;
+ /**
+ Computes the membership function evaluated at @f$x@f$
+ @param x
+ @return @f$ \begin{cases}
+ 1h & \mbox{if $x \leq s$} \cr
+ h(1 - 2\left((x - s) / (e-s)\right)^2) & \mbox{if $x \leq 0.5(s+e)$}\cr
+ h(2 \left((x - e) / (e-s)\right)^2) & \mbox{if $x < e$}\cr
+ 0h & \mbox{otherwise}
+ \end{cases}@f$
+
+ where @f$h@f$ is the height of the Term,
+ @f$s@f$ is the start of the ZShape,
+ @f$e@f$ is the end of the ZShape.
+ */
virtual scalar membership(scalar x) const FL_IOVERRIDE;
+ virtual scalar tsukamoto(scalar activationDegree,
+ scalar minimum, scalar maximum) const FL_IOVERRIDE;
+
+ virtual bool isMonotonic() const FL_IOVERRIDE;
+
+ /**
+ Sets the start of the edge
+ @param start is the start of the edge
+ */
virtual void setStart(scalar start);
+ /**
+ Gets the start of the edge
+ @return the start of the edge
+ */
virtual scalar getStart() const;
+ /**
+ Sets the end of the edge
+ @param end is the end of the edge
+ */
virtual void setEnd(scalar end);
+ /**
+ Gets the end of the edge
+ @return the end of the edge
+ */
virtual scalar getEnd() const;
virtual ZShape* clone() const FL_IOVERRIDE;
diff --git a/fuzzylite/fl/variable/InputVariable.h b/fuzzylite/fl/variable/InputVariable.h
index bba3c7d..3201e3d 100644
--- a/fuzzylite/fl/variable/InputVariable.h
+++ b/fuzzylite/fl/variable/InputVariable.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_INPUTVARIABLE_H
@@ -29,9 +21,17 @@
namespace fl {
+ /**
+ The InputVariable class is a Variable that represents an input of the
+ fuzzy logic controller.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Variable
+ @see OutputVariable
+ @see Term
+ @since 4.0
+ */
class FL_API InputVariable : public Variable {
- protected:
- scalar _inputValue;
public:
explicit InputVariable(const std::string& name = "",
scalar minimum = -fl::inf,
@@ -39,14 +39,22 @@ namespace fl {
virtual ~InputVariable() FL_IOVERRIDE;
FL_DEFAULT_COPY_AND_MOVE(InputVariable)
- virtual void setInputValue(scalar inputValue);
- virtual scalar getInputValue() const;
+ /**
+ Evaluates the membership function of the current input value @f$x@f$
+ for each term @f$i@f$, resulting in a fuzzy input value in the form
+ @f$\tilde{x}=\sum_i{\mu_i(x)/i}@f$. This is equivalent to a call to
+ Variable::fuzzify() passing @f$x@f$ as input value
+ @return the fuzzy input value expressed as @f$\sum_i{\mu_i(x)/i}@f$
+ */
virtual std::string fuzzyInputValue() const;
+ virtual Variable::Type type() const FL_IOVERRIDE;
+
virtual std::string toString() const FL_IOVERRIDE;
- };
+ virtual InputVariable* clone() const FL_IOVERRIDE;
+ };
}
#endif /* FL_INPUTVARIABLE_H */
diff --git a/fuzzylite/fl/variable/OutputVariable.h b/fuzzylite/fl/variable/OutputVariable.h
index 9d00aaf..b79b13c 100644
--- a/fuzzylite/fl/variable/OutputVariable.h
+++ b/fuzzylite/fl/variable/OutputVariable.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_OUTPUTVARIABLE_H
@@ -27,64 +19,208 @@
#include "fl/variable/Variable.h"
+#include "fl/term/Activated.h"
+#include "fl/term/Aggregated.h"
+
+#include "fl/defuzzifier/Defuzzifier.h"
+
namespace fl {
- class Accumulated;
- class Defuzzifier;
+ /**
+ The OutputVariable class is a Variable that represents an output of the
+ fuzzy logic controller. During the activation of a RuleBlock, the
+ Activated terms of each Rule will be Aggregated in the
+ OutputVariable::fuzzyOutput(), which represents a fuzzy set hereinafter
+ referred to as @f$\tilde{y}@f$. The defuzzification of @f$\tilde{y}@f$
+ translates the fuzzy output value @f$\tilde{y}@f$ into a crisp output
+ value @f$y@f$, which can be retrieved using Variable::getValue(). The
+ value of the OutputVariable is computed and automatically stored when
+ calling OutputVariable::defuzzify(), but the value depends on the
+ following properties (expressed in the FuzzyLite Language):
+
+ - Property `default: scalar` overrides the output value @f$y@f$ with
+ the given fl::scalar whenever the defuzzification process results in
+ a non-finite value (i.e., fl::nan and fl::inf). For example,
+ considering `default: 0.0`, if RuleBlock::activate() does not
+ activate any rules whose Consequent contribute to the OutputVariable,
+ then the fuzzy output value is empty, the Defuzzifier does not
+ operate, and hence @f$y=0.0@f$. By default, `default: NaN`. Relevant
+ methods are OutputVariable::getDefaultValue() and
+ OutputVariable::setDefaultValue().
+
+ - Property `lock-previous: boolean`, if enabled, overrides the output
+ value @f$y^t@f$ at time @f$t@f$ with the previously defuzzified valid
+ output value @f$y^{t-1}@f$ if defuzzification process results in a
+ non-finite value (i.e., fl::nan and fl::inf). When enabled, the
+ property takes precedence over `default` if @f$y^{t-1}@f$ is a finite
+ value. By default, `lock-previous: false`, @f$y^{t-1}=\mbox{NaN}@f$
+ for @f$t=0@f$, and @f$y^{t-1}=\mbox{NaN}@f$ when
+ OutputVariable::clear(). Relevant methods are
+ OutputVariable::lockPreviousValue(),
+ OutputVariable::isLockPreviousValue,
+ OutputVariable::getPreviousValue(), and
+ OutputVariable::setPreviousValue().
+
+ - Property `lock-range: boolean` overrides the output value @f$y@f$ to
+ enforce it lies within the range of the variable determined by
+ Variable::getMinimum() and Variable::getMaximum(). When enabled, this
+ property takes precedence over `lock-previous` and `default`. For
+ example, considering `range: -1.0 1.0` and `lock-range: true`,
+ @f$y=-1.0@f$ if the result from the Defuzzifier is smaller than
+ `-1.0`, and @f$y=1.0@f$ if the result from the Defuzzifier is greater
+ than `1.0`. The property `lock-range` was introduced in version 5.0
+ to substitute the property `lock-valid` in version 4.0. By default,
+ `lock-range: false`. Relevant methods are
+ Variable::lockValueInRange(), Variable::isLockValueInRange(),
+ Variable::getMinimum(), and Variable::getMaximum()
+
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see Variable
+ @see InputVariable
+ @see RuleBlock::activate()
+ @see Term
+ @since 4.0
+ */
class FL_API OutputVariable : public Variable {
private:
- void copyFrom(const OutputVariable& other);
- protected:
- FL_unique_ptr<Accumulated> _fuzzyOutput;
+ FL_unique_ptr<Aggregated> _fuzzyOutput;
FL_unique_ptr<Defuzzifier> _defuzzifier;
- scalar _outputValue;
- scalar _previousOutputValue;
+ scalar _previousValue;
scalar _defaultValue;
- bool _lockOutputValueInRange;
- bool _lockPreviousOutputValue;
+ bool _lockPreviousValue;
+
+ void copyFrom(const OutputVariable& other);
public:
explicit OutputVariable(const std::string& name = "",
scalar minimum = -fl::inf, scalar maximum = fl::inf);
- OutputVariable(const OutputVariable& other);
+ explicit OutputVariable(const OutputVariable& other);
OutputVariable& operator=(const OutputVariable& other);
virtual ~OutputVariable() FL_IOVERRIDE;
FL_DEFAULT_MOVE(OutputVariable)
- virtual Accumulated* fuzzyOutput() const;
+ /**
+ Gets the fuzzy output value @f$\tilde{y}@f$
+ @return the fuzzy output value @f$\tilde{y}@f$
+ @todo rename to fuzzyValue
+ */
+ virtual Aggregated* fuzzyOutput() const;
virtual void setName(const std::string& name) FL_IOVERRIDE;
virtual void setMinimum(scalar minimum) FL_IOVERRIDE;
virtual void setMaximum(scalar maximum) FL_IOVERRIDE;
+ /**
+ Sets the defuzzifier of the output variable
+ @param defuzzifier is the defuzzifier of the output variable
+ */
virtual void setDefuzzifier(Defuzzifier* defuzzifier);
+ /**
+ Gets the defuzzifier of the output variable
+ @return the defuzzifier of the output variable
+ */
virtual Defuzzifier* getDefuzzifier() const;
- virtual void setOutputValue(scalar outputValue);
- virtual scalar getOutputValue() const;
-
- virtual void setPreviousOutputValue(scalar defuzzifiedValue);
- virtual scalar getPreviousOutputValue() const;
-
+ /**
+ Sets the aggregation operator
+ @param aggregation is the aggregation
+ */
+ virtual void setAggregation(SNorm* aggregation);
+
+ /**
+ Gets the aggregation operator
+ @return the aggregation operator
+ */
+ virtual SNorm* getAggregation() const;
+
+ /**
+ Sets the previous value of the output variable
+ @param previousValue is the previous value of the output variable
+ */
+ virtual void setPreviousValue(scalar previousValue);
+ /**
+ Gets the previous value of the output variable
+ @return the previous value of the output variable
+ */
+ virtual scalar getPreviousValue() const;
+
+ /**
+ Sets the default value of the output variable
+ @param defaultValue is the default value of the output variable
+ */
virtual void setDefaultValue(scalar defaultValue);
+ /**
+ Gets the default value of the output variable
+ @return the default value of the output variable
+ */
virtual scalar getDefaultValue() const;
- virtual void setLockOutputValueInRange(bool lockOutputValueInRange);
- virtual bool isLockedOutputValueInRange() const;
-
- virtual void setLockPreviousOutputValue(bool lockPreviousOutputValue);
- virtual bool isLockedPreviousOutputValue() const;
-
+ /**
+ Sets whether to lock the previous value of the output variable
+ @param lockPreviousValue indicates whether to lock the previous value
+ of the output variable
+ */
+ virtual void setLockPreviousValue(bool lockPreviousValue);
+ /**
+ Gets whether to lock the previous value of the output variable
+ @return whether the previous output value of the output variable is
+ locked
+ */
+ virtual bool isLockPreviousValue() const;
+
+ using Variable::complexity;
+ /**
+ Computes the estimated complexity of defuzzifying the activated term
+ with the current configuration of the variable (namely aggregation and
+ defuzzifier
+ @param term is the activated term
+ @return the estimated complexity of defuzzifying the activated term
+ with the current configuration of the variable
+ */
+ virtual Complexity complexity(const Activated& term) const;
+ /**
+ Computes the estimated complexity of aggregating and defuzzifying all
+ the terms in the variable.
+ @return the estimated complexity of aggregating and defuzzifying all
+ the terms in the variable.
+ */
+ virtual Complexity complexityOfDefuzzification() const;
+
+ /**
+ Computes the estimated complexity of aggregating and defuzzifying the
+ terms currently found in the fuzzy output variable.
+ @return the estimated complexity of aggregating and defuzzifying the
+ terms currently found in the fuzzy output variable
+ */
+ virtual Complexity currentComplexity() const;
+
+ /**
+ Defuzzifies the output variable and stores the output value and the
+ previous output value
+ */
virtual void defuzzify();
+ /**
+ Gets a string representation of the fuzzy output value @f$\tilde{y}@f$
+ @return a string representation of the fuzzy output value
+ @f$\tilde{y}@f$
+ */
virtual std::string fuzzyOutputValue() const;
+ /**
+ Clears the output variable by setting @f$\tilde{y}=\{\}@f$,
+ @f$y^{t}=\mbox{NaN}@f$, @f$y^{t-1}=\mbox{NaN}@f$
+ */
virtual void clear();
+ virtual Variable::Type type() const FL_IOVERRIDE;
+
virtual std::string toString() const FL_IOVERRIDE;
- };
+ virtual OutputVariable* clone() const FL_IOVERRIDE;
+ };
}
#endif /* FL_OUTPUTVARIABLE_H */
diff --git a/fuzzylite/fl/variable/Variable.h b/fuzzylite/fl/variable/Variable.h
index 61870af..47530c0 100644
--- a/fuzzylite/fl/variable/Variable.h
+++ b/fuzzylite/fl/variable/Variable.h
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#ifndef FL_VARIABLE_H
@@ -35,62 +27,272 @@ namespace fl {
class Term;
+ /**
+ The Variable class is the base class for linguistic variables.
+
+ @author Juan Rada-Vilela, Ph.D.
+ @see InputVariable
+ @see OutputVariable
+ @see Term
+ @since 4.0
+ */
class FL_API Variable {
- private:
- void copyFrom(const Variable& source);
+ public:
+ /**
+ Indicates the type of the variable to avoid costly `dynamic_casts`
+ */
+ enum Type {
+ None,
+ Input,
+ Output
+ };
protected:
std::string _name;
+ std::string _description;
std::vector<Term*> _terms;
+ scalar _value;
scalar _minimum, _maximum;
bool _enabled;
+ bool _lockValueInRange;
+
+ private:
+ void copyFrom(const Variable& source);
public:
explicit Variable(const std::string& name = "",
scalar minimum = -fl::inf,
scalar maximum = fl::inf);
- Variable(const Variable& other);
+ explicit Variable(const Variable& other);
Variable& operator=(const Variable& other);
virtual ~Variable();
FL_DEFAULT_MOVE(Variable)
+ /**
+ Sets the name of the variable
+ @param name is the name of the variable
+ */
virtual void setName(const std::string& name);
+
+ /**
+ Gets the name of the variable
+ @return the name of the variable
+ */
virtual std::string getName() const;
+ /**
+ Gets the description of the variable
+ @return the description of the variable
+ */
+ virtual std::string getDescription() const;
+
+ /**
+ Sets the description of the variable
+ @param description is the description of the variable
+ */
+ virtual void setDescription(const std::string& description);
+
+ /**
+ Sets the value of the variable
+ @param value is the input value of an InputVariable, or the output
+ value of an OutputVariable
+ */
+ virtual void setValue(scalar value);
+
+ /**
+ Gets the value of the variable
+ @return the input value of an InputVariable, or the output value of
+ an OutputVariable
+ */
+ virtual scalar getValue() const;
+
+ /**
+ Sets the range of the variable between `[minimum, maximum]`
+ @param minimum is the minimum value in range
+ @param maximum is the maximum value in range
+ */
virtual void setRange(scalar minimum, scalar maximum);
+ /**
+ Gets the magnitude of the range of the variable
+ @return `maximum - minimum`
+ */
virtual scalar range() const;
+ /**
+ Sets the minimum value of the range of the variable
+ @param minimum is the minimum value of the range
+ */
virtual void setMinimum(scalar minimum);
+ /**
+ Gets the minimum value of the range of the variable
+ @return the minimum value of the range of the variable
+ */
virtual scalar getMinimum() const;
+ /**
+ Sets the maximum value of the range of the variable
+ @param maximum is the maximum value of the range
+ */
virtual void setMaximum(scalar maximum);
+ /**
+ Gets the maximum value of the range of the variable
+ @return the maximum value of the range of the variable
+ */
virtual scalar getMaximum() const;
+ /**
+ Sets whether the variable is enabled
+ @param enabled determines whether to enable the variable
+ */
virtual void setEnabled(bool enabled);
+ /**
+ Gets whether the variable is enabled
+ @return whether the variable is enabled
+ */
virtual bool isEnabled() const;
+ /**
+ Sets whether the variable locks the current value to the range of the
+ variable.
+
+ If enabled in an InputVariable @f$i@f$, the input value @f$x_i@f$
+ will be used when computing the Antecedent::activationDegree() as
+ long as @f$x_i \in [\mbox{min}, \mbox{max}]@f$. Else, for the case of
+ @f$x_i \not\in [\mbox{min}, \mbox{max}]@f$, the range values will be
+ used instead but without changing the input value @f$x_i@f$.
+
+ If enabled in an OutputVariable @f$j@f$, the output value @f$y_j@f$
+ will be overriden by the range values when @f$y_j \not\in
+ [\mbox{min}, \mbox{max}]@f$. See OutputVariable for more information.
+
+ @param lockValueInRange indicates whether to lock the value to the
+ range of the variable
+ */
+ virtual void setLockValueInRange(bool lockValueInRange);
+
+ /**
+ Gets whether the variable locks the current value to the
+ range of the variable
+
+ If enabled in an InputVariable @f$i@f$, the input value @f$x_i@f$
+ will be used when computing the Antecedent::activationDegree() as
+ long as @f$x_i \in [\mbox{min}, \mbox{max}]@f$. Else, for the case of
+ @f$x_i \not\in [\mbox{min}, \mbox{max}]@f$, the range values will be
+ used instead but without changing the input value @f$x_i@f$.
+
+ If enabled in an OutputVariable @f$j@f$, the output value @f$y_j@f$
+ will be overriden by the range values when @f$y_j \not\in
+ [\mbox{min}, \mbox{max}]@f$. See OutputVariable for more information.
+
+ @return whether the variable locks the current value to the range of
+ the variable
+ */
+ virtual bool isLockValueInRange() const;
+
+ /**
+ Computes the aggregated complexity of the underlying terms
+ @return the aggregated complexity of the underlying terms
+ */
+ virtual Complexity complexity() const;
+
+ /**
+ Evaluates the membership function of value @f$x@f$ for each
+ term @f$i@f$, resulting in a fuzzy value in the form
+ @f$\tilde{x}=\sum_i{\mu_i(x)/i}@f$
+ @param x is the value to fuzzify
+ @return the fuzzy value expressed as @f$\sum_i{\mu_i(x)/i}@f$
+ */
virtual std::string fuzzify(scalar x) const;
+
+ /**
+ Gets the term which has the highest membership function value for
+ @f$x@f$.
+ @param x is the value of interest
+ @param[out] yhighest is a pointer where the highest membership
+ function value will be stored
+ @return the term @f$i@f$ which maximimizes @f$\mu_i(x)@f$
+ */
virtual Term* highestMembership(scalar x, scalar* yhighest = fl::null) const;
+ /**
+ Returns the type of the variable
+ @return the type of the variable
+ */
+ virtual Type type() const;
+
+ /**
+ Gets a string representation of the variable in the FuzzyLite Language
+ @return a string representation of the variable in the FuzzyLite
+ Language
+ @see FllExporter
+ */
virtual std::string toString() const;
/**
- * Operations for iterable datatype _terms
+ Sorts the terms in ascending order according to their centroids
*/
virtual void sort();
+ /**
+ Adds a term to the variable
+ @param term is the term to add
+ */
virtual void addTerm(Term* term);
- virtual void insertTerm(Term* term, int index);
- virtual Term* getTerm(int index) const;
+ /**
+ Inserts the term in the variable
+ @param term is the term to insert
+ @param index is the index where the term will be inserted
+ */
+ virtual void insertTerm(Term* term, std::size_t index);
+ /**
+ Gets the term at the given index
+ @param index is the position of the term in the vector
+ @return the term at the given index
+ */
+ virtual Term* getTerm(std::size_t index) const;
+ /**
+ Gets the term of the given name.
+ @param name is the name of the term to retrieve
+ @return the term of the given name
+ @throws Exception if the term is not found
+ */
virtual Term* getTerm(const std::string& name) const;
+ /**
+ Gets whether a term of the given name has been added
+ @param name the name of the term
+ @return whether the term of the given name is found
+ */
virtual bool hasTerm(const std::string& name) const;
- virtual Term* removeTerm(int index);
- virtual int numberOfTerms() const;
+ /**
+ Removes the term at the given index
+ @param index the index of the term to remove
+ @return the removed term
+ */
+ virtual Term* removeTerm(std::size_t index);
+ /**
+ Gets the number of terms added to the variable
+ @return the number of terms in the variable
+ */
+ virtual std::size_t numberOfTerms() const;
+ /**
+ Sets the terms of the variable
+ @param terms is a vector of terms
+ */
virtual void setTerms(const std::vector<Term*>& terms);
+ /**
+ Gets an immutable vector of the terms
+ @return an immutable vector of terms
+ */
virtual const std::vector<Term*>& terms() const;
+ /**
+ Gets a mutable vector of the terms
+ @return a mutable vector of terms
+ */
virtual std::vector<Term*>& terms();
-
+ /**
+ Creates a clone of the variable
+ @return a clone of the variable
+ */
+ virtual Variable* clone() const;
};
-
}
-
#endif /* FL_VARIABLE_H */
diff --git a/fuzzylite/fuzzylite.doxygen b/fuzzylite/fuzzylite.doxygen
deleted file mode 100644
index 4ee925f..0000000
--- a/fuzzylite/fuzzylite.doxygen
+++ /dev/null
@@ -1,1781 +0,0 @@
-# Doxyfile 1.7.6.1
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project.
-#
-# All text after a hash (#) is considered a comment and will be ignored.
-# The format is:
-# TAG = value [value, ...]
-# For lists items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ").
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
-
-DOXYFILE_ENCODING = UTF-8
-
-# The PROJECT_NAME tag is a single word (or sequence of words) that should
-# identify the project. Note that if you do not use Doxywizard you need
-# to put quotes around the project name if it contains spaces.
-
-PROJECT_NAME = "fuzzylite"
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
-
-PROJECT_NUMBER = 4.0
-
-# Using the PROJECT_BRIEF tag one can provide an optional one line description
-# for a project that appears at the top of each page and should give viewer
-# a quick idea about the purpose of the project. Keep the description short.
-
-PROJECT_BRIEF = "A Fuzzy Logic Control Library in C++"
-
-# With the PROJECT_LOGO tag one can specify an logo or icon that is
-# included in the documentation. The maximum height of the logo should not
-# exceed 55 pixels and the maximum width should not exceed 200 pixels.
-# Doxygen will copy the logo to the output directory.
-
-PROJECT_LOGO = ../fuzzylite.png
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY = docs
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
-
-OUTPUT_LANGUAGE = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF =
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
-
-STRIP_FROM_PATH =
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful if your file system
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
-
-JAVADOC_AUTOBRIEF = NO
-
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
-
-QT_AUTOBRIEF = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
-
-INHERIT_DOCS = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE = 8
-
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES =
-
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding
-# "class=itcl::class" will allow you to use the command class in the
-# itcl::class meaning.
-
-TCL_SUBST =
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = NO
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
-
-OPTIMIZE_FOR_FORTRAN = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
-
-OPTIMIZE_OUTPUT_VHDL = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given extension.
-# Doxygen has a built-in mapping, but you can override or extend it using this
-# tag. The format is ext=language, where ext is a file extension, and language
-# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
-# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
-# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
-
-EXTENSION_MAPPING =
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also makes the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT = YES
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-
-CPP_CLI_SUPPORT = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
-
-SIP_SUPPORT = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
-
-IDL_PROPERTY_SUPPORT = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
-
-SUBGROUPING = YES
-
-# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
-# unions are shown inside the group in which they are included (e.g. using
-# @ingroup) instead of on a separate page (for HTML and Man pages) or
-# section (for LaTeX and RTF).
-
-INLINE_GROUPED_CLASSES = NO
-
-# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
-# unions with only public data fields will be shown inline in the documentation
-# of the scope in which they are defined (i.e. file, namespace, or group
-# documentation), provided this scope is documented. If set to NO (the default),
-# structs, classes, and unions are shown on a separate page (for HTML and Man
-# pages) or section (for LaTeX and RTF).
-
-INLINE_SIMPLE_STRUCTS = NO
-
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-
-TYPEDEF_HIDES_STRUCT = NO
-
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penalty.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will roughly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-SYMBOL_CACHE_SIZE = 0
-
-# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
-# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
-# their name and scope. Since this can be an expensive process and often the
-# same symbol appear multiple times in the code, doxygen keeps a cache of
-# pre-resolved symbols. If the cache is too small doxygen will become slower.
-# If the cache is too large, memory is wasted. The cache size is given by this
-# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-LOOKUP_CACHE_SIZE = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL = YES
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
-
-EXTRACT_PRIVATE = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
-
-EXTRACT_STATIC = YES
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES = YES
-
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespaces are hidden.
-
-EXTRACT_ANON_NSPACES = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS = NO
-
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
-
-SHOW_INCLUDE_FILES = YES
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
-
-FORCE_LOCAL_INCLUDES = NO
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
-
-INLINE_INFO = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
-
-SORT_MEMBER_DOCS = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
-
-SORT_BRIEF_DOCS = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
-
-SORT_GROUP_NAMES = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME = NO
-
-# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
-# do proper type resolution of all parameters of a function it will reject a
-# match between the prototype and the implementation of a member function even
-# if there is only one candidate or it is obvious which candidate to choose
-# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
-# will still accept a match between prototype and implementation in such cases.
-
-STRICT_PROTO_MATCHING = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
-
-GENERATE_TODOLIST = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
-
-GENERATE_TESTLIST = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
-
-GENERATE_BUGLIST = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or macro consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and macros in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES = YES
-
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = YES
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
-
-SHOW_FILES = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page.
-# This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
-
-SHOW_NAMESPACES = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER =
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
-# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. The create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
-
-LAYOUT_FILE =
-
-# The CITE_BIB_FILES tag can be used to specify one or more bib files
-# containing the references data. This must be a list of .bib files. The
-# .bib extension is automatically appended if omitted. Using this command
-# requires the bibtex tool to be installed. See also
-# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
-# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
-# feature you need bibtex and perl available in the search path.
-
-CITE_BIB_FILES =
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
-
-WARNINGS = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR = YES
-
-# The WARN_NO_PARAMDOC option can be enabled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
-
-WARN_NO_PARAMDOC = YES
-
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
-
-WARN_LOGFILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
-
-INPUT =
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
-
-INPUT_ENCODING = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
-# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
-# *.f90 *.f *.for *.vhd *.vhdl
-
-FILE_PATTERNS = *.h *.cpp
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
-
-RECURSIVE = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should be
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-# Note that relative paths are relative to the directory from which doxygen is
-# run.
-
-EXCLUDE = bin/ CMakeFiles/ docs/ lib/ nbproject/
-
-# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
-# directories that are symbolic links (a Unix file system feature) are excluded
-# from the input.
-
-EXCLUDE_SYMLINKS = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS =
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-
-EXCLUDE_SYMBOLS =
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
-
-EXAMPLE_PATH =
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
-
-EXAMPLE_PATTERNS =
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
-
-IMAGE_PATH =
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output.
-# If FILTER_PATTERNS is specified, this tag will be
-# ignored.
-
-INPUT_FILTER =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis.
-# Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match.
-# The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty or if
-# non of the patterns match the file name, INPUT_FILTER is applied.
-
-FILTER_PATTERNS =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES = NO
-
-# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
-# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
-# and it is also possible to disable source filtering for a specific pattern
-# using *.ext= (so without naming a filter). This option only has effect when
-# FILTER_SOURCE_FILES is enabled.
-
-FILTER_SOURCE_PATTERNS =
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = NO
-
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
-
-REFERENCES_RELATION = NO
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code.
-# Otherwise they will link to the documentation.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
-
-USE_HTAGS = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX = YES
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX = 5
-
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX =
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
-
-GENERATE_HTML = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
-# for the proper inclusion of any scripts and style sheets that doxygen
-# needs, which is dependent on the configuration options used.
-# It is advised to generate a default header using "doxygen -w html
-# header.html footer.html stylesheet.css YourConfigFile" and then modify
-# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
-# changing the value of configuration settings such as GENERATE_TREEVIEW!
-
-HTML_HEADER =
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
-
-HTML_FOOTER =
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# style sheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET =
-
-# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
-# other source files which should be copied to the HTML output directory. Note
-# that these files will be copied to the base HTML output directory. Use the
-# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
-# files. In the HTML_STYLESHEET file, use the file name only. Also note that
-# the files will be copied as-is; there are no commands or markers available.
-
-HTML_EXTRA_FILES =
-
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the style sheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
-
-HTML_COLORSTYLE_HUE = 220
-
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
-
-HTML_COLORSTYLE_SAT = 100
-
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
-
-HTML_COLORSTYLE_GAMMA = 80
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
-
-HTML_TIMESTAMP = YES
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
-
-HTML_DYNAMIC_SECTIONS = NO
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
-
-GENERATE_DOCSET = NO
-
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
-
-DOCSET_FEEDNAME = "Doxygen generated docs"
-
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
-
-DOCSET_BUNDLE_ID = com.fuzzylite
-
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
-# the documentation publisher. This should be a reverse domain-name style
-# string, e.g. com.mycompany.MyDocSet.documentation.
-
-DOCSET_PUBLISHER_ID = com.fuzzylite.documentation
-
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
-
-DOCSET_PUBLISHER_NAME = Juan Rada-Vilela
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
-# written to the html output directory.
-
-CHM_FILE =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
-
-CHM_INDEX_ENCODING =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
-
-GENERATE_QHP = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
-
-QCH_FILE =
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
-
-QHP_NAMESPACE = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
-
-QHP_VIRTUAL_FOLDER = doc
-
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
-
-QHP_CUST_FILTER_NAME =
-
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
-
-QHP_CUST_FILTER_ATTRS =
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
-
-QHP_SECT_FILTER_ATTRS =
-
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
-
-QHG_LOCATION =
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-# will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
-
-GENERATE_ECLIPSEHELP = NO
-
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
-
-ECLIPSE_DOC_ID = org.doxygen.Project
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
-# at top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it. Since the tabs have the same information as the
-# navigation tree you can set this option to NO if you already set
-# GENERATE_TREEVIEW to YES.
-
-DISABLE_INDEX = NO
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-# Since the tree basically has the same information as the tab index you
-# could consider to set DISABLE_INDEX to NO when enabling this option.
-
-GENERATE_TREEVIEW = YES
-
-# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
-# (range [0,1..20]) that doxygen will group on one line in the generated HTML
-# documentation. Note that a value of 0 will completely suppress the enum
-# values from appearing in the overview section.
-
-ENUM_VALUES_PER_LINE = 4
-
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
-
-TREEVIEW_WIDTH = 250
-
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
-
-EXT_LINKS_IN_WINDOW = NO
-
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
-
-FORMULA_FONTSIZE = 10
-
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
-
-FORMULA_TRANSPARENT = YES
-
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
-# (see http://www.mathjax.org) which uses client side Javascript for the
-# rendering instead of using prerendered bitmaps. Use this if you do not
-# have LaTeX installed or if you want to formulas look prettier in the HTML
-# output. When enabled you also need to install MathJax separately and
-# configure the path to it using the MATHJAX_RELPATH option.
-
-USE_MATHJAX = NO
-
-# When MathJax is enabled you need to specify the location relative to the
-# HTML output directory using the MATHJAX_RELPATH option. The destination
-# directory should contain the MathJax.js script. For instance, if the mathjax
-# directory is located at the same level as the HTML output directory, then
-# MATHJAX_RELPATH should be ../mathjax. The default value points to the
-# mathjax.org site, so you can quickly see the result without installing
-# MathJax, but it is strongly recommended to install a local copy of MathJax
-# before deployment.
-
-MATHJAX_RELPATH = http://www.mathjax.org/mathjax
-
-# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
-# names that should be enabled during MathJax rendering.
-
-MATHJAX_EXTENSIONS =
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
-
-SEARCHENGINE = YES
-
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a PHP enabled web server instead of at the web client
-# using Javascript. Doxygen will generate the search PHP script and index
-# file to put on the web server. The advantage of the server
-# based approach is that it scales better to large projects and allows
-# full text search. The disadvantages are that it is more difficult to setup
-# and does not have live searching capabilities.
-
-SERVER_BASED_SEARCH = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
-
-GENERATE_LATEX = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
-
-LATEX_CMD_NAME = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
-
-MAKEINDEX_CMD_NAME = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_LATEX = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, letter, legal and
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE = a4
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES =
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER =
-
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
-# the generated latex document. The footer should contain everything after
-# the last chapter. If it is left blank doxygen will generate a
-# standard footer. Notice: only use this tag if you know what you are doing!
-
-LATEX_FOOTER =
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS = YES
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
-# higher quality PDF documentation.
-
-USE_PDFLATEX = YES
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
-
-LATEX_HIDE_INDICES = NO
-
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
-
-LATEX_SOURCE_CODE = NO
-
-# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
-# http://en.wikipedia.org/wiki/BibTeX for more info.
-
-LATEX_BIB_STYLE = plain
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
-
-GENERATE_RTF = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_RTF = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS = NO
-
-# Load style sheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE =
-
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
-
-GENERATE_MAN = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT = man
-
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
-
-GENERATE_XML = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD =
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
-
-GENERATE_PERLMOD = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader.
-# This is useful
-# if you want to understand what is going on.
-# On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY = YES
-
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
-
-ENABLE_PREPROCESSING = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
-EXPAND_ONLY_PREDEF = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# pointed to by INCLUDE_PATH will be searched when a #include is found.
-
-SEARCH_INCLUDES = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
-
-INCLUDE_PATH =
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
-
-INCLUDE_FILE_PATTERNS =
-
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
-
-PREDEFINED =
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition that
-# overrules the definition found in the source code.
-
-EXPAND_AS_DEFINED =
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all references to function-like macros
-# that are alone on a line, have an all uppercase name, and do not end with a
-# semicolon, because these will confuse the parser if not removed.
-
-SKIP_FUNCTION_MACROS = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-#
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-#
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES =
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE =
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
-
-ALLEXTERNALS = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
-
-EXTERNAL_GROUPS = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option also works with HAVE_DOT disabled, but it is recommended to
-# install and use dot, since it yields more powerful graphs.
-
-CLASS_DIAGRAMS = YES
-
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH =
-
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT = YES
-
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
-
-DOT_NUM_THREADS = 0
-
-# By default doxygen will use the Helvetica font for all dot files that
-# doxygen generates. When you want a differently looking font you can specify
-# the font name using DOT_FONTNAME. You need to make sure dot is able to find
-# the font, which can be done by putting it in a standard location or by setting
-# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
-# directory containing the font.
-
-DOT_FONTNAME = Helvetica
-
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
-
-DOT_FONTSIZE = 10
-
-# By default doxygen will tell dot to use the Helvetica font.
-# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
-# set the path where dot can find it.
-
-DOT_FONTPATH =
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH = YES
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-
-UML_LOOK = YES
-
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
-
-INCLUDE_GRAPH = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH = YES
-
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
-
-CALL_GRAPH = NO
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
-
-CALLER_GRAPH = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will generate a graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY = YES
-
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used. If you choose svg you need to set
-# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible in IE 9+ (other browsers do not have this requirement).
-
-DOT_IMAGE_FORMAT = png
-
-# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
-# enable generation of interactive SVG images that allow zooming and panning.
-# Note that this requires a modern browser other than Internet Explorer.
-# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
-# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
-# visible. Older versions of IE do not have SVG support.
-
-INTERACTIVE_SVG = YES
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH =
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
-
-DOTFILE_DIRS =
-
-# The MSCFILE_DIRS tag can be used to specify one or more directories that
-# contain msc files that are included in the documentation (see the
-# \mscfile command).
-
-MSCFILE_DIRS =
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-
-DOT_GRAPH_MAX_NODES = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-
-MAX_DOT_GRAPH_DEPTH = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS = YES
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
-
-DOT_CLEANUP = YES
diff --git a/fuzzylite/fuzzylite.pc.in b/fuzzylite/fuzzylite.pc.in
index 421c61a..f6f7bee 100644
--- a/fuzzylite/fuzzylite.pc.in
+++ b/fuzzylite/fuzzylite.pc.in
@@ -1,10 +1,10 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=${exec_prefix}/include
-libdir=@CMAKE_INSTALL_LIBDIR@
+libdir=${exec_prefix}/lib
Name: fuzzylite
Description: A fuzzy logic control library in C++
Version: @FL_VERSION@
Libs: -L${libdir} -lfuzzylite
-Cflags: -I${includedir}/fl
+Cflags: -I${includedir}
diff --git a/fuzzylite/src/Benchmark.cpp b/fuzzylite/src/Benchmark.cpp
new file mode 100644
index 0000000..9d318df
--- /dev/null
+++ b/fuzzylite/src/Benchmark.cpp
@@ -0,0 +1,460 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/Benchmark.h"
+
+#include "fl/Engine.h"
+#include "fl/Operation.h"
+#include "fl/rule/Rule.h"
+#include "fl/rule/RuleBlock.h"
+#include "fl/variable/InputVariable.h"
+#include "fl/variable/OutputVariable.h"
+
+#ifdef FL_CPP98
+//timing is only available in C++11
+#else
+#include <chrono>
+#endif
+
+namespace fl {
+
+ Benchmark::Benchmark(const std::string& name, Engine* engine, scalar tolerance)
+ : _name(name), _engine(engine), _tolerance(tolerance) { }
+
+ Benchmark::~Benchmark() { }
+
+ void Benchmark::setName(const std::string& name) {
+ this->_name = name;
+ }
+
+ std::string Benchmark::getName() const {
+ return this->_name;
+ }
+
+ void Benchmark::setEngine(Engine* engine) {
+ this->_engine = engine;
+ }
+
+ Engine* Benchmark::getEngine() const {
+ return this->_engine;
+ }
+
+ void Benchmark::setExpected(const std::vector<std::vector<scalar> >& expected) {
+ this->_expected = expected;
+ }
+
+ const std::vector<std::vector<scalar> >& Benchmark::getExpected() const {
+ return this->_expected;
+ }
+
+ void Benchmark::setObtained(const std::vector<std::vector<scalar> >& obtained) {
+ this->_obtained = obtained;
+ }
+
+ const std::vector<std::vector<scalar> >& Benchmark::getObtained() const {
+ return this->_obtained;
+ }
+
+ void Benchmark::setTimes(const std::vector<scalar> nanoSeconds) {
+ this->_times = nanoSeconds;
+ }
+
+ const std::vector<scalar>& Benchmark::getTimes() const {
+ return this->_times;
+ }
+
+ void Benchmark::setTolerance(scalar tolerance) {
+ this->_tolerance = tolerance;
+ }
+
+ scalar Benchmark::getTolerance() const {
+ return this->_tolerance;
+ }
+
+ void Benchmark::prepare(int values, FldExporter::ScopeOfValues scope) {
+ if (not _engine) {
+ throw Exception("[benchmark error] engine not set before preparing for values and scope", FL_AT);
+ }
+ int resolution;
+ if (scope == FldExporter::AllVariables)
+ resolution = -1 + (int) std::max(1.0, std::pow(
+ values, 1.0 / _engine->numberOfInputVariables()));
+ else //if (scope == EachVariable)
+ resolution = values - 1;
+
+ std::vector<int> sampleValues, minSampleValues, maxSampleValues;
+ for (std::size_t i = 0; i < _engine->numberOfInputVariables(); ++i) {
+ sampleValues.push_back(0);
+ minSampleValues.push_back(0);
+ maxSampleValues.push_back(resolution);
+ }
+
+ _expected = std::vector<std::vector<scalar> >();
+ do {
+ std::vector<scalar> expectedValues(_engine->numberOfInputVariables());
+ for (std::size_t i = 0; i < _engine->numberOfInputVariables(); ++i) {
+ InputVariable* inputVariable = _engine->getInputVariable(i);
+ expectedValues.at(i) = inputVariable->getMinimum()
+ + sampleValues.at(i) * inputVariable->range() / std::max(1, resolution);
+ }
+ _expected.push_back(expectedValues);
+ } while (Op::increment(sampleValues, minSampleValues, maxSampleValues));
+ }
+
+ void Benchmark::prepare(std::istream& reader, long numberOfLines) {
+ _expected = std::vector<std::vector<scalar> >();
+ std::string line;
+ int lineNumber = 0;
+ while (lineNumber != numberOfLines and std::getline(reader, line)) {
+ ++lineNumber;
+ line = Op::trim(line);
+ if (line.empty() or line.at(0) == '#')
+ continue; //comments are ignored, blank lines are retained
+ std::vector<scalar> expectedValues;
+ if (lineNumber == 1) { //automatic detection of header.
+ try {
+ expectedValues = Op::toScalars(line);
+ } catch (std::exception&) {
+ continue;
+ }
+ } else {
+ expectedValues = Op::toScalars(line);
+ }
+ _expected.push_back(expectedValues);
+ }
+ }
+
+ scalar Benchmark::runOnce() {
+ return run(1).front();
+ }
+
+ std::vector<scalar> Benchmark::run(int times) {
+ if (not _engine) {
+ throw Exception("[benchmark error] engine not set for benchmark", FL_AT);
+ }
+ std::vector<scalar> runTimes(times, fl::nan);
+ const std::size_t offset(_engine->inputVariables().size());
+ for (int t = 0; t < times; ++t) {
+ _obtained = std::vector<std::vector<scalar> >(_expected.size(),
+ std::vector<scalar>(_engine->variables().size()));
+ _engine->restart();
+
+#ifdef FL_CPP98
+ //ignore timing
+#else
+ auto start = std::chrono::high_resolution_clock::now();
+#endif
+
+ for (std::size_t evaluation = 0; evaluation < _expected.size(); ++evaluation) {
+ const std::vector<scalar>& expectedValues = _expected[evaluation];
+ std::vector<scalar>& obtainedValues = _obtained[evaluation];
+
+ if (expectedValues.size() < _engine->inputVariables().size()) {
+ std::ostringstream ex;
+ ex << "[benchmark error] the number of input values given <" <<
+ expectedValues.size() << "> at line <" << (evaluation + 1) << "> "
+ "must be at least the same number of input variables "
+ "<" << _engine->inputVariables().size() << "> in the engine";
+ throw Exception(ex.str());
+ }
+ for (std::size_t i = 0; i < _engine->inputVariables().size(); ++i) {
+ _engine->getInputVariable(i)->setValue(expectedValues[i]);
+ obtainedValues[i] = expectedValues[i];
+ }
+
+ _engine->process();
+
+ for (std::size_t i = 0; i < _engine->outputVariables().size(); ++i) {
+ obtainedValues[i + offset] = _engine->getOutputVariable(i)->getValue();
+ }
+ }
+
+#ifdef FL_CPP98
+ //ignore timing
+#else
+ auto end = std::chrono::high_resolution_clock::now();
+ runTimes.at(t) = std::chrono::duration<scalar, std::nano>(end - start).count();
+#endif
+ }
+ _times.insert(_times.end(), runTimes.begin(), runTimes.end());
+ return runTimes;
+ }
+
+ void Benchmark::reset() {
+ this->_obtained.clear();
+ this->_times.clear();
+ }
+
+ bool Benchmark::canComputeErrors() const {
+ return not (_engine == fl::null or _expected.empty() or _obtained.empty()
+ or _expected.size() != _obtained.size()
+ or _expected.front().size() != _obtained.front().size()
+ or _expected.front().size() != _engine->variables().size());
+ }
+
+ scalar Benchmark::meanSquaredError() const {
+ return meanSquaredError(fl::null);
+ }
+
+ scalar Benchmark::meanSquaredError(const OutputVariable* outputVariable) const {
+ if (not canComputeErrors()) {
+ return fl::nan;
+ }
+
+ scalar mse = 0.0;
+ int errors = 0;
+ const std::size_t offset = _engine->numberOfInputVariables();
+ for (std::size_t i = 0; i < _expected.size(); ++i) {
+ const std::vector<scalar>& e = _expected.at(i);
+ const std::vector<scalar>& o = _obtained.at(i);
+
+ for (std::size_t y = 0; y < _engine->numberOfOutputVariables(); ++y) {
+ if (outputVariable == fl::null
+ or outputVariable == _engine->getOutputVariable(y)) {
+ scalar difference = e.at(offset + y) - o.at(offset + y);
+ if (Op::isFinite(difference)
+ and not Op::isEq(difference, 0.0, _tolerance)) {
+ mse += difference * difference;
+ ++errors;
+ }
+ }
+ }
+ }
+
+ if (errors > 0) {
+ mse /= errors;
+ }
+ return mse;
+ }
+
+ int Benchmark::allErrors() const {
+ return allErrors(fl::null);
+ }
+
+ int Benchmark::allErrors(const OutputVariable* outputVariable) const {
+ return numberOfErrors(All, outputVariable);
+ }
+
+ int Benchmark::nonFiniteErrors() const {
+ return nonFiniteErrors(fl::null);
+ }
+
+ int Benchmark::nonFiniteErrors(const OutputVariable* outputVariable) const {
+ return numberOfErrors(NonFinite, outputVariable);
+ }
+
+ int Benchmark::accuracyErrors() const {
+ return accuracyErrors(fl::null);
+ }
+
+ int Benchmark::accuracyErrors(const OutputVariable* outputVariable) const {
+ return numberOfErrors(Accuracy, outputVariable);
+ }
+
+ int Benchmark::numberOfErrors(ErrorType errorType) const {
+ return numberOfErrors(errorType, fl::null);
+ }
+
+ int Benchmark::numberOfErrors(ErrorType errorType,
+ const OutputVariable* outputVariable) const {
+ if (not canComputeErrors()) {
+ return -1;
+ }
+
+ int errors = 0;
+ const std::size_t offset = _engine->numberOfInputVariables();
+ for (std::size_t i = 0; i < _expected.size(); ++i) {
+ const std::vector<scalar>& e = _expected.at(i);
+ const std::vector<scalar>& o = _obtained.at(i);
+
+ for (std::size_t y = 0; y < _engine->numberOfOutputVariables(); ++y) {
+ if (outputVariable == fl::null
+ or outputVariable == _engine->getOutputVariable(y)) {
+ if (not Op::isEq(e.at(y + offset), o.at(y + offset), _tolerance)) {
+ scalar difference = e.at(y + offset) - o.at(y + offset);
+ if (errorType == Accuracy and Op::isFinite(difference)) {
+ ++errors;
+ } else if (errorType == NonFinite and not Op::isFinite(difference)) {
+ ++errors;
+ } else if (errorType == All) {
+ ++errors;
+ }
+ }
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ std::string Benchmark::stringOf(TimeUnit unit) {
+ if (unit == NanoSeconds) return "nanoseconds";
+ if (unit == MicroSeconds) return "microseconds";
+ if (unit == MilliSeconds) return "milliseconds";
+ if (unit == Seconds) return "seconds";
+ if (unit == Minutes) return "minutes";
+ if (unit == Hours) return "hours";
+ return "undefined";
+ }
+
+ scalar Benchmark::factorOf(TimeUnit unit) {
+ if (unit == NanoSeconds) return 1.0;
+ else if (unit == MicroSeconds) return 1.0e-3;
+ else if (unit == MilliSeconds) return 1.0e-6;
+ else if (unit == Seconds) return 1.0e-9;
+ else if (unit == Minutes) return 1.0e-9 / 60;
+ else if (unit == Hours) return 1.0e-9 / 3600;
+ return fl::nan;
+ }
+
+ scalar Benchmark::convert(scalar x, TimeUnit from, TimeUnit to) {
+ return x * factorOf(to) / factorOf(from);
+ }
+
+ std::vector<std::string> Benchmark::header(int runs, bool includeErrors) {
+ Benchmark result;
+
+ Engine dummy;
+ dummy.addOutputVariable(new OutputVariable); //canCompute() == true
+ result.setEngine(&dummy);
+
+ result.setTimes(std::vector<scalar>(runs, fl::nan));
+
+ if (includeErrors) {
+ std::vector<std::vector<scalar> > dummyVector(1,
+ std::vector<scalar>(1, fl::nan));
+ result.setExpected(dummyVector);
+ result.setObtained(dummyVector);
+ }
+ std::vector<Benchmark::Result> dummyResults = result.results();
+
+ std::vector<std::string> names;
+ for (std::size_t i = 0; i < dummyResults.size(); ++i) {
+ names.push_back(dummyResults.at(i).first);
+ }
+ return names;
+ }
+
+ std::vector<Benchmark::Result> Benchmark::results(TimeUnit timeUnit, bool includeTimes) const {
+ return results(fl::null, timeUnit, includeTimes);
+ }
+
+ std::vector<Benchmark::Result> Benchmark::results(
+ const OutputVariable* outputVariable, TimeUnit unit, bool includeTimes) const {
+ if (not _engine) {
+ throw Exception("[benchmark error] engine not set for benchmark", FL_AT);
+ }
+
+ std::vector<scalar> time = _times;
+
+ std::vector<Result> result;
+ result.push_back(Result("library", fuzzylite::library()));
+ result.push_back(Result("name", _name));
+ result.push_back(Result("inputs", Op::str(_engine->numberOfInputVariables())));
+ result.push_back(Result("outputs", Op::str(_engine->numberOfOutputVariables())));
+ result.push_back(Result("ruleBlocks", Op::str(_engine->numberOfRuleBlocks())));
+ std::size_t rules = 0;
+ for (std::size_t i = 0; i < _engine->ruleBlocks().size(); ++i) {
+ rules += _engine->ruleBlocks().at(i)->rules().size();
+ }
+ result.push_back(Result("rules", Op::str(rules)));
+ result.push_back(Result("runs", Op::str(_times.size())));
+ result.push_back(Result("evaluations", Op::str(_expected.size())));
+ if (canComputeErrors()) {
+ std::vector<std::string> names;
+ scalar meanRange = 0.0;
+ scalar rmse = std::sqrt(meanSquaredError(outputVariable));
+ scalar nrmse = 0.0;
+ scalar weights = 0.0;
+ for (std::size_t i = 0; i < _engine->outputVariables().size(); ++i) {
+ const OutputVariable* y = _engine->outputVariables().at(i);
+ if (outputVariable == fl::null or outputVariable == y) {
+ names.push_back(y->getName());
+ meanRange += y->range();
+ nrmse += std::sqrt(meanSquaredError(y)) * 1.0 / y->range();
+ weights += 1.0 / y->range();
+ }
+ }
+ meanRange /= names.size();
+ nrmse /= weights;
+
+ result.push_back(Result("outputVariable", Op::join(names, ",")));
+ result.push_back(Result("range", Op::str(meanRange)));
+
+ result.push_back(Result("tolerance", Op::str(getTolerance(), -1, std::ios_base::fmtflags(0x0))));
+ result.push_back(Result("errors", Op::str(allErrors(outputVariable))));
+
+ result.push_back(Result("nfErrors", Op::str(nonFiniteErrors(outputVariable))));
+ result.push_back(Result("accErrors", Op::str(accuracyErrors(outputVariable))));
+
+ result.push_back(Result("rmse", Op::str(rmse, 6, std::ios_base::scientific)));
+ result.push_back(Result("nrmse", Op::str(nrmse, 6, std::ios_base::scientific)));
+ }
+ result.push_back(Result("units", stringOf(unit)));
+ result.push_back(Result("sum(t)", Op::str(convert(Op::sum(time), NanoSeconds, unit),
+ unit == NanoSeconds ? 0 : fuzzylite::decimals())));
+ result.push_back(Result("mean(t)", Op::str(convert(Op::mean(time), NanoSeconds, unit))));
+ result.push_back(Result("sd(t)", Op::str(convert(Op::standardDeviation(time), NanoSeconds, unit))));
+
+ if (includeTimes) {
+ for (std::size_t i = 0; i < time.size(); ++i) {
+ result.push_back(Result("t" + Op::str(i + 1),
+ Op::str(time.at(i), unit == NanoSeconds ? 0 : fuzzylite::decimals())));
+ }
+ }
+ return result;
+ }
+
+ std::string Benchmark::format(std::vector<Result> results, TableShape shape,
+ TableContents contents, const std::string& delimiter) const {
+ std::ostringstream os;
+
+ if (shape == Vertical) {
+ for (std::size_t i = 0; i < results.size(); ++i) {
+ Result pair = results.at(i);
+ if (contents bitand Header) {
+ os << pair.first;
+ }
+ if (contents == HeaderAndBody) {
+ os << delimiter;
+ }
+ if (contents bitand Body) {
+ os << pair.second;
+ }
+ if (i + 1 < results.size()) os << "\n";
+ }
+
+ } else if (shape == Horizontal) {
+ std::ostringstream header;
+ std::ostringstream body;
+ for (std::size_t i = 0; i < results.size(); ++i) {
+ Result pair = results.at(i);
+ if (contents bitand Header) {
+ header << pair.first;
+ if (i + 1 < results.size()) header << delimiter;
+ }
+ if (contents bitand Body) {
+ body << pair.second;
+ if (i + 1 < results.size()) body << delimiter;
+ }
+ }
+ if (contents bitand Header) os << header.str();
+ if (contents == HeaderAndBody) os << "\n";
+ if (contents bitand Body) os << body.str();
+ }
+ return os.str();
+ }
+}
diff --git a/fuzzylite/src/Complexity.cpp b/fuzzylite/src/Complexity.cpp
new file mode 100644
index 0000000..8a91c60
--- /dev/null
+++ b/fuzzylite/src/Complexity.cpp
@@ -0,0 +1,283 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/Complexity.h"
+
+#include "fl/Engine.h"
+
+#include "fl/variable/InputVariable.h"
+#include "fl/variable/OutputVariable.h"
+
+#include "fl/rule/RuleBlock.h"
+#include "fl/rule/Rule.h"
+
+namespace fl {
+
+ Complexity::Complexity(scalar all) :
+ _comparison(all), _arithmetic(all), _function(all) { }
+
+ Complexity::Complexity(scalar comparison, scalar arithmetic,
+ scalar function)
+ : _comparison(comparison), _arithmetic(arithmetic), _function(function) { }
+
+ Complexity::~Complexity() { }
+
+ Complexity& Complexity::operator+=(const Complexity& other) {
+ return this->plus(other);
+ }
+
+ Complexity& Complexity::operator-=(const Complexity& other) {
+ return this->minus(other);
+ }
+
+ Complexity& Complexity::operator*=(const Complexity& other) {
+ return this->multiply(other);
+ }
+
+ Complexity& Complexity::operator/=(const Complexity& other) {
+ return this->divide(other);
+ }
+
+ Complexity Complexity::operator+(const Complexity& rhs) const {
+ return Complexity(*this).plus(rhs);
+ }
+
+ Complexity Complexity::operator-(const Complexity& rhs) const {
+ return Complexity(*this).minus(rhs);
+ }
+
+ Complexity Complexity::operator*(const Complexity& rhs) const {
+ return Complexity(*this).multiply(rhs);
+ }
+
+ Complexity Complexity::operator/(const Complexity& rhs) const {
+ return Complexity(*this).divide(rhs);
+ }
+
+ bool Complexity::operator==(const Complexity& rhs) const {
+ return equals(rhs);
+ }
+
+ bool Complexity::operator!=(const Complexity& rhs) const {
+ return not equals(rhs);
+ }
+
+ bool Complexity::operator<(const Complexity& rhs) const {
+ return lessThan(rhs);
+ }
+
+ bool Complexity::operator<=(const Complexity& rhs) const {
+ return lessThanOrEqualsTo(rhs);
+ }
+
+ bool Complexity::operator>(const Complexity& rhs) const {
+ return greaterThan(rhs);
+ }
+
+ bool Complexity::operator>=(const Complexity& rhs) const {
+ return greaterThanOrEqualsTo(rhs);
+ }
+
+ Complexity& Complexity::plus(const Complexity& other) {
+ this->_arithmetic += other._arithmetic;
+ this->_comparison += other._comparison;
+ this->_function += other._function;
+ return *this;
+ }
+
+ Complexity& Complexity::plus(scalar x) {
+ return this->plus(Complexity().arithmetic(x).comparison(x).function(x));
+ }
+
+ Complexity& Complexity::minus(const Complexity& other) {
+ this->_comparison -= other._comparison;
+ this->_arithmetic -= other._arithmetic;
+ this->_function -= other._function;
+ return *this;
+ }
+
+ Complexity& Complexity::minus(scalar x) {
+ return this->minus(Complexity().arithmetic(x).comparison(x).function(x));
+ }
+
+ Complexity& Complexity::multiply(const Complexity& other) {
+ this->_comparison *= other._comparison;
+ this->_arithmetic *= other._arithmetic;
+ this->_function *= other._function;
+ return *this;
+ }
+
+ Complexity& Complexity::multiply(scalar x) {
+ return this->multiply(Complexity().arithmetic(x).comparison(x).function(x));
+ }
+
+ Complexity& Complexity::divide(const Complexity& other) {
+ this->_comparison /= other._comparison;
+ this->_arithmetic /= other._arithmetic;
+ this->_function /= other._function;
+ return *this;
+ }
+
+ Complexity& Complexity::divide(scalar x) {
+ return this->divide(Complexity().arithmetic(x).comparison(x).function(x));
+ }
+
+ bool Complexity::equals(const Complexity& x, scalar macheps) const {
+ return Op::isEq(_comparison, x._comparison, macheps) and
+ Op::isEq(_arithmetic, x._arithmetic, macheps) and
+ Op::isEq(_function, x._function, macheps);
+ }
+
+ bool Complexity::lessThan(const Complexity& x, scalar macheps) const {
+ return Op::isLt(_comparison, x._comparison, macheps) and
+ Op::isLt(_arithmetic, x._arithmetic, macheps) and
+ Op::isLt(_function, x._function, macheps);
+ }
+
+ bool Complexity::lessThanOrEqualsTo(const Complexity& x, scalar macheps) const {
+ return Op::isLE(_comparison, x._comparison, macheps) and
+ Op::isLE(_arithmetic, x._arithmetic, macheps) and
+ Op::isLE(_function, x._function, macheps);
+ }
+
+ bool Complexity::greaterThan(const Complexity& x, scalar macheps) const {
+ return Op::isGt(_comparison, x._comparison, macheps) and
+ Op::isGt(_arithmetic, x._arithmetic, macheps) and
+ Op::isGt(_function, x._function, macheps);
+ }
+
+ bool Complexity::greaterThanOrEqualsTo(const Complexity& x, scalar macheps) const {
+ return Op::isGE(_comparison, x._comparison, macheps) and
+ Op::isGE(_arithmetic, x._arithmetic, macheps) and
+ Op::isGE(_function, x._function, macheps);
+ }
+
+ Complexity& Complexity::comparison(scalar comparison) {
+ this->_comparison += comparison;
+ return *this;
+ }
+
+ void Complexity::setComparison(scalar comparison) {
+ this->_comparison = comparison;
+ }
+
+ scalar Complexity::getComparison() const {
+ return _comparison;
+ }
+
+ Complexity& Complexity::arithmetic(scalar arithmetic) {
+ this->_arithmetic += arithmetic;
+ return *this;
+ }
+
+ void Complexity::setArithmetic(scalar arithmetic) {
+ this->_arithmetic = arithmetic;
+ }
+
+ scalar Complexity::getArithmetic() const {
+ return _arithmetic;
+ }
+
+ Complexity& Complexity::function(scalar trigonometric) {
+ this->_function += trigonometric;
+ return *this;
+ }
+
+ void Complexity::setFunction(scalar trigonometric) {
+ this->_function = trigonometric;
+ }
+
+ scalar Complexity::getFunction() const {
+ return _function;
+ }
+
+ std::vector<Complexity::Measure> Complexity::measures() const {
+ std::vector<Measure> result;
+ result.push_back(Measure("arithmetic", _arithmetic));
+ result.push_back(Measure("comparison", _comparison));
+ result.push_back(Measure("function", _function));
+ return result;
+ }
+
+ scalar Complexity::sum() const {
+ return _arithmetic + _comparison + _function;
+ }
+
+ scalar Complexity::norm() const {
+ return std::sqrt(Complexity(*this).multiply(*this).sum());
+ }
+
+ std::string Complexity::toString() const {
+ std::vector<std::string> result;
+ result.push_back("a=" + Op::str(_arithmetic));
+ result.push_back("c=" + Op::str(_comparison));
+ result.push_back("f=" + Op::str(_function));
+ return "C[" + Op::join(result, ", ") + "]";
+ }
+
+ Complexity Complexity::compute(const Engine* engine) const {
+ return engine->complexity();
+ }
+
+ Complexity Complexity::compute(const InputVariable* inputVariable) const {
+ return inputVariable->complexity();
+ }
+
+ Complexity Complexity::compute(const OutputVariable* outputVariable) const {
+ return outputVariable->complexity();
+ }
+
+ Complexity Complexity::compute(const RuleBlock* ruleBlock) const {
+ return ruleBlock->complexity();
+ }
+
+ Complexity Complexity::compute(const std::vector<InputVariable*>& inputVariables) const {
+ Complexity result;
+ for (std::size_t i = 0; i < inputVariables.size(); ++i) {
+ result += inputVariables.at(i)->complexity();
+ }
+ return result;
+ }
+
+ Complexity Complexity::compute(const std::vector<OutputVariable*>& outputVariables,
+ bool complexityOfDefuzzification) const {
+ Complexity result;
+ for (std::size_t i = 0; i < outputVariables.size(); ++i) {
+ if (complexityOfDefuzzification)
+ result += outputVariables.at(i)->complexityOfDefuzzification();
+ else
+ result += outputVariables.at(i)->complexity();
+ }
+ return result;
+ }
+
+ Complexity Complexity::compute(const std::vector<Variable*>& variables) const {
+ Complexity result;
+ for (std::size_t i = 0; i < variables.size(); ++i) {
+ result += variables.at(i)->complexity();
+ }
+ return result;
+ }
+
+ Complexity Complexity::compute(const std::vector<RuleBlock*>& ruleBlocks) const {
+ Complexity result;
+ for (std::size_t i = 0; i < ruleBlocks.size(); ++i) {
+ result += ruleBlocks.at(i)->complexity();
+ }
+ return result;
+ }
+
+}
diff --git a/fuzzylite/src/Console.cpp b/fuzzylite/src/Console.cpp
index 3a55fc5..5a00c50 100644
--- a/fuzzylite/src/Console.cpp
+++ b/fuzzylite/src/Console.cpp
@@ -1,37 +1,24 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/Console.h"
#include "fl/Headers.h"
-#include <algorithm>
-#include <cctype>
#include <fstream>
-#include <stdlib.h>
-#include <utility>
-#include <vector>
#ifdef FL_UNIX
#include <termios.h>
@@ -40,9 +27,6 @@
#include <conio.h>
#endif
-#ifdef FL_CPP11
-#include <chrono>
-#endif
namespace fl {
const std::string Console::KW_INPUT_FILE = "-i";
@@ -51,11 +35,16 @@ namespace fl {
const std::string Console::KW_OUTPUT_FORMAT = "-of";
const std::string Console::KW_EXAMPLE = "-example";
const std::string Console::KW_DECIMALS = "-decimals";
- const std::string Console::KW_DATA_INPUT = "-d";
- const std::string Console::KW_DATA_MAXIMUM = "-dmaximum";
+ const std::string Console::KW_DATA_INPUT_FILE = "-d";
+ const std::string Console::KW_DATA_VALUES = "-values";
+ const std::string Console::KW_DATA_VALUES_SCOPE = "-scope";
+
const std::string Console::KW_DATA_EXPORT_HEADER = "-dheader";
const std::string Console::KW_DATA_EXPORT_INPUTS = "-dinputs";
+ Console::Option::Option(const std::string& key, const std::string& value, const std::string& description) :
+ key(key), value(value), description(description) { }
+
std::vector<Console::Option> Console::availableOptions() {
std::vector<Console::Option> options;
options.push_back(Option(KW_INPUT_FILE, "inputfile", "file to import your engine from"));
@@ -64,8 +53,9 @@ namespace fl {
options.push_back(Option(KW_OUTPUT_FORMAT, "format", "format of the file to export (fll | fld | cpp | java | fis | fcl)"));
options.push_back(Option(KW_EXAMPLE, "letter", "if not inputfile, built-in example to use as engine: (m)amdani or (t)akagi-sugeno"));
options.push_back(Option(KW_DECIMALS, "number", "number of decimals to write floating-poing values"));
- options.push_back(Option(KW_DATA_INPUT, "datafile", "if exporting to fld, file of input values to evaluate your engine on"));
- options.push_back(Option(KW_DATA_MAXIMUM, "number", "if exporting to fld without datafile, maximum number of results to export"));
+ options.push_back(Option(KW_DATA_INPUT_FILE, "file", "if exporting to fld, FLD file of input values to evaluate your engine on"));
+ options.push_back(Option(KW_DATA_VALUES, "number", "if exporting to fld without datafile, number of results to export within scope (default: EachVariable)"));
+ options.push_back(Option(KW_DATA_VALUES_SCOPE, "scope", "if exporting to fld without datafile, scope of " + KW_DATA_VALUES + ": [EachVariable|AllVariables]"));
options.push_back(Option(KW_DATA_EXPORT_HEADER, "boolean", "if true and exporting to fld, include headers"));
options.push_back(Option(KW_DATA_EXPORT_INPUTS, "boolean", "if true and exporting to fld, include input values"));
return options;
@@ -74,14 +64,16 @@ namespace fl {
std::string Console::usage() {
std::vector<Console::Option> options = availableOptions();
std::ostringstream ss;
-
+
ss << "========================================\n";
ss << "fuzzylite: a fuzzy logic control library\n";
- ss << "version: " << fuzzylite::longVersion() << "\n";
+ ss << "version: " << fuzzylite::version() << "\n";
ss << "author: " << fuzzylite::author() << "\n";
ss << "license: " << fuzzylite::license() << "\n";
ss << "========================================\n\n";
ss << "usage: fuzzylite inputfile outputfile\n";
+ ss << " or: fuzzylite benchmark engine.fll input.fld runs [output.tsv]\n";
+ ss << " or: fuzzylite benchmarks fllFiles.txt fldFiles.txt runs [output.tsv]\n";
ss << " or: fuzzylite ";
for (std::size_t i = 0; i < options.size(); ++i) {
ss << "[" << options.at(i).key << " " << options.at(i).value << "] ";
@@ -103,15 +95,15 @@ namespace fl {
ss << "\n";
ss << "Visit " << fuzzylite::website() << " for more information.\n\n";
- ss << "Copyright (C) 2010-2015 FuzzyLite Limited.\n";
+ ss << "Copyright (C) 2010-2017 by FuzzyLite Limited.\n";
ss << "All rights reserved.";
-
+
return ss.str();
}
- std::map<std::string, std::string> Console::parse(int argc, char** argv) {
+ std::map<std::string, std::string> Console::parse(int argc, const char* argv[]) {
if ((argc - 1) % 2 != 0) {
- throw fl::Exception("[option error] incomplete number of parameters [key value]", FL_AT);
+ throw Exception("[option error] incomplete number of parameters [key value]", FL_AT);
}
std::map<std::string, std::string> options;
for (int i = 1; i < argc - 1; i += 2) {
@@ -139,7 +131,7 @@ namespace fl {
}
}
if (not isValid) {
- throw fl::Exception("[option error] option <" + it->first + "> not recognized", FL_AT);
+ throw Exception("[option error] option <" + it->first + "> not recognized", FL_AT);
}
}
}
@@ -151,7 +143,7 @@ namespace fl {
it = options.find(KW_DECIMALS);
if (it != options.end()) {
- fl::fuzzylite::setDecimals((int) fl::Op::toScalar(it->second));
+ fuzzylite::setDecimals((int) Op::toScalar(it->second));
}
std::string example;
@@ -170,7 +162,7 @@ namespace fl {
} else if (example == "t" or example == "ts" or example == "takagi-sugeno") {
engine = takagiSugeno();
} else {
- throw fl::Exception("[option error] example <" + example + "> not available", FL_AT);
+ throw Exception("[option error] example <" + example + "> not available", FL_AT);
}
inputFormat = "fll";
textEngine << FllExporter().toString(engine);
@@ -179,12 +171,12 @@ namespace fl {
} else {
it = options.find(KW_INPUT_FILE);
if (it == options.end()) {
- throw fl::Exception("[option error] no input file specified", FL_AT);
+ throw Exception("[option error] no input file specified", FL_AT);
}
std::string inputFilename = it->second;
std::ifstream inputFile(inputFilename.c_str());
if (not inputFile.is_open()) {
- throw fl::Exception("[file error] file <" + inputFilename + "> could not be opened", FL_AT);
+ throw Exception("[file error] file <" + inputFilename + "> could not be opened", FL_AT);
}
std::string line;
while (std::getline(inputFile, line)) {
@@ -200,7 +192,7 @@ namespace fl {
if (extensionIndex != std::string::npos) {
inputFormat = inputFilename.substr(extensionIndex + 1);
} else {
- throw fl::Exception("[format error] unspecified format of input file", FL_AT);
+ throw Exception("[format error] unspecified format of input file", FL_AT);
}
}
}
@@ -220,7 +212,7 @@ namespace fl {
if (extensionIndex != std::string::npos) {
outputFormat = outputFilename.substr(extensionIndex + 1);
} else {
- throw fl::Exception("[format error] unspecified format of output file", FL_AT);
+ throw Exception("[format error] unspecified format of output file", FL_AT);
}
}
@@ -230,7 +222,7 @@ namespace fl {
} else {
std::ofstream writer(outputFilename.c_str());
if (not writer.is_open()) {
- throw fl::Exception("[file error] file <" + outputFilename + "> could not be created", FL_AT);
+ throw Exception("[file error] file <" + outputFilename + "> could not be created", FL_AT);
}
process(textEngine.str(), writer, inputFormat, outputFormat, options);
writer.flush();
@@ -252,7 +244,7 @@ namespace fl {
} else if ("fis" == inputFormat) {
importer.reset(new FisImporter);
} else {
- throw fl::Exception("[import error] format <" + inputFormat + "> "
+ throw Exception("[import error] format <" + inputFormat + "> "
"not supported", FL_AT);
}
@@ -262,7 +254,7 @@ namespace fl {
std::map<std::string, std::string>::const_iterator it;
FldExporter fldExporter;
- fldExporter.setSeparator("\t");
+ fldExporter.setSeparator(" ");
bool exportHeaders = true;
if ((it = options.find(KW_DATA_EXPORT_HEADER)) != options.end()) {
exportHeaders = ("true" == it->second);
@@ -273,22 +265,32 @@ namespace fl {
exportInputValues = ("true" == it->second);
}
fldExporter.setExportInputValues(exportInputValues);
- if ((it = options.find(KW_DATA_INPUT)) != options.end()) {
+ if ((it = options.find(KW_DATA_INPUT_FILE)) != options.end()) {
std::ifstream dataFile(it->second.c_str());
if (not dataFile.is_open()) {
- throw fl::Exception("[export error] file <" + it->second + "> could not be opened", FL_AT);
+ throw Exception("[export error] file <" + it->second + "> could not be opened", FL_AT);
}
try {
fldExporter.write(engine.get(), writer, dataFile);
} catch (std::exception& ex) {
- (void) ex;
+ FL_IUNUSED(ex);
dataFile.close();
throw;
}
} else {
- if ((it = options.find(KW_DATA_MAXIMUM)) != options.end()) {
- fldExporter.write(engine.get(), writer, (int) fl::Op::toScalar(it->second));
+ if ((it = options.find(KW_DATA_VALUES)) != options.end()) {
+ int values = (int) Op::toScalar(it->second);
+ FldExporter::ScopeOfValues scope = FldExporter::EachVariable;
+ if ((it = options.find(KW_DATA_VALUES_SCOPE)) != options.end()) {
+ if ("AllVariables" == it->second)
+ scope = FldExporter::AllVariables;
+ else if ("EachVariable" == it->second)
+ scope = FldExporter::EachVariable;
+ else throw Exception("[export error] unknown scope of values <"
+ + it->second + ">", FL_AT);
+ }
+ fldExporter.write(engine.get(), writer, values, scope);
} else {
std::ostringstream buffer;
buffer << "#FuzzyLite Interactive Console (press H for help)\n";
@@ -311,7 +313,7 @@ namespace fl {
exporter.reset(new CppExporter);
} else if ("java" == outputFormat) {
exporter.reset(new JavaExporter);
- } else throw fl::Exception("[export error] format <" + outputFormat + "> "
+ } else throw Exception("[export error] format <" + outputFormat + "> "
"not supported", FL_AT);
writer << exporter->toString(engine.get());
}
@@ -321,14 +323,14 @@ namespace fl {
int ch = 0;
#ifdef FL_UNIX
struct termios oldt, newt;
- tcgetattr(STDIN_FILENO, &oldt);
+ ::tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
- tcsetattr(STDIN_FILENO, TCSANOW, &newt);
- ch = getchar();
- tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
+ ::tcsetattr(STDIN_FILENO, TCSANOW, &newt);
+ ch = ::getchar();
+ ::tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
#elif defined(FL_WINDOWS)
- ch = _getch();
+ ch = ::_getch();
#endif
return ch;
}
@@ -349,13 +351,17 @@ namespace fl {
ch = readCharacter();
+ if (ch == EOF) {
+ break;
+ }
+
if (std::isspace(ch)) {
- scalar value = engine->getInputVariable(inputValues.size())->getInputValue();
+ scalar value = engine->getInputVariable(inputValues.size())->getValue();
try {
- value = fl::Op::toScalar(inputValue.str());
+ value = Op::toScalar(inputValue.str());
} catch (std::exception& ex) {
- (void) ex;
- buffer << "[" << fl::Op::str(value) << "]";
+ FL_IUNUSED(ex);
+ buffer << "[" << Op::str(value) << "]";
}
buffer << space;
inputValue.str("");
@@ -375,7 +381,7 @@ namespace fl {
case 'r':
case 'R': engine->restart();
buffer << "#[Restart]";
- //fall through
+ continue; //fall through
case 'd':
case 'D': inputValues.clear();
buffer << "#[Discard]\n>";
@@ -388,15 +394,15 @@ namespace fl {
for (std::size_t i = 0; i < inputValues.size(); ++i) {
InputVariable* inputVariable = engine->inputVariables().at(i);
- inputVariable->setInputValue(inputValues.at(i));
+ inputVariable->setValue(inputValues.at(i));
}
std::vector<scalar> missingInputs;
for (std::size_t i = inputValues.size(); i < engine->inputVariables().size(); ++i) {
InputVariable* inputVariable = engine->inputVariables().at(i);
- missingInputs.push_back(inputVariable->getInputValue());
+ missingInputs.push_back(inputVariable->getValue());
}
inputValues.clear();
- buffer << fl::Op::join(missingInputs, space);
+ buffer << Op::join(missingInputs, space);
if (not missingInputs.empty()) buffer << space;
buffer << "=" << space;
try {
@@ -405,9 +411,9 @@ namespace fl {
for (std::size_t i = 0; i < engine->outputVariables().size(); ++i) {
OutputVariable* outputVariable = engine->outputVariables().at(i);
outputVariable->defuzzify();
- outputValues.push_back(outputVariable->getOutputValue());
+ outputValues.push_back(outputVariable->getValue());
}
- buffer << fl::Op::join(outputValues, space) << "\n>";
+ buffer << Op::join(outputValues, space) << "\n>";
} catch (std::exception& ex) {
buffer << "#[Error: " << ex.what() << "]";
@@ -422,7 +428,7 @@ namespace fl {
inputValue.str("");
break;
}
- } while (not (ch == 'Q' or ch == 'q'));
+ } while (not (ch == 'Q' or ch == 'q' or ch == 4));
writer << std::endl;
}
@@ -439,145 +445,283 @@ namespace fl {
}
Engine* Console::mamdani() {
- Engine* engine = new Engine("simple-dimmer");
-
- InputVariable* ambient = new InputVariable("Ambient", 0, 1);
- ambient->addTerm(new Triangle("DARK", .0, .25, .5));
- ambient->addTerm(new Triangle("MEDIUM", .25, .5, .75));
- ambient->addTerm(new Triangle("BRIGHT", .5, .75, 1));
+ Engine* engine = new Engine;
+ engine->setName("simple-dimmer");
+ engine->setDescription("");
+
+ InputVariable* ambient = new InputVariable;
+ ambient->setName("ambient");
+ ambient->setDescription("");
+ ambient->setEnabled(true);
+ ambient->setRange(0.000, 1.000);
+ ambient->setLockValueInRange(false);
+ ambient->addTerm(new Triangle("DARK", 0.000, 0.250, 0.500));
+ ambient->addTerm(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+ ambient->addTerm(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
engine->addInputVariable(ambient);
-
- OutputVariable* power = new OutputVariable("Power", 0, 2);
+ OutputVariable* power = new OutputVariable;
+ power->setName("power");
+ power->setDescription("");
+ power->setEnabled(true);
+ power->setRange(0.000, 2.000);
+ power->setLockValueInRange(false);
+ power->setAggregation(new Maximum);
+ power->setDefuzzifier(new Centroid(200));
power->setDefaultValue(fl::nan);
- power->addTerm(new Triangle("LOW", 0.0, 0.5, 1));
- power->addTerm(new Triangle("MEDIUM", 0.5, 1, 1.5));
- power->addTerm(new Triangle("HIGH", 1, 1.5, 2));
+ power->setLockPreviousValue(false);
+ power->addTerm(new Triangle("LOW", 0.000, 0.500, 1.000));
+ power->addTerm(new Triangle("MEDIUM", 0.500, 1.000, 1.500));
+ power->addTerm(new Triangle("HIGH", 1.000, 1.500, 2.000));
engine->addOutputVariable(power);
- RuleBlock* ruleblock = new RuleBlock();
- ruleblock->addRule(Rule::parse("if Ambient is DARK then Power is HIGH", engine));
- ruleblock->addRule(Rule::parse("if Ambient is MEDIUM then Power is MEDIUM", engine));
- ruleblock->addRule(Rule::parse("if Ambient is BRIGHT then Power is LOW", engine));
-
- engine->addRuleBlock(ruleblock);
-
- engine->configure("", "", "Minimum", "Maximum", "Centroid");
+ RuleBlock* ruleBlock = new RuleBlock;
+ ruleBlock->setName("");
+ ruleBlock->setDescription("");
+ ruleBlock->setEnabled(true);
+ ruleBlock->setConjunction(fl::null);
+ ruleBlock->setDisjunction(fl::null);
+ ruleBlock->setImplication(new Minimum);
+ ruleBlock->setActivation(new General);
+ ruleBlock->addRule(Rule::parse("if ambient is DARK then power is HIGH", engine));
+ ruleBlock->addRule(Rule::parse("if ambient is MEDIUM then power is MEDIUM", engine));
+ ruleBlock->addRule(Rule::parse("if ambient is BRIGHT then power is LOW", engine));
+ engine->addRuleBlock(ruleBlock);
return engine;
}
Engine* Console::takagiSugeno() {
- Engine* engine = new Engine("approximation of sin(x)/x");
-
- fl::InputVariable* inputX = new fl::InputVariable("inputX");
- inputX->setRange(0, 10);
- inputX->addTerm(new fl::Triangle("NEAR_1", 0, 1, 2));
- inputX->addTerm(new fl::Triangle("NEAR_2", 1, 2, 3));
- inputX->addTerm(new fl::Triangle("NEAR_3", 2, 3, 4));
- inputX->addTerm(new fl::Triangle("NEAR_4", 3, 4, 5));
- inputX->addTerm(new fl::Triangle("NEAR_5", 4, 5, 6));
- inputX->addTerm(new fl::Triangle("NEAR_6", 5, 6, 7));
- inputX->addTerm(new fl::Triangle("NEAR_7", 6, 7, 8));
- inputX->addTerm(new fl::Triangle("NEAR_8", 7, 8, 9));
- inputX->addTerm(new fl::Triangle("NEAR_9", 8, 9, 10));
+ Engine* engine = new Engine;
+ engine->setName("approximation");
+ engine->setDescription("approximation of sin(x)/x");
+
+ InputVariable* inputX = new InputVariable;
+ inputX->setName("inputX");
+ inputX->setDescription("value of x");
+ inputX->setEnabled(true);
+ inputX->setRange(0.000, 10.000);
+ inputX->setLockValueInRange(false);
+ inputX->addTerm(new Triangle("NEAR_1", 0.000, 1.000, 2.000));
+ inputX->addTerm(new Triangle("NEAR_2", 1.000, 2.000, 3.000));
+ inputX->addTerm(new Triangle("NEAR_3", 2.000, 3.000, 4.000));
+ inputX->addTerm(new Triangle("NEAR_4", 3.000, 4.000, 5.000));
+ inputX->addTerm(new Triangle("NEAR_5", 4.000, 5.000, 6.000));
+ inputX->addTerm(new Triangle("NEAR_6", 5.000, 6.000, 7.000));
+ inputX->addTerm(new Triangle("NEAR_7", 6.000, 7.000, 8.000));
+ inputX->addTerm(new Triangle("NEAR_8", 7.000, 8.000, 9.000));
+ inputX->addTerm(new Triangle("NEAR_9", 8.000, 9.000, 10.000));
engine->addInputVariable(inputX);
-
- fl::OutputVariable* outputFx = new fl::OutputVariable("outputFx");
- outputFx->setRange(-1, 1);
+ OutputVariable* outputFx = new OutputVariable;
+ outputFx->setName("outputFx");
+ outputFx->setDescription("value of the approximation of x");
+ outputFx->setEnabled(true);
+ outputFx->setRange(-1.000, 1.000);
+ outputFx->setLockValueInRange(false);
+ outputFx->setAggregation(fl::null);
+ outputFx->setDefuzzifier(new WeightedAverage("Automatic"));
outputFx->setDefaultValue(fl::nan);
- outputFx->setLockPreviousOutputValue(true); //To use its value with diffFx
- outputFx->addTerm(new Constant("f1", 0.84));
- outputFx->addTerm(new Constant("f2", 0.45));
- outputFx->addTerm(new Constant("f3", 0.04));
- outputFx->addTerm(new Constant("f4", -0.18));
- outputFx->addTerm(new Constant("f5", -0.19));
- outputFx->addTerm(new Constant("f6", -0.04));
- outputFx->addTerm(new Constant("f7", 0.09));
- outputFx->addTerm(new Constant("f8", 0.12));
- outputFx->addTerm(new Constant("f9", 0.04));
+ outputFx->setLockPreviousValue(true);
+ outputFx->addTerm(new Constant("f1", 0.840));
+ outputFx->addTerm(new Constant("f2", 0.450));
+ outputFx->addTerm(new Constant("f3", 0.040));
+ outputFx->addTerm(new Constant("f4", -0.180));
+ outputFx->addTerm(new Constant("f5", -0.190));
+ outputFx->addTerm(new Constant("f6", -0.040));
+ outputFx->addTerm(new Constant("f7", 0.090));
+ outputFx->addTerm(new Constant("f8", 0.120));
+ outputFx->addTerm(new Constant("f9", 0.040));
engine->addOutputVariable(outputFx);
- fl::OutputVariable* trueFx = new fl::OutputVariable("trueFx");
- trueFx->setRange(fl::nan, fl::nan);
- trueFx->setLockPreviousOutputValue(true); //To use its value with diffFx
- trueFx->addTerm(fl::Function::create("fx", "sin(inputX)/inputX", engine));
- engine->addOutputVariable(trueFx);
-
- fl::OutputVariable* diffFx = new fl::OutputVariable("diffFx");
- diffFx->addTerm(fl::Function::create("diff", "fabs(outputFx-trueFx)", engine));
- diffFx->setRange(fl::nan, fl::nan);
- // diffFx->setLockValidOutput(true); //To use in input diffPreviousFx
- engine->addOutputVariable(diffFx);
-
- fl::RuleBlock* block = new fl::RuleBlock();
- block->addRule(fl::Rule::parse("if inputX is NEAR_1 then outputFx is f1", engine));
- block->addRule(fl::Rule::parse("if inputX is NEAR_2 then outputFx is f2", engine));
- block->addRule(fl::Rule::parse("if inputX is NEAR_3 then outputFx is f3", engine));
- block->addRule(fl::Rule::parse("if inputX is NEAR_4 then outputFx is f4", engine));
- block->addRule(fl::Rule::parse("if inputX is NEAR_5 then outputFx is f5", engine));
- block->addRule(fl::Rule::parse("if inputX is NEAR_6 then outputFx is f6", engine));
- block->addRule(fl::Rule::parse("if inputX is NEAR_7 then outputFx is f7", engine));
- block->addRule(fl::Rule::parse("if inputX is NEAR_8 then outputFx is f8", engine));
- block->addRule(fl::Rule::parse("if inputX is NEAR_9 then outputFx is f9", engine));
- block->addRule(fl::Rule::parse("if inputX is any then trueFx is fx and diffFx is diff", engine));
- engine->addRuleBlock(block);
-
- engine->configure("", "", "AlgebraicProduct", "AlgebraicSum", "WeightedAverage");
+ OutputVariable* trueValue = new OutputVariable;
+ trueValue->setName("trueValue");
+ trueValue->setDescription("value of f(x)=sin(x)/x");
+ trueValue->setEnabled(true);
+ trueValue->setRange(-1.060, 1.000);
+ trueValue->setLockValueInRange(false);
+ trueValue->setAggregation(fl::null);
+ trueValue->setDefuzzifier(new WeightedAverage("Automatic"));
+ trueValue->setDefaultValue(fl::nan);
+ trueValue->setLockPreviousValue(true);
+ trueValue->addTerm(Function::create("fx", "sin(inputX)/inputX", engine));
+ engine->addOutputVariable(trueValue);
+
+ OutputVariable* difference = new OutputVariable;
+ difference->setName("difference");
+ difference->setDescription("error e=f(x) - f'(x)");
+ difference->setEnabled(true);
+ difference->setRange(-1.000, 1.000);
+ difference->setLockValueInRange(false);
+ difference->setAggregation(fl::null);
+ difference->setDefuzzifier(new WeightedAverage("Automatic"));
+ difference->setDefaultValue(fl::nan);
+ difference->setLockPreviousValue(false);
+ difference->addTerm(Function::create("error", "outputFx-trueValue", engine));
+ engine->addOutputVariable(difference);
+
+ RuleBlock* ruleBlock = new RuleBlock;
+ ruleBlock->setName("");
+ ruleBlock->setDescription("");
+ ruleBlock->setEnabled(true);
+ ruleBlock->setConjunction(fl::null);
+ ruleBlock->setDisjunction(fl::null);
+ ruleBlock->setImplication(new AlgebraicProduct);
+ ruleBlock->setActivation(new General);
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_1 then outputFx is f1", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_2 then outputFx is f2", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_3 then outputFx is f3", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_4 then outputFx is f4", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_5 then outputFx is f5", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_6 then outputFx is f6", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_7 then outputFx is f7", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_8 then outputFx is f8", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is NEAR_9 then outputFx is f9", engine));
+ ruleBlock->addRule(Rule::parse("if inputX is any then trueValue is fx and difference is error", engine));
+ engine->addRuleBlock(ruleBlock);
+
+ return engine;
+ }
+
+ Engine* Console::hybrid() {
+ Engine* engine = new Engine;
+ engine->setName("tipper");
+ engine->setDescription("(service and food) -> (tip)");
+
+ InputVariable* service = new InputVariable;
+ service->setName("service");
+ service->setDescription("quality of service");
+ service->setEnabled(true);
+ service->setRange(0.000, 10.000);
+ service->setLockValueInRange(true);
+ service->addTerm(new Trapezoid("poor", 0.000, 0.000, 2.500, 5.000));
+ service->addTerm(new Triangle("good", 2.500, 5.000, 7.500));
+ service->addTerm(new Trapezoid("excellent", 5.000, 7.500, 10.000, 10.000));
+ engine->addInputVariable(service);
+
+ InputVariable* food = new InputVariable;
+ food->setName("food");
+ food->setDescription("quality of food");
+ food->setEnabled(true);
+ food->setRange(0.000, 10.000);
+ food->setLockValueInRange(true);
+ food->addTerm(new Trapezoid("rancid", 0.000, 0.000, 2.500, 7.500));
+ food->addTerm(new Trapezoid("delicious", 2.500, 7.500, 10.000, 10.000));
+ engine->addInputVariable(food);
+
+ OutputVariable* mTip = new OutputVariable;
+ mTip->setName("mTip");
+ mTip->setDescription("tip based on Mamdani inference");
+ mTip->setEnabled(true);
+ mTip->setRange(0.000, 30.000);
+ mTip->setLockValueInRange(false);
+ mTip->setAggregation(new Maximum);
+ mTip->setDefuzzifier(new Centroid(100));
+ mTip->setDefaultValue(fl::nan);
+ mTip->setLockPreviousValue(false);
+ mTip->addTerm(new Triangle("cheap", 0.000, 5.000, 10.000));
+ mTip->addTerm(new Triangle("average", 10.000, 15.000, 20.000));
+ mTip->addTerm(new Triangle("generous", 20.000, 25.000, 30.000));
+ engine->addOutputVariable(mTip);
+
+ OutputVariable* tsTip = new OutputVariable;
+ tsTip->setName("tsTip");
+ tsTip->setDescription("tip based on Takagi-Sugeno inference");
+ tsTip->setEnabled(true);
+ tsTip->setRange(0.000, 30.000);
+ tsTip->setLockValueInRange(false);
+ tsTip->setAggregation(fl::null);
+ tsTip->setDefuzzifier(new WeightedAverage("TakagiSugeno"));
+ tsTip->setDefaultValue(fl::nan);
+ tsTip->setLockPreviousValue(false);
+ tsTip->addTerm(new Constant("cheap", 5.000));
+ tsTip->addTerm(new Constant("average", 15.000));
+ tsTip->addTerm(new Constant("generous", 25.000));
+ engine->addOutputVariable(tsTip);
+
+ RuleBlock* mamdaniRuleBlock = new RuleBlock;
+ mamdaniRuleBlock->setName("mamdani");
+ mamdaniRuleBlock->setDescription("Mamdani inference");
+ mamdaniRuleBlock->setEnabled(true);
+ mamdaniRuleBlock->setConjunction(new AlgebraicProduct);
+ mamdaniRuleBlock->setDisjunction(new AlgebraicSum);
+ mamdaniRuleBlock->setImplication(new Minimum);
+ mamdaniRuleBlock->setActivation(new General);
+ mamdaniRuleBlock->addRule(Rule::parse("if service is poor or food is rancid then mTip is cheap", engine));
+ mamdaniRuleBlock->addRule(Rule::parse("if service is good then mTip is average", engine));
+ mamdaniRuleBlock->addRule(Rule::parse("if service is excellent or food is delicious then mTip is generous with 0.5", engine));
+ mamdaniRuleBlock->addRule(Rule::parse("if service is excellent and food is delicious then mTip is generous with 1.0", engine));
+ engine->addRuleBlock(mamdaniRuleBlock);
+
+ RuleBlock* takagiSugenoRuleBlock = new RuleBlock;
+ takagiSugenoRuleBlock->setName("takagiSugeno");
+ takagiSugenoRuleBlock->setDescription("Takagi-Sugeno inference");
+ takagiSugenoRuleBlock->setEnabled(true);
+ takagiSugenoRuleBlock->setConjunction(new AlgebraicProduct);
+ takagiSugenoRuleBlock->setDisjunction(new AlgebraicSum);
+ takagiSugenoRuleBlock->setImplication(fl::null);
+ takagiSugenoRuleBlock->setActivation(new General);
+ takagiSugenoRuleBlock->addRule(Rule::parse("if service is poor or food is rancid then tsTip is cheap", engine));
+ takagiSugenoRuleBlock->addRule(Rule::parse("if service is good then tsTip is average", engine));
+ takagiSugenoRuleBlock->addRule(Rule::parse("if service is excellent or food is delicious then tsTip is generous with 0.5", engine));
+ takagiSugenoRuleBlock->addRule(Rule::parse("if service is excellent and food is delicious then tsTip is generous with 1.0", engine));
+ engine->addRuleBlock(takagiSugenoRuleBlock);
return engine;
}
void Console::exportAllExamples(const std::string& from, const std::string& to) {
- Console::exportAllExamples(from, to, ".");
+ Console::exportAllExamples(from, to, "./", "/tmp/");
}
- void Console::exportAllExamples(const std::string& from, const std::string& to, const std::string& path) {
+ void Console::exportAllExamples(const std::string& from, const std::string& to,
+ const std::string& sourcePath, const std::string& targetPath) {
std::vector<std::string> examples;
- examples.push_back("/mamdani/AllTerms");
- // examples.push_back("/mamdani/Laundry");
- examples.push_back("/mamdani/SimpleDimmer");
- // examples.push_back("/mamdani/SimpleDimmerInverse");
- examples.push_back("/mamdani/matlab/mam21");
- examples.push_back("/mamdani/matlab/mam22");
- examples.push_back("/mamdani/matlab/shower");
- examples.push_back("/mamdani/matlab/tank");
- examples.push_back("/mamdani/matlab/tank2");
- examples.push_back("/mamdani/matlab/tipper");
- examples.push_back("/mamdani/matlab/tipper1");
- examples.push_back("/mamdani/octave/investment_portfolio");
- examples.push_back("/mamdani/octave/mamdani_tip_calculator");
- examples.push_back("/takagi-sugeno/approximation");
- examples.push_back("/takagi-sugeno/SimpleDimmer");
- examples.push_back("/takagi-sugeno/matlab/fpeaks");
- examples.push_back("/takagi-sugeno/matlab/invkine1");
- examples.push_back("/takagi-sugeno/matlab/invkine2");
- examples.push_back("/takagi-sugeno/matlab/juggler");
- examples.push_back("/takagi-sugeno/matlab/membrn1");
- examples.push_back("/takagi-sugeno/matlab/membrn2");
- examples.push_back("/takagi-sugeno/matlab/slbb");
- examples.push_back("/takagi-sugeno/matlab/slcp");
- examples.push_back("/takagi-sugeno/matlab/slcp1");
- examples.push_back("/takagi-sugeno/matlab/slcpp1");
- examples.push_back("/takagi-sugeno/matlab/sltbu_fl");
- examples.push_back("/takagi-sugeno/matlab/sugeno1");
- examples.push_back("/takagi-sugeno/matlab/tanksg");
- examples.push_back("/takagi-sugeno/matlab/tippersg");
- examples.push_back("/takagi-sugeno/octave/cubic_approximator");
- examples.push_back("/takagi-sugeno/octave/heart_disease_risk");
- examples.push_back("/takagi-sugeno/octave/linear_tip_calculator");
- examples.push_back("/takagi-sugeno/octave/sugeno_tip_calculator");
- examples.push_back("/tsukamoto/tsukamoto");
-
- std::string sourceBase = path + "/original";
- std::string targetBase = path + "/tmp/";
+ examples.push_back("mamdani/AllTerms");
+ examples.push_back("mamdani/SimpleDimmer");
+ examples.push_back("mamdani/Laundry");
+ examples.push_back("mamdani/ObstacleAvoidance");
+ examples.push_back("mamdani/SimpleDimmerChained");
+ examples.push_back("mamdani/SimpleDimmerInverse");
+ examples.push_back("mamdani/matlab/mam21");
+ examples.push_back("mamdani/matlab/mam22");
+ examples.push_back("mamdani/matlab/shower");
+ examples.push_back("mamdani/matlab/tank");
+ examples.push_back("mamdani/matlab/tank2");
+ examples.push_back("mamdani/matlab/tipper");
+ examples.push_back("mamdani/matlab/tipper1");
+ examples.push_back("mamdani/octave/investment_portfolio");
+ examples.push_back("mamdani/octave/mamdani_tip_calculator");
+ examples.push_back("takagi-sugeno/approximation");
+ examples.push_back("takagi-sugeno/ObstacleAvoidance");
+ examples.push_back("takagi-sugeno/SimpleDimmer");
+ examples.push_back("takagi-sugeno/matlab/fpeaks");
+ examples.push_back("takagi-sugeno/matlab/invkine1");
+ examples.push_back("takagi-sugeno/matlab/invkine2");
+ examples.push_back("takagi-sugeno/matlab/juggler");
+ examples.push_back("takagi-sugeno/matlab/membrn1");
+ examples.push_back("takagi-sugeno/matlab/membrn2");
+ examples.push_back("takagi-sugeno/matlab/slbb");
+ examples.push_back("takagi-sugeno/matlab/slcp");
+ examples.push_back("takagi-sugeno/matlab/slcp1");
+ examples.push_back("takagi-sugeno/matlab/slcpp1");
+ examples.push_back("takagi-sugeno/matlab/sltbu_fl");
+ examples.push_back("takagi-sugeno/matlab/sugeno1");
+ examples.push_back("takagi-sugeno/matlab/tanksg");
+ examples.push_back("takagi-sugeno/matlab/tippersg");
+ examples.push_back("takagi-sugeno/octave/cubic_approximator");
+ examples.push_back("takagi-sugeno/octave/heart_disease_risk");
+ examples.push_back("takagi-sugeno/octave/linear_tip_calculator");
+ examples.push_back("takagi-sugeno/octave/sugeno_tip_calculator");
+ examples.push_back("tsukamoto/tsukamoto");
+ examples.push_back("hybrid/tipper");
+ examples.push_back("hybrid/ObstacleAvoidance");
FL_unique_ptr<Importer> importer;
if (from == "fll") importer.reset(new FllImporter);
else if (from == "fis") importer.reset(new FisImporter);
else if (from == "fcl") importer.reset(new FclImporter);
- else throw fl::Exception("[examples error] unrecognized format <" + from + "> to import", FL_AT);
+ else throw Exception("[examples error] unrecognized format <" + from + "> to import", FL_AT);
FL_unique_ptr<Exporter> exporter;
if (to == "fll") exporter.reset(new FllExporter);
@@ -586,16 +730,19 @@ namespace fl {
else if (to == "fis") exporter.reset(new FisExporter);
else if (to == "cpp") exporter.reset(new CppExporter);
else if (to == "java") exporter.reset(new JavaExporter);
- else throw fl::Exception("[examples error] unrecognized format <" + to + "> to export", FL_AT);
+ else if (to == "R") exporter.reset(new RScriptExporter());
+ else throw Exception("[examples error] unrecognized format <" + to + "> to export", FL_AT);
std::vector<std::pair<Exporter*, Importer*> > tests;
tests.push_back(std::pair<Exporter*, Importer*>(new FllExporter, new FllImporter));
tests.push_back(std::pair<Exporter*, Importer*>(new FisExporter, new FisImporter));
tests.push_back(std::pair<Exporter*, Importer*>(new FclExporter, new FclImporter));
for (std::size_t i = 0; i < examples.size(); ++i) {
- FL_LOG("Processing " << (i + 1) << "/" << examples.size() << ": " << examples.at(i));
+ std::string example = examples.at(i);
+ FL_LOG((i + 1) << "/" << examples.size());
+ FL_LOG("Importing from: " << sourcePath << "/" << example << "." << from);
std::ostringstream ss;
- std::string input = sourceBase + examples.at(i) + "." + from;
+ std::string input = sourcePath + "/" + example + "." + from;
std::ifstream source(input.c_str());
if (source.is_open()) {
std::string line;
@@ -604,29 +751,40 @@ namespace fl {
ss << line << "\n";
}
source.close();
- } else throw fl::Exception("[examples error] file not found: " + input, FL_AT);
+ } else throw Exception("[examples error] file not found: " + input, FL_AT);
FL_unique_ptr<Engine> engine(importer->fromString(ss.str()));
for (std::size_t t = 0; t < tests.size(); ++t) {
- std::string out = tests.at(t).first->toString(engine.get());
- FL_unique_ptr<Engine> copy(tests.at(t).second->fromString(out));
- std::string out_copy = tests.at(t).first->toString(copy.get());
-
- if (out != out_copy) {
- std::ostringstream ss;
- ss << "[imex error] different results <"
- << importer->name() << "," << exporter->name() << "> "
- "at " + examples.at(t) + "." + from + ":\n";
- ss << "<Engine A>\n" << out << "\n\n" <<
+ if ("mamdani/Laundry" == example
+ or "mamdani/SimpleDimmerInverse" == example
+ or "mamdani/SimpleDimmerChained" == example
+ or "hybrid/tipper" == example
+ or "hybrid/ObstacleAvoidance" == example) {
+ if (tests.at(t).second->name() == FisImporter().name()) {
+ continue;
+ }
+ }
+
+ std::string exported = tests.at(t).first->toString(engine.get());
+ FL_unique_ptr<Engine> engineFromExport(tests.at(t).second->fromString(exported));
+ std::string imported = tests.at(t).first->toString(engineFromExport.get());
+
+ if (exported != imported) {
+ std::ostringstream msg;
+ msg << "[imex error] different results <"
+ << tests.at(t).first->name() << "," << tests.at(t).second->name() << "> "
+ "at " << example << "." << from << ":\n";
+ msg << "<Engine A>\n" << exported << "\n\n" <<
"================================\n\n" <<
- "<Engine B>\n" << out_copy;
- throw fl::Exception(ss.str(), FL_AT);
+ "<Engine B>\n" << imported;
+ throw Exception(msg.str(), FL_AT);
}
}
- std::string output = targetBase + examples.at(i) + "." + to;
+ std::string output = targetPath + "/" + example + "." + to;
std::ofstream target(output.c_str());
+ FL_LOG("Exporting to: " << output << "\n");
if (target.is_open()) {
if (to == "cpp") {
target << "#include <fl/Headers.h>\n\n"
@@ -634,8 +792,9 @@ namespace fl {
<< exporter->toString(engine.get())
<< "\n}\n";
} else if (to == "java") {
- std::string className = examples.at(i).substr(examples.at(i).find_last_of('/') + 1);
+ std::string className = example.substr(example.find_last_of('/') + 1);
target << "import com.fuzzylite.*;\n"
+ << "import com.fuzzylite.activation.*\n"
<< "import com.fuzzylite.defuzzifier.*;\n"
<< "import com.fuzzylite.factory.*;\n"
<< "import com.fuzzylite.hedge.*;\n"
@@ -650,171 +809,215 @@ namespace fl {
<< "public static void main(String[] args){\n"
<< exporter->toString(engine.get())
<< "\n}\n}\n";
+ } else if (to == "R") {
+ RScriptExporter* rScript = dynamic_cast<RScriptExporter*> (exporter.get());
+ InputVariable* a = engine->getInputVariable(0);
+ InputVariable* b = engine->getInputVariable(1 % engine->numberOfInputVariables());
+ std::string pathToDF = example.substr(example.find_last_of('/') + 1) + ".fld";
+ rScript->writeScriptImportingDataFrame(engine.get(), target,
+ a, b, pathToDF, engine->outputVariables());
} else {
target << exporter->toString(engine.get());
}
target.close();
}
Engine copyConstructor(*engine.get());
- (void) copyConstructor;
+ FL_IUNUSED(copyConstructor);
Engine assignmentOperator = *engine.get();
- (void) assignmentOperator;
+ FL_IUNUSED(assignmentOperator);
}
+ FL_LOG("Please, make sure the output contains the following structure:\n"
+ "mkdir -p " << targetPath << "mamdani/matlab; "
+ "mkdir -p " << targetPath << "mamdani/octave; "
+ "mkdir -p " << targetPath << "takagi-sugeno/matlab; "
+ "mkdir -p " << targetPath << "takagi-sugeno/octave; "
+ "mkdir -p " << targetPath << "tsukamoto; "
+ "mkdir -p " << targetPath << "hybrid;");
for (std::size_t i = 0; i < tests.size(); ++i) {
delete tests.at(i).first;
delete tests.at(i).second;
}
}
-#ifdef FL_CPP11
-
- void Console::benchmarkExamples(const std::string& path, int runs) {
- std::string sourceBase = path + "/original";
- typedef std::pair<std::string, int > Example;
- std::vector<Example> examples;
- examples.push_back(Example("/mamdani/AllTerms", 1e4));
- examples.push_back(Example("/mamdani/SimpleDimmer", 1e5));
- examples.push_back(Example("/mamdani/matlab/mam21", 128));
- examples.push_back(Example("/mamdani/matlab/mam22", 128));
- examples.push_back(Example("/mamdani/matlab/shower", 256));
- examples.push_back(Example("/mamdani/matlab/tank", 256));
- examples.push_back(Example("/mamdani/matlab/tank2", 512));
- examples.push_back(Example("/mamdani/matlab/tipper", 256));
- examples.push_back(Example("/mamdani/matlab/tipper1", 1e5));
- examples.push_back(Example("/mamdani/octave/investment_portfolio", 256));
- examples.push_back(Example("/mamdani/octave/mamdani_tip_calculator", 256));
- examples.push_back(Example("/takagi-sugeno/approximation", 1e6));
- examples.push_back(Example("/takagi-sugeno/SimpleDimmer", 2e6));
- examples.push_back(Example("/takagi-sugeno/matlab/fpeaks", 512));
- examples.push_back(Example("/takagi-sugeno/matlab/invkine1", 256));
- examples.push_back(Example("/takagi-sugeno/matlab/invkine2", 256));
- examples.push_back(Example("/takagi-sugeno/matlab/juggler", 512));
- examples.push_back(Example("/takagi-sugeno/matlab/membrn1", 1024));
- examples.push_back(Example("/takagi-sugeno/matlab/membrn2", 512));
- examples.push_back(Example("/takagi-sugeno/matlab/slbb", 20));
- examples.push_back(Example("/takagi-sugeno/matlab/slcp", 20));
- examples.push_back(Example("/takagi-sugeno/matlab/slcp1", 15));
- examples.push_back(Example("/takagi-sugeno/matlab/slcpp1", 9));
- examples.push_back(Example("/takagi-sugeno/matlab/sltbu_fl", 128));
- examples.push_back(Example("/takagi-sugeno/matlab/sugeno1", 2e6));
- examples.push_back(Example("/takagi-sugeno/matlab/tanksg", 1024));
- examples.push_back(Example("/takagi-sugeno/matlab/tippersg", 1024));
- examples.push_back(Example("/takagi-sugeno/octave/cubic_approximator", 2e6));
- examples.push_back(Example("/takagi-sugeno/octave/heart_disease_risk", 1024));
- examples.push_back(Example("/takagi-sugeno/octave/linear_tip_calculator", 1024));
- examples.push_back(Example("/takagi-sugeno/octave/sugeno_tip_calculator", 512));
- examples.push_back(Example("/tsukamoto/tsukamoto", 1e6));
-
- for (std::size_t i = 0; i < examples.size(); ++i) {
- FL_LOG(examples.at(i).first << "\t" << examples.at(i).second);
+ void Console::benchmark(const std::string& fllFile, const std::string& fldFile,
+ int runs, std::ofstream* writer) const {
+ FL_unique_ptr<Engine> engine(FllImporter().fromFile(fllFile));
+ std::ifstream reader(fldFile.c_str());
+ if (not reader.is_open()) {
+ throw Exception("File <" + fldFile + "> could not be opened");
+ }
+ Benchmark benchmark(engine->getName(), engine.get());
+ benchmark.prepare(reader);
+ if (writer) {
+ FL_LOG("\tEvaluating on " << benchmark.getExpected().size() <<
+ " values read from " << fldFile << " ...");
}
-
- std::vector<std::string> runNumbers(runs);
for (int i = 0; i < runs; ++i) {
- runNumbers.at(i) = std::to_string(i + 1);
+ benchmark.runOnce();
}
- std::string spacedPath(40, ' ');
- std::copy(path.begin(), path.end(), spacedPath.begin());
- FL_LOG(spacedPath << "\t" << "mean\tstdev\n" << Op::join(runNumbers, "\t"));
-
- FllImporter importer;
- FldExporter exporter;
- exporter.setExportHeader(false);
- exporter.setExportInputValues(false);
- exporter.setExportOutputValues(false);
- std::ostream dummy(0);
+ if (writer) {
+ FL_LOG("\tMean(t)=" << Op::mean(benchmark.getTimes()) << " nanoseconds");
+ *writer << benchmark.format(benchmark.results(),
+ Benchmark::Horizontal, Benchmark::Body) << "\n";
+ } else {
+ FL_LOGP(benchmark.format(benchmark.results(),
+ Benchmark::Horizontal, Benchmark::Body));
+ }
+ }
- for (std::size_t e = 0; e < examples.size(); ++e) {
- FL_unique_ptr<Engine> engine(importer.fromFile(sourceBase + examples.at(e).first + ".fll"));
+ void Console::benchmarks(const std::string& fllFileList,
+ const std::string& fldFileList, int runs, std::ofstream* writer) const {
+ std::vector<std::string> fllFiles, fldFiles;
- std::vector<scalar> seconds;
- int results = std::pow(1.0 * examples.at(e).second, engine->numberOfInputVariables());
+ {
+ std::ifstream fllReader(fllFileList.c_str());
+ if (not fllReader.is_open()) {
+ throw Exception("[error] file <" + fllFileList + "> could not be opened");
+ }
+ std::ifstream fldReader(fldFileList.c_str());
+ if (not fldReader.is_open()) {
+ throw Exception("[error] file <" + fldFileList + "> could not be opened");
+ }
- for (int r = 0; r < runs; ++r) {
- auto start = std::chrono::system_clock::now();
- exporter.write(engine.get(), dummy, results);
- auto end = std::chrono::system_clock::now();
+ std::string fllLine, fldLine;
+ while (std::getline(fllReader, fllLine) and std::getline(fldReader, fldLine)) {
+ fllLine = Op::trim(fllLine);
+ fldLine = Op::trim(fldLine);
+ if (fllLine.empty() or fllLine[0] == '#')
+ continue;
+ fllFiles.push_back(fllLine);
+ fldFiles.push_back(fldLine);
+ }
+ }
- auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds> (end - start);
+ if (writer) {
+ *writer << Op::join(Benchmark().header(runs, true), "\t") << "\n";
+ } else {
+ FL_LOGP(Op::join(Benchmark().header(runs, true), "\t"));
+ }
- seconds.push_back(elapsed.count() / 1e3);
+ for (std::size_t i = 0; i < fllFiles.size(); ++i) {
+ if (writer) {
+ FL_LOG("Benchmark " << (i + 1) << "/" << fllFiles.size() << ": "
+ << fllFiles.at(i));
}
- scalar mean = Op::mean(seconds);
- scalar stdev = Op::standardDeviation(seconds, mean);
-
- std::string spacedExample(40, ' ');
- std::string exampleName = examples.at(e).first;
- std::copy(exampleName.begin(), exampleName.end(), spacedExample.begin());
- FL_LOG(spacedExample << "\t" << fl::Op::str(mean) << "\t" << fl::Op::str(stdev) << "\n" <<
- Op::join(seconds, "\t"));
+ benchmark(fllFiles.at(i), fldFiles.at(i), runs, writer);
}
}
-#endif
- int Console::main(int argc, char** argv) {
- (void) argc;
- (void) argv;
+ int Console::main(int argc, const char* argv[]) {
+ fuzzylite::setLogging(true);
+
+ Console console;
if (argc <= 2) {
- std::cout << usage() << std::endl;
+ FL_LOGP(console.usage() << "\n");
return EXIT_SUCCESS;
}
- const std::string firstArgument = std::string(argv[1]);
-
+ const std::string firstArgument(argv[1]);
if (firstArgument == "export-examples") {
std::string path = ".";
if (argc > 2) {
path = std::string(argv[2]);
}
- FL_LOG("Path=" << path);
+ std::string outputPath = "/tmp/";
+ if (argc > 3) {
+ outputPath = std::string(argv[3]);
+ }
+ FL_LOG("Origin=" << path);
+ FL_LOG("Target=" << outputPath);
+ fuzzylite::setDecimals(3);
try {
- fuzzylite::setDecimals(3);
FL_LOG("Processing fll->fll");
- exportAllExamples("fll", "fll", path);
+ console.exportAllExamples("fll", "fll", path, outputPath);
FL_LOG("Processing fll->fcl");
- exportAllExamples("fll", "fcl", path);
+ console.exportAllExamples("fll", "fcl", path, outputPath);
FL_LOG("Processing fll->fis");
- exportAllExamples("fll", "fis", path);
+ console.exportAllExamples("fll", "fis", path, outputPath);
FL_LOG("Processing fll->cpp");
- exportAllExamples("fll", "cpp", path);
+ console.exportAllExamples("fll", "cpp", path, outputPath);
FL_LOG("Processing fll->java");
- exportAllExamples("fll", "java", path);
- fuzzylite::setDecimals(8);
- fuzzylite::setMachEps(1e-6);
+ console.exportAllExamples("fll", "java", path, outputPath);
+ FL_LOG("Processing fll->R");
+ console.exportAllExamples("fll", "R", path, outputPath);
+ fuzzylite::setDecimals(9);
FL_LOG("Processing fll->fld");
- exportAllExamples("fll", "fld", path);
+ console.exportAllExamples("fll", "fld", path, outputPath);
+ FL_LOG("Origin=" << path);
+ FL_LOG("Target=" << outputPath);
+ } catch (std::exception& ex) {
+ FL_LOGP(ex.what() << "\n");
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+
+ } else if (firstArgument == "benchmark") {
+ if (argc < 5) {
+ FL_LOG("[error] not enough parameters");
+ return EXIT_FAILURE;
+ }
+ std::string fllFile(argv[2]);
+ std::string fldFile(argv[3]);
+ try {
+ int runs = (int) Op::toScalar(argv[4]);
+ if (argc > 5) {
+ std::string filename(argv[5]);
+ std::ofstream outputFile;
+ outputFile.open(filename.c_str());
+ if (not outputFile.is_open()) {
+ FL_LOG("[error] cannot create file <" << filename << ">");
+ return EXIT_FAILURE;
+ }
+ outputFile << Op::join(Benchmark().header(runs, true), "\t") << "\n";
+ console.benchmark(fllFile, fldFile, runs, &outputFile);
+ } else {
+ FL_LOGP(Op::join(Benchmark().header(runs, true), "\t"));
+ console.benchmark(fllFile, fldFile, runs, fl::null);
+ }
} catch (std::exception& ex) {
- std::cout << ex.what() << "\nBACKTRACE:\n" <<
- fl::Exception::btCallStack() << std::endl;
+ FL_LOGP(ex.what() << "\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
+
} else if (firstArgument == "benchmarks") {
-#ifdef FL_CPP11
- std::string path = ".";
- if (argc > 2) {
- path = std::string(argv[2]);
+ if (argc < 5) {
+ FL_LOG("[error] not enough parameters");
+ return EXIT_FAILURE;
}
- int runs = 10;
- if (argc > 3) {
- runs = (int) Op::toScalar(argv[3]);
+ std::string fllFiles(argv[2]);
+ std::string fldFiles(argv[3]);
+ try {
+ int runs = (int) Op::toScalar(argv[4]);
+ if (argc > 5) {
+ std::string filename(argv[5]);
+ std::ofstream outputFile;
+ outputFile.open(filename.c_str());
+ if (not outputFile.is_open()) {
+ FL_LOG("[error] cannot create file <" << filename << ">");
+ return EXIT_FAILURE;
+ }
+ console.benchmarks(fllFiles, fldFiles, runs, &outputFile);
+ } else {
+ console.benchmarks(fllFiles, fldFiles, runs, fl::null);
+ }
+ } catch (std::exception& ex) {
+ FL_LOGP(ex.what() << "\n");
+ return EXIT_FAILURE;
}
- fuzzylite::setDecimals(3);
- Console::benchmarkExamples(path, runs);
return EXIT_SUCCESS;
-#else
- throw fl::Exception("[benchmarks error] implementation available only when built with C++11 (-DFL_CPP11)", FL_AT);
-#endif
}
+ //MAIN:
try {
- std::map<std::string, std::string> options = parse(argc, argv);
- process(options);
+ std::map<std::string, std::string> options = console.parse(argc, argv);
+ console.process(options);
+
} catch (std::exception& ex) {
- std::cout << ex.what() << "\n" << std::endl;
- // std::cout << fl::Exception::btCallStack() << std::endl;
+ FL_LOGP(ex.what() << "\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
+
}
diff --git a/fuzzylite/src/Engine.cpp b/fuzzylite/src/Engine.cpp
index f1e23c0..dbe4b17 100644
--- a/fuzzylite/src/Engine.cpp
+++ b/fuzzylite/src/Engine.cpp
@@ -1,46 +1,35 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/Engine.h"
+#include "fl/activation/General.h"
#include "fl/defuzzifier/WeightedAverage.h"
#include "fl/defuzzifier/WeightedSum.h"
#include "fl/factory/DefuzzifierFactory.h"
#include "fl/factory/FactoryManager.h"
-#include "fl/factory/SNormFactory.h"
-#include "fl/factory/TNormFactory.h"
-#include "fl/hedge/Hedge.h"
#include "fl/imex/FllExporter.h"
#include "fl/norm/t/AlgebraicProduct.h"
#include "fl/rule/Consequent.h"
#include "fl/rule/Expression.h"
#include "fl/rule/Rule.h"
#include "fl/rule/RuleBlock.h"
-#include "fl/term/Accumulated.h"
+#include "fl/term/Aggregated.h"
#include "fl/term/Constant.h"
#include "fl/term/Linear.h"
-#include "fl/term/Function.h"
#include "fl/term/Ramp.h"
#include "fl/term/Sigmoid.h"
#include "fl/term/SShape.h"
@@ -48,21 +37,19 @@
#include "fl/variable/InputVariable.h"
#include "fl/variable/OutputVariable.h"
-
namespace fl {
- Engine::Engine(const std::string& name) : _name(name) {
- }
+ Engine::Engine(const std::string& name) : _name(name) { }
- Engine::Engine(const Engine& other) : _name("") {
+ Engine::Engine(const Engine& other) : _name(""), _description("") {
copyFrom(other);
}
Engine& Engine::operator=(const Engine& other) {
if (this != &other) {
- for (std::size_t i = 0; i < _ruleblocks.size(); ++i)
- delete _ruleblocks.at(i);
- _ruleblocks.clear();
+ for (std::size_t i = 0; i < _ruleBlocks.size(); ++i)
+ delete _ruleBlocks.at(i);
+ _ruleBlocks.clear();
for (std::size_t i = 0; i < _outputVariables.size(); ++i)
delete _outputVariables.at(i);
_outputVariables.clear();
@@ -77,6 +64,7 @@ namespace fl {
void Engine::copyFrom(const Engine& other) {
_name = other._name;
+ _description = other._description;
for (std::size_t i = 0; i < other._inputVariables.size(); ++i)
_inputVariables.push_back(new InputVariable(*other._inputVariables.at(i)));
for (std::size_t i = 0; i < other._outputVariables.size(); ++i)
@@ -84,13 +72,14 @@ namespace fl {
updateReferences();
- for (std::size_t i = 0; i < other._ruleblocks.size(); ++i) {
- RuleBlock* ruleBlock = new RuleBlock(*other._ruleblocks.at(i));
+ for (std::size_t i = 0; i < other._ruleBlocks.size(); ++i) {
+ RuleBlock* ruleBlock = new RuleBlock(*other._ruleBlocks.at(i));
try {
ruleBlock->loadRules(this);
} catch (...) {
+ //ignore
}
- _ruleblocks.push_back(ruleBlock);
+ _ruleBlocks.push_back(ruleBlock);
}
}
@@ -98,78 +87,89 @@ namespace fl {
std::vector<Variable*> myVariables = variables();
for (std::size_t i = 0; i < myVariables.size(); ++i) {
Variable* variable = myVariables.at(i);
- for (int t = 0; t < variable->numberOfTerms(); ++t) {
- Term::updateReference(variable->getTerm(t), this);
+ for (std::size_t t = 0; t < variable->numberOfTerms(); ++t) {
+ variable->getTerm(t)->updateReference(this);
}
}
}
Engine::~Engine() {
- for (std::size_t i = 0; i < _ruleblocks.size(); ++i) delete _ruleblocks.at(i);
- for (std::size_t i = 0; i < _outputVariables.size(); ++i) delete _outputVariables.at(i);
- for (std::size_t i = 0; i < _inputVariables.size(); ++i) delete _inputVariables.at(i);
+ for (std::size_t i = 0; i < _ruleBlocks.size(); ++i)
+ delete _ruleBlocks.at(i);
+ for (std::size_t i = 0; i < _outputVariables.size(); ++i)
+ delete _outputVariables.at(i);
+ for (std::size_t i = 0; i < _inputVariables.size(); ++i)
+ delete _inputVariables.at(i);
}
- void Engine::configure(const std::string& conjunctionT, const std::string& disjunctionS,
- const std::string& activationT, const std::string& accumulationS,
- const std::string& defuzzifierName, int resolution) {
+ void Engine::configure(const std::string& conjunction, const std::string& disjunction,
+ const std::string& implication, const std::string& aggregation,
+ const std::string& defuzzifier, const std::string& activation) {
TNormFactory* tnormFactory = FactoryManager::instance()->tnorm();
SNormFactory* snormFactory = FactoryManager::instance()->snorm();
DefuzzifierFactory* defuzzFactory = FactoryManager::instance()->defuzzifier();
- TNorm* conjunction = tnormFactory->constructObject(conjunctionT);
- SNorm* disjunction = snormFactory->constructObject(disjunctionS);
- TNorm* activation = tnormFactory->constructObject(activationT);
- SNorm* accumulation = snormFactory->constructObject(accumulationS);
- Defuzzifier* defuzzifier = defuzzFactory->constructObject(defuzzifierName);
- IntegralDefuzzifier* integralDefuzzifier = dynamic_cast<IntegralDefuzzifier*> (defuzzifier);
- if (integralDefuzzifier) integralDefuzzifier->setResolution(resolution);
+ ActivationFactory* activationFactory = FactoryManager::instance()->activation();
+
+ TNorm* conjunctionObject = tnormFactory->constructObject(conjunction);
+ SNorm* disjunctionObject = snormFactory->constructObject(disjunction);
+ TNorm* implicationObject = tnormFactory->constructObject(implication);
+ SNorm* aggregationObject = snormFactory->constructObject(aggregation);
+ Defuzzifier* defuzzifierObject = defuzzFactory->constructObject(defuzzifier);
+ Activation* activationObject = activationFactory->constructObject(activation);
- configure(conjunction, disjunction, activation, accumulation, defuzzifier);
+ configure(conjunctionObject, disjunctionObject,
+ implicationObject, aggregationObject, defuzzifierObject,
+ activationObject);
}
void Engine::configure(TNorm* conjunction, SNorm* disjunction,
- TNorm* activation, SNorm* accumulation, Defuzzifier* defuzzifier) {
- for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
- _ruleblocks.at(i)->setConjunction(conjunction ? conjunction->clone() : fl::null);
- _ruleblocks.at(i)->setDisjunction(disjunction ? disjunction->clone() : fl::null);
- _ruleblocks.at(i)->setActivation(activation ? activation->clone() : fl::null);
+ TNorm* implication, SNorm* aggregation, Defuzzifier* defuzzifier,
+ Activation* activation) {
+ for (std::size_t i = 0; i < numberOfRuleBlocks(); ++i) {
+ RuleBlock* ruleBlock = ruleBlocks().at(i);
+ ruleBlock->setConjunction(conjunction ? conjunction->clone() : fl::null);
+ ruleBlock->setDisjunction(disjunction ? disjunction->clone() : fl::null);
+ ruleBlock->setImplication(implication ? implication->clone() : fl::null);
+ ruleBlock->setActivation(activation ? activation->clone() : new General);
}
- for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
- _outputVariables.at(i)->setDefuzzifier(defuzzifier ? defuzzifier->clone() : fl::null);
- _outputVariables.at(i)->fuzzyOutput()->setAccumulation(
- accumulation ? accumulation->clone() : fl::null);
+ for (std::size_t i = 0; i < numberOfOutputVariables(); ++i) {
+ OutputVariable* outputVariable = getOutputVariable(i);
+ outputVariable->setDefuzzifier(defuzzifier ? defuzzifier->clone() : fl::null);
+ outputVariable->setAggregation(aggregation ? aggregation->clone() : fl::null);
}
if (defuzzifier) delete defuzzifier;
- if (accumulation) delete accumulation;
- if (activation) delete activation;
+ if (aggregation) delete aggregation;
+ if (implication) delete implication;
if (disjunction) delete disjunction;
if (conjunction) delete conjunction;
+ if (activation) delete activation;
}
bool Engine::isReady(std::string* status) const {
std::ostringstream ss;
- if (_inputVariables.empty()) {
- ss << "- Engine <" << _name << "> has no input variables\n";
+ if (inputVariables().empty()) {
+ ss << "- Engine <" << getName() << "> has no input variables\n";
}
- for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
- InputVariable* inputVariable = _inputVariables.at(i);
+ for (std::size_t i = 0; i < inputVariables().size(); ++i) {
+ InputVariable* inputVariable = inputVariables().at(i);
if (not inputVariable) {
- ss << "- Engine <" << _name << "> has a fl::null input variable at index <" << i << ">\n";
- } else if (inputVariable->terms().empty()) {
- //ignore because sometimes inputs can be empty: takagi-sugeno/matlab/slcpp1.fis
- // ss << "- Input variable <" << _inputVariables.at(i)->getName() << ">"
- // << " has no terms\n";
+ ss << "- Engine <" << getName() << "> has a fl::null input variable at index <" << i << ">\n";
}
+ /*else if (inputVariable->terms().empty()) {
+ ignore because sometimes inputs can be empty: takagi-sugeno/matlab/slcpp1.fis
+ ss << "- Input variable <" << _inputVariables.at(i)->getName() << ">"
+ << " has no terms\n";
+ }*/
}
- if (_outputVariables.empty()) {
+ if (outputVariables().empty()) {
ss << "- Engine <" << _name << "> has no output variables\n";
}
- for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
- OutputVariable* outputVariable = _outputVariables.at(i);
+ for (std::size_t i = 0; i < outputVariables().size(); ++i) {
+ OutputVariable* outputVariable = outputVariables().at(i);
if (not outputVariable) {
- ss << "- Engine <" << _name << "> has a fl::null output variable at index <" << i << ">\n";
+ ss << "- Engine <" << getName() << "> has a fl::null output variable at index <" << i << ">\n";
} else {
if (outputVariable->terms().empty()) {
ss << "- Output variable <" << outputVariable->getName() << ">"
@@ -180,29 +180,29 @@ namespace fl {
ss << "- Output variable <" << outputVariable->getName() << ">"
<< " has no defuzzifier\n";
}
- SNorm* accumulation = outputVariable->fuzzyOutput()->getAccumulation();
- if (not accumulation and dynamic_cast<IntegralDefuzzifier*> (defuzzifier)) {
+ SNorm* aggregation = outputVariable->fuzzyOutput()->getAggregation();
+ if (not aggregation and dynamic_cast<IntegralDefuzzifier*> (defuzzifier)) {
ss << "- Output variable <" << outputVariable->getName() << ">"
- << " has no accumulation operator\n";
+ << " has no aggregation operator\n";
}
}
}
- if (_ruleblocks.empty()) {
- ss << "- Engine <" << _name << "> has no rule blocks\n";
+ if (ruleBlocks().empty()) {
+ ss << "- Engine <" << getName() << "> has no rule blocks\n";
}
- for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
- RuleBlock* ruleblock = _ruleblocks.at(i);
+ for (std::size_t i = 0; i < ruleBlocks().size(); ++i) {
+ RuleBlock* ruleblock = ruleBlocks().at(i);
if (not ruleblock) {
- ss << "- Engine <" << _name << "> has a fl::null rule block at index <" << i << ">\n";
+ ss << "- Engine <" << getName() << "> has a fl::null rule block at index <" << i << ">\n";
} else {
if (ruleblock->rules().empty()) {
ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no rules\n";
}
int requiresConjunction = 0;
int requiresDisjunction = 0;
- int requiresActivation = 0;
- for (int r = 0; r < ruleblock->numberOfRules(); ++r) {
+ int requiresImplication = 0;
+ for (std::size_t r = 0; r < ruleblock->numberOfRules(); ++r) {
Rule* rule = ruleblock->getRule(r);
if (not rule) {
ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName()
@@ -224,7 +224,7 @@ namespace fl {
const OutputVariable* outputVariable =
dynamic_cast<const OutputVariable*> (proposition->variable);
if (outputVariable and dynamic_cast<IntegralDefuzzifier*> (outputVariable->getDefuzzifier())) {
- ++requiresActivation;
+ ++requiresImplication;
break;
}
}
@@ -243,11 +243,11 @@ namespace fl {
ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has "
<< requiresDisjunction << " rules that require disjunction operator\n";
}
- const TNorm* activation = ruleblock->getActivation();
- if (requiresActivation > 0 and not activation) {
- ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no activation operator\n";
+ const TNorm* implication = ruleblock->getImplication();
+ if (requiresImplication > 0 and not implication) {
+ ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has no implication operator\n";
ss << "- Rule block " << (i + 1) << " <" << ruleblock->getName() << "> has "
- << requiresActivation << " rules that require activation operator\n";
+ << requiresImplication << " rules that require implication operator\n";
}
}
}
@@ -256,14 +256,25 @@ namespace fl {
}
void Engine::restart() {
- for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
- _inputVariables.at(i)->setInputValue(fl::nan);
+ for (std::size_t i = 0; i < inputVariables().size(); ++i) {
+ inputVariables().at(i)->setValue(fl::nan);
}
- for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
- _outputVariables.at(i)->clear();
+ for (std::size_t i = 0; i < outputVariables().size(); ++i) {
+ outputVariables().at(i)->clear();
}
}
+ Complexity Engine::complexity() const {
+ Complexity result;
+ for (std::size_t i = 0; i < _ruleBlocks.size(); ++i) {
+ const RuleBlock* ruleBlock = _ruleBlocks.at(i);
+ if (ruleBlock->isEnabled()) {
+ result += ruleBlock->complexity();
+ }
+ }
+ return result;
+ }
+
void Engine::process() {
for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
_outputVariables.at(i)->fuzzyOutput()->clear();
@@ -274,7 +285,7 @@ namespace fl {
FL_DBG("CURRENT INPUTS:");
for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
InputVariable* inputVariable = _inputVariables.at(i);
- scalar inputValue = inputVariable->getInputValue();
+ scalar inputValue = inputVariable->getValue();
if (inputVariable->isEnabled()) {
FL_DBG(inputVariable->getName() << ".input = " << Op::str(inputValue));
FL_DBG(inputVariable->getName() << ".fuzzy = " << inputVariable->fuzzify(inputValue));
@@ -285,9 +296,11 @@ namespace fl {
FL_DEBUG_END;
- for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
- RuleBlock* ruleBlock = _ruleblocks.at(i);
+ for (std::size_t i = 0; i < _ruleBlocks.size(); ++i) {
+ RuleBlock* ruleBlock = _ruleBlocks.at(i);
if (ruleBlock->isEnabled()) {
+ FL_DBG("===============");
+ FL_DBG("RULE BLOCK: " << ruleBlock->getName());
ruleBlock->activate();
}
}
@@ -306,12 +319,12 @@ namespace fl {
<< outputVariable->getDefaultValue());
FL_DBG(outputVariable->getName() << ".lockValueInRange = "
- << outputVariable->isLockedOutputValueInRange());
+ << outputVariable->isLockValueInRange());
FL_DBG(outputVariable->getName() << ".lockPreviousValue= "
- << outputVariable->isLockedPreviousOutputValue());
+ << outputVariable->isLockPreviousValue());
- scalar output = outputVariable->getOutputValue();
+ scalar output = outputVariable->getValue();
FL_DBG(outputVariable->getName() << ".output = " << output);
FL_DBG(outputVariable->getName() << ".fuzzy = " <<
outputVariable->fuzzify(output));
@@ -332,12 +345,20 @@ namespace fl {
return this->_name;
}
+ void Engine::setDescription(const std::string& description) {
+ this->_description = description;
+ }
+
+ std::string Engine::getDescription() const {
+ return this->_description;
+ }
+
std::string Engine::toString() const {
return FllExporter().toString(this);
}
Engine::Type Engine::type(std::string* name, std::string* reason) const {
- if (_outputVariables.empty()) {
+ if (outputVariables().empty()) {
if (name) *name = "Unknown";
if (reason) *reason = "- Engine has no output variables";
return Engine::Unknown;
@@ -345,24 +366,24 @@ namespace fl {
//Mamdani
bool mamdani = true;
- for (std::size_t i = 0; mamdani and i < _outputVariables.size(); ++i) {
- OutputVariable* outputVariable = _outputVariables.at(i);
+ for (std::size_t i = 0; mamdani and i < outputVariables().size(); ++i) {
+ OutputVariable* outputVariable = outputVariables().at(i);
//Defuzzifier must be integral
mamdani = mamdani and dynamic_cast<IntegralDefuzzifier*> (outputVariable->getDefuzzifier());
}
//Larsen
- bool larsen = mamdani and not _ruleblocks.empty();
- //Larsen is Mamdani with AlgebraicProduct as Activation
+ bool larsen = mamdani and not ruleBlocks().empty();
+ //Larsen is Mamdani with AlgebraicProduct as Implication
if (mamdani) {
- for (std::size_t i = 0; larsen and i < _ruleblocks.size(); ++i) {
- RuleBlock* ruleBlock = _ruleblocks.at(i);
- larsen = larsen and dynamic_cast<const AlgebraicProduct*> (ruleBlock->getActivation());
+ for (std::size_t i = 0; larsen and i < ruleBlocks().size(); ++i) {
+ RuleBlock* ruleBlock = ruleBlocks().at(i);
+ larsen = larsen and dynamic_cast<const AlgebraicProduct*> (ruleBlock->getImplication());
}
}
if (larsen) {
if (name) *name = "Larsen";
if (reason) *reason = "- Output variables have integral defuzzifiers\n"
- "- Rule blocks activate using the algebraic product T-Norm";
+ "- Implication in rule blocks is the algebraic product T-Norm";
return Engine::Larsen;
}
if (mamdani) {
@@ -374,8 +395,8 @@ namespace fl {
//TakagiSugeno
bool takagiSugeno = true;
- for (std::size_t i = 0; takagiSugeno and i < _outputVariables.size(); ++i) {
- OutputVariable* outputVariable = _outputVariables.at(i);
+ for (std::size_t i = 0; takagiSugeno and i < outputVariables().size(); ++i) {
+ OutputVariable* outputVariable = outputVariables().at(i);
//Defuzzifier is Weighted
WeightedDefuzzifier* weightedDefuzzifier =
dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier());
@@ -386,7 +407,7 @@ namespace fl {
if (takagiSugeno) {
//Takagi-Sugeno has only Constant, Linear or Function terms
- for (int t = 0; takagiSugeno and t < outputVariable->numberOfTerms(); ++t) {
+ for (std::size_t t = 0; takagiSugeno and t < outputVariable->numberOfTerms(); ++t) {
Term* term = outputVariable->getTerm(t);
takagiSugeno = takagiSugeno and
weightedDefuzzifier->inferType(term) == WeightedDefuzzifier::TakagiSugeno;
@@ -402,8 +423,8 @@ namespace fl {
//Tsukamoto
bool tsukamoto = true;
- for (std::size_t i = 0; tsukamoto and i < _outputVariables.size(); ++i) {
- OutputVariable* outputVariable = _outputVariables.at(i);
+ for (std::size_t i = 0; tsukamoto and i < outputVariables().size(); ++i) {
+ OutputVariable* outputVariable = outputVariables().at(i);
//Defuzzifier is Weighted
WeightedDefuzzifier* weightedDefuzzifier =
dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier());
@@ -413,9 +434,9 @@ namespace fl {
weightedDefuzzifier->getType() == WeightedDefuzzifier::Tsukamoto);
if (tsukamoto) {
//Tsukamoto has only monotonic terms: Concave, Ramp, Sigmoid, SShape, or ZShape
- for (int t = 0; tsukamoto and t < outputVariable->numberOfTerms(); ++t) {
+ for (std::size_t t = 0; tsukamoto and t < outputVariable->numberOfTerms(); ++t) {
Term* term = outputVariable->getTerm(t);
- tsukamoto = tsukamoto and weightedDefuzzifier->isMonotonic(term);
+ tsukamoto = tsukamoto and term->isMonotonic();
}
}
}
@@ -428,8 +449,8 @@ namespace fl {
//Inverse Tsukamoto
bool inverseTsukamoto = true;
- for (std::size_t i = 0; inverseTsukamoto and i < _outputVariables.size(); ++i) {
- OutputVariable* outputVariable = _outputVariables.at(i);
+ for (std::size_t i = 0; inverseTsukamoto and i < outputVariables().size(); ++i) {
+ OutputVariable* outputVariable = outputVariables().at(i);
//Defuzzifier cannot be integral
WeightedDefuzzifier* weightedDefuzzifier =
dynamic_cast<WeightedDefuzzifier*> (outputVariable->getDefuzzifier());
@@ -444,19 +465,19 @@ namespace fl {
}
bool hybrid = true;
- for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
- OutputVariable* outputVariable = _outputVariables.at(i);
+ for (std::size_t i = 0; i < outputVariables().size(); ++i) {
+ OutputVariable* outputVariable = outputVariables().at(i);
//Output variables have non-fl::null defuzzifiers
hybrid = hybrid and outputVariable->getDefuzzifier();
}
if (hybrid) {
if (name) *name = "Hybrid";
- if (reason) *reason = "- Output variables have different defuzzifiers";
+ if (reason) *reason = "- Output variables have different types of defuzzifiers";
return Engine::Hybrid;
}
if (name) *name = "Unknown";
- if (reason) *reason = "- There are output variables without a defuzzifier";
+ if (reason) *reason = "- One or more output variables do not have a defuzzifier";
return Engine::Unknown;
}
@@ -466,9 +487,9 @@ namespace fl {
std::vector<Variable*> Engine::variables() const {
std::vector<Variable*> result;
- result.reserve(_inputVariables.size() + _outputVariables.size());
- result.insert(result.end(), _inputVariables.begin(), _inputVariables.end());
- result.insert(result.end(), _outputVariables.begin(), _outputVariables.end());
+ result.reserve(inputVariables().size() + outputVariables().size());
+ result.insert(result.end(), inputVariables().begin(), inputVariables().end());
+ result.insert(result.end(), outputVariables().begin(), outputVariables().end());
return result;
}
@@ -477,63 +498,62 @@ namespace fl {
*/
void Engine::setInputValue(const std::string& name, scalar value) {
InputVariable* inputVariable = getInputVariable(name);
- inputVariable->setInputValue(value);
+ inputVariable->setValue(value);
}
void Engine::addInputVariable(InputVariable* inputVariable) {
- this->_inputVariables.push_back(inputVariable);
+ inputVariables().push_back(inputVariable);
}
- InputVariable* Engine::setInputVariable(InputVariable* inputVariable, int index) {
- InputVariable* result = this->_inputVariables.at(index);
- this->_inputVariables.at(index) = inputVariable;
+ InputVariable* Engine::setInputVariable(InputVariable* inputVariable, std::size_t index) {
+ InputVariable* result = inputVariables().at(index);
+ inputVariables().at(index) = inputVariable;
return result;
}
- void Engine::insertInputVariable(InputVariable* inputVariable, int index) {
- this->_inputVariables.insert(this->_inputVariables.begin() + index,
- inputVariable);
+ void Engine::insertInputVariable(InputVariable* inputVariable, std::size_t index) {
+ inputVariables().insert(inputVariables().begin() + index, inputVariable);
}
- InputVariable* Engine::getInputVariable(int index) const {
- return this->_inputVariables.at(index);
+ InputVariable* Engine::getInputVariable(std::size_t index) const {
+ return inputVariables().at(index);
}
InputVariable* Engine::getInputVariable(const std::string& name) const {
- for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
- if (_inputVariables.at(i)->getName() == name)
- return _inputVariables.at(i);
+ for (std::size_t i = 0; i < inputVariables().size(); ++i) {
+ if (inputVariables().at(i)->getName() == name)
+ return inputVariables().at(i);
}
- throw fl::Exception("[engine error] input variable <" + name + "> not found", FL_AT);
+ throw Exception("[engine error] input variable <" + name + "> not found", FL_AT);
}
bool Engine::hasInputVariable(const std::string& name) const {
- for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
- if (_inputVariables.at(i)->getName() == name)
+ for (std::size_t i = 0; i < inputVariables().size(); ++i) {
+ if (inputVariables().at(i)->getName() == name)
return true;
}
return false;
}
- InputVariable* Engine::removeInputVariable(int index) {
- InputVariable* result = this->_inputVariables.at(index);
- this->_inputVariables.erase(this->_inputVariables.begin() + index);
+ InputVariable* Engine::removeInputVariable(std::size_t index) {
+ InputVariable* result = inputVariables().at(index);
+ inputVariables().erase(inputVariables().begin() + index);
return result;
}
InputVariable* Engine::removeInputVariable(const std::string& name) {
- for (std::size_t i = 0; i < _inputVariables.size(); ++i) {
- if (_inputVariables.at(i)->getName() == name) {
- InputVariable* result = this->_inputVariables.at(i);
- this->_inputVariables.erase(this->_inputVariables.begin() + i);
+ for (std::size_t i = 0; i < inputVariables().size(); ++i) {
+ if (inputVariables().at(i)->getName() == name) {
+ InputVariable* result = inputVariables().at(i);
+ inputVariables().erase(inputVariables().begin() + i);
return result;
}
}
- throw fl::Exception("[engine error] input variable <" + name + "> not found", FL_AT);
+ throw Exception("[engine error] input variable <" + name + "> not found", FL_AT);
}
- int Engine::numberOfInputVariables() const {
- return this->_inputVariables.size();
+ std::size_t Engine::numberOfInputVariables() const {
+ return inputVariables().size();
}
const std::vector<InputVariable*>& Engine::inputVariables() const {
@@ -553,63 +573,62 @@ namespace fl {
*/
scalar Engine::getOutputValue(const std::string& name) {
OutputVariable* outputVariable = getOutputVariable(name);
- return outputVariable->getOutputValue();
+ return outputVariable->getValue();
}
void Engine::addOutputVariable(OutputVariable* outputVariable) {
- this->_outputVariables.push_back(outputVariable);
+ outputVariables().push_back(outputVariable);
}
- OutputVariable* Engine::setOutputVariable(OutputVariable* outputVariable, int index) {
- OutputVariable* result = this->_outputVariables.at(index);
- this->_outputVariables.at(index) = outputVariable;
+ OutputVariable* Engine::setOutputVariable(OutputVariable* outputVariable, std::size_t index) {
+ OutputVariable* result = outputVariables().at(index);
+ outputVariables().at(index) = outputVariable;
return result;
}
- void Engine::insertOutputVariable(OutputVariable* outputVariable, int index) {
- this->_outputVariables.insert(this->_outputVariables.begin() + index,
- outputVariable);
+ void Engine::insertOutputVariable(OutputVariable* outputVariable, std::size_t index) {
+ outputVariables().insert(outputVariables().begin() + index, outputVariable);
}
- OutputVariable* Engine::getOutputVariable(int index) const {
- return this->_outputVariables.at(index);
+ OutputVariable* Engine::getOutputVariable(std::size_t index) const {
+ return outputVariables().at(index);
}
OutputVariable* Engine::getOutputVariable(const std::string& name) const {
- for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
- if (_outputVariables.at(i)->getName() == name)
- return _outputVariables.at(i);
+ for (std::size_t i = 0; i < outputVariables().size(); ++i) {
+ if (outputVariables().at(i)->getName() == name)
+ return outputVariables().at(i);
}
- throw fl::Exception("[engine error] output variable <" + name + "> not found", FL_AT);
+ throw Exception("[engine error] output variable <" + name + "> not found", FL_AT);
}
bool Engine::hasOutputVariable(const std::string& name) const {
- for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
- if (_outputVariables.at(i)->getName() == name)
+ for (std::size_t i = 0; i < outputVariables().size(); ++i) {
+ if (outputVariables().at(i)->getName() == name)
return true;
}
return false;
}
- OutputVariable* Engine::removeOutputVariable(int index) {
- OutputVariable* result = this->_outputVariables.at(index);
- this->_outputVariables.erase(this->_outputVariables.begin() + index);
+ OutputVariable* Engine::removeOutputVariable(std::size_t index) {
+ OutputVariable* result = outputVariables().at(index);
+ outputVariables().erase(outputVariables().begin() + index);
return result;
}
OutputVariable* Engine::removeOutputVariable(const std::string& name) {
- for (std::size_t i = 0; i < _outputVariables.size(); ++i) {
- if (_outputVariables.at(i)->getName() == name) {
- OutputVariable* result = this->_outputVariables.at(i);
- this->_outputVariables.erase(this->_outputVariables.begin() + i);
+ for (std::size_t i = 0; i < outputVariables().size(); ++i) {
+ if (outputVariables().at(i)->getName() == name) {
+ OutputVariable* result = outputVariables().at(i);
+ outputVariables().erase(outputVariables().begin() + i);
return result;
}
}
- throw fl::Exception("[engine error] output variable <" + name + "> not found", FL_AT);
+ throw Exception("[engine error] output variable <" + name + "> not found", FL_AT);
}
- int Engine::numberOfOutputVariables() const {
- return this->_outputVariables.size();
+ std::size_t Engine::numberOfOutputVariables() const {
+ return outputVariables().size();
}
const std::vector<OutputVariable*>& Engine::outputVariables() const {
@@ -628,71 +647,70 @@ namespace fl {
* Operations for iterable datatype _ruleblocks
*/
void Engine::addRuleBlock(RuleBlock* ruleblock) {
- this->_ruleblocks.push_back(ruleblock);
+ ruleBlocks().push_back(ruleblock);
}
- RuleBlock* Engine::setRuleBlock(RuleBlock* ruleBlock, int index) {
- RuleBlock* result = this->_ruleblocks.at(index);
- this->_ruleblocks.at(index) = ruleBlock;
+ RuleBlock* Engine::setRuleBlock(RuleBlock* ruleBlock, std::size_t index) {
+ RuleBlock* result = ruleBlocks().at(index);
+ ruleBlocks().at(index) = ruleBlock;
return result;
}
- void Engine::insertRuleBlock(RuleBlock* ruleblock, int index) {
- this->_ruleblocks.insert(this->_ruleblocks.begin() + index, ruleblock);
+ void Engine::insertRuleBlock(RuleBlock* ruleblock, std::size_t index) {
+ ruleBlocks().insert(ruleBlocks().begin() + index, ruleblock);
}
- RuleBlock* Engine::getRuleBlock(int index) const {
- return this->_ruleblocks.at(index);
+ RuleBlock* Engine::getRuleBlock(std::size_t index) const {
+ return ruleBlocks().at(index);
}
RuleBlock* Engine::getRuleBlock(const std::string& name) const {
- for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
- if (_ruleblocks.at(i)->getName() == name)
- return _ruleblocks.at(i);
+ for (std::size_t i = 0; i < ruleBlocks().size(); ++i) {
+ if (ruleBlocks().at(i)->getName() == name)
+ return ruleBlocks().at(i);
}
- throw fl::Exception("[engine error] rule block <" + name + "> not found", FL_AT);
+ throw Exception("[engine error] rule block <" + name + "> not found", FL_AT);
}
bool Engine::hasRuleBlock(const std::string& name) const {
- for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
- if (_ruleblocks.at(i)->getName() == name)
+ for (std::size_t i = 0; i < ruleBlocks().size(); ++i) {
+ if (ruleBlocks().at(i)->getName() == name)
return true;
}
return false;
}
- RuleBlock* Engine::removeRuleBlock(int index) {
- RuleBlock* result = this->_ruleblocks.at(index);
- this->_ruleblocks.erase(this->_ruleblocks.begin() + index);
+ RuleBlock* Engine::removeRuleBlock(std::size_t index) {
+ RuleBlock* result = ruleBlocks().at(index);
+ ruleBlocks().erase(ruleBlocks().begin() + index);
return result;
}
RuleBlock* Engine::removeRuleBlock(const std::string& name) {
- for (std::size_t i = 0; i < _ruleblocks.size(); ++i) {
- if (_ruleblocks.at(i)->getName() == name) {
- RuleBlock* result = this->_ruleblocks.at(i);
- this->_ruleblocks.erase(this->_ruleblocks.begin() + i);
+ for (std::size_t i = 0; i < ruleBlocks().size(); ++i) {
+ if (ruleBlocks().at(i)->getName() == name) {
+ RuleBlock* result = ruleBlocks().at(i);
+ ruleBlocks().erase(ruleBlocks().begin() + i);
return result;
}
}
- throw fl::Exception("[engine error] rule block <" + name + "> not found", FL_AT);
+ throw Exception("[engine error] rule block <" + name + "> not found", FL_AT);
}
- int Engine::numberOfRuleBlocks() const {
- return this->_ruleblocks.size();
+ std::size_t Engine::numberOfRuleBlocks() const {
+ return ruleBlocks().size();
}
const std::vector<RuleBlock*>& Engine::ruleBlocks() const {
- return this->_ruleblocks;
+ return this->_ruleBlocks;
}
void Engine::setRuleBlocks(const std::vector<RuleBlock*>& ruleBlocks) {
- this->_ruleblocks = ruleBlocks;
+ this->_ruleBlocks = ruleBlocks;
}
std::vector<RuleBlock*>& Engine::ruleBlocks() {
- return this->_ruleblocks;
+ return this->_ruleBlocks;
}
-
}
diff --git a/fuzzylite/src/Exception.cpp b/fuzzylite/src/Exception.cpp
index d24adac..1c27e70 100644
--- a/fuzzylite/src/Exception.cpp
+++ b/fuzzylite/src/Exception.cpp
@@ -1,48 +1,47 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/Exception.h"
-#ifdef FL_BACKTRACE_OFF
-//do nothing
+#ifdef FL_BACKTRACE
-#elif defined FL_UNIX
+#ifdef FL_UNIX
#include <execinfo.h>
#elif defined FL_WINDOWS
#include <windows.h>
#include <winbase.h>
+
#ifndef __MINGW32__
+/*Disable warning 8.1\Include\um\dbghelp.h(1544):
+warning C4091: 'typedef ': ignored on left of '' when no variable is declared*/
+#pragma warning (push)
+#pragma warning (disable:4091)
#include <dbghelp.h>
+#pragma warning (pop)
#endif
+
+#endif
+
#endif
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
+#include <csignal>
+#include <cstring>
namespace fl {
@@ -58,8 +57,7 @@ namespace fl {
FL_DBG(this->what());
}
- Exception::~Exception() FL_INOEXCEPT {
- }
+ Exception::~Exception() FL_INOEXCEPT { }
void Exception::setWhat(const std::string& what) {
this->_what = what;
@@ -90,23 +88,25 @@ namespace fl {
}
std::string Exception::btCallStack() {
-#ifdef FL_BACKTRACE_OFF
- return "[backtrace disabled] fuzzylite was built with option -DFL_BACKTRACE_OFF";
+#ifndef FL_BACKTRACE
+ return "[backtrace disabled] fuzzylite was built without -DFL_BACKTRACE";
#elif defined FL_UNIX
std::ostringstream btStream;
const int bufferSize = 30;
void* buffer[bufferSize];
- int backtraceSize = backtrace(buffer, bufferSize);
- char **btSymbols = backtrace_symbols(buffer, backtraceSize);
+ int backtraceSize = ::backtrace(buffer, bufferSize);
+ char **btSymbols = ::backtrace_symbols(buffer, backtraceSize);
if (btSymbols == fl::null) {
btStream << "[backtrace error] no symbols could be retrieved";
} else {
- if (backtraceSize == 0) btStream << "[backtrace is empty]";
+ if (backtraceSize == 0) {
+ btStream << "[backtrace is empty]";
+ }
for (int i = 0; i < backtraceSize; ++i) {
btStream << btSymbols[i] << "\n";
}
}
- free(btSymbols);
+ ::free(btSymbols);
return btStream.str();
@@ -123,51 +123,52 @@ namespace fl {
} else {
btSymbol->MaxNameLen = 255;
btSymbol->SizeOfStruct = sizeof ( SYMBOL_INFO);
- if (backtraceSize == 0) btStream << "[backtrace is empty]";
+ if (backtraceSize == 0) {
+ btStream << "[backtrace is empty]";
+ }
for (int i = 0; i < backtraceSize; ++i) {
SymFromAddr(GetCurrentProcess(), (DWORD64) (buffer[ i ]), 0, btSymbol);
btStream << (backtraceSize - i - 1) << ": " <<
btSymbol->Name << " at 0x" << btSymbol->Address << "\n";
}
}
- free(btSymbol);
+ ::free(btSymbol);
return btStream.str();
#else
return "[backtrace missing] supported only in Unix and Windows platforms";
#endif
}
- //execinfo
- void Exception::signalHandler(int signal) {
+ void Exception::signalHandler(int unixSignal) {
std::ostringstream ex;
- ex << "[unexpected signal " << signal << "] ";
+ ex << "[unexpected signal " << unixSignal << "] ";
#ifdef FL_UNIX
- ex << strsignal(signal);
+ ex << ::strsignal(unixSignal);
#endif
ex << "\nBACKTRACE:\n" << btCallStack();
- fl::Exception::catchException(fl::Exception(ex.str(), FL_AT));
- exit(EXIT_FAILURE);
+ Exception::catchException(Exception(ex.str(), FL_AT));
+ ::exit(EXIT_FAILURE);
}
- void Exception::convertToException(int signal) {
+ void Exception::convertToException(int unixSignal) {
std::string signalDescription;
#ifdef FL_UNIX
//Unblock the signal
sigset_t empty;
sigemptyset(&empty);
- sigaddset(&empty, signal);
+ sigaddset(&empty, unixSignal);
sigprocmask(SIG_UNBLOCK, &empty, fl::null);
- signalDescription = strsignal(signal);
+ signalDescription = ::strsignal(unixSignal);
#endif
std::ostringstream ex;
- ex << "[signal " << signal << "] " << signalDescription << "\n";
+ ex << "[signal " << unixSignal << "] " << signalDescription << "\n";
ex << "BACKTRACE:\n" << btCallStack();
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
void Exception::terminate() {
- fl::Exception::catchException(fl::Exception("[unexpected exception] BACKTRACE:\n" + btCallStack(), FL_AT));
- exit(EXIT_FAILURE);
+ Exception::catchException(Exception("[unexpected exception] BACKTRACE:\n" + btCallStack(), FL_AT));
+ ::exit(EXIT_FAILURE);
}
void Exception::catchException(const std::exception& exception) {
diff --git a/fuzzylite/src/Operation.cpp b/fuzzylite/src/Operation.cpp
deleted file mode 100644
index 1596ea4..0000000
--- a/fuzzylite/src/Operation.cpp
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
-
- This file is part of fuzzylite.
-
- fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
-
- */
-
-#include "fl/Operation.h"
-
-#include "fl/defuzzifier/Defuzzifier.h"
-#include "fl/norm/Norm.h"
-#include "fl/norm/SNorm.h"
-#include "fl/norm/TNorm.h"
-
-#include <algorithm>
-#include <iomanip>
-#include <cstdarg>
-#include <cctype>
-
-namespace fl {
-
- template <typename T>
- T Operation::min(T a, T b) {
- if (isNaN(a)) return b;
- if (isNaN(b)) return a;
- return a < b ? a : b;
- }
- template FL_API scalar Operation::min(scalar a, scalar b);
- template FL_API int Operation::min(int a, int b);
-
- template <typename T>
- T Operation::max(T a, T b) {
- if (isNaN(a)) return b;
- if (isNaN(b)) return a;
- return a > b ? a : b;
- }
- template FL_API scalar Operation::max(scalar a, scalar b);
- template FL_API int Operation::max(int a, int b);
-
- template <typename T>
- T Operation::bound(T x, T min, T max) {
- if (isGt(x, max)) return max;
- if (isLt(x, min)) return min;
- return x;
- }
- template FL_API scalar Operation::bound(scalar x, scalar min, scalar max);
- template FL_API int Operation::bound(int x, int min, int max);
-
- template <typename T>
- bool Operation::in(T x, T min, T max, bool geq, bool leq) {
- bool left = geq ? isGE(x, min) : isGt(x, min);
- bool right = leq ? isLE(x, max) : isLt(x, max);
- return (left and right);
- }
- template FL_API bool Operation::in(scalar x, scalar min, scalar max, bool geq, bool leq);
- template FL_API bool Operation::in(int x, int min, int max, bool geq, bool leq);
-
- template <typename T>
- bool Operation::isInf(T x) {
- return std::abs(x) == fl::inf;
- }
- template FL_API bool Operation::isInf(int x);
- template FL_API bool Operation::isInf(scalar x);
-
- template <typename T>
- bool Operation::isNaN(T x) {
- return not (x == x);
- }
- template FL_API bool Operation::isNaN(int x);
- template FL_API bool Operation::isNaN(scalar x);
-
- template<typename T>
- bool Operation::isFinite(T x) {
- return not (isNaN(x) or isInf(x));
- }
- template FL_API bool Operation::isFinite(int x);
- template FL_API bool Operation::isFinite(scalar x);
-
- bool Operation::isLt(scalar a, scalar b, scalar macheps) {
- return not isEq(a, b, macheps) and a < b;
- }
-
- bool Operation::isLE(scalar a, scalar b, scalar macheps) {
- return isEq(a, b, macheps) or a < b;
- }
-
- bool Operation::isEq(scalar a, scalar b, scalar macheps) {
- return a == b or std::fabs(a - b) < macheps or (isNaN(a) and isNaN(b));
- }
-
- bool Operation::isGt(scalar a, scalar b, scalar macheps) {
- return not isEq(a, b, macheps) and a > b;
- }
-
- bool Operation::isGE(scalar a, scalar b, scalar macheps) {
- return isEq(a, b, macheps) or a > b;
- }
-
- scalar Operation::scale(scalar x, scalar fromMin, scalar fromMax, scalar toMin, scalar toMax, bool bounded) {
- scalar result = (toMax - toMin) / (fromMax - fromMin) * (x - fromMin) + toMin;
- return bounded ? fl::Op::bound(result, toMin, toMax) : result;
- }
-
- scalar Operation::add(scalar a, scalar b) {
- return a + b;
- }
-
- scalar Operation::subtract(scalar a, scalar b) {
- return a - b;
- }
-
- scalar Operation::multiply(scalar a, scalar b) {
- return a * b;
- }
-
- scalar Operation::divide(scalar a, scalar b) {
- return a / b;
- }
-
- scalar Operation::modulo(scalar a, scalar b) {
- return fmod(a, b);
- }
-
- scalar Operation::logicalAnd(scalar a, scalar b) {
- return (isEq(a, 1.0) and isEq(b, 1.0)) ? 1.0 : 0.0;
- }
-
- scalar Operation::logicalOr(scalar a, scalar b) {
- return (isEq(a, 1.0) or isEq(b, 1.0)) ? 1.0 : 0.0;
- }
-
- scalar Operation::logicalNot(scalar a) {
- return isEq(a, 1.0) ? 0.0 : 1.0;
- }
-
- scalar Operation::negate(scalar a) {
- return -a;
- }
-
- scalar Operation::round(scalar x) {
- return (x > 0.0) ? std::floor(x + 0.5) : std::ceil(x - 0.5);
- }
-
- scalar Operation::gt(scalar a, scalar b) {
- return isGt(a, b);
- }
-
- scalar Operation::ge(scalar a, scalar b) {
- return isGE(a, b);
- }
-
- scalar Operation::eq(scalar a, scalar b) {
- return isEq(a, b);
- }
-
- scalar Operation::neq(scalar a, scalar b) {
- return not isEq(a, b);
- }
-
- scalar Operation::le(scalar a, scalar b) {
- return isLE(a, b);
- }
-
- scalar Operation::lt(scalar a, scalar b) {
- return isLt(a, b);
- }
-
- bool Operation::increment(std::vector<int>& x, std::vector<int>& min, std::vector<int>& max) {
- return increment(x, (int) x.size() - 1, min, max);
- }
-
- bool Operation::increment(std::vector<int>& x, int position, std::vector<int>& min, std::vector<int>& max) {
- if (x.empty() or position < 0) return true;
-
- bool overflow = false;
- if (x.at(position) < max.at(position)) {
- ++x.at(position);
- } else {
- overflow = (position == 0);
- x.at(position) = min.at(position);
- --position;
- if (position >= 0) {
- overflow = increment(x, position, min, max);
- }
- }
- return overflow;
- }
-
- double Operation::mean(const std::vector<scalar>& x) {
- if (x.size() == 0) return fl::nan;
- scalar sum = 0.0;
- for (std::size_t i = 0; i < x.size(); ++i) sum += x.at(i);
- return sum / x.size();
- }
-
- double Operation::standardDeviation(const std::vector<scalar>& x) {
- if (x.size() <= 1) return 0.0;
- return standardDeviation(x, mean(x));
- }
-
- double Operation::standardDeviation(const std::vector<scalar>& x, scalar mean) {
- if (x.size() <= 1) return 0.0;
- return std::sqrt(variance(x, mean));
- }
-
- double Operation::variance(const std::vector<scalar>& x) {
- if (x.size() <= 1) return 0.0;
- return variance(x, mean(x));
- }
-
- double Operation::variance(const std::vector<scalar>& x, scalar mean) {
- if (x.size() <= 1) return 0.0;
- scalar result = 0;
- for (std::size_t i = 0; i < x.size(); ++i) {
- result += (x.at(i) - mean) * (x.at(i) - mean);
- }
- result /= -1 + x.size();
- return result;
- }
-
-
-
- //Text Operations:
-
- std::string Operation::validName(const std::string& name) {
- if (trim(name).empty()) return "unnamed";
- std::ostringstream ss;
- for (std::size_t i = 0; i < name.length(); ++i) {
- char c = name[i];
- if (c == '_' or c == '.' or isalnum(c)) {
- ss << c;
- }
- }
- return ss.str();
- }
-
- int Operation::isValidForName(int character) {
- return character == '_' or character == '.' or isalnum(character);
- }
-
- std::string Operation::findReplace(const std::string& str, const std::string& find,
- const std::string& replace, bool replaceAll) {
- std::ostringstream result;
- std::size_t fromIndex = 0, nextIndex;
- do {
- nextIndex = str.find(find, fromIndex);
- result << str.substr(fromIndex, nextIndex - fromIndex);
- if (nextIndex != std::string::npos)
- result << replace;
- fromIndex = nextIndex + find.size();
- } while (replaceAll and nextIndex != std::string::npos);
- return result.str();
- }
-
- std::vector<std::string> Operation::split(const std::string& str,
- const std::string& delimiter, bool ignoreEmpty) {
- std::vector<std::string> result;
- if (str.empty() or delimiter.empty()) {
- result.push_back(str);
- return result;
- }
- std::string::const_iterator position = str.begin(), next = str.begin();
- while (next != str.end()) {
- next = std::search(position, str.end(), delimiter.begin(), delimiter.end());
- std::string token(position, next);
- if (not (token.empty() and ignoreEmpty)) {
- result.push_back(token);
- }
- if (next != str.end()) {
- position = next + delimiter.size();
- }
- }
- return result;
- }
-
- std::string Operation::trim(const std::string& text) {
- if (text.empty()) return text;
- if (not (std::isspace(text.at(0)) or std::isspace(text.at(text.size() - 1))))
- return text;
- int start = 0, end = text.size() - 1;
- while (start <= end and std::isspace(text.at(start))) {
- ++start;
- }
- while (end >= start and std::isspace(text.at(end))) {
- --end;
- }
- int length = end - start + 1;
- if (length <= 0) return "";
- return text.substr(start, length);
- }
-
- std::string Operation::format(const std::string& text, int matchesChar(int),
- const std::string& replacement) {
- std::ostringstream ss;
- std::string::const_iterator it = text.begin();
- while (it != text.end()) {
- if (matchesChar(*it)) {
- ss << *it;
- } else {
- ss << replacement;
- }
- ++it;
- }
- return ss.str();
- }
-
- scalar Operation::toScalar(const std::string& x) {
- std::istringstream iss(x);
- scalar result;
- iss >> result;
- char strict;
- if (not (iss.fail() or iss.get(strict))) return result;
-
- std::ostringstream nan, pInf, nInf;
- nan << fl::nan;
- pInf << fl::inf;
- nInf << (-fl::inf);
-
- if (x == nan.str() or x == "nan")
- return fl::nan;
- if (x == pInf.str() or x == "inf")
- return fl::inf;
- if (x == nInf.str() or x == "-inf")
- return -fl::inf;
-
- std::ostringstream ex;
- ex << "[conversion error] from <" << x << "> to scalar";
- throw fl::Exception(ex.str(), FL_AT);
- }
-
- scalar Operation::toScalar(const std::string& x, scalar alternative) FL_INOEXCEPT {
- std::istringstream iss(x);
- scalar result;
- iss >> result;
- char strict;
- if (not (iss.fail() or iss.get(strict))) return result;
-
- std::ostringstream nan, pInf, nInf;
- nan << fl::nan;
- pInf << fl::inf;
- nInf << (-fl::inf);
-
- if (x == nan.str() or x == "nan")
- return fl::nan;
- if (x == pInf.str() or x == "inf")
- return fl::inf;
- if (x == nInf.str() or x == "-inf")
- return -fl::inf;
-
- return alternative;
- }
-
- bool Operation::isNumeric(const std::string& x) {
- try {
- fl::Op::toScalar(x);
- return true;
- } catch (std::exception& ex) {
- (void) ex;
- return false;
- }
- }
-
- template <typename T>
- std::string Operation::str(T x, int decimals) {
- std::ostringstream ss;
- ss << std::setprecision(decimals) << std::fixed;
- if (fl::Op::isNaN(x)) {
- ss << "nan";
- } else if (fl::Op::isInf(x)) {
- ss << (fl::Op::isLt(x, 0.0) ? "-inf" : "inf");
- } else if (fl::Op::isEq(x, 0.0)) {
- ss << 0.0;
- } else ss << x;
- return ss.str();
- }
- template FL_API std::string Operation::str(int x, int precision);
- template FL_API std::string Operation::str(scalar x, int precision);
-
- template <> FL_API std::string Operation::str(const std::string& x, int precision) {
- (void) precision;
- return x;
- }
-
- template <typename T>
- std::string Operation::join(const std::vector<T>& x,
- const std::string& separator) {
- std::ostringstream ss;
- for (std::size_t i = 0; i < x.size(); ++i) {
- ss << str(x.at(i));
- if (i + 1 < x.size()) ss << separator;
- }
- return ss.str();
- }
- template FL_API std::string Operation::join(const std::vector<int>& x,
- const std::string& separator);
- template FL_API std::string Operation::join(const std::vector<scalar>& x,
- const std::string& separator);
-
- template <> FL_API
- std::string Operation::join(const std::vector<std::string>& x,
- const std::string& separator) {
- std::ostringstream ss;
- for (std::size_t i = 0; i < x.size(); ++i) {
- ss << x.at(i);
- if (i + 1 < x.size()) ss << separator;
- }
- return ss.str();
- }
-
- template <typename T>
- std::string Operation::join(int items, const std::string& separator, T first, ...) {
- std::ostringstream ss;
- ss << str(first);
- if (items > 1) ss << separator;
- va_list args;
- va_start(args, first);
- for (int i = 0; i < items - 1; ++i) {
- ss << str(va_arg(args, T));
- if (i + 1 < items - 1) ss << separator;
- }
- va_end(args);
- return ss.str();
- }
-
- template FL_API std::string Operation::join(int items, const std::string& separator,
- int first, ...);
- template FL_API std::string Operation::join(int items, const std::string& separator,
- double first, ...);
-
- template <> FL_API std::string Operation::join(int items, const std::string& separator,
- float first, ...) {
- std::ostringstream ss;
- ss << str(first);
- if (items > 1) ss << separator;
- va_list args;
- va_start(args, first);
- for (int i = 0; i < items - 1; ++i) {
- ss << str(va_arg(args, double)); //automatic promotion
- if (i + 1 < items - 1) ss << separator;
- }
- va_end(args);
- return ss.str();
- }
-
- template <> FL_API
- std::string Operation::join(int items, const std::string& separator, const char* first, ...) {
- std::ostringstream ss;
- ss << first;
- if (items > 1) ss << separator;
- va_list args;
- va_start(args, first);
- for (int i = 0; i < items - 1; ++i) {
- ss << va_arg(args, const char*);
- if (i + 1 < items - 1) ss << separator;
- }
- va_end(args);
- return ss.str();
- }
-
-}
diff --git a/fuzzylite/src/activation/First.cpp b/fuzzylite/src/activation/First.cpp
new file mode 100644
index 0000000..fcf7484
--- /dev/null
+++ b/fuzzylite/src/activation/First.cpp
@@ -0,0 +1,122 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/activation/First.h"
+
+#include "fl/rule/RuleBlock.h"
+#include "fl/rule/Rule.h"
+#include "fl/Operation.h"
+
+namespace fl {
+
+ First::First(int numberOfRules, scalar threshold) : Activation(),
+ _numberOfRules(numberOfRules), _threshold(threshold) { }
+
+ First::~First() { }
+
+ std::string First::className() const {
+ return "First";
+ }
+
+ std::string First::parameters() const {
+ return Op::str(getNumberOfRules()) + " " + Op::str(getThreshold());
+ }
+
+ void First::configure(const std::string& parameters) {
+ if (parameters.empty()) return;
+ std::vector<std::string> values = Op::split(parameters, " ");
+ std::size_t required = 2;
+ if (values.size() < required) {
+ std::ostringstream ex;
+ ex << "[configuration error] activation <" << className() << ">"
+ << " requires <" << required << "> parameters";
+ throw Exception(ex.str(), FL_AT);
+ }
+ setNumberOfRules((int) Op::toScalar(values.at(0)));
+ setThreshold(Op::toScalar(values.at(1)));
+ }
+
+ Complexity First::complexity(const RuleBlock* ruleBlock) const {
+ Complexity result;
+
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ Complexity meanFiring;
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ result.comparison(1 + 3);
+ const Rule* rule = ruleBlock->getRule(i);
+ result += rule->complexityOfActivation(conjunction, disjunction);
+ meanFiring += rule->complexityOfFiring(implication);
+ }
+ meanFiring.divide(scalar(ruleBlock->numberOfRules()));
+
+ result += meanFiring.multiply(getNumberOfRules());
+ result += Complexity().arithmetic(1).multiply(getNumberOfRules());
+ return result;
+ }
+
+ void First::activate(RuleBlock* ruleBlock) {
+ FL_DBG("Activation: " << className() << " " << parameters());
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ int activated = 0;
+ for (std::vector<Rule*>::const_iterator it = ruleBlock->rules().begin();
+ it != ruleBlock->rules().end(); ++it) {
+ Rule* rule = (*it);
+ rule->deactivate();
+
+ if (rule->isLoaded()) {
+ scalar activationDegree = rule->activateWith(conjunction, disjunction);
+ if (activated < _numberOfRules
+ and Op::isGt(activationDegree, 0.0)
+ and Op::isGE(activationDegree, _threshold)) {
+ rule->trigger(implication);
+ ++activated;
+ }
+ }
+ }
+ }
+
+ void First::setNumberOfRules(int numberOfRules) {
+ this->_numberOfRules = numberOfRules;
+ }
+
+ int First::getNumberOfRules() const {
+ return this->_numberOfRules;
+ }
+
+ void First::setThreshold(scalar threshold) {
+ this->_threshold = threshold;
+ }
+
+ scalar First::getThreshold() const {
+ return this->_threshold;
+ }
+
+ First* First::clone() const {
+ return new First(*this);
+ }
+
+ Activation* First::constructor() {
+ return new First;
+ }
+
+}
+
diff --git a/fuzzylite/src/activation/General.cpp b/fuzzylite/src/activation/General.cpp
new file mode 100644
index 0000000..a42c588
--- /dev/null
+++ b/fuzzylite/src/activation/General.cpp
@@ -0,0 +1,77 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/activation/General.h"
+
+#include "fl/rule/RuleBlock.h"
+#include "fl/rule/Rule.h"
+#include "fl/Operation.h"
+
+namespace fl {
+
+ General::General() : Activation() { }
+
+ General::~General() { }
+
+ std::string General::className() const {
+ return "General";
+ }
+
+ std::string General::parameters() const {
+ return "";
+ }
+
+ void General::configure(const std::string& parameters) {
+ FL_IUNUSED(parameters);
+ }
+
+ Complexity General::complexity(const RuleBlock* ruleBlock) const {
+ Complexity result;
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ result.comparison(1);
+ result += ruleBlock->getRule(i)->complexity(
+ ruleBlock->getConjunction(), ruleBlock->getDisjunction(),
+ ruleBlock->getImplication());
+ }
+ return result;
+ }
+
+ void General::activate(RuleBlock* ruleBlock) {
+ FL_DBG("Activation: " << className() << " " << parameters());
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ const std::size_t numberOfRules = ruleBlock->numberOfRules();
+ for (std::size_t i = 0; i < numberOfRules; ++i) {
+ Rule* rule = ruleBlock->getRule(i);
+ rule->deactivate();
+ if (rule->isLoaded()) {
+ rule->activateWith(conjunction, disjunction);
+ rule->trigger(implication);
+ }
+ }
+ }
+
+ General* General::clone() const {
+ return new General(*this);
+ }
+
+ Activation* General::constructor() {
+ return new General;
+ }
+
+}
diff --git a/fuzzylite/src/activation/Highest.cpp b/fuzzylite/src/activation/Highest.cpp
new file mode 100644
index 0000000..612c16b
--- /dev/null
+++ b/fuzzylite/src/activation/Highest.cpp
@@ -0,0 +1,120 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/activation/Highest.h"
+
+#include "fl/rule/RuleBlock.h"
+#include "fl/rule/Rule.h"
+#include "fl/Operation.h"
+
+#include <queue>
+
+namespace fl {
+
+ Highest::Highest(int numberOfRules) : Activation(), _numberOfRules(numberOfRules) { }
+
+ Highest::~Highest() { }
+
+ std::string Highest::className() const {
+ return "Highest";
+ }
+
+ std::string Highest::parameters() const {
+ return Op::str(getNumberOfRules());
+ }
+
+ void Highest::configure(const std::string& parameters) {
+ setNumberOfRules((int) Op::toScalar(parameters));
+ }
+
+ int Highest::getNumberOfRules() const {
+ return this->_numberOfRules;
+ }
+
+ void Highest::setNumberOfRules(int numberOfRules) {
+ this->_numberOfRules = numberOfRules;
+ }
+
+ Complexity Highest::complexity(const RuleBlock* ruleBlock) const {
+ //Cost of priority_queue:
+ //http://stackoverflow.com/questions/2974470/efficiency-of-the-stl-priority-queue
+ Complexity result;
+
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ Complexity meanFiring;
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ const Rule* rule = ruleBlock->getRule(i);
+ result += rule->complexityOfActivation(conjunction, disjunction);
+ meanFiring += rule->complexityOfFiring(implication);
+ }
+ meanFiring.divide(scalar(ruleBlock->numberOfRules()));
+
+ //Complexity of push is O(log n)
+ result += Complexity().function(1).multiply(ruleBlock->numberOfRules()
+ * std::log(scalar(ruleBlock->numberOfRules())));
+
+ result += Complexity().comparison(2).arithmetic(1).multiply(getNumberOfRules());
+ result += meanFiring.multiply(getNumberOfRules());
+ //Complexity of pop is 2 * O(log n)
+ result += Complexity().function(1).multiply(getNumberOfRules() *
+ 2 * std::log(scalar(ruleBlock->numberOfRules())));
+ return result;
+ }
+
+ struct Descending {
+
+ bool operator()(const Rule* a, const Rule* b) const {
+ return a->getActivationDegree() < b->getActivationDegree();
+ }
+ };
+
+ void Highest::activate(RuleBlock* ruleBlock) {
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ std::priority_queue<Rule*, std::vector<Rule*>, Descending> rulesToActivate;
+
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ Rule* rule = ruleBlock->getRule(i);
+ rule->deactivate();
+ if (rule->isLoaded()) {
+ scalar activationDegree = rule->activateWith(conjunction, disjunction);
+ if (Op::isGt(activationDegree, 0.0))
+ rulesToActivate.push(rule);
+ }
+ }
+
+ int activated = 0;
+ while (rulesToActivate.size() > 0 and activated++ < _numberOfRules) {
+ Rule* rule = rulesToActivate.top();
+ rule->trigger(implication);
+ rulesToActivate.pop();
+ }
+ }
+
+ Highest* Highest::clone() const {
+ return new Highest(*this);
+ }
+
+ Activation* Highest::constructor() {
+ return new Highest;
+ }
+
+}
diff --git a/fuzzylite/src/activation/Last.cpp b/fuzzylite/src/activation/Last.cpp
new file mode 100644
index 0000000..90b5dc9
--- /dev/null
+++ b/fuzzylite/src/activation/Last.cpp
@@ -0,0 +1,121 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/activation/Last.h"
+
+#include "fl/rule/RuleBlock.h"
+#include "fl/rule/Rule.h"
+#include "fl/Operation.h"
+
+namespace fl {
+
+ Last::Last(int numberOfRules, scalar threshold) : Activation(),
+ _numberOfRules(numberOfRules), _threshold(threshold) { }
+
+ Last::~Last() { }
+
+ std::string Last::className() const {
+ return "Last";
+ }
+
+ std::string Last::parameters() const {
+ return Op::str(getNumberOfRules()) + " " + Op::str(getThreshold());
+ }
+
+ void Last::configure(const std::string& parameters) {
+ if (parameters.empty()) return;
+ std::vector<std::string> values = Op::split(parameters, " ");
+ std::size_t required = 2;
+ if (values.size() < required) {
+ std::ostringstream ex;
+ ex << "[configuration error] activation <" << className() << ">"
+ << " requires <" << required << "> parameters";
+ throw Exception(ex.str(), FL_AT);
+ }
+ setNumberOfRules((int) Op::toScalar(values.at(0)));
+ setThreshold(Op::toScalar(values.at(1)));
+ }
+
+ void Last::setNumberOfRules(int numberOfRules) {
+ this->_numberOfRules = numberOfRules;
+ }
+
+ int Last::getNumberOfRules() const {
+ return this->_numberOfRules;
+ }
+
+ void Last::setThreshold(scalar threshold) {
+ this->_threshold = threshold;
+ }
+
+ scalar Last::getThreshold() const {
+ return this->_threshold;
+ }
+
+ Complexity Last::complexity(const RuleBlock* ruleBlock) const {
+ Complexity result;
+
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ Complexity meanFiring;
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ result.comparison(1 + 3);
+ const Rule* rule = ruleBlock->getRule(i);
+ result += rule->complexityOfActivation(conjunction, disjunction);
+ meanFiring += rule->complexityOfFiring(implication);
+ }
+ meanFiring.divide(scalar(ruleBlock->numberOfRules()));
+
+ result += meanFiring.multiply(getNumberOfRules());
+ result += Complexity().arithmetic(1).multiply(getNumberOfRules());
+ return result;
+ }
+
+ void Last::activate(RuleBlock* ruleBlock) {
+ FL_DBG("Activation: " << className() << " " << parameters());
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ int activated = 0;
+ for (std::vector<Rule*>::const_reverse_iterator it = ruleBlock->rules().rbegin();
+ it != ruleBlock->rules().rend(); ++it) {
+ Rule* rule = (*it);
+ rule->deactivate();
+
+ if (rule->isLoaded()) {
+ scalar activationDegree = rule->activateWith(conjunction, disjunction);
+ if (activated < _numberOfRules
+ and Op::isGt(activationDegree, 0.0)
+ and Op::isGE(activationDegree, _threshold)) {
+ rule->trigger(implication);
+ ++activated;
+ }
+ }
+ }
+ }
+
+ Last* Last::clone() const {
+ return new Last(*this);
+ }
+
+ Activation* Last::constructor() {
+ return new Last;
+ }
+
+}
diff --git a/fuzzylite/src/activation/Lowest.cpp b/fuzzylite/src/activation/Lowest.cpp
new file mode 100644
index 0000000..52e7e85
--- /dev/null
+++ b/fuzzylite/src/activation/Lowest.cpp
@@ -0,0 +1,122 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/activation/Lowest.h"
+
+#include "fl/rule/RuleBlock.h"
+#include "fl/rule/Rule.h"
+#include "fl/Operation.h"
+
+#include <queue>
+
+namespace fl {
+
+ Lowest::Lowest(int numberOfRules) : Activation(), _numberOfRules(numberOfRules) { }
+
+ Lowest::~Lowest() { }
+
+ std::string Lowest::className() const {
+ return "Lowest";
+ }
+
+ std::string Lowest::parameters() const {
+ return Op::str(getNumberOfRules());
+ }
+
+ void Lowest::configure(const std::string& parameters) {
+ setNumberOfRules((int) Op::toScalar(parameters));
+ }
+
+ int Lowest::getNumberOfRules() const {
+ return this->_numberOfRules;
+ }
+
+ void Lowest::setNumberOfRules(int activatedRules) {
+ this->_numberOfRules = activatedRules;
+ }
+
+ Complexity Lowest::complexity(const RuleBlock* ruleBlock) const {
+ //Cost of priority_queue:
+ //http://stackoverflow.com/questions/2974470/efficiency-of-the-stl-priority-queue
+ Complexity result;
+
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ Complexity meanFiring;
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ const Rule* rule = ruleBlock->getRule(i);
+ result.comparison(2);
+ result += rule->complexityOfActivation(conjunction, disjunction);
+ meanFiring += rule->complexityOfFiring(implication);
+ }
+ meanFiring.divide(scalar(ruleBlock->numberOfRules()));
+
+ //Complexity of push is O(log n)
+ result += Complexity().function(1).multiply(ruleBlock->numberOfRules()
+ * std::log(scalar(ruleBlock->numberOfRules())));
+
+ result += Complexity().comparison(2).arithmetic(1).multiply(getNumberOfRules());
+ result += meanFiring.multiply(getNumberOfRules());
+ //Complexity of pop is 2 * O(log n)
+ result += Complexity().function(1).multiply(getNumberOfRules() *
+ 2 * std::log(scalar(ruleBlock->numberOfRules())));
+ return result;
+ }
+
+ struct Ascending {
+
+ bool operator()(const Rule* a, const Rule* b) {
+ return a->getActivationDegree() > b->getActivationDegree();
+ }
+ };
+
+ void Lowest::activate(RuleBlock* ruleBlock) {
+ FL_DBG("Activation: " << className() << " " << parameters());
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ std::priority_queue<Rule*, std::vector<Rule*>, Ascending> rulesToActivate;
+
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ Rule* rule = ruleBlock->getRule(i);
+ rule->deactivate();
+ if (rule->isLoaded()) {
+ scalar activationDegree = rule->activateWith(conjunction, disjunction);
+ if (Op::isGt(activationDegree, 0.0))
+ rulesToActivate.push(rule);
+ }
+ }
+
+ int activated = 0;
+ while (rulesToActivate.size() > 0 and activated++ < _numberOfRules) {
+ Rule* rule = rulesToActivate.top();
+ rule->trigger(implication);
+ rulesToActivate.pop();
+ }
+ }
+
+ Lowest* Lowest::clone() const {
+ return new Lowest(*this);
+ }
+
+ Activation* Lowest::constructor() {
+ return new Lowest;
+ }
+
+}
diff --git a/fuzzylite/src/activation/Proportional.cpp b/fuzzylite/src/activation/Proportional.cpp
new file mode 100644
index 0000000..07fa2aa
--- /dev/null
+++ b/fuzzylite/src/activation/Proportional.cpp
@@ -0,0 +1,91 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/activation/Proportional.h"
+
+#include "fl/rule/RuleBlock.h"
+#include "fl/rule/Rule.h"
+#include "fl/Operation.h"
+
+namespace fl {
+
+ Proportional::Proportional() : Activation() { }
+
+ Proportional::~Proportional() { }
+
+ std::string Proportional::className() const {
+ return "Proportional";
+ }
+
+ std::string Proportional::parameters() const {
+ return "";
+ }
+
+ void Proportional::configure(const std::string& parameters) {
+ FL_IUNUSED(parameters);
+ }
+
+ Complexity Proportional::complexity(const RuleBlock* ruleBlock) const {
+ Complexity result;
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ result.comparison(1).arithmetic(1);
+ result += ruleBlock->getRule(i)->complexityOfActivation(
+ ruleBlock->getConjunction(), ruleBlock->getDisjunction());
+ }
+
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ result.arithmetic(1);
+ result += ruleBlock->getRule(i)->complexityOfFiring(ruleBlock->getImplication());
+ }
+ return result;
+ }
+
+ void Proportional::activate(RuleBlock* ruleBlock) {
+ FL_DBG("Activation: " << className() << " " << parameters());
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ scalar sumActivationDegrees = 0.0;
+ std::vector<Rule*> rulesToActivate;
+ const std::size_t numberOfRules = ruleBlock->numberOfRules();
+ for (std::size_t i = 0; i < numberOfRules; ++i) {
+ Rule* rule = ruleBlock->getRule(i);
+ rule->deactivate();
+ if (rule->isLoaded()) {
+ scalar activationDegree = rule->activateWith(conjunction, disjunction);
+ rulesToActivate.push_back(rule);
+ sumActivationDegrees += activationDegree;
+ }
+ }
+
+ for (std::size_t i = 0; i < rulesToActivate.size(); ++i) {
+ Rule* rule = rulesToActivate.at(i);
+ scalar activationDegree = rule->getActivationDegree() / sumActivationDegrees;
+ rule->setActivationDegree(activationDegree);
+ rule->trigger(implication);
+ }
+ }
+
+ Proportional* Proportional::clone() const {
+ return new Proportional(*this);
+ }
+
+ Activation* Proportional::constructor() {
+ return new Proportional;
+ }
+
+}
diff --git a/fuzzylite/src/activation/Threshold.cpp b/fuzzylite/src/activation/Threshold.cpp
new file mode 100644
index 0000000..cd1f034
--- /dev/null
+++ b/fuzzylite/src/activation/Threshold.cpp
@@ -0,0 +1,170 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/activation/Threshold.h"
+
+#include "fl/rule/RuleBlock.h"
+#include "fl/rule/Rule.h"
+#include "fl/Operation.h"
+
+namespace fl {
+
+ Threshold::Threshold(Comparison comparison, scalar threshold) : Activation(),
+ _comparison(comparison), _value(threshold) { }
+
+ Threshold::Threshold(const std::string& comparison, scalar threshold) : Activation(),
+ _comparison(parseComparison(comparison)), _value(threshold) { }
+
+ Threshold::~Threshold() { }
+
+ std::string Threshold::className() const {
+ return "Threshold";
+ }
+
+ std::string Threshold::parameters() const {
+ std::ostringstream ss;
+ ss << comparisonOperator() << " " << Op::str(getValue());
+ return ss.str();
+ }
+
+ void Threshold::configure(const std::string& parameters) {
+ if (parameters.empty()) return;
+ std::vector<std::string> values = Op::split(parameters, " ");
+ std::size_t required = 2;
+ if (values.size() < required) {
+ std::ostringstream ex;
+ ex << "[configuration error] activation <" << className() << ">"
+ << " requires <" << required << "> parameters";
+ throw Exception(ex.str(), FL_AT);
+ }
+ setComparison(parseComparison(values.at(0)));
+ setValue(Op::toScalar(values.at(1)));
+ }
+
+ void Threshold::setComparison(Comparison comparison) {
+ this->_comparison = comparison;
+ }
+
+ Threshold::Comparison Threshold::getComparison() const {
+ return this->_comparison;
+ }
+
+ std::string Threshold::comparisonOperator() const {
+ return comparisonOperator(getComparison());
+ }
+
+ std::string Threshold::comparisonOperator(Comparison comparison) const {
+ switch (comparison) {
+ case LessThan: return "<";
+ case LessThanOrEqualTo: return "<=";
+ case EqualTo: return "==";
+ case NotEqualTo: return "!=";
+ case GreaterThanOrEqualTo: return ">=";
+ case GreaterThan: return ">";
+ default: return "?";
+ }
+ }
+
+ std::vector<std::string> Threshold::availableComparisonOperators() const {
+ std::vector<std::string> result;
+ result.push_back("<");
+ result.push_back("<=");
+ result.push_back("==");
+ result.push_back("!=");
+ result.push_back(">=");
+ result.push_back(">");
+ return result;
+ }
+
+ Threshold::Comparison Threshold::parseComparison(const std::string& name) const {
+ if (name == "<") return LessThan;
+ if (name == "<=") return LessThanOrEqualTo;
+ if (name == "==") return EqualTo;
+ if (name == "!=") return NotEqualTo;
+ if (name == ">=") return GreaterThanOrEqualTo;
+ if (name == ">") return GreaterThan;
+ throw Exception("[syntax error] invalid threshold type by name <" + name + ">", FL_AT);
+ }
+
+ void Threshold::setValue(scalar value) {
+ this->_value = value;
+ }
+
+ scalar Threshold::getValue() const {
+ return this->_value;
+ }
+
+ void Threshold::setThreshold(Comparison comparison, scalar threshold) {
+ setComparison(comparison);
+ setValue(threshold);
+ }
+
+ void Threshold::setThreshold(const std::string& comparison, scalar value) {
+ setComparison(parseComparison(comparison));
+ setValue(value);
+ }
+
+ bool Threshold::activatesWith(scalar activationDegree) const {
+ switch (getComparison()) {
+ case LessThan: return Op::isLt(activationDegree, getValue());
+ case LessThanOrEqualTo: return Op::isLE(activationDegree, getValue());
+ case EqualTo: return Op::isEq(activationDegree, getValue());
+ case NotEqualTo: return not Op::isEq(activationDegree, getValue());
+ case GreaterThanOrEqualTo: return Op::isGE(activationDegree, getValue());
+ case GreaterThan: return Op::isGt(activationDegree, getValue());
+ default: return false;
+ }
+ }
+
+ Complexity Threshold::complexity(const RuleBlock* ruleBlock) const {
+ Complexity result;
+ for (std::size_t i = 0; i < ruleBlock->rules().size(); ++i) {
+ result.comparison(2);
+ result += ruleBlock->rules().at(i)->complexity(
+ ruleBlock->getConjunction(), ruleBlock->getDisjunction(),
+ ruleBlock->getImplication());
+ }
+ return result;
+ }
+
+ void Threshold::activate(RuleBlock* ruleBlock) {
+ FL_DBG("Activation: " << className() << " " << parameters());
+ const TNorm* conjunction = ruleBlock->getConjunction();
+ const SNorm* disjunction = ruleBlock->getDisjunction();
+ const TNorm* implication = ruleBlock->getImplication();
+
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ Rule* rule = ruleBlock->getRule(i);
+ rule->deactivate();
+ if (rule->isLoaded()) {
+ scalar activationDegree = rule->activateWith(conjunction, disjunction);
+ if (activatesWith(activationDegree)) {
+ rule->trigger(implication);
+ }
+ }
+ }
+ }
+
+ Threshold* Threshold::clone() const {
+ return new Threshold(*this);
+ }
+
+ Activation* Threshold::constructor() {
+ return new Threshold;
+ }
+
+}
+
diff --git a/fuzzylite/src/defuzzifier/Bisector.cpp b/fuzzylite/src/defuzzifier/Bisector.cpp
index ee4d2fc..ed61b6f 100644
--- a/fuzzylite/src/defuzzifier/Bisector.cpp
+++ b/fuzzylite/src/defuzzifier/Bisector.cpp
@@ -1,76 +1,60 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/Bisector.h"
-#include "fl/term/Accumulated.h"
#include "fl/term/Term.h"
namespace fl {
Bisector::Bisector(int resolution)
- : IntegralDefuzzifier(resolution) {
- }
+ : IntegralDefuzzifier(resolution) { }
- Bisector::~Bisector() {
-
- }
+ Bisector::~Bisector() { }
std::string Bisector::className() const {
return "Bisector";
}
+ Complexity Bisector::complexity(const Term* term) const {
+ return Complexity().comparison(1).arithmetic(1 + 2 + 5) +
+ term->complexity().comparison(1).arithmetic(1 + 5).multiply(getResolution());
+ }
+
scalar Bisector::defuzzify(const Term* term, scalar minimum, scalar maximum) const {
- if (not fl::Op::isFinite(minimum + maximum)) {
- return fl::nan;
- }
- if (maximum - minimum > _resolution) {
- FL_DBG("[accuracy warning] the resolution <" << _resolution << "> "
- "is smaller than the range <" << minimum << ", " << maximum << ">. In order to "
- "improve the accuracy, the resolution should be at least equal to the range.");
- }
- scalar dx = (maximum - minimum) / _resolution;
+ if (not Op::isFinite(minimum + maximum)) return fl::nan;
- int counter = _resolution;
+ const scalar dx = (maximum - minimum) / getResolution();
+ int counter = getResolution();
int left = 0, right = 0;
scalar leftArea = 0, rightArea = 0;
scalar xLeft = minimum, xRight = maximum;
while (counter-- > 0) {
- if (fl::Op::isLE(leftArea, rightArea)) {
+ if (Op::isLE(leftArea, rightArea)) {
xLeft = minimum + (left + 0.5) * dx;
leftArea += term->membership(xLeft);
- left++;
+ ++left;
} else {
xRight = maximum - (right + 0.5) * dx;
rightArea += term->membership(xRight);
- right++;
+ ++right;
}
}
-
//Inverse weighted average to compensate
- scalar bisector = (leftArea * xRight + rightArea * xLeft) / (leftArea + rightArea);
- return bisector;
+ return (leftArea * xRight + rightArea * xLeft) / (leftArea + rightArea);
}
Bisector* Bisector::clone() const {
@@ -81,5 +65,4 @@ namespace fl {
return new Bisector;
}
-
}
diff --git a/fuzzylite/src/defuzzifier/Centroid.cpp b/fuzzylite/src/defuzzifier/Centroid.cpp
index 01490d3..177da26 100644
--- a/fuzzylite/src/defuzzifier/Centroid.cpp
+++ b/fuzzylite/src/defuzzifier/Centroid.cpp
@@ -1,71 +1,60 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/Centroid.h"
-#include "fl/term/Accumulated.h"
#include "fl/term/Term.h"
-
namespace fl {
Centroid::Centroid(int resolution)
- : IntegralDefuzzifier(resolution) {
- }
-
- Centroid::~Centroid() {
+ : IntegralDefuzzifier(resolution) { }
- }
+ Centroid::~Centroid() { }
std::string Centroid::className() const {
return "Centroid";
}
+ Complexity Centroid::complexity(const Term* term) const {
+ return Complexity().comparison(1).arithmetic(1 + 2 + 1) +
+ term->complexity().arithmetic(6).multiply(getResolution());
+ }
+
scalar Centroid::defuzzify(const Term* term, scalar minimum, scalar maximum) const {
- if (not fl::Op::isFinite(minimum + maximum)) {
- return fl::nan;
- }
- if (maximum - minimum > _resolution) {
- FL_DBG("[accuracy warning] the resolution <" << _resolution << "> "
- "is smaller than the range <" << minimum << ", " << maximum << ">. In order to "
- "improve the accuracy, the resolution should be at least equal to the range.");
- }
- scalar dx = (maximum - minimum) / _resolution;
+ if (not Op::isFinite(minimum + maximum)) return fl::nan;
+
+ const int resolution = getResolution();
+ const scalar dx = (maximum - minimum) / resolution;
scalar x, y;
- scalar area = 0, xcentroid = 0, ycentroid = 0;
- for (int i = 0; i < _resolution; ++i) {
+ scalar area = 0, xcentroid = 0;
+ //scalar ycentroid = 0;
+ for (int i = 0; i < resolution; ++i) {
x = minimum + (i + 0.5) * dx;
y = term->membership(x);
xcentroid += y * x;
- ycentroid += y * y;
+ //ycentroid += y * y;
area += y;
}
- xcentroid /= area;
- ycentroid /= 2 * area;
- area *= dx; //total area... unused, but for future reference.
- return xcentroid;
+ //Final results not computed for efficiency
+ //xcentroid /= area;
+ //ycentroid /= 2 * area;
+ //area *= dx;
+ return xcentroid / area;
}
Centroid* Centroid::clone() const {
@@ -76,5 +65,4 @@ namespace fl {
return new Centroid;
}
-
}
diff --git a/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp b/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp
index 2badf14..3b06b42 100644
--- a/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp
+++ b/fuzzylite/src/defuzzifier/IntegralDefuzzifier.cpp
@@ -1,32 +1,24 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/IntegralDefuzzifier.h"
namespace fl {
- int IntegralDefuzzifier::_defaultResolution = 200;
+ int IntegralDefuzzifier::_defaultResolution = 100;
void IntegralDefuzzifier::setDefaultResolution(int defaultResolution) {
_defaultResolution = defaultResolution;
@@ -37,11 +29,9 @@ namespace fl {
}
IntegralDefuzzifier::IntegralDefuzzifier(int resolution)
- : Defuzzifier(), _resolution(resolution) {
- }
+ : Defuzzifier(), _resolution(resolution) { }
- IntegralDefuzzifier::~IntegralDefuzzifier() {
- }
+ IntegralDefuzzifier::~IntegralDefuzzifier() { }
void IntegralDefuzzifier::setResolution(int resolution) {
this->_resolution = resolution;
@@ -50,4 +40,5 @@ namespace fl {
int IntegralDefuzzifier::getResolution() const {
return this->_resolution;
}
+
}
diff --git a/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp b/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp
index 470af52..ff05707 100644
--- a/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp
+++ b/fuzzylite/src/defuzzifier/LargestOfMaximum.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/LargestOfMaximum.h"
@@ -30,29 +22,27 @@
namespace fl {
LargestOfMaximum::LargestOfMaximum(int resolution)
- : IntegralDefuzzifier(resolution) {
- }
+ : IntegralDefuzzifier(resolution) { }
- LargestOfMaximum::~LargestOfMaximum() {
- }
+ LargestOfMaximum::~LargestOfMaximum() { }
std::string LargestOfMaximum::className() const {
return "LargestOfMaximum";
}
+ Complexity LargestOfMaximum::complexity(const Term* term) const {
+ return Complexity().comparison(1).arithmetic(1 + 2) +
+ term->complexity().comparison(1).arithmetic(3).multiply(getResolution());
+ }
+
scalar LargestOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const {
- if (not fl::Op::isFinite(minimum + maximum)) {
- return fl::nan;
- }
- if (maximum - minimum > _resolution) {
- FL_DBG("[accuracy warning] the resolution <" << _resolution << "> "
- "is smaller than the range <" << minimum << ", " << maximum << ">. In order to "
- "improve the accuracy, the resolution should be at least equal to the range.");
- }
- scalar dx = (maximum - minimum) / _resolution;
+ if (not Op::isFinite(minimum + maximum)) return fl::nan;
+
+ const int resolution = getResolution();
+ const scalar dx = (maximum - minimum) / resolution;
scalar x, y;
scalar ymax = -1.0, xlargest = maximum;
- for (int i = 0; i < _resolution; ++i) {
+ for (int i = 0; i < resolution; ++i) {
x = minimum + (i + 0.5) * dx;
y = term->membership(x);
diff --git a/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp b/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp
index 7c40527..961e505 100644
--- a/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp
+++ b/fuzzylite/src/defuzzifier/MeanOfMaximum.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/MeanOfMaximum.h"
@@ -27,36 +19,33 @@
#include "fl/Exception.h"
#include "fl/term/Term.h"
-
namespace fl {
MeanOfMaximum::MeanOfMaximum(int resolution)
- : IntegralDefuzzifier(resolution) {
- }
+ : IntegralDefuzzifier(resolution) { }
- MeanOfMaximum::~MeanOfMaximum() {
- }
+ MeanOfMaximum::~MeanOfMaximum() { }
std::string MeanOfMaximum::className() const {
return "MeanOfMaximum";
}
+ Complexity MeanOfMaximum::complexity(const Term* term) const {
+ return Complexity().comparison(1).arithmetic(1 + 2 + 2) +
+ term->complexity().comparison(4).arithmetic(3).multiply(getResolution());
+ }
+
scalar MeanOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const {
- if (not fl::Op::isFinite(minimum + maximum)) {
- return fl::nan;
- }
- if (maximum - minimum > _resolution) {
- FL_DBG("[accuracy warning] the resolution <" << _resolution << "> "
- "is smaller than the range <" << minimum << ", " << maximum << ">. In order to "
- "improve the accuracy, the resolution should be at least equal to the range.");
- }
- scalar dx = (maximum - minimum) / _resolution;
+ if (not Op::isFinite(minimum + maximum)) return fl::nan;
+
+ const int resolution = getResolution();
+ const scalar dx = (maximum - minimum) / resolution;
scalar x, y;
scalar ymax = -1.0;
scalar xsmallest = minimum;
scalar xlargest = maximum;
bool samePlateau = false;
- for (int i = 0; i < _resolution; ++i) {
+ for (int i = 0; i < resolution; ++i) {
x = minimum + (i + 0.5) * dx;
y = term->membership(x);
@@ -67,14 +56,14 @@ namespace fl {
xlargest = x;
samePlateau = true;
- } else if (Op::isEq(y, ymax) and samePlateau) {
+ } else if (samePlateau and Op::isEq(y, ymax)) {
xlargest = x;
} else if (Op::isLt(y, ymax)) {
samePlateau = false;
}
}
- return (xlargest + xsmallest) / 2.0;
+ return 0.5 * (xlargest + xsmallest);
}
MeanOfMaximum* MeanOfMaximum::clone() const {
diff --git a/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp b/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp
index 1e67395..7333702 100644
--- a/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp
+++ b/fuzzylite/src/defuzzifier/SmallestOfMaximum.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/SmallestOfMaximum.h"
@@ -27,33 +19,30 @@
#include "fl/Exception.h"
#include "fl/term/Term.h"
-
namespace fl {
SmallestOfMaximum::SmallestOfMaximum(int resolution)
- : IntegralDefuzzifier(resolution) {
- }
+ : IntegralDefuzzifier(resolution) { }
- SmallestOfMaximum::~SmallestOfMaximum() {
- }
+ SmallestOfMaximum::~SmallestOfMaximum() { }
std::string SmallestOfMaximum::className() const {
return "SmallestOfMaximum";
}
+ Complexity SmallestOfMaximum::complexity(const Term* term) const {
+ return Complexity().comparison(1).arithmetic(1 + 2) +
+ term->complexity().comparison(1).arithmetic(3).multiply(getResolution());
+ }
+
scalar SmallestOfMaximum::defuzzify(const Term* term, scalar minimum, scalar maximum) const {
- if (not fl::Op::isFinite(minimum + maximum)) {
- return fl::nan;
- }
- if (maximum - minimum > _resolution) {
- FL_DBG("[accuracy warning] the resolution <" << _resolution << "> "
- "is smaller than the range <" << minimum << ", " << maximum << ">. In order to "
- "improve the accuracy, the resolution should be at least equal to the range.");
- }
- scalar dx = (maximum - minimum) / _resolution;
+ if (not Op::isFinite(minimum + maximum)) return fl::nan;
+
+ const int resolution = getResolution();
+ const scalar dx = (maximum - minimum) / resolution;
scalar x, y;
scalar ymax = -1.0, xsmallest = minimum;
- for (int i = 0; i < _resolution; ++i) {
+ for (int i = 0; i < resolution; ++i) {
x = minimum + (i + 0.5) * dx;
y = term->membership(x);
@@ -74,4 +63,3 @@ namespace fl {
}
}
-
diff --git a/fuzzylite/src/defuzzifier/WeightedAverage.cpp b/fuzzylite/src/defuzzifier/WeightedAverage.cpp
index 105c9d4..34af8c9 100644
--- a/fuzzylite/src/defuzzifier/WeightedAverage.cpp
+++ b/fuzzylite/src/defuzzifier/WeightedAverage.cpp
@@ -1,113 +1,89 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/WeightedAverage.h"
-#include "fl/term/Accumulated.h"
-#include "fl/term/Activated.h"
-#include "fl/norm/Norm.h"
-#include "fl/norm/SNorm.h"
-#include "fl/norm/TNorm.h"
+#include "fl/term/Aggregated.h"
#include <map>
namespace fl {
- WeightedAverage::WeightedAverage(Type type) : WeightedDefuzzifier(type) {
- }
+ WeightedAverage::WeightedAverage(Type type) : WeightedDefuzzifier(type) { }
- WeightedAverage::WeightedAverage(const std::string& type) : WeightedDefuzzifier(type) {
- }
+ WeightedAverage::WeightedAverage(const std::string& type) : WeightedDefuzzifier(type) { }
- WeightedAverage::~WeightedAverage() {
- }
+ WeightedAverage::~WeightedAverage() { }
std::string WeightedAverage::className() const {
return "WeightedAverage";
}
+ Complexity WeightedAverage::complexity(const Term* term) const {
+ Complexity result;
+ result.comparison(4).function(1); //for dynamic_cast
+ const Aggregated* fuzzyOutput = dynamic_cast<const Aggregated*> (term);
+ if (fuzzyOutput) {
+ result += term->complexity().arithmetic(3).multiply(scalar(fuzzyOutput->numberOfTerms()));
+ }
+ return result;
+ }
+
scalar WeightedAverage::defuzzify(const Term* term,
scalar minimum, scalar maximum) const {
- const Accumulated* fuzzyOutput = dynamic_cast<const Accumulated*> (term);
+ const Aggregated* fuzzyOutput = dynamic_cast<const Aggregated*> (term);
if (not fuzzyOutput) {
std::ostringstream ss;
ss << "[defuzzification error]"
- << "expected an Accumulated term instead of"
- << "<" << term->toString() << ">";
- throw fl::Exception(ss.str(), FL_AT);
+ << "expected an Aggregated term instead of"
+ << "<" << (term ? term->toString() : "null") << ">";
+ throw Exception(ss.str(), FL_AT);
}
+ if (fuzzyOutput->isEmpty()) return fl::nan;
+
minimum = fuzzyOutput->getMinimum();
maximum = fuzzyOutput->getMaximum();
+ Type type = getType();
+ if (type == Automatic) {
+ type = inferType(&(fuzzyOutput->terms().front()));
+ }
+
scalar sum = 0.0;
scalar weights = 0.0;
-
- if (not fuzzyOutput->getAccumulation()) {
- Type type = _type;
- for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) {
- Activated* activated = fuzzyOutput->getTerm(i);
- scalar w = activated->getDegree();
-
- if (type == Automatic) type = inferType(activated->getTerm());
-
- scalar z = (type == TakagiSugeno)
- //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work.
- ? activated->getTerm()->membership(w) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions
- : tsukamoto(activated->getTerm(), w, minimum, maximum);
-
+ const std::size_t numberOfTerms = fuzzyOutput->numberOfTerms();
+ if (type == TakagiSugeno) {
+ //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions
+ scalar w, z;
+ for (std::size_t i = 0; i < numberOfTerms; ++i) {
+ const Activated& activated = fuzzyOutput->getTerm(i);
+ w = activated.getDegree();
+ z = activated.getTerm()->membership(w);
sum += w * z;
weights += w;
}
} else {
- typedef std::map<const Term*, std::vector<Activated*> > TermGroup;
- TermGroup groups;
- for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) {
- Activated* value = fuzzyOutput->getTerm(i);
- const Term* key = value->getTerm();
- groups[key].push_back(value);
- }
- TermGroup::const_iterator it = groups.begin();
- Type type = _type;
- while (it != groups.end()) {
- const Term* activatedTerm = it->first;
- scalar accumulatedDegree = 0.0;
- for (std::size_t i = 0; i < it->second.size(); ++i)
- accumulatedDegree = fuzzyOutput->getAccumulation()->compute(
- accumulatedDegree, it->second.at(i)->getDegree());
-
- if (type == Automatic) type = inferType(activatedTerm);
-
- scalar z = (type == TakagiSugeno)
- //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work.
- ? activatedTerm->membership(accumulatedDegree) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions
- : tsukamoto(activatedTerm, accumulatedDegree, minimum, maximum);
-
- sum += accumulatedDegree * z;
- weights += accumulatedDegree;
-
- ++it;
+ scalar w, z;
+ for (std::size_t i = 0; i < numberOfTerms; ++i) {
+ const Activated& activated = fuzzyOutput->getTerm(i);
+ w = activated.getDegree();
+ z = activated.getTerm()->tsukamoto(w, minimum, maximum);
+ sum += w * z;
+ weights += w;
}
}
return sum / weights;
@@ -120,4 +96,5 @@ namespace fl {
Defuzzifier* WeightedAverage::constructor() {
return new WeightedAverage;
}
+
}
diff --git a/fuzzylite/src/defuzzifier/WeightedAverageCustom.cpp b/fuzzylite/src/defuzzifier/WeightedAverageCustom.cpp
new file mode 100644
index 0000000..0beb722
--- /dev/null
+++ b/fuzzylite/src/defuzzifier/WeightedAverageCustom.cpp
@@ -0,0 +1,117 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/defuzzifier/WeightedAverageCustom.h"
+
+#include "fl/term/Aggregated.h"
+
+#include <map>
+
+namespace fl {
+
+ WeightedAverageCustom::WeightedAverageCustom(Type type) : WeightedDefuzzifier(type) { }
+
+ WeightedAverageCustom::WeightedAverageCustom(const std::string& type) : WeightedDefuzzifier(type) { }
+
+ WeightedAverageCustom::~WeightedAverageCustom() { }
+
+ std::string WeightedAverageCustom::className() const {
+ return "WeightedAverageCustom";
+ }
+
+ Complexity WeightedAverageCustom::complexity(const Term* term) const {
+ Complexity result;
+ result.comparison(3).arithmetic(1).function(1);
+ const Aggregated* fuzzyOutput = dynamic_cast<const Aggregated*> (term);
+ if (fuzzyOutput) {
+ result += term->complexity().arithmetic(3).comparison(2)
+ .multiply(scalar(fuzzyOutput->numberOfTerms()));
+ }
+ return result;
+ }
+
+ scalar WeightedAverageCustom::defuzzify(const Term* term,
+ scalar minimum, scalar maximum) const {
+ const Aggregated* fuzzyOutput = dynamic_cast<const Aggregated*> (term);
+ if (not fuzzyOutput) {
+ std::ostringstream ss;
+ ss << "[defuzzification error]"
+ << "expected an Aggregated term instead of"
+ << "<" << (term ? term->toString() : "null") << ">";
+ throw Exception(ss.str(), FL_AT);
+ }
+
+ if (fuzzyOutput->isEmpty()) return fl::nan;
+
+ minimum = fuzzyOutput->getMinimum();
+ maximum = fuzzyOutput->getMaximum();
+
+ SNorm* aggregation = fuzzyOutput->getAggregation();
+
+ Type type = getType();
+ if (type == Automatic) {
+ type = inferType(&(fuzzyOutput->terms().front()));
+ }
+
+ scalar sum = 0.0;
+ scalar weights = 0.0;
+ const std::size_t numberOfTerms = fuzzyOutput->numberOfTerms();
+ if (type == TakagiSugeno) {
+ //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions
+ scalar w, z, wz;
+ for (std::size_t i = 0; i < numberOfTerms; ++i) {
+ const Activated& activated = fuzzyOutput->getTerm(i);
+ w = activated.getDegree();
+ z = activated.getTerm()->membership(w);
+ const TNorm* implication = activated.getImplication();
+ wz = implication ? implication->compute(w, z) : (w * z);
+ if (aggregation) {
+ sum = aggregation->compute(sum, wz);
+ weights = aggregation->compute(weights, w);
+ } else {
+ sum += wz;
+ weights += w;
+ }
+ }
+ } else {
+ scalar w, z, wz;
+ for (std::size_t i = 0; i < numberOfTerms; ++i) {
+ const Activated& activated = fuzzyOutput->getTerm(i);
+ w = activated.getDegree();
+ z = activated.getTerm()->tsukamoto(w, minimum, maximum);
+ const TNorm* implication = activated.getImplication();
+ wz = implication ? implication->compute(w, z) : (w * z);
+ if (aggregation) {
+ sum = aggregation->compute(sum, wz);
+ weights = aggregation->compute(weights, w);
+ } else {
+ sum += wz;
+ weights += w;
+ }
+ }
+ }
+ return sum / weights;
+ }
+
+ WeightedAverageCustom* WeightedAverageCustom::clone() const {
+ return new WeightedAverageCustom(*this);
+ }
+
+ Defuzzifier* WeightedAverageCustom::constructor() {
+ return new WeightedAverageCustom;
+ }
+
+}
diff --git a/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp b/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp
index 760a5dc..743c59f 100644
--- a/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp
+++ b/fuzzylite/src/defuzzifier/WeightedDefuzzifier.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/WeightedDefuzzifier.h"
@@ -36,24 +28,20 @@
namespace fl {
- WeightedDefuzzifier::WeightedDefuzzifier(Type type) : _type(type) {
-
- }
+ WeightedDefuzzifier::WeightedDefuzzifier(Type type) : _type(type) { }
WeightedDefuzzifier::WeightedDefuzzifier(const std::string& type) {
- if (type == "Automatic") _type = Automatic;
- else if (type == "TakagiSugeno") _type = TakagiSugeno;
- else if (type == "Tsukamoto") _type = Tsukamoto;
+ if (type == "Automatic") setType(Automatic);
+ else if (type == "TakagiSugeno") setType(TakagiSugeno);
+ else if (type == "Tsukamoto") setType(Tsukamoto);
else {
- _type = Automatic;
+ setType(Automatic);
FL_LOG("[warning] incorrect type <" + type + "> of WeightedDefuzzifier"
+ " has been defaulted to <Automatic>");
}
}
- WeightedDefuzzifier::~WeightedDefuzzifier() {
-
- }
+ WeightedDefuzzifier::~WeightedDefuzzifier() { }
std::string WeightedDefuzzifier::typeName(Type type) {
switch (type) {
@@ -73,7 +61,7 @@ namespace fl {
}
std::string WeightedDefuzzifier::getTypeName() const {
- return typeName(this->_type);
+ return typeName(getType());
}
WeightedDefuzzifier::Type WeightedDefuzzifier::inferType(const Term* term) const {
@@ -85,94 +73,4 @@ namespace fl {
return Tsukamoto;
}
- bool WeightedDefuzzifier::isMonotonic(const Term* term) const {
- return (dynamic_cast<const Concave*> (term)) or
- (dynamic_cast<const Ramp*> (term)) or
- (dynamic_cast<const Sigmoid*> (term)) or
- (dynamic_cast<const SShape*> (term)) or
- (dynamic_cast<const ZShape*> (term));
- }
-
- /**
- * Instead of computing y=f(x), the goal of Tsukamoto is to find x=f(w),
- * where f is monotonic.
- */
- scalar WeightedDefuzzifier::tsukamoto(const Term* monotonic, scalar activationDegree,
- scalar minimum, scalar maximum) const {
- scalar w = activationDegree;
- scalar z = fl::nan; //result;
- bool isTsukamoto = true;
- if (const Ramp* ramp = dynamic_cast<const Ramp*> (monotonic)) {
- z = Op::scale(w, 0, 1, ramp->getStart(), ramp->getEnd());
-
- } else if (const Sigmoid* sigmoid = dynamic_cast<const Sigmoid*> (monotonic)) {
- if (Op::isEq(w, 1.0)) {
- if (Op::isGE(sigmoid->getSlope(), 0.0)) {
- z = maximum;
- } else {
- z = minimum;
- }
-
- } else if (Op::isEq(w, 0.0)) {
- if (Op::isGE(sigmoid->getSlope(), 0.0)) {
- z = minimum;
- } else {
- z = maximum;
- }
- } else {
- scalar a = sigmoid->getSlope();
- scalar b = sigmoid->getInflection();
- z = b + (std::log(1.0 / w - 1.0) / -a);
- }
-
- } else if (const SShape* sshape = dynamic_cast<const SShape*> (monotonic)) {
- scalar difference = sshape->getEnd() - sshape->getStart();
- scalar a = sshape->getStart() + std::sqrt(w * difference * difference / 2.0);
- scalar b = sshape->getEnd() + std::sqrt(difference * difference * (w - 1.0) / -2.0);
- if (std::fabs(w - monotonic->membership(a)) <
- std::fabs(w - monotonic->membership(b))) {
- z = a;
- } else {
- z = b;
- }
-
- } else if (const ZShape* zshape = dynamic_cast<const ZShape*> (monotonic)) {
- scalar difference = zshape->getEnd() - zshape->getStart();
- scalar a = zshape->getStart() + std::sqrt(difference * difference * (w - 1.0) / -2.0);
- scalar b = zshape->getEnd() + std::sqrt(w * difference * difference / 2.0);
- if (std::fabs(w - monotonic->membership(a)) <
- std::fabs(w - monotonic->membership(b))) {
- z = a;
- } else {
- z = b;
- }
-
- } else if (const Concave* concave = dynamic_cast<const Concave*> (monotonic)) {
- scalar i = concave->getInflection();
- scalar e = concave->getEnd();
- z = (i - e) / concave->membership(w) + 2 * e - i;
- } else {
- isTsukamoto = false;
- }
-
- if (isTsukamoto) {
- //Compare difference between estimated and true value
- scalar fz = monotonic->membership(z);
- if (not Op::isEq(w, fz, 1e-2)) {
- FL_DBG("[tsukamoto warning] difference <" << Op::str(std::abs(w - fz)) << "> "
- "might suggest an inaccurate computation of z because it is "
- "expected w=f(z) in " << monotonic->className() <<
- " term <" << monotonic->getName() << ">, but "
- "w=" << w << " "
- "f(z)=" << fz << " and "
- "z=" << Op::str(z));
- }
- } else {
- // else fallback to the regular Takagi-Sugeno or inverse Tsukamoto (according to term)
- z = monotonic->membership(w);
- }
- return z;
- }
-
-
}
diff --git a/fuzzylite/src/defuzzifier/WeightedSum.cpp b/fuzzylite/src/defuzzifier/WeightedSum.cpp
index fb3e2e3..6c2343d 100644
--- a/fuzzylite/src/defuzzifier/WeightedSum.cpp
+++ b/fuzzylite/src/defuzzifier/WeightedSum.cpp
@@ -1,110 +1,86 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/defuzzifier/WeightedSum.h"
-#include "fl/term/Accumulated.h"
-#include "fl/term/Activated.h"
-#include "fl/norm/SNorm.h"
-#include "fl/norm/TNorm.h"
+#include "fl/term/Aggregated.h"
#include <map>
+
namespace fl {
- WeightedSum::WeightedSum(Type type) : WeightedDefuzzifier(type) {
- }
+ WeightedSum::WeightedSum(Type type) : WeightedDefuzzifier(type) { }
- WeightedSum::WeightedSum(const std::string& type) : WeightedDefuzzifier(type) {
+ WeightedSum::WeightedSum(const std::string& type) : WeightedDefuzzifier(type) { }
- }
-
- WeightedSum::~WeightedSum() {
- }
+ WeightedSum::~WeightedSum() { }
std::string WeightedSum::className() const {
return "WeightedSum";
}
+ Complexity WeightedSum::complexity(const Term* term) const {
+ Complexity result;
+ result.comparison(4).function(1);
+ const Aggregated* fuzzyOutput = dynamic_cast<const Aggregated*> (term);
+ if (fuzzyOutput) {
+ result += term->complexity().arithmetic(2).multiply(scalar(fuzzyOutput->numberOfTerms()));
+ }
+ return result;
+ }
+
scalar WeightedSum::defuzzify(const Term* term,
scalar minimum, scalar maximum) const {
- const Accumulated* fuzzyOutput = dynamic_cast<const Accumulated*> (term);
+ const Aggregated* fuzzyOutput = dynamic_cast<const Aggregated*> (term);
if (not fuzzyOutput) {
std::ostringstream ss;
ss << "[defuzzification error]"
- << "expected an Accumulated term instead of"
- << "<" << term->toString() << ">";
- throw fl::Exception(ss.str(), FL_AT);
+ << "expected an Aggregated term instead of"
+ << "<" << (term ? term->toString() : "null") << ">";
+ throw Exception(ss.str(), FL_AT);
}
+ if (fuzzyOutput->isEmpty()) return fl::nan;
+
minimum = fuzzyOutput->getMinimum();
maximum = fuzzyOutput->getMaximum();
+ Type type = getType();
+ if (type == Automatic) {
+ type = inferType(&(fuzzyOutput->terms().front()));
+ }
scalar sum = 0.0;
-
- if (not fuzzyOutput->getAccumulation()) {
- Type type = _type;
- for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) {
- Activated* activated = fuzzyOutput->getTerm(i);
- scalar w = activated->getDegree();
-
- if (type == Automatic) type = inferType(activated->getTerm());
-
- scalar z = (type == TakagiSugeno)
- //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work.
- ? activated->getTerm()->membership(w) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions
- : tsukamoto(activated->getTerm(), w, minimum, maximum);
-
+ const std::size_t numberOfTerms = fuzzyOutput->numberOfTerms();
+ if (type == TakagiSugeno) {
+ //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions
+ scalar w, z;
+ for (std::size_t i = 0; i < numberOfTerms; ++i) {
+ const Activated& activated = fuzzyOutput->getTerm(i);
+ w = activated.getDegree();
+ z = activated.getTerm()->membership(w);
sum += w * z;
}
} else {
- typedef std::map<const Term*, std::vector<Activated*> > TermGroup;
- TermGroup groups;
- for (int i = 0; i < fuzzyOutput->numberOfTerms(); ++i) {
- Activated* value = fuzzyOutput->getTerm(i);
- const Term* key = value->getTerm();
- groups[key].push_back(value);
- }
- TermGroup::const_iterator it = groups.begin();
- Type type = _type;
- while (it != groups.end()) {
- const Term* activatedTerm = it->first;
- scalar accumulatedDegree = 0.0;
- for (std::size_t i = 0; i < it->second.size(); ++i)
- accumulatedDegree = fuzzyOutput->getAccumulation()->compute(
- accumulatedDegree, it->second.at(i)->getDegree());
-
- if (type == Automatic) type = inferType(activatedTerm);
-
- scalar z = (type == TakagiSugeno)
- //? activated.getTerm()->membership(fl::nan) Would ensure no Tsukamoto applies, but Inverse Tsukamoto with Functions would not work.
- ? activatedTerm->membership(accumulatedDegree) //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions
- : tsukamoto(activatedTerm, accumulatedDegree, minimum, maximum);
-
- sum += accumulatedDegree * z;
-
- ++it;
+ scalar w, z;
+ for (std::size_t i = 0; i < numberOfTerms; ++i) {
+ const Activated& activated = fuzzyOutput->getTerm(i);
+ w = activated.getDegree();
+ z = activated.getTerm()->tsukamoto(w, minimum, maximum);
+ sum += w * z;
}
}
return sum;
diff --git a/fuzzylite/src/defuzzifier/WeightedSumCustom.cpp b/fuzzylite/src/defuzzifier/WeightedSumCustom.cpp
new file mode 100644
index 0000000..5a9084c
--- /dev/null
+++ b/fuzzylite/src/defuzzifier/WeightedSumCustom.cpp
@@ -0,0 +1,112 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/defuzzifier/WeightedSumCustom.h"
+
+#include "fl/term/Aggregated.h"
+
+#include <map>
+
+namespace fl {
+
+ WeightedSumCustom::WeightedSumCustom(Type type) : WeightedDefuzzifier(type) { }
+
+ WeightedSumCustom::WeightedSumCustom(const std::string& type) : WeightedDefuzzifier(type) { }
+
+ WeightedSumCustom::~WeightedSumCustom() { }
+
+ std::string WeightedSumCustom::className() const {
+ return "WeightedSumCustom";
+ }
+
+ Complexity WeightedSumCustom::complexity(const Term* term) const {
+ Complexity result;
+ result.comparison(4).function(1);
+ const Aggregated* fuzzyOutput = dynamic_cast<const Aggregated*> (term);
+ if (fuzzyOutput) {
+ result += term->complexity().arithmetic(2).comparison(2)
+ .multiply(scalar(fuzzyOutput->numberOfTerms()));
+ }
+ return result;
+ }
+
+ scalar WeightedSumCustom::defuzzify(const Term* term,
+ scalar minimum, scalar maximum) const {
+ const Aggregated* fuzzyOutput = dynamic_cast<const Aggregated*> (term);
+ if (not fuzzyOutput) {
+ std::ostringstream ss;
+ ss << "[defuzzification error]"
+ << "expected an Aggregated term instead of"
+ << "<" << (term ? term->toString() : "null") << ">";
+ throw Exception(ss.str(), FL_AT);
+ }
+
+ if (fuzzyOutput->isEmpty()) return fl::nan;
+
+ minimum = fuzzyOutput->getMinimum();
+ maximum = fuzzyOutput->getMaximum();
+
+ Type type = getType();
+ if (type == Automatic) {
+ type = inferType(&(fuzzyOutput->terms().front()));
+ }
+
+ SNorm* aggregation = fuzzyOutput->getAggregation();
+
+ scalar sum = 0.0;
+ const std::size_t numberOfTerms = fuzzyOutput->numberOfTerms();
+ if (type == TakagiSugeno) {
+ //Provides Takagi-Sugeno and Inverse Tsukamoto of Functions
+ scalar w, z, wz;
+ for (std::size_t i = 0; i < numberOfTerms; ++i) {
+ const Activated& activated = fuzzyOutput->getTerm(i);
+ w = activated.getDegree();
+ z = activated.getTerm()->membership(w);
+ const TNorm* implication = activated.getImplication();
+ wz = implication ? implication->compute(w, z) : (w * z);
+ if (aggregation) {
+ sum = aggregation->compute(sum, wz);
+ } else {
+ sum += wz;
+ }
+ }
+ } else {
+ scalar w, z, wz;
+ for (std::size_t i = 0; i < numberOfTerms; ++i) {
+ const Activated& activated = fuzzyOutput->getTerm(i);
+ w = activated.getDegree();
+ z = activated.getTerm()->tsukamoto(w, minimum, maximum);
+ const TNorm* implication = activated.getImplication();
+ wz = implication ? implication->compute(w, z) : (w * z);
+ if (aggregation) {
+ sum = aggregation->compute(sum, wz);
+ } else {
+ sum += wz;
+ }
+ }
+ }
+ return sum;
+ }
+
+ WeightedSumCustom* WeightedSumCustom::clone() const {
+ return new WeightedSumCustom(*this);
+ }
+
+ Defuzzifier* WeightedSumCustom::constructor() {
+ return new WeightedSumCustom;
+ }
+
+}
diff --git a/fuzzylite/src/factory/ActivationFactory.cpp b/fuzzylite/src/factory/ActivationFactory.cpp
new file mode 100644
index 0000000..d000667
--- /dev/null
+++ b/fuzzylite/src/factory/ActivationFactory.cpp
@@ -0,0 +1,42 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/factory/ActivationFactory.h"
+
+#include "fl/activation/First.h"
+#include "fl/activation/General.h"
+#include "fl/activation/Highest.h"
+#include "fl/activation/Last.h"
+#include "fl/activation/Lowest.h"
+#include "fl/activation/Proportional.h"
+#include "fl/activation/Threshold.h"
+
+namespace fl {
+
+ ActivationFactory::ActivationFactory() : ConstructionFactory<Activation*>("Activation") {
+ registerConstructor("", fl::null);
+ registerConstructor(First().className(), &(First::constructor));
+ registerConstructor(General().className(), &(General::constructor));
+ registerConstructor(Highest().className(), &(Highest::constructor));
+ registerConstructor(Last().className(), &(Last::constructor));
+ registerConstructor(Lowest().className(), &(Lowest::constructor));
+ registerConstructor(Proportional().className(), &(Proportional::constructor));
+ registerConstructor(Threshold().className(), &(Threshold::constructor));
+ }
+
+ ActivationFactory::~ActivationFactory() { }
+
+}
diff --git a/fuzzylite/src/factory/CloningFactory.cpp b/fuzzylite/src/factory/CloningFactory.cpp
deleted file mode 100644
index b187171..0000000
--- a/fuzzylite/src/factory/CloningFactory.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
-
- This file is part of fuzzylite.
-
- fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
-
- */
-
-#include "fl/factory/CloningFactory.h"
-
-#include "fl/Exception.h"
-#include "fl/term/Function.h"
-
-namespace fl {
-
- template<typename T>
- CloningFactory<T>::CloningFactory(const std::string& name) : _name(name) {
-
- }
-
- template<typename T>
- CloningFactory<T>::CloningFactory(const CloningFactory& other) {
- typename std::map<std::string, T>::const_iterator it = other._objects.begin();
- while (it != other._objects.end()) {
- T clone = fl::null;
- if (it->second) clone = it->second->clone();
- this->_objects[it->first] = clone;
- ++it;
- }
- }
-
- template<typename T>
- CloningFactory<T>& CloningFactory<T>::operator=(const CloningFactory& other) {
- if (this != &other) {
- typename std::map<std::string, T>::const_iterator it = this->_objects.begin();
- while (it != this->_objects.end()) {
- if (it->second) delete it->second;
- ++it;
- }
- this->_objects.clear();
-
- it = other._objects.begin();
- while (it != other._objects.end()) {
- T clone = fl::null;
- if (it->second) clone = it->second->clone();
- this->_objects[it->first] = clone;
- ++it;
- }
- }
- return *this;
- }
-
- template<typename T>
- CloningFactory<T>::~CloningFactory() {
- typename std::map<std::string, T>::const_iterator it = this->_objects.begin();
- while (it != this->_objects.end()) {
- if (it->second) delete it->second;
- ++it;
- }
- }
-
- template<typename T>
- std::string CloningFactory<T>::name() const {
- return this->_name;
- }
-
- template<typename T>
- void CloningFactory<T>::registerObject(const std::string& key, T object) {
- this->_objects[key] = object;
- }
-
- template<typename T>
- void CloningFactory<T>::deregisterObject(const std::string& key) {
- typename std::map<std::string, T>::iterator it = this->_objects.find(key);
- if (it != this->_objects.end()) {
- this->_objects.erase(it);
- delete it->second;
- }
- }
-
- template<typename T>
- bool CloningFactory<T>::hasObject(const std::string& key) const {
- typename std::map<std::string, T>::const_iterator it = this->_objects.find(key);
- return (it != this->_objects.end());
- }
-
- template<typename T>
- T CloningFactory<T>::getObject(const std::string& key) const {
- typename std::map<std::string, T>::const_iterator it = this->_objects.find(key);
- if (it != this->_objects.end()) {
- if (it->second) return it->second;
- }
- return fl::null;
- }
-
- template<typename T>
- T CloningFactory<T>::cloneObject(const std::string& key) const {
- typename std::map<std::string, T>::const_iterator it = this->_objects.find(key);
- if (it != this->_objects.end()) {
- if (it->second) return it->second->clone();
- return fl::null;
- }
- throw fl::Exception("[cloning error] " + _name + " object by name <" + key + "> not registered", FL_AT);
- }
-
- template<typename T>
- std::vector<std::string> CloningFactory<T>::available() const {
- std::vector<std::string> result;
- typename std::map<std::string, T>::const_iterator it = this->_objects.begin();
- while (it != this->_objects.end()) {
- result.push_back(it->first);
- }
- return result;
- }
-
- template class fl::CloningFactory<fl::Function::Element*>;
-}
-
-
diff --git a/fuzzylite/src/factory/ConstructionFactory.cpp b/fuzzylite/src/factory/ConstructionFactory.cpp
deleted file mode 100644
index b316e52..0000000
--- a/fuzzylite/src/factory/ConstructionFactory.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
-
- This file is part of fuzzylite.
-
- fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
-
- */
-
-#include "fl/factory/ConstructionFactory.h"
-
-#include "fl/Exception.h"
-#include "fl/defuzzifier/Defuzzifier.h"
-#include "fl/hedge/Hedge.h"
-#include "fl/norm/SNorm.h"
-#include "fl/norm/TNorm.h"
-#include "fl/term/Function.h"
-#include "fl/term/Term.h"
-
-
-
-namespace fl {
-
- template <typename T>
- ConstructionFactory<T>::ConstructionFactory(const std::string& name) : _name(name) {
-
- }
-
- template <typename T>
- ConstructionFactory<T>::~ConstructionFactory() {
- }
-
- template<typename T>
- std::string ConstructionFactory<T>::name() const {
- return this->_name;
- }
-
- template <typename T>
- void ConstructionFactory<T>::registerConstructor(const std::string& key, Constructor constructor) {
- this->_constructors[key] = constructor;
- }
-
- template <typename T>
- void ConstructionFactory<T>::deregisterConstructor(const std::string& key) {
- typename std::map<std::string, Constructor>::iterator it = this->_constructors.find(key);
- if (it != this->_constructors.end()) {
- this->_constructors.erase(it);
- }
- }
-
- template <typename T>
- bool ConstructionFactory<T>::hasConstructor(const std::string& key) const {
- typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key);
- return (it != this->_constructors.end());
- }
-
- template <typename T>
- typename ConstructionFactory<T>::Constructor ConstructionFactory<T>::getConstructor(const std::string& key) const {
- typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key);
- if (it != this->_constructors.end()) {
- return it->second;
- }
- return fl::null;
- }
-
- template <typename T>
- T ConstructionFactory<T>::constructObject(const std::string& key) const {
- typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.find(key);
- if (it != this->_constructors.end()) {
- if (it->second) {
- return it->second();
- }
- return fl::null;
- }
- std::ostringstream ss;
- ss << "[factory error] constructor of " + _name + " <" << key << "> not registered";
- throw fl::Exception(ss.str(), FL_AT);
- }
-
- template <typename T>
- std::vector<std::string> ConstructionFactory<T>::available() const {
- std::vector<std::string> result;
- typename std::map<std::string, Constructor>::const_iterator it = this->_constructors.begin();
- while (it != this->_constructors.end()) {
- result.push_back(it->first);
- ++it;
- }
- return result;
- }
-
- template class ConstructionFactory<Defuzzifier*>;
- template class ConstructionFactory<Hedge*>;
- template class ConstructionFactory<SNorm*>;
- template class ConstructionFactory<TNorm*>;
- template class ConstructionFactory<Term*>;
-}
-
-
-
diff --git a/fuzzylite/src/factory/DefuzzifierFactory.cpp b/fuzzylite/src/factory/DefuzzifierFactory.cpp
index 8d89c2d..3b0bfb1 100644
--- a/fuzzylite/src/factory/DefuzzifierFactory.cpp
+++ b/fuzzylite/src/factory/DefuzzifierFactory.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/factory/DefuzzifierFactory.h"
@@ -30,7 +22,9 @@
#include "fl/defuzzifier/LargestOfMaximum.h"
#include "fl/defuzzifier/MeanOfMaximum.h"
#include "fl/defuzzifier/WeightedAverage.h"
+#include "fl/defuzzifier/WeightedAverageCustom.h"
#include "fl/defuzzifier/WeightedSum.h"
+#include "fl/defuzzifier/WeightedSumCustom.h"
namespace fl {
@@ -42,12 +36,12 @@ namespace fl {
registerConstructor(MeanOfMaximum().className(), &(MeanOfMaximum::constructor));
registerConstructor(SmallestOfMaximum().className(), &(SmallestOfMaximum::constructor));
registerConstructor(WeightedAverage().className(), &(WeightedAverage::constructor));
+// registerConstructor(WeightedAverageCustom().className(), &(WeightedAverageCustom::constructor));
registerConstructor(WeightedSum().className(), &(WeightedSum::constructor));
+// registerConstructor(WeightedSumCustom().className(), &(WeightedSumCustom::constructor));
}
- DefuzzifierFactory::~DefuzzifierFactory() {
-
- }
+ DefuzzifierFactory::~DefuzzifierFactory() { }
Defuzzifier* DefuzzifierFactory::constructDefuzzifier(const std::string& key,
int resolution, WeightedDefuzzifier::Type type) const {
@@ -75,4 +69,5 @@ namespace fl {
}
return result;
}
+
}
diff --git a/fuzzylite/src/factory/FactoryManager.cpp b/fuzzylite/src/factory/FactoryManager.cpp
index c2374dc..367d982 100644
--- a/fuzzylite/src/factory/FactoryManager.cpp
+++ b/fuzzylite/src/factory/FactoryManager.cpp
@@ -1,60 +1,46 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/factory/FactoryManager.h"
-#include "fl/factory/DefuzzifierFactory.h"
-#include "fl/factory/FunctionFactory.h"
-#include "fl/factory/HedgeFactory.h"
-#include "fl/factory/SNormFactory.h"
-#include "fl/factory/TermFactory.h"
-#include "fl/factory/TNormFactory.h"
-
namespace fl {
- FactoryManager FactoryManager::_instance;
-
FactoryManager* FactoryManager::instance() {
+ static FL_ITHREAD_LOCAL FactoryManager _instance;
return &_instance;
}
FactoryManager::FactoryManager() :
- _tnorm(new TNormFactory), _snorm(new SNormFactory), _defuzzifier(new DefuzzifierFactory),
- _term(new TermFactory), _hedge(new HedgeFactory), _function(new FunctionFactory) {
- }
+ _tnorm(new TNormFactory), _snorm(new SNormFactory), _activation(new ActivationFactory),
+ _defuzzifier(new DefuzzifierFactory), _term(new TermFactory),
+ _hedge(new HedgeFactory), _function(new FunctionFactory) { }
FactoryManager::FactoryManager(TNormFactory* tnorm, SNormFactory* snorm,
- DefuzzifierFactory* defuzzifier, TermFactory* term,
- HedgeFactory* hedge, FunctionFactory* function) :
- _tnorm(tnorm), _snorm(snorm), _defuzzifier(defuzzifier), _term(term), _hedge(hedge),
- _function(function) {
- }
+ ActivationFactory* activation, DefuzzifierFactory* defuzzifier,
+ TermFactory* term, HedgeFactory* hedge, FunctionFactory* function) :
+ _tnorm(tnorm), _snorm(snorm), _activation(activation),
+ _defuzzifier(defuzzifier), _term(term), _hedge(hedge), _function(function) { }
FactoryManager::FactoryManager(const FactoryManager& other)
- : _tnorm(fl::null), _snorm(fl::null), _defuzzifier(fl::null), _term(fl::null), _hedge(fl::null), _function(fl::null) {
+ : _tnorm(fl::null), _snorm(fl::null), _activation(fl::null),
+ _defuzzifier(fl::null), _term(fl::null), _hedge(fl::null),
+ _function(fl::null) {
if (other._tnorm.get()) this->_tnorm.reset(new TNormFactory(*other._tnorm.get()));
if (other._snorm.get()) this->_snorm.reset(new SNormFactory(*other._snorm.get()));
+ if (other._activation.get()) this->_activation.reset(new ActivationFactory(*other._activation.get()));
if (other._defuzzifier.get()) this->_defuzzifier.reset(new DefuzzifierFactory(*other._defuzzifier.get()));
if (other._term.get()) this->_term.reset(new TermFactory(*other._term.get()));
if (other._hedge.get()) this->_hedge.reset(new HedgeFactory(*other._hedge.get()));
@@ -63,8 +49,17 @@ namespace fl {
FactoryManager& FactoryManager::operator=(const FactoryManager& other) {
if (this != &other) {
+ _tnorm.reset(fl::null);
+ _snorm.reset(fl::null);
+ _activation.reset(fl::null);
+ _defuzzifier.reset(fl::null);
+ _term.reset(fl::null);
+ _hedge.reset(fl::null);
+ _function.reset(fl::null);
+
if (other._tnorm.get()) this->_tnorm.reset(new TNormFactory(*other._tnorm.get()));
if (other._snorm.get()) this->_snorm.reset(new SNormFactory(*other._snorm.get()));
+ if (other._activation.get()) this->_activation.reset(new ActivationFactory(*other._activation.get()));
if (other._defuzzifier.get()) this->_defuzzifier.reset(new DefuzzifierFactory(*other._defuzzifier.get()));
if (other._term.get()) this->_term.reset(new TermFactory(*other._term.get()));
if (other._hedge.get()) this->_hedge.reset(new HedgeFactory(*other._hedge.get()));
@@ -73,8 +68,7 @@ namespace fl {
return *this;
}
- FactoryManager::~FactoryManager() {
- }
+ FactoryManager::~FactoryManager() { }
void FactoryManager::setTnorm(TNormFactory* tnorm) {
this->_tnorm.reset(tnorm);
@@ -92,6 +86,14 @@ namespace fl {
return this->_snorm.get();
}
+ void FactoryManager::setActivation(ActivationFactory* activation) {
+ this->_activation.reset(activation);
+ }
+
+ ActivationFactory* FactoryManager::activation() const {
+ return this->_activation.get();
+ }
+
void FactoryManager::setDefuzzifier(DefuzzifierFactory* defuzzifier) {
this->_defuzzifier.reset(defuzzifier);
}
diff --git a/fuzzylite/src/factory/FunctionFactory.cpp b/fuzzylite/src/factory/FunctionFactory.cpp
index 3c0718d..8e52ddf 100644
--- a/fuzzylite/src/factory/FunctionFactory.cpp
+++ b/fuzzylite/src/factory/FunctionFactory.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/factory/FunctionFactory.h"
@@ -33,125 +25,130 @@ namespace fl {
registerFunctions();
}
- FunctionFactory::~FunctionFactory() {
-
- }
+ FunctionFactory::~FunctionFactory() { }
void FunctionFactory::registerOperators() {
//OPERATORS:
int p = 100;
//First order: not, negate:
registerObject("!", new Function::Element("!", "Logical NOT",
- Function::Element::OPERATOR, &(fl::Op::logicalNot), p, 1)); //logical not
+ Function::Element::Operator, &(Op::logicalNot), p, 1)); //logical not
registerObject("~", new Function::Element("~", "Negation",
- Function::Element::OPERATOR, &(fl::Op::negate), p, 1)); // ~ negates a number
+ Function::Element::Operator, &(Op::negate), p, 1)); // ~ negates a number
p -= 10;
//Second order: power
registerObject("^", new Function::Element("^", "Power",
- Function::Element::OPERATOR, &(std::pow), p, 1));
+ Function::Element::Operator, &(std::pow), p, 1));
p -= 10;
//Third order: multiplication, division, modulo
registerObject("*", new Function::Element("*", "Multiplication",
- Function::Element::OPERATOR, &(fl::Op::multiply), p));
+ Function::Element::Operator, &(Op::multiply), p));
registerObject("/", new Function::Element("/", "Division",
- Function::Element::OPERATOR, &(fl::Op::divide), p));
+ Function::Element::Operator, &(Op::divide), p));
registerObject("%", new Function::Element("%", "Modulo",
- Function::Element::OPERATOR, &(fl::Op::modulo), p));
+ Function::Element::Operator, &(Op::modulo), p));
p -= 10;
//Fourth order: addition, subtraction
registerObject("+", new Function::Element("+", "Addition",
- Function::Element::OPERATOR, &(fl::Op::add), p));
+ Function::Element::Operator, &(Op::add), p));
registerObject("-", new Function::Element("-", "Subtraction",
- Function::Element::OPERATOR, &(fl::Op::subtract), p));
+ Function::Element::Operator, &(Op::subtract), p));
//Fifth order: logical and, logical or
p -= 10; //Logical AND
- registerObject(fl::Rule::andKeyword(), new Function::Element(fl::Rule::andKeyword(), "Logical AND",
- Function::Element::OPERATOR, &(fl::Op::logicalAnd), p));
+ registerObject(Rule::andKeyword(), new Function::Element(Rule::andKeyword(), "Logical AND",
+ Function::Element::Operator, &(Op::logicalAnd), p));
p -= 10; //Logical OR
- registerObject(fl::Rule::orKeyword(), new Function::Element(fl::Rule::orKeyword(), "Logical OR",
- Function::Element::OPERATOR, &(fl::Op::logicalOr), p));
+ registerObject(Rule::orKeyword(), new Function::Element(Rule::orKeyword(), "Logical OR",
+ Function::Element::Operator, &(Op::logicalOr), p));
}
void FunctionFactory::registerFunctions() {
//FUNCTIONS
registerObject("gt", new Function::Element("gt", "Greater than (>)",
- Function::Element::FUNCTION, &(fl::Op::gt)));
+ Function::Element::Function, &(Op::gt)));
registerObject("ge", new Function::Element("ge", "Greater than or equal to (>=)",
- Function::Element::FUNCTION, &(fl::Op::ge)));
+ Function::Element::Function, &(Op::ge)));
registerObject("eq", new Function::Element("eq", "Equal to (==)",
- Function::Element::FUNCTION, &(fl::Op::eq)));
+ Function::Element::Function, &(Op::eq)));
registerObject("neq", new Function::Element("neq", "Not equal to (!=)",
- Function::Element::FUNCTION, &(fl::Op::neq)));
+ Function::Element::Function, &(Op::neq)));
registerObject("le", new Function::Element("le", "Less than or equal to (<=)",
- Function::Element::FUNCTION, &(fl::Op::le)));
+ Function::Element::Function, &(Op::le)));
registerObject("lt", new Function::Element("lt", "Less than (<)",
- Function::Element::FUNCTION, &(fl::Op::lt)));
+ Function::Element::Function, &(Op::lt)));
+
+ registerObject("min", new Function::Element("min", "Minimum",
+ Function::Element::Function, &(Op::min)));
+ registerObject("max", new Function::Element("max", "Maximum",
+ Function::Element::Function, &(Op::max)));
registerObject("acos", new Function::Element("acos", "Inverse cosine",
- Function::Element::FUNCTION, &(std::acos)));
+ Function::Element::Function, &(std::acos)));
registerObject("asin", new Function::Element("asin", "Inverse sine",
- Function::Element::FUNCTION, &(std::asin)));
+ Function::Element::Function, &(std::asin)));
registerObject("atan", new Function::Element("atan", "Inverse tangent",
- Function::Element::FUNCTION, &(std::atan)));
+ Function::Element::Function, &(std::atan)));
registerObject("ceil", new Function::Element("ceil", "Ceiling",
- Function::Element::FUNCTION, &(std::ceil)));
+ Function::Element::Function, &(std::ceil)));
registerObject("cos", new Function::Element("cos", "Cosine",
- Function::Element::FUNCTION, &(std::cos)));
+ Function::Element::Function, &(std::cos)));
registerObject("cosh", new Function::Element("cosh", "Hyperbolic cosine",
- Function::Element::FUNCTION, &(std::cosh)));
+ Function::Element::Function, &(std::cosh)));
registerObject("exp", new Function::Element("exp", "Exponential",
- Function::Element::FUNCTION, &(std::exp)));
+ Function::Element::Function, &(std::exp)));
+ registerObject("abs", new Function::Element("abs", "Absolute",
+ Function::Element::Function, &(std::abs)));
registerObject("fabs", new Function::Element("fabs", "Absolute",
- Function::Element::FUNCTION, &(std::fabs)));
+ Function::Element::Function, &(std::fabs)));
registerObject("floor", new Function::Element("floor", "Floor",
- Function::Element::FUNCTION, &(std::floor)));
+ Function::Element::Function, &(std::floor)));
registerObject("log", new Function::Element("log", "Natural logarithm",
- Function::Element::FUNCTION, &(std::log)));
+ Function::Element::Function, &(std::log)));
registerObject("log10", new Function::Element("log10", "Common logarithm",
- Function::Element::FUNCTION, &(std::log10)));
+ Function::Element::Function, &(std::log10)));
registerObject("round", new Function::Element("round", "Round",
- Function::Element::FUNCTION, &(fl::Op::round)));
+ Function::Element::Function, &(Op::round)));
registerObject("sin", new Function::Element("sin", "Sine",
- Function::Element::FUNCTION, &(std::sin)));
+ Function::Element::Function, &(std::sin)));
registerObject("sinh", new Function::Element("sinh", "Hyperbolic sine",
- Function::Element::FUNCTION, &(std::sinh)));
+ Function::Element::Function, &(std::sinh)));
registerObject("sqrt", new Function::Element("sqrt", "Square root",
- Function::Element::FUNCTION, &(std::sqrt)));
+ Function::Element::Function, &(std::sqrt)));
registerObject("tan", new Function::Element("tan", "Tangent",
- Function::Element::FUNCTION, &(std::tan)));
+ Function::Element::Function, &(std::tan)));
registerObject("tanh", new Function::Element("tanh", "Hyperbolic tangent",
- Function::Element::FUNCTION, &(std::tanh)));
+ Function::Element::Function, &(std::tanh)));
#if defined(FL_UNIX) && !defined(FL_USE_FLOAT)
//found in Unix when using double precision. not found in Windows.
registerObject("log1p", new Function::Element("log1p", "Natural logarithm plus one",
- Function::Element::FUNCTION, &(log1p)));
+ Function::Element::Function, &(log1p)));
registerObject("acosh", new Function::Element("acosh", "Inverse hyperbolic cosine",
- Function::Element::FUNCTION, &(acosh)));
+ Function::Element::Function, &(acosh)));
registerObject("asinh", new Function::Element("asinh", "Inverse hyperbolic sine",
- Function::Element::FUNCTION, &(asinh)));
+ Function::Element::Function, &(asinh)));
registerObject("atanh", new Function::Element("atanh", "Inverse hyperbolic tangent",
- Function::Element::FUNCTION, &(atanh)));
+ Function::Element::Function, &(atanh)));
#endif
registerObject("pow", new Function::Element("pow", "Power",
- Function::Element::FUNCTION, &(std::pow)));
+ Function::Element::Function, &(std::pow)));
registerObject("atan2", new Function::Element("atan2", "Inverse tangent (y,x)",
- Function::Element::FUNCTION, &(std::atan2)));
+ Function::Element::Function, &(std::atan2)));
registerObject("fmod", new Function::Element("fmod", "Floating-point remainder",
- Function::Element::FUNCTION, &(std::fmod)));
+ Function::Element::Function, &(std::fmod)));
}
std::vector<std::string> FunctionFactory::availableOperators() const {
std::vector<std::string> result;
- std::map<std::string, Function::Element*>::const_iterator it = this->_objects.begin();
- while (it != this->_objects.end()) {
- if (it->second and it->second->type == Function::Element::OPERATOR)
+ std::map<std::string, Function::Element*>::const_iterator it = this->objects().begin();
+ while (it != this->objects().end()) {
+ if (it->second and it->second->type == Function::Element::Operator)
result.push_back(it->first);
++it;
}
@@ -160,9 +157,9 @@ namespace fl {
std::vector<std::string> FunctionFactory::availableFunctions() const {
std::vector<std::string> result;
- std::map<std::string, Function::Element*>::const_iterator it = this->_objects.begin();
- while (it != this->_objects.end()) {
- if (it->second and it->second->type == Function::Element::FUNCTION)
+ std::map<std::string, Function::Element*>::const_iterator it = this->objects().begin();
+ while (it != this->objects().end()) {
+ if (it->second and it->second->type == Function::Element::Function)
result.push_back(it->first);
++it;
}
diff --git a/fuzzylite/src/factory/HedgeFactory.cpp b/fuzzylite/src/factory/HedgeFactory.cpp
index ea5f77a..1a6452c 100644
--- a/fuzzylite/src/factory/HedgeFactory.cpp
+++ b/fuzzylite/src/factory/HedgeFactory.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/factory/HedgeFactory.h"
@@ -31,7 +23,6 @@
#include "fl/hedge/Somewhat.h"
#include "fl/hedge/Very.h"
-
namespace fl {
HedgeFactory::HedgeFactory() : ConstructionFactory<Hedge*>("Hedge") {
@@ -44,8 +35,6 @@ namespace fl {
registerConstructor(Very().name(), &(Very::constructor));
}
- HedgeFactory::~HedgeFactory() {
-
- }
+ HedgeFactory::~HedgeFactory() { }
}
diff --git a/fuzzylite/src/factory/SNormFactory.cpp b/fuzzylite/src/factory/SNormFactory.cpp
index 6e42551..fdaef87 100644
--- a/fuzzylite/src/factory/SNormFactory.cpp
+++ b/fuzzylite/src/factory/SNormFactory.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/factory/SNormFactory.h"
@@ -32,6 +24,7 @@
#include "fl/norm/s/Maximum.h"
#include "fl/norm/s/NilpotentMaximum.h"
#include "fl/norm/s/NormalizedSum.h"
+#include "fl/norm/s/UnboundedSum.h"
namespace fl {
@@ -45,11 +38,9 @@ namespace fl {
registerConstructor(Maximum().className(), &(Maximum::constructor));
registerConstructor(NilpotentMaximum().className(), &(NilpotentMaximum::constructor));
registerConstructor(NormalizedSum().className(), &(NormalizedSum::constructor));
+ registerConstructor(UnboundedSum().className(), &(UnboundedSum::constructor));
}
- SNormFactory::~SNormFactory() {
-
- }
-
+ SNormFactory::~SNormFactory() { }
}
diff --git a/fuzzylite/src/factory/TNormFactory.cpp b/fuzzylite/src/factory/TNormFactory.cpp
index 95628cc..0dda02e 100644
--- a/fuzzylite/src/factory/TNormFactory.cpp
+++ b/fuzzylite/src/factory/TNormFactory.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/factory/TNormFactory.h"
@@ -45,9 +37,6 @@ namespace fl {
registerConstructor(NilpotentMinimum().className(), &(NilpotentMinimum::constructor));
}
- TNormFactory::~TNormFactory() {
-
- }
-
+ TNormFactory::~TNormFactory() { }
}
diff --git a/fuzzylite/src/factory/TermFactory.cpp b/fuzzylite/src/factory/TermFactory.cpp
index 10f3c15..e135704 100644
--- a/fuzzylite/src/factory/TermFactory.cpp
+++ b/fuzzylite/src/factory/TermFactory.cpp
@@ -1,32 +1,23 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/factory/TermFactory.h"
-#include "fl/Exception.h"
-#include "fl/term/Term.h"
#include "fl/term/Bell.h"
+#include "fl/term/Binary.h"
#include "fl/term/Concave.h"
#include "fl/term/Constant.h"
#include "fl/term/Cosine.h"
@@ -52,6 +43,7 @@ namespace fl {
TermFactory::TermFactory() : ConstructionFactory<Term*>("Term") {
registerConstructor("", fl::null);
registerConstructor(Bell().className(), &(Bell::constructor));
+ registerConstructor(Binary().className(), &(Binary::constructor));
registerConstructor(Concave().className(), &(Concave::constructor));
registerConstructor(Constant().className(), &(Constant::constructor));
registerConstructor(Cosine().className(), &(Cosine::constructor));
@@ -73,9 +65,6 @@ namespace fl {
registerConstructor(ZShape().className(), &(ZShape::constructor));
}
- TermFactory::~TermFactory() {
-
- }
-
+ TermFactory::~TermFactory() { }
}
diff --git a/fuzzylite/src/fuzzylite.cpp b/fuzzylite/src/fuzzylite.cpp
index 06b635a..db17fec 100644
--- a/fuzzylite/src/fuzzylite.cpp
+++ b/fuzzylite/src/fuzzylite.cpp
@@ -1,73 +1,31 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/fuzzylite.h"
namespace fl {
+
int fuzzylite::_decimals = 3;
+ std::ios_base::fmtflags fuzzylite::_scalarFormat = std::ios_base::fixed;
scalar fuzzylite::_macheps = 1e-6;
- bool fuzzylite::_debug = false;
+ bool fuzzylite::_debugging = false;
bool fuzzylite::_logging = true;
- std::string fuzzylite::name() {
- return "fuzzylite";
- }
-
- std::string fuzzylite::fullname() {
- return name() + "-" + longVersion();
- }
-
- std::string fuzzylite::version() {
- return FL_VERSION;
- }
-
- std::string fuzzylite::longVersion() {
- return FL_VERSION "b" FL_DATE;
- }
-
- std::string fuzzylite::license() {
- return "GNU Lesser General Public License v3.0";
- }
-
- std::string fuzzylite::author() {
- return "Juan Rada-Vilela, Ph.D.";
- }
-
- std::string fuzzylite::company() {
- return "FuzzyLite Limited";
- }
-
- std::string fuzzylite::website() {
- return "http://www.fuzzylite.com/";
- }
-
- std::string fuzzylite::date() {
- return FL_DATE;
- }
-
- std::string fuzzylite::platform() {
+ std::string platform() {
#ifdef FL_UNIX
return "Unix";
#elif defined FL_WINDOWS
@@ -77,9 +35,9 @@ namespace fl {
#endif
}
- std::string fuzzylite::floatingPoint() {
+ std::string floatingPoint() {
scalar someScalar = 0;
- (void) someScalar;
+ FL_IUNUSED(someScalar);
std::string type;
std::ostringstream ss;
@@ -92,37 +50,4 @@ namespace fl {
sizeof (someScalar) << " bytes";
return ss.str();
}
-
- void fuzzylite::setDebug(bool debug) {
- _debug = debug;
- }
-
- bool fuzzylite::debug() {
- return _debug;
- }
-
- void fuzzylite::setDecimals(int decimals) {
- _decimals = decimals;
- }
-
- int fuzzylite::decimals() {
- return _decimals;
- }
-
- void fuzzylite::setMachEps(scalar macheps) {
- _macheps = macheps;
- }
-
- scalar fuzzylite::macheps() {
- return _macheps;
- }
-
- void fuzzylite::setLogging(bool logging) {
- _logging = logging;
- }
-
- bool fuzzylite::logging() {
- return _logging;
- }
-
}
diff --git a/fuzzylite/src/hedge/Any.cpp b/fuzzylite/src/hedge/Any.cpp
index 72724f1..9d04262 100644
--- a/fuzzylite/src/hedge/Any.cpp
+++ b/fuzzylite/src/hedge/Any.cpp
@@ -1,43 +1,37 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/hedge/Any.h"
namespace fl {
- Any::Any() {
- }
+ Any::Any() { }
- Any::~Any() {
- }
+ Any::~Any() { }
std::string Any::name() const {
return "any";
}
+ Complexity Any::complexity() const {
+ return Complexity();
+ }
+
scalar Any::hedge(scalar x) const {
- (void) x;
+ FL_IUNUSED(x);
return 1.0;
}
@@ -50,3 +44,4 @@ namespace fl {
}
}
+
diff --git a/fuzzylite/src/hedge/Extremely.cpp b/fuzzylite/src/hedge/Extremely.cpp
index eabbb60..60d3abd 100644
--- a/fuzzylite/src/hedge/Extremely.cpp
+++ b/fuzzylite/src/hedge/Extremely.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/hedge/Extremely.h"
@@ -32,10 +24,14 @@ namespace fl {
return "extremely";
}
+ Complexity Extremely::complexity() const {
+ return Complexity().comparison(1).arithmetic(5);
+ }
+
scalar Extremely::hedge(scalar x) const {
return Op::isLE(x, 0.5)
? 2.0 * x * x
- : 1.0 - 2.0 * (1.0 - x) * (1.0 - x);
+ : (1.0 - 2.0 * (1.0 - x) * (1.0 - x));
}
Extremely* Extremely::clone() const {
@@ -46,5 +42,5 @@ namespace fl {
return new Extremely;
}
-
}
+
diff --git a/fuzzylite/src/hedge/HedgeFunction.cpp b/fuzzylite/src/hedge/HedgeFunction.cpp
new file mode 100644
index 0000000..c31c72c
--- /dev/null
+++ b/fuzzylite/src/hedge/HedgeFunction.cpp
@@ -0,0 +1,63 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/hedge/HedgeFunction.h"
+
+namespace fl {
+
+ HedgeFunction::HedgeFunction(const std::string& formula) : Hedge() {
+ _function.variables["x"] = fl::nan;
+ if (not formula.empty()) {
+ _function.load(formula);
+ }
+ }
+
+ std::string HedgeFunction::name() const {
+ return "HedgeFunction";
+ }
+
+ Complexity HedgeFunction::complexity() const {
+ if (_function.root())
+ return _function.complexity().function(2 * std::log(scalar(_function.variables.size())));
+ return _function.complexity();
+ }
+
+ scalar HedgeFunction::hedge(scalar x) const {
+ _function.variables["x"] = x;
+ return _function.membership(x);
+ }
+
+ Function& HedgeFunction::function() {
+ return this->_function;
+ }
+
+ void HedgeFunction::setFormula(const std::string& formula) {
+ _function.load(formula);
+ }
+
+ std::string HedgeFunction::getFormula() const {
+ return _function.getFormula();
+ }
+
+ HedgeFunction* HedgeFunction::clone() const {
+ return new HedgeFunction(*this);
+ }
+
+ Hedge* HedgeFunction::constructor() {
+ return new HedgeFunction;
+ }
+
+}
diff --git a/fuzzylite/src/hedge/Not.cpp b/fuzzylite/src/hedge/Not.cpp
index 531213f..defbabd 100644
--- a/fuzzylite/src/hedge/Not.cpp
+++ b/fuzzylite/src/hedge/Not.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/hedge/Not.h"
@@ -30,6 +22,10 @@ namespace fl {
return "not";
}
+ Complexity Not::complexity() const {
+ return Complexity().arithmetic(1);
+ }
+
scalar Not::hedge(scalar x) const {
return 1.0 - x;
}
@@ -42,5 +38,4 @@ namespace fl {
return new Not;
}
-
}
diff --git a/fuzzylite/src/hedge/Seldom.cpp b/fuzzylite/src/hedge/Seldom.cpp
index d87b48a..092e873 100644
--- a/fuzzylite/src/hedge/Seldom.cpp
+++ b/fuzzylite/src/hedge/Seldom.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/hedge/Seldom.h"
@@ -32,10 +24,14 @@ namespace fl {
return "seldom";
}
+ Complexity Seldom::complexity() const {
+ return Complexity().comparison(1).function(1).arithmetic(3);
+ }
+
scalar Seldom::hedge(scalar x) const {
return Op::isLE(x, 0.5)
- ? std::sqrt(x / 2.0)
- : 1.0 - std::sqrt((1.0 - x) / 2.0);
+ ? std::sqrt(0.5 * x)
+ : (1.0 - std::sqrt(0.5 * (1.0 - x)));
}
Seldom* Seldom::clone() const {
@@ -46,5 +42,4 @@ namespace fl {
return new Seldom;
}
-
}
diff --git a/fuzzylite/src/hedge/Somewhat.cpp b/fuzzylite/src/hedge/Somewhat.cpp
index 16c371b..4d68c20 100644
--- a/fuzzylite/src/hedge/Somewhat.cpp
+++ b/fuzzylite/src/hedge/Somewhat.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/hedge/Somewhat.h"
@@ -30,6 +22,10 @@ namespace fl {
return "somewhat";
}
+ Complexity Somewhat::complexity() const {
+ return Complexity().function(1);
+ }
+
scalar Somewhat::hedge(scalar x) const {
return std::sqrt(x);
}
diff --git a/fuzzylite/src/hedge/Very.cpp b/fuzzylite/src/hedge/Very.cpp
index dc1fbec..5ac7a86 100644
--- a/fuzzylite/src/hedge/Very.cpp
+++ b/fuzzylite/src/hedge/Very.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/hedge/Very.h"
@@ -30,6 +22,10 @@ namespace fl {
return "very";
}
+ Complexity Very::complexity() const {
+ return Complexity().arithmetic(1);
+ }
+
scalar Very::hedge(scalar x) const {
return x * x;
}
diff --git a/fuzzylite/src/imex/CppExporter.cpp b/fuzzylite/src/imex/CppExporter.cpp
index 7b21087..8a77c0c 100644
--- a/fuzzylite/src/imex/CppExporter.cpp
+++ b/fuzzylite/src/imex/CppExporter.cpp
@@ -1,75 +1,73 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/CppExporter.h"
#include "fl/Headers.h"
-#include <algorithm>
-
namespace fl {
- CppExporter::CppExporter(bool prefixNamespace) : Exporter(),
- _prefixNamespace(prefixNamespace) {
- }
+ CppExporter::CppExporter(bool prefixNamespace, bool usingVariableNames) : Exporter(),
+ _usingNamespace(prefixNamespace), _usingVariableNames(usingVariableNames) { }
- CppExporter::~CppExporter() {
- }
+ CppExporter::~CppExporter() { }
std::string CppExporter::name() const {
return "CppExporter";
}
std::string CppExporter::fl(const std::string& clazz) const {
- return _prefixNamespace ? "fl::" + clazz : clazz;
+ return _usingNamespace ? "fl::" + clazz : clazz;
+ }
+
+ void CppExporter::setUsingNamespace(bool usingNamespace) {
+ this->_usingNamespace = usingNamespace;
}
- void CppExporter::setPrefixNamespace(bool prefixNamespace){
- this->_prefixNamespace = prefixNamespace;
+ bool CppExporter::isUsingNamespace() const {
+ return this->_usingNamespace;
}
- bool CppExporter::isPrefixNamespace() const{
- return this->_prefixNamespace;
+ void CppExporter::setUsingVariableNames(bool usingVariableNames) {
+ this->_usingVariableNames = usingVariableNames;
+ }
+
+ bool CppExporter::isUsingVariableNames() const {
+ return this->_usingVariableNames;
}
std::string CppExporter::toString(const Engine* engine) const {
std::ostringstream cpp;
- if (not _prefixNamespace) cpp << "using namespace fl;\n\n";
+ cpp << "//Code automatically generated with " << fuzzylite::library() << ".\n\n";
+ if (not isUsingNamespace()) cpp << "using namespace fl;\n\n";
cpp << fl("Engine* ") << "engine = new " << fl("Engine;\n");
cpp << "engine->setName(\"" << engine->getName() << "\");\n";
+ cpp << "engine->setDescription(\"" << engine->getDescription() << "\");\n";
cpp << "\n";
- for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i) {
cpp << toString(engine->getInputVariable(i), engine) << "\n";
}
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i) {
cpp << toString(engine->getOutputVariable(i), engine) << "\n";
}
- for (int i = 0; i < engine->numberOfRuleBlocks(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfRuleBlocks(); ++i) {
cpp << toString(engine->getRuleBlock(i), engine) << "\n";
}
@@ -77,21 +75,28 @@ namespace fl {
}
std::string CppExporter::toString(const InputVariable* inputVariable, const Engine* engine) const {
- std::ostringstream ss;
- std::string name = "inputVariable";
- if (engine->numberOfInputVariables() > 1) {
- int index = std::distance(engine->inputVariables().begin(),
- std::find(engine->inputVariables().begin(),
- engine->inputVariables().end(), inputVariable));
- name += Op::str<int>(index + 1);
+ std::string name;
+ if (isUsingVariableNames()) {
+ name = Op::validName(inputVariable->getName());
+ } else {
+ name = "inputVariable";
+ if (engine->numberOfInputVariables() > 1) {
+ std::size_t index = std::distance(engine->inputVariables().begin(),
+ std::find(engine->inputVariables().begin(),
+ engine->inputVariables().end(), inputVariable));
+ name += Op::str(index + 1);
+ }
}
+ std::ostringstream ss;
ss << fl("InputVariable* ") << name << " = new " << fl("InputVariable;\n");
- ss << name << "->setEnabled(" << (inputVariable->isEnabled() ? "true" : "false") << ");\n";
ss << name << "->setName(\"" << inputVariable->getName() << "\");\n";
+ ss << name << "->setDescription(\"" << inputVariable->getDescription() << "\");\n";
+ ss << name << "->setEnabled(" << (inputVariable->isEnabled() ? "true" : "false") << ");\n";
ss << name << "->setRange(" <<
toString(inputVariable->getMinimum()) << ", " <<
toString(inputVariable->getMaximum()) << ");\n";
- for (int t = 0; t < inputVariable->numberOfTerms(); ++t) {
+ ss << name << "->setLockValueInRange(" << (inputVariable->isLockValueInRange() ? "true" : "false") << ");\n";
+ for (std::size_t t = 0; t < inputVariable->numberOfTerms(); ++t) {
ss << name << "->addTerm(" << toString(inputVariable->getTerm(t)) << ");\n";
}
ss << "engine->addInputVariable(" << name << ");\n";
@@ -99,58 +104,73 @@ namespace fl {
}
std::string CppExporter::toString(const OutputVariable* outputVariable, const Engine* engine) const {
- std::ostringstream ss;
- std::string name = "outputVariable";
- if (engine->numberOfOutputVariables() > 1) {
- int index = std::distance(engine->outputVariables().begin(),
- std::find(engine->outputVariables().begin(),
- engine->outputVariables().end(), outputVariable));
- name += Op::str<int>(index + 1);
+ std::string name;
+ if (isUsingVariableNames()) {
+ name = Op::validName(outputVariable->getName());
+ } else {
+ name = "outputVariable";
+ if (engine->numberOfOutputVariables() > 1) {
+ std::size_t index = std::distance(engine->outputVariables().begin(),
+ std::find(engine->outputVariables().begin(),
+ engine->outputVariables().end(), outputVariable));
+ name += Op::str(index + 1);
+ }
}
+ std::ostringstream ss;
ss << fl("OutputVariable* ") << name << " = new " << fl("OutputVariable;\n");
- ss << name << "->setEnabled(" << (outputVariable->isEnabled() ? "true" : "false") << ");\n";
ss << name << "->setName(\"" << outputVariable->getName() << "\");\n";
+ ss << name << "->setDescription(\"" << outputVariable->getDescription() << "\");\n";
+ ss << name << "->setEnabled(" << (outputVariable->isEnabled() ? "true" : "false") << ");\n";
ss << name << "->setRange(" <<
toString(outputVariable->getMinimum()) << ", " <<
toString(outputVariable->getMaximum()) << ");\n";
- ss << name << "->fuzzyOutput()->setAccumulation(" <<
- toString(outputVariable->fuzzyOutput()->getAccumulation()) << ");\n";
+ ss << name << "->setLockValueInRange(" <<
+ (outputVariable->isLockValueInRange() ? "true" : "false") << ");\n";
+ ss << name << "->setAggregation(" <<
+ toString(outputVariable->fuzzyOutput()->getAggregation()) << ");\n";
ss << name << "->setDefuzzifier(" <<
toString(outputVariable->getDefuzzifier()) << ");\n";
ss << name << "->setDefaultValue(" <<
toString(outputVariable->getDefaultValue()) << ");\n";
- ss << name << "->setLockPreviousOutputValue(" <<
- (outputVariable->isLockedPreviousOutputValue() ? "true" : "false") << ");\n";
- ss << name << "->setLockOutputValueInRange(" <<
- (outputVariable->isLockedOutputValueInRange() ? "true" : "false") << ");\n";
- for (int t = 0; t < outputVariable->numberOfTerms(); ++t) {
+ ss << name << "->setLockPreviousValue(" <<
+ (outputVariable->isLockPreviousValue() ? "true" : "false") << ");\n";
+ for (std::size_t t = 0; t < outputVariable->numberOfTerms(); ++t) {
ss << name << "->addTerm(" << toString(outputVariable->getTerm(t)) << ");\n";
}
ss << "engine->addOutputVariable(" << name << ");\n";
return ss.str();
}
- //TODO: addRules using `new Rule` instead of `Rule::parse` in version 6.0
std::string CppExporter::toString(const RuleBlock* ruleBlock, const Engine* engine) const {
- std::ostringstream ss;
- std::string name = "ruleBlock";
- if (engine->numberOfRuleBlocks() > 1) {
- int index = std::distance(engine->ruleBlocks().begin(),
- std::find(engine->ruleBlocks().begin(),
- engine->ruleBlocks().end(), ruleBlock));
- name += Op::str<int>(index + 1);
+ std::string name;
+
+ if (isUsingVariableNames() and not ruleBlock->getName().empty()) {
+ name = Op::validName(ruleBlock->getName());
+ } else {
+ name = "ruleBlock";
+ if (engine->numberOfRuleBlocks() > 1) {
+ std::size_t index = std::distance(engine->ruleBlocks().begin(),
+ std::find(engine->ruleBlocks().begin(),
+ engine->ruleBlocks().end(), ruleBlock));
+ name += Op::str(index + 1);
+ }
}
+
+ std::ostringstream ss;
ss << fl("RuleBlock* ") << name << " = new " << fl("RuleBlock;\n");
- ss << name << "->setEnabled(" << (ruleBlock->isEnabled() ? "true" : "false") << ");\n";
ss << name << "->setName(\"" << ruleBlock->getName() << "\");\n";
+ ss << name << "->setDescription(\"" << ruleBlock->getDescription() << "\");\n";
+ ss << name << "->setEnabled(" << (ruleBlock->isEnabled() ? "true" : "false") << ");\n";
ss << name << "->setConjunction(" <<
toString(ruleBlock->getConjunction()) << ");\n";
ss << name << "->setDisjunction("
<< toString(ruleBlock->getDisjunction()) << ");\n";
+ ss << name << "->setImplication("
+ << toString(ruleBlock->getImplication()) << ");\n";
ss << name << "->setActivation("
<< toString(ruleBlock->getActivation()) << ");\n";
- for (int r = 0; r < ruleBlock->numberOfRules(); ++r) {
- ss << name << "->addRule(" << "fl::Rule::parse(\"" <<
+ for (std::size_t r = 0; r < ruleBlock->numberOfRules(); ++r) {
+ ss << name << "->addRule(" << fl("Rule") << "::parse(\"" <<
ruleBlock->getRule(r)->getText() << "\", engine));\n";
}
ss << "engine->addRuleBlock(" << name << ");\n";
@@ -158,12 +178,12 @@ namespace fl {
}
std::string CppExporter::toString(scalar value) const {
- if (fl::Op::isNaN(value))
+ if (Op::isNaN(value))
return "fl::nan";
- if (fl::Op::isInf(value)){
- return (value > 0 ? "fl::inf" : "-fl::inf");
+ if (Op::isInf(value)) {
+ return (value > 0 ? "fl::inf" : "-fl::inf");
}
- return fl::Op::str(value);
+ return Op::str(value);
}
std::string CppExporter::toString(const Term* term) const {
@@ -172,8 +192,8 @@ namespace fl {
if (const Discrete * discrete = dynamic_cast<const Discrete*> (term)) {
std::ostringstream ss;
ss << fl(term->className()) << "::create(\"" << term->getName() << "\", "
- << discrete->xy().size() * 2 << ", "
- << fl::Op::join(Discrete::toVector(discrete->xy()), ", ") << ")";
+ << (discrete->xy().size() * 2) << ", "
+ << Op::join(Discrete::toVector(discrete->xy()), ", ") << ")";
return ss.str();
}
@@ -187,7 +207,7 @@ namespace fl {
if (const Linear * linear = dynamic_cast<const Linear*> (term)) {
std::ostringstream ss;
ss << fl(term->className()) << "::create(\"" << term->getName() << "\", "
- << "engine, " << fl::Op::join(linear->coefficients(), ", ") << ")";
+ << "engine, " << Op::join(linear->coefficients(), ", ") << ")";
return ss.str();
}
@@ -217,7 +237,7 @@ namespace fl {
if (const IntegralDefuzzifier * integralDefuzzifier =
dynamic_cast<const IntegralDefuzzifier*> (defuzzifier)) {
return "new " + fl(integralDefuzzifier->className()) + "("
- + fl::Op::str(integralDefuzzifier->getResolution()) + ")";
+ + Op::str(integralDefuzzifier->getResolution()) + ")";
}
if (const WeightedDefuzzifier * weightedDefuzzifier =
dynamic_cast<const WeightedDefuzzifier*> (defuzzifier)) {
@@ -227,6 +247,19 @@ namespace fl {
return "new " + fl(defuzzifier->className());
}
+ std::string CppExporter::toString(const Activation* activation) const {
+ if (not activation) return "fl::null";
+ std::string parameters = Op::trim(activation->parameters());
+ if (parameters.empty()) return "new " + fl(activation->className());
+
+ std::vector<std::string> values = Op::split(parameters, " ");
+ for (std::size_t i = 0; i < values.size(); ++i) {
+ std::string parameter = values.at(i);
+ values.at(i) = (Op::isNumeric(parameter) ? parameter : ("\"" + parameter + "\""));
+ }
+ return "new " + fl(activation->className()) + "(" + Op::join(values, ", ") + ")";
+ }
+
CppExporter* CppExporter::clone() const {
return new CppExporter(*this);
}
diff --git a/fuzzylite/src/imex/Exporter.cpp b/fuzzylite/src/imex/Exporter.cpp
index 5b0fe1b..1aaf24e 100644
--- a/fuzzylite/src/imex/Exporter.cpp
+++ b/fuzzylite/src/imex/Exporter.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/Exporter.h"
@@ -29,18 +21,14 @@
namespace fl {
- Exporter::Exporter() {
-
- }
-
- Exporter::~Exporter() {
+ Exporter::Exporter() { }
- }
+ Exporter::~Exporter() { }
void Exporter::toFile(const std::string& path, const Engine* engine) const {
std::ofstream writer(path.c_str());
if (not writer.is_open()) {
- throw fl::Exception("[file error] file <" + path + "> could not be created", FL_AT);
+ throw Exception("[file error] file <" + path + "> could not be created", FL_AT);
}
writer << toString(engine) << std::endl;
writer.close();
diff --git a/fuzzylite/src/imex/FclExporter.cpp b/fuzzylite/src/imex/FclExporter.cpp
index cf8ffb0..98f1177 100644
--- a/fuzzylite/src/imex/FclExporter.cpp
+++ b/fuzzylite/src/imex/FclExporter.cpp
@@ -1,39 +1,28 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
+
#include "fl/imex/FclExporter.h"
#include "fl/Headers.h"
-#include <sstream>
-
namespace fl {
- FclExporter::FclExporter(const std::string& indent) : Exporter(), _indent(indent) {
- }
+ FclExporter::FclExporter(const std::string& indent) : Exporter(), _indent(indent) { }
- FclExporter::~FclExporter() {
- }
+ FclExporter::~FclExporter() { }
void FclExporter::setIndent(const std::string& indent) {
this->_indent = indent;
@@ -49,31 +38,32 @@ namespace fl {
std::string FclExporter::toString(const Engine* engine) const {
std::ostringstream fcl;
+ fcl << "//Code automatically generated with " << fuzzylite::library() << ".\n\n";
fcl << "FUNCTION_BLOCK " << engine->getName() << "\n\n";
fcl << "VAR_INPUT\n";
- for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i) {
fcl << _indent << Op::validName(engine->getInputVariable(i)->getName()) << ": REAL;\n";
}
fcl << "END_VAR\n\n";
fcl << "VAR_OUTPUT\n";
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i) {
fcl << _indent << Op::validName(engine->getOutputVariable(i)->getName()) << ": REAL;\n";
}
fcl << "END_VAR\n\n";
- for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i) {
InputVariable* inputVariable = engine->getInputVariable(i);
fcl << toString(inputVariable) << "\n";
}
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i) {
OutputVariable* outputVariable = engine->getOutputVariable(i);
fcl << toString(outputVariable) << "\n";
}
- for (int i = 0; i < engine->numberOfRuleBlocks(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfRuleBlocks(); ++i) {
RuleBlock* ruleblock = engine->getRuleBlock(i);
fcl << toString(ruleblock) << "\n";
}
@@ -85,15 +75,11 @@ namespace fl {
std::string FclExporter::toString(const InputVariable* inputVariable) const {
std::ostringstream fcl;
fcl << "FUZZIFY " << Op::validName(inputVariable->getName()) << "\n";
- if (not inputVariable->isEnabled()) {
- fcl << _indent << "ENABLED : " <<
- (inputVariable->isEnabled() ? "TRUE" : "FALSE") << ";\n";
- }
- fcl << _indent << "RANGE := (" << fl::Op::join(2, " .. ",
+ fcl << _indent << "RANGE := (" << Op::join(2, " .. ",
inputVariable->getMinimum(), inputVariable->getMaximum())
<< ");\n";
- for (int t = 0; t < inputVariable->numberOfTerms(); ++t) {
+ for (std::size_t t = 0; t < inputVariable->numberOfTerms(); ++t) {
Term* term = inputVariable->getTerm(t);
fcl << _indent << "TERM " << Op::validName(term->getName()) << " := " << toString(term)
<< ";\n";
@@ -105,15 +91,11 @@ namespace fl {
std::string FclExporter::toString(const OutputVariable* outputVariable) const {
std::ostringstream fcl;
fcl << "DEFUZZIFY " << Op::validName(outputVariable->getName()) << "\n";
- if (not outputVariable->isEnabled()) {
- fcl << _indent << "ENABLED : " <<
- (outputVariable->isEnabled() ? "TRUE" : "FALSE") << ";\n";
- }
- fcl << _indent << "RANGE := (" << fl::Op::join(2, " .. ",
+ fcl << _indent << "RANGE := (" << Op::join(2, " .. ",
outputVariable->getMinimum(), outputVariable->getMaximum())
<< ");\n";
- for (int t = 0; t < outputVariable->numberOfTerms(); ++t) {
+ for (std::size_t t = 0; t < outputVariable->numberOfTerms(); ++t) {
Term* term = outputVariable->getTerm(t);
fcl << _indent << "TERM " << Op::validName(term->getName()) << " := " << toString(term)
<< ";\n";
@@ -121,19 +103,15 @@ namespace fl {
if (outputVariable->getDefuzzifier()) {
fcl << _indent << "METHOD : " << toString(outputVariable->getDefuzzifier()) << ";\n";
}
- if (outputVariable->fuzzyOutput()->getAccumulation())
- fcl << _indent << "ACCU : " << toString(outputVariable->fuzzyOutput()->getAccumulation()) << ";\n";
+ if (outputVariable->fuzzyOutput()->getAggregation())
+ fcl << _indent << "ACCU : " << toString(outputVariable->fuzzyOutput()->getAggregation()) << ";\n";
- fcl << _indent << "DEFAULT := " << fl::Op::str(outputVariable->getDefaultValue());
- if (outputVariable->isLockedPreviousOutputValue()) {
+ fcl << _indent << "DEFAULT := " << Op::str(outputVariable->getDefaultValue());
+ if (outputVariable->isLockPreviousValue()) {
fcl << " | NC";
}
fcl << ";\n";
- if (outputVariable->isLockedOutputValueInRange()) {
- fcl << _indent << "LOCK : RANGE;\n";
- }
-
fcl << "END_DEFUZZIFY\n";
return fcl.str();
}
@@ -141,28 +119,24 @@ namespace fl {
std::string FclExporter::toString(const RuleBlock* ruleBlock) const {
std::ostringstream fcl;
fcl << "RULEBLOCK " << ruleBlock->getName() << "\n";
- if (not ruleBlock->isEnabled()) {
- fcl << _indent << "ENABLED : " <<
- (ruleBlock->isEnabled() ? "TRUE" : "FALSE") << ";\n";
- }
if (ruleBlock->getConjunction())
fcl << _indent << "AND : " << toString(ruleBlock->getConjunction()) << ";\n";
if (ruleBlock->getDisjunction())
fcl << _indent << "OR : " << toString(ruleBlock->getDisjunction()) << ";\n";
- if (ruleBlock->getActivation())
- fcl << _indent << "ACT : " << toString(ruleBlock->getActivation()) << ";\n";
+ if (ruleBlock->getImplication())
+ fcl << _indent << "ACT : " << toString(ruleBlock->getImplication()) << ";\n";
- for (int r = 0; r < ruleBlock->numberOfRules(); ++r) {
+ for (std::size_t r = 0; r < ruleBlock->numberOfRules(); ++r) {
fcl << _indent << "RULE " << (r + 1) << " : " <<
ruleBlock->getRule(r)->getText() << "\n";
}
fcl << "END_RULEBLOCK\n";
return fcl.str();
}
-
- std::string FclExporter::toString(const Norm* norm) const{
+
+ std::string FclExporter::toString(const Norm* norm) const {
if (not norm) return "NONE";
-
+
std::string name = norm->className();
//TNorms
if (name == Minimum().className()) return "MIN";
@@ -172,7 +146,7 @@ namespace fl {
if (name == EinsteinProduct().className()) return "EPROD";
if (name == HamacherProduct().className()) return "HPROD";
if (name == NilpotentMinimum().className()) return "NMIN";
-
+
//SNorms
if (name == Maximum().className()) return "MAX";
if (name == AlgebraicSum().className()) return "ASUM";
@@ -182,37 +156,8 @@ namespace fl {
if (name == EinsteinSum().className()) return "ESUM";
if (name == HamacherSum().className()) return "HSUM";
if (name == NilpotentMaximum().className()) return "NMAX";
-
- return norm->className();
- }
-
- //TODO: Delete in v6.0
- std::string FclExporter::toString(const TNorm* tnorm) const {
- if (not tnorm) return "NONE";
- std::string name = tnorm->className();
- if (name == Minimum().className()) return "MIN";
- if (name == AlgebraicProduct().className()) return "PROD";
- if (name == BoundedDifference().className()) return "BDIF";
- if (name == DrasticProduct().className()) return "DPROD";
- if (name == EinsteinProduct().className()) return "EPROD";
- if (name == HamacherProduct().className()) return "HPROD";
- if (name == NilpotentMinimum().className()) return "NMIN";
- return tnorm->className();
- }
- //TODO: Delete in v6.0
- std::string FclExporter::toString(const SNorm* snorm) const {
- if (not snorm) return "NONE";
- std::string name = snorm->className();
- if (name == Maximum().className()) return "MAX";
- if (name == AlgebraicSum().className()) return "ASUM";
- if (name == NormalizedSum().className()) return "NSUM";
- if (name == BoundedSum().className()) return "BSUM";
- if (name == DrasticSum().className()) return "DSUM";
- if (name == EinsteinSum().className()) return "ESUM";
- if (name == HamacherSum().className()) return "HSUM";
- if (name == NilpotentMaximum().className()) return "NMAX";
- return snorm->className();
+ return norm->className();
}
std::string FclExporter::toString(const Defuzzifier* defuzzifier) const {
@@ -232,15 +177,15 @@ namespace fl {
if (const Discrete * discrete = dynamic_cast<const Discrete*> (term)) {
std::ostringstream ss;
for (std::size_t i = 0; i < discrete->xy().size(); ++i) {
- ss << "(" << fl::Op::str(discrete->xy(i).first) << ", "
- << fl::Op::str(discrete->xy(i).second) << ")";
+ ss << "(" << Op::str(discrete->xy(i).first) << ", "
+ << Op::str(discrete->xy(i).second) << ")";
if (i + 1 < discrete->xy().size()) ss << " ";
}
return ss.str();
}
if (const Constant * constant = dynamic_cast<const Constant*> (term)) {
- return fl::Op::str(constant->getValue());
+ return Op::str(constant->getValue());
}
std::ostringstream ss;
@@ -252,5 +197,4 @@ namespace fl {
return new FclExporter(*this);
}
-
}
diff --git a/fuzzylite/src/imex/FclImporter.cpp b/fuzzylite/src/imex/FclImporter.cpp
index a56a9e1..06879cd 100644
--- a/fuzzylite/src/imex/FclImporter.cpp
+++ b/fuzzylite/src/imex/FclImporter.cpp
@@ -1,41 +1,28 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/FclImporter.h"
#include "fl/Headers.h"
-#include <iostream>
-#include <sstream>
-
namespace fl {
- FclImporter::FclImporter() : Importer() {
- }
+ FclImporter::FclImporter() : Importer() { }
- FclImporter::~FclImporter() {
- }
+ FclImporter::~FclImporter() { }
std::string FclImporter::name() const {
return "FclImporter";
@@ -57,24 +44,16 @@ namespace fl {
std::istringstream fclReader(fcl);
std::string line;
- int lineNumber = 0;
+ std::size_t lineNumber = 0;
while (std::getline(fclReader, line)) {
++lineNumber;
- std::vector<std::string> comments;
- comments = Op::split(line, "//");
- if (comments.size() > 1) {
- line = comments.front();
- }
- comments = Op::split(line, "#");
- if (comments.size() > 1) {
- line = comments.front();
- }
- line = Op::trim(line);
- if (line.empty() or line.at(0) == '%' or line.at(0) == '#'
- or (line.substr(0, 2) == "//")) {
+ line = Op::split(line, "//", false).front();
+ line = Op::split(line, "#", false).front();
+ line = Op::trim(Op::findReplace(line, ";", ""));
+ if (line.empty() or line.at(0) == '%') {
continue;
}
- line = fl::Op::findReplace(line, ";", "");
+
std::istringstream tokenizer(line);
std::string firstToken;
tokenizer >> firstToken;
@@ -102,7 +81,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] unknown block definition <" << firstToken
<< "> " << " in line " << lineNumber << ": " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
currentTag = tagFinder->first;
closingTag = tagFinder->second;
@@ -122,7 +101,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected <" << closingTag << "> before <"
<< firstToken << "> in line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
} else {
block << line << "\n";
}
@@ -138,7 +117,7 @@ namespace fl {
} else {
ex << "expected <" << closingTag << ">, but not found";
}
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
return engine.release();
}
@@ -155,7 +134,7 @@ namespace fl {
} else {
std::ostringstream ex;
ex << "[syntax error] unexpected tag <" << tag << "> for block:\n" << block;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
}
@@ -169,9 +148,9 @@ namespace fl {
if (token.size() != 2) {
std::ostringstream ex;
ex << "[syntax error] expected property of type (key : value) in line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
- std::string name = fl::Op::validName(token.at(0));
+ std::string name = Op::validName(token.at(0));
if (tag == "VAR_INPUT")
engine->addInputVariable(new InputVariable(name));
else if (tag == "VAR_OUTPUT")
@@ -179,7 +158,7 @@ namespace fl {
else {
std::ostringstream ex;
ex << "[syntax error] unexpected tag <" << tag << "> in line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
}
}
@@ -192,17 +171,17 @@ namespace fl {
std::string name;
std::size_t index = line.find_first_of(' ');
if (index != std::string::npos) {
- name = fl::Op::validName(line.substr(index + 1));
+ name = Op::validName(line.substr(index + 1));
} else {
std::ostringstream ex;
ex << "[syntax error] expected name of input variable in line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if (not engine->hasInputVariable(name)) {
std::ostringstream ex;
ex << "[syntax error] engine does not contain "
"input variable <" << name << "> from line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
InputVariable* inputVariable = engine->getInputVariable(name);
@@ -219,9 +198,9 @@ namespace fl {
inputVariable->setEnabled(parseEnabled(line));
} else if (firstToken == "TERM") {
inputVariable->addTerm(parseTerm(line, engine));
- } else throw fl::Exception("[syntax error] unexpected token "
+ } else throw Exception("[syntax error] unexpected token "
"<" + firstToken + ">" + line, FL_AT);
- } catch (fl::Exception& ex) {
+ } catch (Exception& ex) {
ex.append("At line: <" + line + ">");
throw;
}
@@ -237,23 +216,23 @@ namespace fl {
std::string name;
std::size_t index = line.find_first_of(' ');
if (index != std::string::npos) {
- name = fl::Op::validName(line.substr(index + 1));
+ name = Op::validName(line.substr(index + 1));
} else {
std::ostringstream ex;
ex << "[syntax error] expected an output variable name in line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if (not engine->hasOutputVariable(name)) {
std::ostringstream ex;
ex << "[syntax error] output variable <" << name
<< "> not registered in engine. "
<< "Line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
OutputVariable* outputVariable = engine->getOutputVariable(name);
while (std::getline(blockReader, line)) {
- line = fl::Op::trim(line);
+ line = Op::trim(line);
std::istringstream tokenizer(line);
std::string firstToken;
tokenizer >> firstToken;
@@ -262,27 +241,27 @@ namespace fl {
} else if (firstToken == "METHOD") {
outputVariable->setDefuzzifier(parseDefuzzifier(line));
} else if (firstToken == "ACCU") {
- outputVariable->fuzzyOutput()->setAccumulation(parseSNorm(line));
+ outputVariable->fuzzyOutput()->setAggregation(parseSNorm(line));
} else if (firstToken == "DEFAULT") {
std::pair<scalar, bool> defaultAndLock = parseDefaultValue(line);
outputVariable->setDefaultValue(defaultAndLock.first);
- outputVariable->setLockPreviousOutputValue(defaultAndLock.second or
- outputVariable->isLockedPreviousOutputValue());
+ outputVariable->setLockPreviousValue(defaultAndLock.second or
+ outputVariable->isLockPreviousValue());
} else if (firstToken == "RANGE") {
std::pair<scalar, scalar> minmax = parseRange(line);
outputVariable->setMinimum(minmax.first);
outputVariable->setMaximum(minmax.second);
} else if (firstToken == "LOCK") {
std::pair<bool, bool> output_range = parseLocks(line);
- outputVariable->setLockPreviousOutputValue(output_range.first);
- outputVariable->setLockOutputValueInRange(output_range.second);
+ outputVariable->setLockPreviousValue(output_range.first);
+ outputVariable->setLockValueInRange(output_range.second);
} else if (firstToken == "ENABLED") {
outputVariable->setEnabled(parseEnabled(line));
} else {
std::ostringstream ex;
ex << "[syntax error] unexpected token <" << firstToken <<
"> in line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
}
@@ -295,8 +274,9 @@ namespace fl {
std::string name;
std::getline(blockReader, line);
std::size_t index = line.find_last_of(' ');
- if (index != std::string::npos) name = line.substr(index);
+ if (index != std::string::npos) name = line.substr(index + 1);
RuleBlock * ruleblock = new RuleBlock(name);
+ ruleblock->setActivation(new General);
engine->addRuleBlock(ruleblock);
while (std::getline(blockReader, line)) {
@@ -306,14 +286,14 @@ namespace fl {
} else if (firstToken == "OR") {
ruleblock->setDisjunction(parseSNorm(line));
} else if (firstToken == "ACT") {
- ruleblock->setActivation(parseTNorm(line));
+ ruleblock->setImplication(parseTNorm(line));
} else if (firstToken == "ENABLED") {
ruleblock->setEnabled(parseEnabled(line));
} else if (firstToken == "RULE") {
std::size_t ruleStart = line.find_first_of(':');
if (ruleStart == std::string::npos) ruleStart = 4; // "RULE".size()
std::string ruleText = line.substr(ruleStart + 1);
- ruleText = fl::Op::trim(ruleText);
+ ruleText = Op::trim(ruleText);
Rule* rule = new Rule(ruleText);
try {
rule->load(engine);
@@ -325,7 +305,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] keyword <" << firstToken
<< "> not recognized in line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
}
}
@@ -336,7 +316,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected property of type (key : value) in line: "
<< line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
std::string name = Op::trim(token.at(1));
std::string className = name;
@@ -358,7 +338,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected property of type (key : value) in line: "
<< line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
std::string name = Op::trim(token.at(1));
std::string className = name;
@@ -412,7 +392,7 @@ namespace fl {
continue;
}
if (state == S_TERMCLASS) {
- if (fl::Op::isNumeric(token)) {
+ if (Op::isNumeric(token)) {
termClass = Constant().className();
parameters.push_back(token);
} else if (token == "(") {
@@ -429,16 +409,16 @@ namespace fl {
continue;
}
if (token == ";") break;
- parameters.push_back(fl::Op::trim(token));
+ parameters.push_back(Op::trim(token));
}
}
if (state <= S_TERMCLASS)
- throw fl::Exception("[syntax error] malformed term in line: " + line, FL_AT);
+ throw Exception("[syntax error] malformed term in line: " + line, FL_AT);
FL_unique_ptr<Term> term;
term.reset(FactoryManager::instance()->term()->constructObject(termClass));
- Term::updateReference(term.get(), engine);
- term->setName(fl::Op::validName(name));
+ term->updateReference(engine);
+ term->setName(Op::validName(name));
std::string separator;
if (not dynamic_cast<Function*> (term.get())) {
separator = " ";
@@ -453,10 +433,10 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected property of type (key : value) in "
<< "line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
- std::string name = fl::Op::trim(token.at(1));
+ std::string name = Op::trim(token.at(1));
std::string className = name;
if (name == "NONE") className = "";
else if (name == "COG") className = Centroid().className();
@@ -476,7 +456,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected property of type (key := value) in line: "
<< line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
std::vector<std::string> values = Op::split(token.at(1), "|");
@@ -485,24 +465,24 @@ namespace fl {
std::string nc;
if (values.size() == 2) nc = values.back();
- defaultValue = fl::Op::trim(defaultValue);
- nc = fl::Op::trim(nc);
+ defaultValue = Op::trim(defaultValue);
+ nc = Op::trim(nc);
scalar value;
try {
- value = fl::Op::toScalar(defaultValue);
+ value = Op::toScalar(defaultValue);
} catch (...) {
std::ostringstream ex;
ex << "[syntax error] expected numeric value, "
<< "but found <" << defaultValue << "> in line: "
<< line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
bool lockPreviousOutput = (nc == "NC");
if (not (lockPreviousOutput or nc.empty())) {
- throw fl::Exception("[syntax error] expected keyword <NC>, "
+ throw Exception("[syntax error] expected keyword <NC>, "
"but found <" + nc + "> in line: " + line, FL_AT);
}
@@ -515,7 +495,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected property of type (key := value) in line: "
<< line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
std::string rangeToken = token.at(1);
@@ -532,7 +512,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected property of type 'start .. end', "
<< "but found <" << range.str() << "> in line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
scalar minimum, maximum;
int index;
@@ -540,11 +520,11 @@ namespace fl {
minimum = Op::toScalar(token.at(index = 0));
maximum = Op::toScalar(token.at(index = 1));
} catch (std::exception& ex) {
- (void) ex;
+ FL_IUNUSED(ex);
std::ostringstream ss;
ss << "[syntax error] expected numeric value, but found <" << token.at(index) << "> in "
<< "line: " << line;
- throw fl::Exception(ss.str(), FL_AT);
+ throw Exception(ss.str(), FL_AT);
}
return std::pair<scalar, scalar>(minimum, maximum);
}
@@ -552,32 +532,32 @@ namespace fl {
std::pair<bool, bool> FclImporter::parseLocks(const std::string& line) const {
std::size_t index = line.find_first_of(":");
if (index == std::string::npos) {
- throw fl::Exception("[syntax error] expected property of type "
+ throw Exception("[syntax error] expected property of type "
"'key : value' in line: " + line, FL_AT);
}
bool output, range;
std::string value = line.substr(index + 1);
- std::vector<std::string> flags = fl::Op::split(value, "|");
+ std::vector<std::string> flags = Op::split(value, "|");
if (flags.size() == 1) {
- std::string flag = fl::Op::trim(flags.front());
+ std::string flag = Op::trim(flags.front());
output = (flag == "PREVIOUS");
range = (flag == "RANGE");
if (not (output or range)) {
- throw fl::Exception("[syntax error] expected locking flags "
+ throw Exception("[syntax error] expected locking flags "
"<PREVIOUS|RANGE>, but found <" + flag + "> in line: " + line, FL_AT);
}
} else if (flags.size() == 2) {
- std::string flagA = fl::Op::trim(flags.front());
- std::string flagB = fl::Op::trim(flags.back());
+ std::string flagA = Op::trim(flags.front());
+ std::string flagB = Op::trim(flags.back());
output = (flagA == "PREVIOUS" or flagB == "PREVIOUS");
range = (flagA == "RANGE" or flagB == "RANGE");
if (not (output and range)) {
- throw fl::Exception("[syntax error] expected locking flags "
+ throw Exception("[syntax error] expected locking flags "
"<PREVIOUS|RANGE>, but found "
"<" + flags.front() + "|" + flags.back() + "> in line: " + line, FL_AT);
}
} else {
- throw fl::Exception("[syntax error] expected locking flags "
+ throw Exception("[syntax error] expected locking flags "
"<PREVIOUS|RANGE>, but found "
"<" + value + "> in line: " + line, FL_AT);
}
@@ -590,13 +570,13 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected property of type (key : value) in "
<< "line: " << line;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
- std::string boolean = fl::Op::trim(tokens.at(1));
+ std::string boolean = Op::trim(tokens.at(1));
if (boolean == "TRUE") return true;
if (boolean == "FALSE") return false;
- throw fl::Exception("[syntax error] expected boolean <TRUE|FALSE>, but found <" + line + ">", FL_AT);
+ throw Exception("[syntax error] expected boolean <TRUE|FALSE>, but found <" + line + ">", FL_AT);
}
FclImporter* FclImporter::clone() const {
diff --git a/fuzzylite/src/imex/FisExporter.cpp b/fuzzylite/src/imex/FisExporter.cpp
index 0934b33..2daac9a 100644
--- a/fuzzylite/src/imex/FisExporter.cpp
+++ b/fuzzylite/src/imex/FisExporter.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/FisExporter.h"
@@ -30,11 +22,9 @@
namespace fl {
- FisExporter::FisExporter() : Exporter() {
- }
+ FisExporter::FisExporter() : Exporter() { }
- FisExporter::~FisExporter() {
- }
+ FisExporter::~FisExporter() { }
std::string FisExporter::name() const {
return "FisExporter";
@@ -52,9 +42,10 @@ namespace fl {
return fis.str();
}
- //TODO: deal with multiple ruleblocks, merge them into one.
+
std::string FisExporter::exportSystem(const Engine* engine) const {
std::ostringstream fis;
+ fis << "#Code automatically generated with " << fuzzylite::library() << ".\n\n";
fis << "[System]\n";
fis << "Name='" << engine->getName() << "'\n";
std::string type;
@@ -66,57 +57,54 @@ namespace fl {
type = "tsukamoto";
} else if (engine->type() == Engine::InverseTsukamoto) {
type = "inverse tsukamoto";
- }else if (engine->type() == Engine::Hybrid){
+ } else if (engine->type() == Engine::Hybrid) {
type = "hybrid";
} else {
type = "unknown";
}
fis << "Type='" << type << "'\n";
- // fis << "Version=" << FL_VERSION << "\n";
+ fis << "Version=" << fuzzylite::version() << "\n";
fis << "NumInputs=" << engine->numberOfInputVariables() << "\n";
fis << "NumOutputs=" << engine->numberOfOutputVariables() << "\n";
-
- int numberOfRules = 0;
+
+ std::size_t numberOfRules = 0;
const TNorm* conjunction = fl::null;
const SNorm* disjunction = fl::null;
- const TNorm* activation = fl::null;
- for (int i = 0; i < engine->numberOfRuleBlocks(); ++i) {
+ const TNorm* implication = fl::null;
+ for (std::size_t i = 0; i < engine->numberOfRuleBlocks(); ++i) {
RuleBlock* rb = engine->getRuleBlock(i);
numberOfRules += rb->numberOfRules();
if (not conjunction) conjunction = rb->getConjunction();
if (not disjunction) disjunction = rb->getDisjunction();
- if (not activation) activation = rb->getActivation();
+ if (not implication) implication = rb->getImplication();
}
fis << "NumRules=" << numberOfRules << "\n";
- fis << "AndMethod='" << toString(conjunction) << "'\n";
- fis << "OrMethod='" << toString(disjunction) << "'\n";
- fis << "ImpMethod='" << toString(activation) << "'\n";
+ fis << "AndMethod='" << (conjunction ? toString(conjunction) : "min") << "'\n";
+ fis << "OrMethod='" << (disjunction ? toString(disjunction) : "max") << "'\n";
+ fis << "ImpMethod='" << (implication ? toString(implication) : "min") << "'\n";
- const SNorm* accumulation = fl::null;
+ const SNorm* aggregation = fl::null;
Defuzzifier* defuzzifier = fl::null;
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i) {
OutputVariable* outputVariable = engine->getOutputVariable(i);
- if (not accumulation) accumulation = outputVariable->fuzzyOutput()->getAccumulation();
+ if (not aggregation) aggregation = outputVariable->fuzzyOutput()->getAggregation();
if (not defuzzifier) defuzzifier = outputVariable->getDefuzzifier();
}
- fis << "AggMethod='" << toString(accumulation) << "'\n";
+ fis << "AggMethod='" << (aggregation ? toString(aggregation) : "max") << "'\n";
fis << "DefuzzMethod='" << toString(defuzzifier) << "'\n";
return fis.str();
}
std::string FisExporter::exportInputs(const Engine* engine) const {
std::ostringstream fis;
- for (int ixVar = 0; ixVar < engine->numberOfInputVariables(); ++ixVar) {
+ for (std::size_t ixVar = 0; ixVar < engine->numberOfInputVariables(); ++ixVar) {
InputVariable* var = engine->getInputVariable(ixVar);
fis << "[Input" << (ixVar + 1) << "]\n";
- if (not var->isEnabled()) {
- fis << "Enabled=" << var->isEnabled() << "\n";
- }
fis << "Name='" << Op::validName(var->getName()) << "'\n";
- fis << "Range=[" << fl::Op::join(2, " ", var->getMinimum(), var->getMaximum()) << "]\n";
+ fis << "Range=[" << Op::join(2, " ", var->getMinimum(), var->getMaximum()) << "]\n";
fis << "NumMFs=" << var->numberOfTerms() << "\n";
- for (int ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) {
+ for (std::size_t ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) {
fis << "MF" << (ixTerm + 1) << "='" << Op::validName(var->getTerm(ixTerm)->getName()) << "':"
<< toString(var->getTerm(ixTerm)) << "\n";
}
@@ -127,25 +115,13 @@ namespace fl {
std::string FisExporter::exportOutputs(const Engine* engine) const {
std::ostringstream fis;
- for (int ixVar = 0; ixVar < engine->numberOfOutputVariables(); ++ixVar) {
+ for (std::size_t ixVar = 0; ixVar < engine->numberOfOutputVariables(); ++ixVar) {
OutputVariable* var = engine->getOutputVariable(ixVar);
fis << "[Output" << (ixVar + 1) << "]\n";
- if (not var->isEnabled()) {
- fis << "Enabled=" << var->isEnabled() << "\n";
- }
fis << "Name='" << Op::validName(var->getName()) << "'\n";
- fis << "Range=[" << fl::Op::join(2, " ", var->getMinimum(), var->getMaximum()) << "]\n";
- if (not fl::Op::isNaN(var->getDefaultValue())) {
- fis << "Default=" << fl::Op::str(var->getDefaultValue()) << "\n";
- }
- if (var->isLockedPreviousOutputValue()) {
- fis << "LockPrevious=" << var->isLockedPreviousOutputValue() << "\n";
- }
- if (var->isLockedOutputValueInRange()) {
- fis << "LockRange=" << var->isLockedOutputValueInRange() << "\n";
- }
+ fis << "Range=[" << Op::join(2, " ", var->getMinimum(), var->getMaximum()) << "]\n";
fis << "NumMFs=" << var->numberOfTerms() << "\n";
- for (int ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) {
+ for (std::size_t ixTerm = 0; ixTerm < var->numberOfTerms(); ++ixTerm) {
fis << "MF" << (ixTerm + 1) << "='" << Op::validName(var->getTerm(ixTerm)->getName()) << "':"
<< toString(var->getTerm(ixTerm)) << "\n";
}
@@ -157,10 +133,10 @@ namespace fl {
std::string FisExporter::exportRules(const Engine* engine) const {
std::ostringstream fis;
fis << "[Rules]\n";
- for (int ixRuleBlock = 0; ixRuleBlock < engine->numberOfRuleBlocks(); ++ixRuleBlock) {
+ for (std::size_t ixRuleBlock = 0; ixRuleBlock < engine->numberOfRuleBlocks(); ++ixRuleBlock) {
RuleBlock* rb = engine->getRuleBlock(ixRuleBlock);
if (engine->numberOfRuleBlocks() > 1) fis << "# RuleBlock " << rb->getName() << "\n";
- for (int ixRule = 0; ixRule < rb->numberOfRules(); ++ixRule) {
+ for (std::size_t ixRule = 0; ixRule < rb->numberOfRules(); ++ixRule) {
Rule* rule = rb->getRule(ixRule);
if (rule->isLoaded()) {
fis << exportRule(rule, engine) << "\n";
@@ -198,15 +174,15 @@ namespace fl {
}
}
if (not equalOperators) {
- throw fl::Exception("[exporter error] "
+ throw Exception("[exporter error] "
"fis files do not support rules with different connectors "
"(i.e. ['and', 'or']). All connectors within a rule must be the same", FL_AT);
}
std::ostringstream fis;
std::vector<Variable*> inputVariables, outputVariables;
- for (int i = 0; i < engine->numberOfInputVariables(); ++i)
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i)
inputVariables.push_back(engine->getInputVariable(i));
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i)
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i)
outputVariables.push_back(engine->getOutputVariable(i));
fis << translate(propositions, inputVariables) << ", ";
@@ -226,14 +202,14 @@ namespace fl {
std::ostringstream ss;
for (std::size_t ixVariable = 0; ixVariable < variables.size(); ++ixVariable) {
Variable* variable = variables.at(ixVariable);
- int termIndexPlusOne = 0;
+ std::size_t termIndexPlusOne = 0;
scalar plusHedge = 0;
int negated = 1;
for (std::size_t ixProposition = 0; ixProposition < propositions.size(); ++ixProposition) {
Proposition* proposition = propositions.at(ixProposition);
if (proposition->variable != variable) continue;
- for (int termIndex = 0; termIndex < variable->numberOfTerms(); ++termIndex) {
+ for (std::size_t termIndex = 0; termIndex < variable->numberOfTerms(); ++termIndex) {
if (variable->getTerm(termIndex) == proposition->term) {
termIndexPlusOne = termIndex + 1;
break;
@@ -259,8 +235,8 @@ namespace fl {
break;
}
if (negated < 0) ss << "-";
- if (not fl::Op::isNaN(plusHedge)) {
- ss << fl::Op::str(termIndexPlusOne + plusHedge);
+ if (not Op::isNaN(plusHedge)) {
+ ss << Op::str(termIndexPlusOne + plusHedge);
} else {
ss << termIndexPlusOne << ".?"; // Unreconized hedge combination
}
@@ -268,29 +244,6 @@ namespace fl {
}
return ss.str();
}
-
- std::string FisExporter::toString(const Norm * norm) const {
- if (not norm) return "";
- //TNorm
- if (norm->className() == Minimum().className()) return "min";
- if (norm->className() == AlgebraicProduct().className()) return "prod";
- if (norm->className() == BoundedDifference().className()) return "bounded_difference";
- if (norm->className() == DrasticProduct().className()) return "drastic_product";
- if (norm->className() == EinsteinProduct().className()) return "einstein_product";
- if (norm->className() == HamacherProduct().className()) return "hamacher_product";
- if (norm->className() == NilpotentMinimum().className()) return "nilpotent_minimum";
- //SNorm
- if (norm->className() == Maximum().className()) return "max";
- if (norm->className() == AlgebraicSum().className()) return "sum";
- if (norm->className() == BoundedSum().className()) return "bounded_sum";
- if (norm->className() == NormalizedSum().className()) return "normalized_sum";
- if (norm->className() == DrasticSum().className()) return "drastic_sum";
- if (norm->className() == EinsteinSum().className()) return "einstein_sum";
- if (norm->className() == HamacherSum().className()) return "hamacher_sum";
- if (norm->className() == NilpotentMaximum().className()) return "nilpotent_maximum";
-
- return norm->className();
- }
std::string FisExporter::toString(const TNorm * tnorm) const {
if (not tnorm) return "";
@@ -304,16 +257,17 @@ namespace fl {
return tnorm->className();
}
- std::string FisExporter::toString(const SNorm * snorm) const {
+ std::string FisExporter::toString(const SNorm* snorm) const {
if (not snorm) return "";
if (snorm->className() == Maximum().className()) return "max";
- if (snorm->className() == AlgebraicSum().className()) return "sum";
+ if (snorm->className() == AlgebraicSum().className()) return "probor";
if (snorm->className() == BoundedSum().className()) return "bounded_sum";
if (snorm->className() == NormalizedSum().className()) return "normalized_sum";
if (snorm->className() == DrasticSum().className()) return "drastic_sum";
if (snorm->className() == EinsteinSum().className()) return "einstein_sum";
if (snorm->className() == HamacherSum().className()) return "hamacher_sum";
if (snorm->className() == NilpotentMaximum().className()) return "nilpotent_maximum";
+ if (snorm->className() == UnboundedSum().className()) return "sum";
return snorm->className();
}
@@ -332,30 +286,36 @@ namespace fl {
std::string FisExporter::toString(const Term * term) const {
std::ostringstream ss;
if (const Bell * x = dynamic_cast<const Bell*> (term)) {
- ss << "'gbellmf',[" << fl::Op::join(3, " ",
+ ss << "'gbellmf',[" << Op::join(3, " ",
x->getWidth(), x->getSlope(), x->getCenter()) << "]";
return ss.str();
}
+ if (const Binary * x = dynamic_cast<const Binary*> (term)) {
+ ss << "'binarymf,[" << Op::join(2, " ",
+ x->getStart(), x->getDirection()) << "]";
+ return ss.str();
+ }
+
if (const Concave * x = dynamic_cast<const Concave*> (term)) {
- ss << "'concavemf',[" << fl::Op::join(2, " ",
+ ss << "'concavemf',[" << Op::join(2, " ",
x->getInflection(), x->getEnd()) << "]";
return ss.str();
}
if (const Constant * x = dynamic_cast<const Constant*> (term)) {
- ss << "'constant',[" << fl::Op::str(x->getValue()) << "]";
+ ss << "'constant',[" << Op::str(x->getValue()) << "]";
return ss.str();
}
if (const Cosine * x = dynamic_cast<const Cosine*> (term)) {
- ss << "'cosinemf',[" << fl::Op::join(2, " ",
+ ss << "'cosinemf',[" << Op::join(2, " ",
x->getCenter(), x->getWidth()) << "]";
return ss.str();
}
if (const Discrete * x = dynamic_cast<const Discrete*> (term)) {
- ss << "'discretemf',[" << fl::Op::join(Discrete::toVector(x->xy()), " ") << "]";
+ ss << "'discretemf',[" << Op::join(Discrete::toVector(x->xy()), " ") << "]";
return ss.str();
}
@@ -365,95 +325,95 @@ namespace fl {
}
if (const Gaussian * x = dynamic_cast<const Gaussian*> (term)) {
- ss << "'gaussmf',[" << fl::Op::join(2, " ",
+ ss << "'gaussmf',[" << Op::join(2, " ",
x->getStandardDeviation(), x->getMean()) << "]";
return ss.str();
}
if (const GaussianProduct * x = dynamic_cast<const GaussianProduct*> (term)) {
- ss << "'gauss2mf',[" << fl::Op::join(4, " ",
+ ss << "'gauss2mf',[" << Op::join(4, " ",
x->getStandardDeviationA(), x->getMeanA(),
x->getStandardDeviationB(), x->getMeanB()) << "]";
return ss.str();
}
if (const Linear * x = dynamic_cast<const Linear*> (term)) {
- ss << "'linear',[" << fl::Op::join<scalar>(x->coefficients(), " ") << "]";
+ ss << "'linear',[" << Op::join<scalar>(x->coefficients(), " ") << "]";
return ss.str();
}
if (const PiShape * x = dynamic_cast<const PiShape*> (term)) {
- ss << "'pimf',[" << fl::Op::join(4, " ",
+ ss << "'pimf',[" << Op::join(4, " ",
x->getBottomLeft(), x->getTopLeft(),
x->getTopRight(), x->getBottomRight()) << "]";
return ss.str();
}
if (const Ramp * x = dynamic_cast<const Ramp*> (term)) {
- ss << "'rampmf',[" << fl::Op::join(2, " ",
+ ss << "'rampmf',[" << Op::join(2, " ",
x->getStart(), x->getEnd()) << "]";
return ss.str();
}
if (const Rectangle * x = dynamic_cast<const Rectangle*> (term)) {
- ss << "'rectmf',[" << fl::Op::join(2, " ",
+ ss << "'rectmf',[" << Op::join(2, " ",
x->getStart(), x->getEnd()) << "]";
return ss.str();
}
if (const SigmoidDifference * x = dynamic_cast<const SigmoidDifference*> (term)) {
- ss << "'dsigmf',[" << fl::Op::join(4, " ",
+ ss << "'dsigmf',[" << Op::join(4, " ",
x->getRising(), x->getLeft(),
x->getFalling(), x->getRight()) << "]";
return ss.str();
}
if (const Sigmoid * x = dynamic_cast<const Sigmoid*> (term)) {
- ss << "'sigmf',[" << fl::Op::join(2, " ",
+ ss << "'sigmf',[" << Op::join(2, " ",
x->getSlope(), x->getInflection()) << "]";
return ss.str();
}
if (const SigmoidProduct * x = dynamic_cast<const SigmoidProduct*> (term)) {
- ss << "'psigmf',[" << fl::Op::join(4, " ",
+ ss << "'psigmf',[" << Op::join(4, " ",
x->getRising(), x->getLeft(),
x->getFalling(), x->getRight()) << "]";
return ss.str();
}
if (const SShape * x = dynamic_cast<const SShape*> (term)) {
- ss << "'smf',[" << fl::Op::join(2, " ",
+ ss << "'smf',[" << Op::join(2, " ",
x->getStart(), x->getEnd()) << "]";
return ss.str();
}
if (const Spike * x = dynamic_cast<const Spike*> (term)) {
- ss << "'spikemf',[" << fl::Op::join(2, " ",
+ ss << "'spikemf',[" << Op::join(2, " ",
x->getCenter(), x->getWidth()) << "]";
return ss.str();
}
if (const Trapezoid * x = dynamic_cast<const Trapezoid*> (term)) {
- ss << "'trapmf',[" << fl::Op::join(4, " ",
+ ss << "'trapmf',[" << Op::join(4, " ",
x->getVertexA(), x->getVertexB(), x->getVertexC(), x->getVertexD()) << "]";
return ss.str();
}
if (const Triangle * x = dynamic_cast<const Triangle*> (term)) {
- ss << "'trimf',[" << fl::Op::join(3, " ",
+ ss << "'trimf',[" << Op::join(3, " ",
x->getVertexA(), x->getVertexB(), x->getVertexC()) << "]";
return ss.str();
}
if (const ZShape * x = dynamic_cast<const ZShape*> (term)) {
- ss << "'zmf',[" << fl::Op::join(2, " ",
+ ss << "'zmf',[" << Op::join(2, " ",
x->getStart(), x->getEnd()) << "]";
return ss.str();
}
- ss << "[exporter error] term of class <" << term->className() << "> not supported";
- throw fl::Exception(ss.str(), FL_AT);
+ ss << "[exporter error] term of class <" << (term ? term->className() : "null") << "> not supported";
+ throw Exception(ss.str(), FL_AT);
}
FisExporter* FisExporter::clone() const {
diff --git a/fuzzylite/src/imex/FisImporter.cpp b/fuzzylite/src/imex/FisImporter.cpp
index 741719c..f846469 100644
--- a/fuzzylite/src/imex/FisImporter.cpp
+++ b/fuzzylite/src/imex/FisImporter.cpp
@@ -1,42 +1,28 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/FisImporter.h"
#include "fl/Headers.h"
-#include <sstream>
-#include <iostream>
-#include <cctype>
-
namespace fl {
- FisImporter::FisImporter() : Importer() {
- }
+ FisImporter::FisImporter() : Importer() { }
- FisImporter::~FisImporter() {
- }
+ FisImporter::~FisImporter() { }
std::string FisImporter::name() const {
return "FisImporter";
@@ -47,27 +33,20 @@ namespace fl {
std::istringstream fisReader(fis);
std::string line;
- int lineNumber = 0;
+ std::size_t lineNumber = 0;
std::vector<std::string> sections;
while (std::getline(fisReader, line)) {
++lineNumber;
- std::vector<std::string> comments;
- comments = Op::split(line, "//");
- if (comments.size() > 1) {
- line = comments.front();
- }
- comments = Op::split(line, "#");
- if (comments.size() > 1) {
- line = comments.front();
- }
+ //remove comments
+ line = Op::split(line, "//", false).front();
+ line = Op::split(line, "#", false).front();
line = Op::trim(line);
- if (line.empty() or line.at(0) == '%' or line.at(0) == '#'
- or (line.substr(0, 2) == "//")) {
+ if (line.empty() or line.at(0) == '%') {
continue;
}
- line = fl::Op::findReplace(line, "'", "");
+ line = Op::findReplace(line, "'", "");
if ("[System]" == line.substr(0, std::string("[System]").size())
or "[Input" == line.substr(0, std::string("[Input").size())
@@ -79,9 +58,9 @@ namespace fl {
sections.at(sections.size() - 1) += "\n" + line;
} else {
std::ostringstream ss;
- ss << "[import error] line " << lineNumber << " <" << line + "> "
+ ss << "[import error] line " << lineNumber << " <" << line << "> "
"does not belong to any section";
- throw fl::Exception(ss.str(), FL_AT);
+ throw Exception(ss.str(), FL_AT);
}
}
}
@@ -96,12 +75,12 @@ namespace fl {
importOutput(sections.at(i), engine.get());
else if ("[Rules]" == sections.at(i).substr(0, std::string("[Rules]").size()))
importRules(sections.at(i), engine.get());
- else throw fl::Exception("[import error] section <"
+ else throw Exception("[import error] section <"
+ sections.at(i) + "> not recognized", FL_AT);
}
- engine->configure(extractTNorm(andMethod), extractSNorm(orMethod),
- extractTNorm(impMethod), extractSNorm(aggMethod),
- extractDefuzzifier(defuzzMethod));
+ engine->configure(translateTNorm(andMethod), translateSNorm(orMethod),
+ translateTNorm(impMethod), translateSNorm(aggMethod),
+ translateDefuzzifier(defuzzMethod), General().className());
return engine.release();
}
@@ -113,14 +92,14 @@ namespace fl {
std::string line;
std::getline(reader, line); //ignore first line [System]
while (std::getline(reader, line)) {
- std::vector<std::string> keyValue = fl::Op::split(line, "=");
+ std::vector<std::string> keyValue = Op::split(line, "=");
- std::string key = fl::Op::trim(keyValue.at(0));
+ std::string key = Op::trim(keyValue.at(0));
std::string value;
for (std::size_t i = 1; i < keyValue.size(); ++i) {
value += keyValue.at(i);
}
- value = fl::Op::trim(value);
+ value = Op::trim(value);
if (key == "Name") engine->setName(value);
else if (key == "AndMethod") andMethod = value;
else if (key == "OrMethod") orMethod = value;
@@ -131,7 +110,7 @@ namespace fl {
or key == "NumInputs" or key == "NumOutputs"
or key == "NumRules" or key == "NumMFs") {
//ignore because are redundant.
- } else throw fl::Exception("[import error] token <" + key + "> not recognized", FL_AT);
+ } else throw Exception("[import error] token <" + key + "> not recognized", FL_AT);
}
}
@@ -144,18 +123,19 @@ namespace fl {
engine->addInputVariable(input);
while (std::getline(reader, line)) {
- std::vector<std::string> keyValue = fl::Op::split(line, "=");
+ std::vector<std::string> keyValue = Op::split(line, "=");
if (keyValue.size() != 2)
- throw fl::Exception("[syntax error] expected a property of type "
+ throw Exception("[syntax error] expected a property of type "
"'key=value', but found <" + line + ">", FL_AT);
- std::string key = fl::Op::trim(keyValue.at(0));
- std::string value = fl::Op::trim(keyValue.at(1));
+ std::string key = Op::trim(keyValue.at(0));
+ std::string value = Op::trim(keyValue.at(1));
- if (key == "Name") input->setName(fl::Op::validName(value));
- else if (key == "Enabled") {
+ if (key == "Name") {
+ input->setName(Op::validName(value));
+ } else if (key == "Enabled") {
input->setEnabled(Op::isEq(Op::toScalar(value), 1.0));
} else if (key == "Range") {
- std::pair<scalar, scalar> minmax = range(value);
+ std::pair<scalar, scalar> minmax = parseRange(value);
input->setMinimum(minmax.first);
input->setMaximum(minmax.second);
} else if (key.substr(0, 2) == "MF") {
@@ -163,7 +143,7 @@ namespace fl {
} else if (key == "NumMFs") {
//ignore
} else {
- throw fl::Exception("[import error] token <" + key + "> not recognized", FL_AT);
+ throw Exception("[import error] token <" + key + "> not recognized", FL_AT);
}
}
}
@@ -178,32 +158,33 @@ namespace fl {
while (std::getline(reader, line)) {
- std::vector<std::string> keyValue = fl::Op::split(line, "=");
+ std::vector<std::string> keyValue = Op::split(line, "=");
if (keyValue.size() != 2)
- throw fl::Exception("[syntax error] expected a property of type "
+ throw Exception("[syntax error] expected a property of type "
"'key=value', but found < " + line + ">", FL_AT);
- std::string key = fl::Op::trim(keyValue.at(0));
- std::string value = fl::Op::trim(keyValue.at(1));
+ std::string key = Op::trim(keyValue.at(0));
+ std::string value = Op::trim(keyValue.at(1));
- if (key == "Name") output->setName(fl::Op::validName(value));
- else if (key == "Enabled") {
+ if (key == "Name") {
+ output->setName(Op::validName(value));
+ } else if (key == "Enabled") {
output->setEnabled(Op::isEq(Op::toScalar(value), 1.0));
} else if (key == "Range") {
- std::pair<scalar, scalar> minmax = range(value);
+ std::pair<scalar, scalar> minmax = parseRange(value);
output->setMinimum(minmax.first);
output->setMaximum(minmax.second);
} else if (key.substr(0, 2) == "MF") {
output->addTerm(parseTerm(value, engine));
} else if (key == "Default") {
- output->setDefaultValue(fl::Op::toScalar(value));
+ output->setDefaultValue(Op::toScalar(value));
} else if (key == "LockPrevious") {
- output->setLockPreviousOutputValue(fl::Op::isEq(fl::Op::toScalar(value), 1.0));
+ output->setLockPreviousValue(Op::isEq(Op::toScalar(value), 1.0));
} else if (key == "LockRange") {
- output->setLockOutputValueInRange(fl::Op::isEq(fl::Op::toScalar(value), 1.0));
+ output->setLockValueInRange(Op::isEq(Op::toScalar(value), 1.0));
} else if (key == "NumMFs") {
//ignore
} else {
- throw fl::Exception("[import error] token <" + key + "> not recognized", FL_AT);
+ throw Exception("[import error] token <" + key + "> not recognized", FL_AT);
}
}
}
@@ -217,78 +198,78 @@ namespace fl {
engine->addRuleBlock(ruleblock);
while (std::getline(reader, line)) {
- std::vector<std::string> inputsAndRest = fl::Op::split(line, ",");
+ std::vector<std::string> inputsAndRest = Op::split(line, ",");
if (inputsAndRest.size() != 2)
- throw fl::Exception("[syntax error] expected rule to match pattern "
+ throw Exception("[syntax error] expected rule to match pattern "
"<'i '+, 'o '+ (w) : '1|2'>, but found instead <" + line + ">", FL_AT);
- std::vector <std::string> outputsAndRest = fl::Op::split(inputsAndRest.at(1), ":");
+ std::vector <std::string> outputsAndRest = Op::split(inputsAndRest.at(1), ":");
if (outputsAndRest.size() != 2)
- throw fl::Exception("[syntax error] expected rule to match pattern "
+ throw Exception("[syntax error] expected rule to match pattern "
"<'i '+, 'o '+ (w) : '1|2'>, but found instead <" + line + ">", FL_AT);
- std::vector<std::string> inputs = fl::Op::split(inputsAndRest.at(0), " ");
- std::vector<std::string> outputs = fl::Op::split(outputsAndRest.at(0), " ");
+ std::vector<std::string> inputs = Op::split(inputsAndRest.at(0), " ");
+ std::vector<std::string> outputs = Op::split(outputsAndRest.at(0), " ");
std::string weightInParenthesis = outputs.at(outputs.size() - 1);
outputs.erase(outputs.begin() + outputs.size() - 1);
- std::string connector = fl::Op::trim(outputsAndRest.at(1));
+ std::string connector = Op::trim(outputsAndRest.at(1));
- if ((int) inputs.size() != engine->numberOfInputVariables()) {
+ if (inputs.size() != engine->numberOfInputVariables()) {
std::ostringstream ss;
ss << "[syntax error] expected <" << engine->numberOfInputVariables() << ">"
" input variables, but found <" << inputs.size() << ">"
" input variables in rule <" << line << ">";
- throw fl::Exception(ss.str(), FL_AT);
+ throw Exception(ss.str(), FL_AT);
}
- if ((int) outputs.size() != engine->numberOfOutputVariables()) {
+ if (outputs.size() != engine->numberOfOutputVariables()) {
std::ostringstream ss;
ss << "[syntax error] expected <" << engine->numberOfOutputVariables() << ">"
" output variables, but found <" << outputs.size() << ">"
" output variables in rule <" << line << ">";
- throw fl::Exception(ss.str(), FL_AT);
+ throw Exception(ss.str(), FL_AT);
}
std::vector<std::string> antecedent, consequent;
for (std::size_t i = 0; i < inputs.size(); ++i) {
- scalar inputCode = fl::Op::toScalar(inputs.at(i));
- if (fl::Op::isEq(inputCode, 0.0)) continue;
+ scalar inputCode = Op::toScalar(inputs.at(i));
+ if (Op::isEq(inputCode, 0.0)) continue;
std::ostringstream ss;
ss << engine->getInputVariable(i)->getName() << " "
- << fl::Rule::isKeyword() << " "
+ << Rule::isKeyword() << " "
<< translateProposition(inputCode, engine->getInputVariable(i));
antecedent.push_back(ss.str());
}
for (std::size_t i = 0; i < outputs.size(); ++i) {
- scalar outputCode = fl::Op::toScalar(outputs.at(i));
- if (fl::Op::isEq(outputCode, 0.0)) continue;
+ scalar outputCode = Op::toScalar(outputs.at(i));
+ if (Op::isEq(outputCode, 0.0)) continue;
std::ostringstream ss;
ss << engine->getOutputVariable(i)->getName() << " "
- << fl::Rule::isKeyword() << " "
+ << Rule::isKeyword() << " "
<< translateProposition(outputCode, engine->getOutputVariable(i));
consequent.push_back(ss.str());
}
std::ostringstream ruleText;
- ruleText << fl::Rule::ifKeyword() << " ";
+ ruleText << Rule::ifKeyword() << " ";
for (std::size_t i = 0; i < antecedent.size(); ++i) {
ruleText << antecedent.at(i);
if (i + 1 < antecedent.size()) {
ruleText << " ";
- if (connector == "1") ruleText << fl::Rule::andKeyword() << " ";
- else if (connector == "2") ruleText << fl::Rule::orKeyword() << " ";
- else throw fl::Exception("[syntax error] connector <"
+ if (connector == "1") ruleText << Rule::andKeyword() << " ";
+ else if (connector == "2") ruleText << Rule::orKeyword() << " ";
+ else throw Exception("[syntax error] connector <"
+ connector + "> not recognized", FL_AT);
}
}
- ruleText << " " << fl::Rule::thenKeyword() << " ";
+ ruleText << " " << Rule::thenKeyword() << " ";
for (std::size_t i = 0; i < consequent.size(); ++i) {
ruleText << consequent.at(i);
if (i + 1 < consequent.size()) {
- ruleText << " " << fl::Rule::andKeyword() << " ";
+ ruleText << " " << Rule::andKeyword() << " ";
}
}
@@ -300,9 +281,9 @@ namespace fl {
ss << weightInParenthesis.at(i);
}
- scalar weight = fl::Op::toScalar(ss.str());
- if (not fl::Op::isEq(weight, 1.0))
- ruleText << " " << fl::Rule::withKeyword() << " " << Op::str(weight);
+ scalar weight = Op::toScalar(ss.str());
+ if (not Op::isEq(weight, 1.0))
+ ruleText << " " << Rule::withKeyword() << " " << Op::str(weight);
Rule* rule = new Rule(ruleText.str());
try {
rule->load(engine);
@@ -314,34 +295,34 @@ namespace fl {
}
std::string FisImporter::translateProposition(scalar code, Variable* variable) const {
- int intPart = (int) std::floor(std::fabs(code)) - 1;
- scalar fracPart = std::fmod(std::fabs(code), 1.0);
- if (intPart >= variable->numberOfTerms()) {
+ int intPart = (int) std::floor(std::abs(code)) - 1;
+ scalar fracPart = std::fmod(std::abs(code), scalar(1.0));
+ if (intPart >= static_cast<int> (variable->numberOfTerms())) {
std::ostringstream ex;
ex << "[syntax error] the code <" << code << "> refers to a term "
"out of range from variable <" << variable->getName() << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
bool isAny = intPart < 0;
std::ostringstream ss;
if (code < 0) ss << Not().name() << " ";
- if (fl::Op::isEq(fracPart, 0.01)) ss << Seldom().name() << " ";
- else if (fl::Op::isEq(fracPart, 0.05)) ss << Somewhat().name() << " ";
- else if (fl::Op::isEq(fracPart, 0.2)) ss << Very().name() << " ";
- else if (fl::Op::isEq(fracPart, 0.3)) ss << Extremely().name() << " ";
- else if (fl::Op::isEq(fracPart, 0.4)) ss << Very().name() << " " << Very().name() << " ";
- else if (fl::Op::isEq(fracPart, 0.99)) ss << Any().name() << " ";
- else if (not fl::Op::isEq(fracPart, 0))
- throw fl::Exception("[syntax error] no hedge defined in FIS format for <"
- + fl::Op::str(fracPart) + ">", FL_AT);
+ if (Op::isEq(fracPart, 0.01)) ss << Seldom().name() << " ";
+ else if (Op::isEq(fracPart, 0.05)) ss << Somewhat().name() << " ";
+ else if (Op::isEq(fracPart, 0.2)) ss << Very().name() << " ";
+ else if (Op::isEq(fracPart, 0.3)) ss << Extremely().name() << " ";
+ else if (Op::isEq(fracPart, 0.4)) ss << Very().name() << " " << Very().name() << " ";
+ else if (Op::isEq(fracPart, 0.99)) ss << Any().name() << " ";
+ else if (not Op::isEq(fracPart, 0.0))
+ throw Exception("[syntax error] no hedge defined in FIS format for <"
+ + Op::str(fracPart) + ">", FL_AT);
if (not isAny) {
ss << variable->getTerm(intPart)->getName();
}
return ss.str();
}
- std::string FisImporter::extractTNorm(const std::string & name) const {
+ std::string FisImporter::translateTNorm(const std::string& name) const {
if (name.empty()) return "";
if (name == "min") return Minimum().className();
if (name == "prod") return AlgebraicProduct().className();
@@ -353,20 +334,21 @@ namespace fl {
return name;
}
- std::string FisImporter::extractSNorm(const std::string & name) const {
+ std::string FisImporter::translateSNorm(const std::string& name) const {
if (name.empty()) return "";
if (name == "max") return Maximum().className();
- if (name == "sum" or name == "probor") return AlgebraicSum().className();
+ if (name == "probor") return AlgebraicSum().className();
if (name == "bounded_sum") return BoundedSum().className();
if (name == "normalized_sum") return NormalizedSum().className();
if (name == "drastic_sum") return DrasticSum().className();
if (name == "einstein_sum") return EinsteinSum().className();
if (name == "hamacher_sum") return HamacherSum().className();
if (name == "nilpotent_maximum") return NilpotentMaximum().className();
+ if (name == "sum") return UnboundedSum().className();
return name;
}
- std::string FisImporter::extractDefuzzifier(const std::string & name) const {
+ std::string FisImporter::translateDefuzzifier(const std::string& name) const {
if (name.empty()) return "";
if (name == "centroid") return Centroid().className();
if (name == "bisector") return Bisector().className();
@@ -378,22 +360,22 @@ namespace fl {
return name;
}
- std::pair<scalar, scalar> FisImporter::range(const std::string& range) const {
- std::vector<std::string> parts = fl::Op::split(range, " ");
+ std::pair<scalar, scalar> FisImporter::parseRange(const std::string& range) const {
+ std::vector<std::string> parts = Op::split(range, " ");
if (parts.size() != 2)
- throw fl::Exception("[syntax error] expected range in format '[begin end]',"
+ throw Exception("[syntax error] expected range in format '[begin end]',"
" but found <" + range + ">", FL_AT);
std::string begin = parts.at(0), end = parts.at(1);
if (begin.at(0) != '[' or end.at(end.size() - 1) != ']')
- throw fl::Exception("[syntax error] expected range in format '[begin end]',"
+ throw Exception("[syntax error] expected range in format '[begin end]',"
" but found <" + range + ">", FL_AT);
std::pair<scalar, scalar> result;
- result.first = fl::Op::toScalar(begin.substr(1));
- result.second = fl::Op::toScalar(end.substr(0, end.size() - 1));
+ result.first = Op::toScalar(begin.substr(1));
+ result.second = Op::toScalar(end.substr(0, end.size() - 1));
return result;
}
- Term * FisImporter::parseTerm(const std::string & fis, const Engine* engine) const {
+ Term * FisImporter::parseTerm(const std::string& fis, const Engine* engine) const {
std::ostringstream ss;
for (std::size_t i = 0; i < fis.size(); ++i) {
if (not (fis.at(i) == '[' or fis.at(i) == ']')) {
@@ -402,35 +384,36 @@ namespace fl {
}
std::string line = ss.str();
- std::vector<std::string> nameTerm = fl::Op::split(line, ":");
+ std::vector<std::string> nameTerm = Op::split(line, ":");
if (nameTerm.size() != 2) {
- throw fl::Exception("[syntax error] expected term in format 'name':'class',[params], "
+ throw Exception("[syntax error] expected term in format 'name':'class',[params], "
"but found <" + line + ">", FL_AT);
}
- std::vector<std::string> termParams = fl::Op::split(nameTerm.at(1), ",");
+ std::vector<std::string> termParams = Op::split(nameTerm.at(1), ",");
if (termParams.size() != 2) {
- throw fl::Exception("[syntax error] expected term in format 'name':'class',[params], "
+ throw Exception("[syntax error] expected term in format 'name':'class',[params], "
"but found " + line, FL_AT);
}
- std::vector<std::string> parameters = fl::Op::split(termParams.at(1), " ");
+ std::vector<std::string> parameters = Op::split(termParams.at(1), " ");
for (std::size_t i = 0; i < parameters.size(); ++i) {
- parameters.at(i) = fl::Op::trim(parameters.at(i));
+ parameters.at(i) = Op::trim(parameters.at(i));
}
return createInstance(
- fl::Op::trim(termParams.at(0)),
- fl::Op::trim(nameTerm.at(0)),
+ Op::trim(termParams.at(0)),
+ Op::trim(nameTerm.at(0)),
parameters, engine);
}
- Term * FisImporter::createInstance(const std::string& mClass,
+ Term* FisImporter::createInstance(const std::string& mClass,
const std::string& name, const std::vector<std::string>& params,
const Engine* engine) const {
std::map<std::string, std::string> mapping;
- mapping["discretemf"] = Discrete().className();
+ mapping["binarymf"] = Binary().className();
mapping["concavemf"] = Concave().className();
mapping["constant"] = Constant().className();
mapping["cosinemf"] = Cosine().className();
+ mapping["discretemf"] = Discrete().className();
mapping["function"] = Function().className();
mapping["gbellmf"] = Bell().className();
mapping["gaussmf"] = Gaussian().className();
@@ -484,7 +467,7 @@ namespace fl {
FL_unique_ptr<Term> term;
term.reset(FactoryManager::instance()->term()->constructObject(flClass));
- Term::updateReference(term.get(), engine);
+ term->updateReference(engine);
term->setName(Op::validName(name));
std::string separator;
if (not dynamic_cast<Function*> (term.get())) {
diff --git a/fuzzylite/src/imex/FldExporter.cpp b/fuzzylite/src/imex/FldExporter.cpp
index 9064250..e25af1b 100644
--- a/fuzzylite/src/imex/FldExporter.cpp
+++ b/fuzzylite/src/imex/FldExporter.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/FldExporter.h"
@@ -30,20 +22,15 @@
#include "fl/variable/InputVariable.h"
#include "fl/variable/OutputVariable.h"
-#include <cmath>
#include <fstream>
-#include <vector>
namespace fl {
FldExporter::FldExporter(const std::string& separator) : Exporter(),
_separator(separator), _exportHeaders(true),
- _exportInputValues(true), _exportOutputValues(true) {
-
- }
+ _exportInputValues(true), _exportOutputValues(true) { }
- FldExporter::~FldExporter() {
- }
+ FldExporter::~FldExporter() { }
std::string FldExporter::name() const {
return "FldExporter";
@@ -84,156 +71,235 @@ namespace fl {
std::string FldExporter::header(const Engine* engine) const {
std::vector<std::string> result;
if (_exportInputValues) {
- for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i) {
InputVariable* inputVariable = engine->getInputVariable(i);
- result.push_back("@InputVariable: " + inputVariable->getName() + ";");
+ result.push_back(inputVariable->getName());
}
}
if (_exportOutputValues) {
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i) {
OutputVariable* outputVariable = engine->getOutputVariable(i);
- result.push_back("@OutputVariable: " + outputVariable->getName() + ";");
+ result.push_back(outputVariable->getName());
}
}
- return "#@Engine: " + engine->getName() + ";\n#" + Op::join(result, _separator);
+ return Op::join(result, _separator);
}
std::string FldExporter::toString(const Engine* engine) const {
- return toString(const_cast<Engine*> (engine), 1024);
+ return toString(const_cast<Engine*> (engine), 1024, AllVariables);
}
- std::string FldExporter::toString(Engine* engine, int maximumNumberOfResults) const {
- std::ostringstream result;
- write(engine, result, maximumNumberOfResults);
- return result.str();
+ std::string FldExporter::toString(Engine* engine, int values, ScopeOfValues scope) const {
+ return toString(engine, values, scope, engine->inputVariables());
}
- void FldExporter::toFile(const std::string& path, Engine* engine, int maximumNumberOfResults) const {
- std::ofstream writer(path.c_str());
- if (not writer.is_open()) {
- throw fl::Exception("[file error] file <" + path + "> could not be created", FL_AT);
- }
- write(engine, writer, maximumNumberOfResults);
- writer.close();
+ std::string FldExporter::toString(Engine* engine, int values, ScopeOfValues scope,
+ const std::vector<InputVariable*>& activeVariables) const {
+ std::ostringstream result;
+ write(engine, result, values, scope, activeVariables);
+ return result.str();
}
- std::string FldExporter::toString(Engine* engine, const std::string& inputData) const {
+ std::string FldExporter::toString(Engine* engine, std::istream& reader) const {
std::ostringstream writer;
if (_exportHeaders) writer << header(engine) << "\n";
- std::istringstream reader(inputData);
std::string line;
+ int lineNumber = 0;
while (std::getline(reader, line)) {
+ ++lineNumber;
line = Op::trim(line);
- if (not line.empty() and line.at(0) == '#') continue; //comments are ignored, blank lines are retained
- std::vector<scalar> inputValues = parse(line);
- write(engine, writer, inputValues);
- writer.flush();
+ if (not line.empty() and line.at(0) == '#')
+ continue; //comments are ignored, blank lines are retained
+ std::vector<scalar> inputValues;
+ if (lineNumber == 1) { //automatic detection of header.
+ try {
+ inputValues = parse(line);
+ } catch (std::exception&) {
+ continue;
+ }
+ } else {
+ inputValues = parse(line);
+ }
+
+ write(engine, writer, inputValues, engine->inputVariables());
}
return writer.str();
}
- void FldExporter::toFile(const std::string& path, Engine* engine, const std::string& inputData) const {
+ void FldExporter::toFile(const std::string& path, Engine* engine, int values, ScopeOfValues scope) const {
+ toFile(path, engine, values, scope, engine->inputVariables());
+ }
+
+ void FldExporter::toFile(const std::string& path, Engine* engine, int values, ScopeOfValues scope,
+ const std::vector<InputVariable*>& activeVariables) const {
std::ofstream writer(path.c_str());
if (not writer.is_open()) {
- throw fl::Exception("[file error] file <" + path + "> could not be created", FL_AT);
+ throw Exception("[file error] file <" + path + "> could not be created", FL_AT);
+ }
+ write(engine, writer, values, scope, activeVariables);
+ writer.close();
+ }
+
+ void FldExporter::toFile(const std::string& path, Engine* engine, std::istream& reader) const {
+ std::ofstream writer(path.c_str());
+ if (not writer.is_open()) {
+ throw Exception("[file error] file <" + path + "> could not be created", FL_AT);
}
if (_exportHeaders) writer << header(engine) << "\n";
- std::istringstream reader(inputData);
+
std::string line;
+ int lineNumber = 0;
while (std::getline(reader, line)) {
+ ++lineNumber;
line = Op::trim(line);
- if (not line.empty() and line.at(0) == '#') continue; //comments are ignored, blank lines are retained
- std::vector<scalar> inputValues = parse(line);
- write(engine, writer, inputValues);
- writer.flush();
+ if (not line.empty() and line.at(0) == '#')
+ continue; //comments are ignored, blank lines are retained
+ std::vector<scalar> inputValues;
+ if (lineNumber == 1) { //automatic detection of header.
+ try {
+ inputValues = parse(line);
+ } catch (std::exception&) {
+ continue;
+ }
+ } else {
+ inputValues = parse(line);
+ }
+
+ write(engine, writer, inputValues, engine->inputVariables());
}
writer.close();
}
- std::vector<scalar> FldExporter::parse(const std::string& x) const {
+ std::vector<scalar> FldExporter::parse(const std::string& values) const {
std::vector<scalar> inputValues;
- if (not (x.empty() or x.at(0) == '#')) {
- std::istringstream tokenizer(x);
- std::string token;
- while (tokenizer >> token)
- inputValues.push_back(fl::Op::toScalar(token));
+ if (not (values.empty() or values.at(0) == '#')) {
+ inputValues = Op::toScalars(values);
}
return inputValues;
}
- void FldExporter::write(Engine* engine, std::ostream& writer, int maximum) const {
+ void FldExporter::write(Engine* engine, std::ostream& writer, int values, ScopeOfValues scope) const {
+ write(engine, writer, values, scope, engine->inputVariables());
+ }
+
+ void FldExporter::write(Engine* engine, std::ostream& writer,
+ int values, ScopeOfValues scope,
+ const std::vector<InputVariable*>& activeVariables) const {
if (_exportHeaders) writer << header(engine) << "\n";
- int resolution = -1 + (int) std::max(1.0, std::pow(
- maximum, 1.0 / engine->numberOfInputVariables()));
+ if (activeVariables.size() != engine->inputVariables().size()) {
+ std::ostringstream ex;
+ ex << "[exporter error] number of active variables "
+ "<" << activeVariables.size() << ">"
+ << "must match the number of input variables in the engine "
+ "<" << engine->inputVariables().size() << ">";
+ throw Exception(ex.str(), FL_AT);
+ }
+
+ int resolution;
+ if (scope == AllVariables)
+ resolution = -1 + (int) std::max(1.0, std::pow(
+ values, 1.0 / engine->numberOfInputVariables()));
+ else //if (scope == EachVariable)
+ resolution = values - 1;
+
std::vector<int> sampleValues, minSampleValues, maxSampleValues;
- for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i) {
sampleValues.push_back(0);
minSampleValues.push_back(0);
- maxSampleValues.push_back(resolution);
+ if (engine->inputVariables().at(i) == activeVariables.at(i))
+ maxSampleValues.push_back(resolution);
+ else maxSampleValues.push_back(0);
}
- engine->restart();
-
- bool overflow = false;
std::vector<scalar> inputValues(engine->numberOfInputVariables());
- while (not overflow) {
- for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ do {
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i) {
InputVariable* inputVariable = engine->getInputVariable(i);
- inputValues.at(i) = inputVariable->getMinimum()
- + sampleValues.at(i) * inputVariable->range() / std::max(1, resolution);
+ if (inputVariable == activeVariables.at(i)) {
+ inputValues.at(i) = inputVariable->getMinimum()
+ + sampleValues.at(i) * inputVariable->range() / std::max(1, resolution);
+ } else {
+ inputValues.at(i) = inputVariable->getValue();
+ }
}
- write(engine, writer, inputValues);
- overflow = Op::increment(sampleValues, minSampleValues, maxSampleValues);
- }
+ write(engine, writer, inputValues, activeVariables);
+ } while (Op::increment(sampleValues, minSampleValues, maxSampleValues));
}
void FldExporter::write(Engine* engine, std::ostream& writer, std::istream& reader) const {
if (_exportHeaders) writer << header(engine) << "\n";
- engine->restart();
-
std::string line;
- int lineNumber = 0;
+ std::size_t lineNumber = 0;
while (std::getline(reader, line)) {
++lineNumber;
- std::vector<scalar> inputValues = parse(Op::trim(line));
+ line = Op::trim(line);
+ if (not line.empty() and line.at(0) == '#')
+ continue; //comments are ignored, blank lines are retained
+ std::vector<scalar> inputValues;
+ if (lineNumber == 1) { //automatic detection of header.
+ try {
+ inputValues = parse(line);
+ } catch (std::exception&) {
+ continue;
+ }
+ } else {
+ inputValues = parse(line);
+ }
try {
- write(engine, writer, inputValues);
- } catch (fl::Exception& ex) {
+ write(engine, writer, inputValues, engine->inputVariables());
+ } catch (Exception& ex) {
ex.append(" writing line <" + Op::str(lineNumber) + ">");
throw;
}
}
}
- void FldExporter::write(Engine* engine, std::ostream& writer, const std::vector<scalar>& inputValues) const {
+ void FldExporter::write(Engine* engine, std::ostream& writer,
+ const std::vector<scalar>& inputValues) const {
+ write(engine, writer, inputValues, engine->inputVariables());
+ }
+
+ void FldExporter::write(Engine* engine, std::ostream& writer,
+ const std::vector<scalar>& inputValues,
+ const std::vector<InputVariable*>& activeVariables) const {
if (inputValues.empty()) {
writer << "\n";
return;
}
- if (int(inputValues.size()) < engine->numberOfInputVariables()) {
+ if (inputValues.size() < engine->numberOfInputVariables()) {
std::ostringstream ex;
ex << "[export error] engine has <" << engine->numberOfInputVariables() << "> "
"input variables, but input data provides <" << inputValues.size() << "> values";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
+ }
+ if (activeVariables.size() != engine->inputVariables().size()) {
+ std::ostringstream ex;
+ ex << "[exporter error] number of active variables <" << activeVariables.size() << "> "
+ "must match the number of input variables in the engine <" << engine->inputVariables().size() << ">";
+ throw Exception(ex.str(), FL_AT);
}
- std::vector<std::string> values;
- for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ std::vector<scalar> values;
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i) {
InputVariable* inputVariable = engine->getInputVariable(i);
- scalar inputValue = inputVariable->isEnabled() ? inputValues.at(i) : fl::nan;
- inputVariable->setInputValue(inputValue);
- if (_exportInputValues) values.push_back(Op::str(inputValue));
+ scalar inputValue;
+ if (inputVariable == activeVariables.at(i)) {
+ inputValue = inputValues.at(i);
+ } else {
+ inputValue = inputVariable->getValue();
+ }
+ inputVariable->setValue(inputValue);
+ if (_exportInputValues) values.push_back(inputValue);
}
engine->process();
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i) {
OutputVariable* outputVariable = engine->getOutputVariable(i);
- outputVariable->defuzzify();
if (_exportOutputValues)
- values.push_back(Op::str(outputVariable->getOutputValue()));
+ values.push_back(outputVariable->getValue());
}
writer << Op::join(values, _separator) << "\n";
diff --git a/fuzzylite/src/imex/FllExporter.cpp b/fuzzylite/src/imex/FllExporter.cpp
index 0ffeb2f..6a86152 100644
--- a/fuzzylite/src/imex/FllExporter.cpp
+++ b/fuzzylite/src/imex/FllExporter.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/FllExporter.h"
@@ -29,11 +21,9 @@
namespace fl {
FllExporter::FllExporter(const std::string& indent, const std::string& separator)
- : Exporter(), _indent(indent), _separator(separator) {
- }
+ : Exporter(), _indent(indent), _separator(separator) { }
- FllExporter::~FllExporter() {
- }
+ FllExporter::~FllExporter() { }
std::string FllExporter::name() const {
return "FllExporter";
@@ -58,9 +48,17 @@ namespace fl {
std::string FllExporter::toString(const Engine* engine) const {
std::vector<std::string> result;
result.push_back("Engine: " + engine->getName());
- result.push_back(toString(engine->inputVariables()));
- result.push_back(toString(engine->outputVariables()));
- result.push_back(toString(engine->ruleBlocks()));
+ if (not engine->getDescription().empty())
+ result.push_back("description: " + engine->getDescription());
+ for (std::size_t i = 0 ; i < engine->numberOfInputVariables(); ++i){
+ result.push_back(toString(engine->getInputVariable(i)));
+ }
+ for (std::size_t i = 0 ; i < engine->numberOfOutputVariables(); ++i){
+ result.push_back(toString(engine->getOutputVariable(i)));
+ }
+ for (std::size_t i = 0 ; i < engine->numberOfRuleBlocks(); ++i){
+ result.push_back(toString(engine->getRuleBlock(i)));
+ }
return Op::join(result, _separator);
}
@@ -99,10 +97,15 @@ namespace fl {
std::string FllExporter::toString(const Variable* variable) const {
std::vector<std::string> result;
result.push_back("Variable: " + Op::validName(variable->getName()));
+ if (not variable->getDescription().empty()) {
+ result.push_back(_indent + "description: " + variable->getDescription());
+ }
result.push_back(_indent + "enabled: " + (variable->isEnabled() ? "true" : "false"));
result.push_back(_indent + "range: " + Op::join(2, " ",
variable->getMinimum(), variable->getMaximum()));
- for (int i = 0; i < variable->numberOfTerms(); ++i) {
+ result.push_back(_indent + "lock-range: " +
+ (variable->isLockValueInRange() ? "true" : "false"));
+ for (std::size_t i = 0; i < variable->numberOfTerms(); ++i) {
result.push_back(_indent + toString(variable->getTerm(i)));
}
return Op::join(result, _separator);
@@ -111,10 +114,15 @@ namespace fl {
std::string FllExporter::toString(const InputVariable* inputVariable) const {
std::vector<std::string> result;
result.push_back("InputVariable: " + Op::validName(inputVariable->getName()));
+ if (not inputVariable->getDescription().empty()) {
+ result.push_back(_indent + "description: " + inputVariable->getDescription());
+ }
result.push_back(_indent + "enabled: " + (inputVariable->isEnabled() ? "true" : "false"));
result.push_back(_indent + "range: " + Op::join(2, " ",
inputVariable->getMinimum(), inputVariable->getMaximum()));
- for (int i = 0; i < inputVariable->numberOfTerms(); ++i) {
+ result.push_back(_indent + "lock-range: " +
+ (inputVariable->isLockValueInRange() ? "true" : "false"));
+ for (std::size_t i = 0; i < inputVariable->numberOfTerms(); ++i) {
result.push_back(_indent + toString(inputVariable->getTerm(i)));
}
return Op::join(result, _separator);
@@ -123,19 +131,22 @@ namespace fl {
std::string FllExporter::toString(const OutputVariable* outputVariable) const {
std::vector<std::string> result;
result.push_back("OutputVariable: " + Op::validName(outputVariable->getName()));
+ if (not outputVariable->getDescription().empty()) {
+ result.push_back(_indent + "description: " + outputVariable->getDescription());
+ }
result.push_back(_indent + "enabled: " + (outputVariable->isEnabled() ? "true" : "false"));
result.push_back(_indent + "range: " + Op::join(2, " ",
outputVariable->getMinimum(), outputVariable->getMaximum()));
- result.push_back(_indent + "accumulation: " +
- toString(outputVariable->fuzzyOutput()->getAccumulation()));
+ result.push_back(_indent + "lock-range: " +
+ (outputVariable->isLockValueInRange() ? "true" : "false"));
+ result.push_back(_indent + "aggregation: " +
+ toString(outputVariable->fuzzyOutput()->getAggregation()));
result.push_back(_indent + "defuzzifier: " +
toString(outputVariable->getDefuzzifier()));
result.push_back(_indent + "default: " + Op::str(outputVariable->getDefaultValue()));
result.push_back(_indent + "lock-previous: " +
- (outputVariable->isLockedPreviousOutputValue() ? "true" : "false"));
- result.push_back(_indent + "lock-range: " +
- (outputVariable->isLockedOutputValueInRange() ? "true" : "false"));
- for (int i = 0; i < outputVariable->numberOfTerms(); ++i) {
+ (outputVariable->isLockPreviousValue() ? "true" : "false"));
+ for (std::size_t i = 0; i < outputVariable->numberOfTerms(); ++i) {
result.push_back(_indent + toString(outputVariable->getTerm(i)));
}
return Op::join(result, _separator);
@@ -144,12 +155,16 @@ namespace fl {
std::string FllExporter::toString(const RuleBlock* ruleBlock) const {
std::vector<std::string> result;
result.push_back("RuleBlock: " + ruleBlock->getName());
+ if (not ruleBlock->getDescription().empty()) {
+ result.push_back(_indent + "description: " + ruleBlock->getDescription());
+ }
result.push_back(_indent + "enabled: " +
(ruleBlock->isEnabled() ? "true" : "false"));
result.push_back(_indent + "conjunction: " + toString(ruleBlock->getConjunction()));
result.push_back(_indent + "disjunction: " + toString(ruleBlock->getDisjunction()));
+ result.push_back(_indent + "implication: " + toString(ruleBlock->getImplication()));
result.push_back(_indent + "activation: " + toString(ruleBlock->getActivation()));
- for (int i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
result.push_back(_indent + toString(ruleBlock->getRule(i)));
}
return Op::join(result, _separator);
@@ -169,11 +184,17 @@ namespace fl {
return "none";
}
+ std::string FllExporter::toString(const Activation* activation) const {
+ if (not activation) return "none";
+ if (activation->parameters().empty()) return activation->className();
+ return activation->className() + " " + activation->parameters();
+ }
+
std::string FllExporter::toString(const Defuzzifier* defuzzifier) const {
if (not defuzzifier) return "none";
if (const IntegralDefuzzifier * integralDefuzzifier =
dynamic_cast<const IntegralDefuzzifier*> (defuzzifier)) {
- return defuzzifier->className() + " " + Op::str<int>(integralDefuzzifier->getResolution());
+ return defuzzifier->className() + " " + Op::str(integralDefuzzifier->getResolution());
} else if (const WeightedDefuzzifier * weightedDefuzzifier =
dynamic_cast<const WeightedDefuzzifier*> (defuzzifier)) {
diff --git a/fuzzylite/src/imex/FllImporter.cpp b/fuzzylite/src/imex/FllImporter.cpp
index 2443d10..ac9d1fc 100644
--- a/fuzzylite/src/imex/FllImporter.cpp
+++ b/fuzzylite/src/imex/FllImporter.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/FllImporter.h"
@@ -31,12 +23,9 @@
namespace fl {
FllImporter::FllImporter(const std::string& separator) : Importer(),
- _separator(separator) {
- }
-
- FllImporter::~FllImporter() {
+ _separator(separator) { }
- }
+ FllImporter::~FllImporter() { }
std::string FllImporter::name() const {
return "FllImporter";
@@ -50,62 +39,48 @@ namespace fl {
return this->_separator;
}
- Engine* FllImporter::fromString(const std::string& fll) const {
+ Engine* FllImporter::fromString(const std::string& code) const {
FL_unique_ptr<Engine> engine(new Engine);
+ const std::string fll = Op::join(Op::split(code, _separator), "\n");
std::string tag;
- std::ostringstream block;
- std::istringstream fclReader(fll);
+ std::vector<std::string> block;
+ std::istringstream fllReader(fll);
std::string line;
- std::queue<std::string> lineQueue;
-
- bool processPending = false;
- int lineNumber = 0;
- while (not lineQueue.empty() or std::getline(fclReader, line)) {
- if (not lineQueue.empty()) {
- line = lineQueue.front();
- lineQueue.pop();
- } else {
- line = clean(line);
- if (line.empty()) continue;
- std::vector<std::string> split = Op::split(line, _separator);
- line = clean(split.front());
- for (std::size_t i = 1; i < split.size(); ++i) {
- lineQueue.push(clean(split.at(i)));
- }
- ++lineNumber;
- }
+
+ while (std::getline(fllReader, line)) {
+ line = Op::trim(Op::split(line, "#", false).front()); //remove comments
if (line.empty()) continue;
std::size_t colon = line.find_first_of(':');
if (colon == std::string::npos) {
- throw fl::Exception("[import error] expected a colon at line " +
- Op::str(lineNumber) + ": " + line, FL_AT);
+ throw Exception("[import error] expected a colon here: " + line, FL_AT);
}
std::string key = Op::trim(line.substr(0, colon));
std::string value = Op::trim(line.substr(colon + 1));
if ("Engine" == key) {
engine->setName(value);
continue;
- } else {
- processPending = (key == "InputVariable"
- or key == "OutputVariable"
- or key == "RuleBlock");
- }
- if (processPending) {
- process(tag, block.str(), engine.get());
- block.str(""); //clear buffer
+ } else if (key == "description" and block.empty()){
+ engine->setDescription(value);
+ continue;
+ } else if (key == "InputVariable"
+ or key == "OutputVariable"
+ or key == "RuleBlock") {
+ process(tag, Op::join(block, "\n"), engine.get());
block.clear(); //clear error flags
- processPending = false;
tag = key;
+ } else if (tag.empty()) {
+ throw Exception("[import error] unexpected block: " + line, FL_AT);
}
- block << key << ":" << value << "\n";
+ block.push_back(key + ":" + value);
}
- process(tag, block.str(), engine.get());
+ process(tag, Op::join(block, "\n"), engine.get());
return engine.release();
}
void FllImporter::process(const std::string& tag, const std::string& block, Engine* engine) const {
if (tag.empty()) return;
+ // FL_LOG("Processing " << tag << "\n" << block);
if ("InputVariable" == tag) {
processInputVariable(block, engine);
} else if ("OutputVariable" == tag) {
@@ -113,42 +88,47 @@ namespace fl {
} else if ("RuleBlock" == tag) {
processRuleBlock(block, engine);
} else {
- throw fl::Exception("[import error] block tag <" + tag + "> not recognized", FL_AT);
+ throw Exception("[import error] block tag <" + tag + "> not recognized", FL_AT);
}
}
void FllImporter::processInputVariable(const std::string& block, Engine* engine) const {
std::istringstream reader(block);
std::string line;
- InputVariable* inputVariable = new InputVariable;
- engine->addInputVariable(inputVariable);
+ FL_unique_ptr<InputVariable> inputVariable(new InputVariable);
while (std::getline(reader, line)) {
std::pair<std::string, std::string> keyValue = parseKeyValue(line, ':');
if ("InputVariable" == keyValue.first) {
inputVariable->setName(Op::validName(keyValue.second));
+ } else if ("description" == keyValue.first) {
+ inputVariable->setDescription(keyValue.second);
} else if ("enabled" == keyValue.first) {
inputVariable->setEnabled(parseBoolean(keyValue.second));
} else if ("range" == keyValue.first) {
std::pair<scalar, scalar> range = parseRange(keyValue.second);
inputVariable->setRange(range.first, range.second);
+ } else if ("lock-range" == keyValue.first) {
+ inputVariable->setLockValueInRange(parseBoolean(keyValue.second));
} else if ("term" == keyValue.first) {
inputVariable->addTerm(parseTerm(keyValue.second, engine));
} else {
- throw fl::Exception("[import error] key <" + keyValue.first + "> not "
+ throw Exception("[import error] key <" + keyValue.first + "> not "
"recognized in pair <" + keyValue.first + ":" + keyValue.second + ">", FL_AT);
}
}
+ engine->addInputVariable(inputVariable.release());
}
void FllImporter::processOutputVariable(const std::string& block, Engine* engine) const {
std::istringstream reader(block);
std::string line;
- OutputVariable* outputVariable = new OutputVariable;
- engine->addOutputVariable(outputVariable);
+ FL_unique_ptr<OutputVariable> outputVariable(new OutputVariable);
while (std::getline(reader, line)) {
std::pair<std::string, std::string> keyValue = parseKeyValue(line, ':');
if ("OutputVariable" == keyValue.first) {
outputVariable->setName(Op::validName(keyValue.second));
+ } else if ("description" == keyValue.first) {
+ outputVariable->setDescription(keyValue.second);
} else if ("enabled" == keyValue.first) {
outputVariable->setEnabled(parseBoolean(keyValue.second));
} else if ("range" == keyValue.first) {
@@ -157,39 +137,64 @@ namespace fl {
} else if ("default" == keyValue.first) {
outputVariable->setDefaultValue(Op::toScalar(keyValue.second));
} else if ("lock-previous" == keyValue.first or "lock-valid" == keyValue.first) {
- outputVariable->setLockPreviousOutputValue(parseBoolean(keyValue.second));
+ outputVariable->setLockPreviousValue(parseBoolean(keyValue.second));
} else if ("lock-range" == keyValue.first) {
- outputVariable->setLockOutputValueInRange(parseBoolean(keyValue.second));
+ outputVariable->setLockValueInRange(parseBoolean(keyValue.second));
} else if ("defuzzifier" == keyValue.first) {
outputVariable->setDefuzzifier(parseDefuzzifier(keyValue.second));
+ } else if ("aggregation" == keyValue.first) {
+ outputVariable->fuzzyOutput()->setAggregation(parseSNorm(keyValue.second));
} else if ("accumulation" == keyValue.first) {
- outputVariable->fuzzyOutput()->setAccumulation(parseSNorm(keyValue.second));
+ outputVariable->fuzzyOutput()->setAggregation(parseSNorm(keyValue.second));
+ FL_LOG("[warning] obsolete usage of identifier <accumulation: SNorm> in OutputVariable");
+ FL_LOG("[information] from version 6.0, the identifier <aggregation: SNorm> should be used");
+ FL_LOG("[backward compatibility] assumed "
+ "<aggregation: " << keyValue.second << "> "
+ "instead of <accumulation: " << keyValue.second << ">");
} else if ("term" == keyValue.first) {
outputVariable->addTerm(parseTerm(keyValue.second, engine));
} else {
- throw fl::Exception("[import error] key <" + keyValue.first + "> not "
+ throw Exception("[import error] key <" + keyValue.first + "> not "
"recognized in pair <" + keyValue.first + ":" + keyValue.second + ">", FL_AT);
}
}
+ engine->addOutputVariable(outputVariable.release());
}
void FllImporter::processRuleBlock(const std::string& block, Engine* engine) const {
std::istringstream reader(block);
std::string line;
- RuleBlock* ruleBlock = new RuleBlock;
- engine->addRuleBlock(ruleBlock);
+ FL_unique_ptr<RuleBlock> ruleBlock(new RuleBlock);
while (std::getline(reader, line)) {
std::pair<std::string, std::string> keyValue = parseKeyValue(line, ':');
if ("RuleBlock" == keyValue.first) {
ruleBlock->setName(keyValue.second);
+ } else if ("description" == keyValue.first) {
+ ruleBlock->setDescription(keyValue.second);
} else if ("enabled" == keyValue.first) {
ruleBlock->setEnabled(parseBoolean(keyValue.second));
} else if ("conjunction" == keyValue.first) {
ruleBlock->setConjunction(parseTNorm(keyValue.second));
} else if ("disjunction" == keyValue.first) {
ruleBlock->setDisjunction(parseSNorm(keyValue.second));
+ } else if ("implication" == keyValue.first) {
+ ruleBlock->setImplication(parseTNorm(keyValue.second));
} else if ("activation" == keyValue.first) {
- ruleBlock->setActivation(parseTNorm(keyValue.second));
+ TNormFactory* tnorm = FactoryManager::instance()->tnorm();
+ //@todo remove backwards compatibility in version 7.0
+ if (tnorm->hasConstructor(keyValue.second)) {
+ ruleBlock->setImplication(parseTNorm(keyValue.second));
+ FL_LOG("[warning] obsolete usage of identifier <activation: TNorm> "
+ "in RuleBlock");
+ FL_LOG("[information] from version 6.0, the identifiers are "
+ "<activation: Activation> for Activation methods "
+ "and <implication: TNorm> for T-Norms");
+ FL_LOG("[backward compatibility] assumed "
+ "<implication: " << keyValue.second << "> "
+ "instead of <activation: " << keyValue.second << ">");
+ } else {
+ ruleBlock->setActivation(parseActivation(keyValue.second));
+ }
} else if ("rule" == keyValue.first) {
Rule* rule = new Rule;
rule->setText(keyValue.second);
@@ -200,10 +205,14 @@ namespace fl {
}
ruleBlock->addRule(rule);
} else {
- throw fl::Exception("[import error] key <" + keyValue.first + "> not "
+ throw Exception("[import error] key <" + keyValue.first + "> not "
"recognized in pair <" + keyValue.first + ":" + keyValue.second + ">", FL_AT);
}
}
+ if (not ruleBlock->getActivation()){
+ ruleBlock->setActivation(new General);
+ }
+ engine->addRuleBlock(ruleBlock.release());
}
Term* FllImporter::parseTerm(const std::string& text, Engine* engine) const {
@@ -212,12 +221,12 @@ namespace fl {
//MEDIUM Triangle 0.500 1.000 1.500
if (tokens.size() < 2) {
- throw fl::Exception("[syntax error] expected a term in format <name class parameters>, "
+ throw Exception("[syntax error] expected a term in format <name class parameters>, "
"but found <" + text + ">", FL_AT);
}
FL_unique_ptr<Term> term;
term.reset(FactoryManager::instance()->term()->constructObject(tokens.at(1)));
- Term::updateReference(term.get(), engine);
+ term->updateReference(engine);
term->setName(Op::validName(tokens.at(0)));
std::ostringstream parameters;
for (std::size_t i = 2; i < tokens.size(); ++i) {
@@ -238,6 +247,20 @@ namespace fl {
return FactoryManager::instance()->snorm()->constructObject(name);
}
+ Activation* FllImporter::parseActivation(const std::string& name) const {
+ if (name == "none") return FactoryManager::instance()->activation()->constructObject("");
+ std::vector<std::string> tokens = Op::split(name, " ");
+ Activation* result = FactoryManager::instance()->activation()->constructObject(tokens.front());
+
+ std::ostringstream parameters;
+ for (std::size_t i = 1; i < tokens.size(); ++i) {
+ parameters << tokens.at(i);
+ if (i + 1 < tokens.size()) parameters << " ";
+ }
+ result->configure(parameters.str());
+ return result;
+ }
+
Defuzzifier* FllImporter::parseDefuzzifier(const std::string& text) const {
std::vector<std::string> parameters = Op::split(text, " ");
std::string name = parameters.at(0);
@@ -252,7 +275,7 @@ namespace fl {
if (parameter == "Automatic") type = WeightedDefuzzifier::Automatic;
else if (parameter == "TakagiSugeno") type = WeightedDefuzzifier::TakagiSugeno;
else if (parameter == "Tsukamoto") type = WeightedDefuzzifier::Tsukamoto;
- else throw fl::Exception("[syntax error] unknown parameter of WeightedDefuzzifier <" + parameter + ">", FL_AT);
+ else throw Exception("[syntax error] unknown parameter of WeightedDefuzzifier <" + parameter + ">", FL_AT);
weightedDefuzzifier->setType(type);
}
}
@@ -267,7 +290,7 @@ namespace fl {
bool FllImporter::parseBoolean(const std::string& boolean) const {
if ("true" == boolean) return true;
if ("false" == boolean) return false;
- throw fl::Exception("[syntax error] expected boolean <true|false>, "
+ throw Exception("[syntax error] expected boolean <true|false>, "
"but found <" + boolean + ">", FL_AT);
}
@@ -278,7 +301,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected pair in the form "
"<key" << separator << "value>, but found <" << text << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
std::pair<std::string, std::string> result;
result.first = text.substr(0, half);
@@ -286,32 +309,8 @@ namespace fl {
return result;
}
- std::string FllImporter::clean(const std::string& line) const {
- if (line.empty()) return line;
- if (line.size() == 1) return isspace(line.at(0)) ? "" : line;
- int start = 0, end = line.size() - 1;
- while (start <= end and isspace(line.at(start))) {
- ++start;
- }
- int sharp = start;
- while (sharp <= end) {
- if (line.at(sharp) == '#') {
- end = sharp - 1;
- break;
- }
- ++sharp;
- }
- while (end >= start and (line.at(end) == '#' or isspace(line.at(end)))) {
- --end;
- }
-
- int length = end - start + 1;
- return line.substr(start, length);
- }
-
FllImporter* FllImporter::clone() const {
return new FllImporter(*this);
}
-
}
diff --git a/fuzzylite/src/imex/Importer.cpp b/fuzzylite/src/imex/Importer.cpp
index faef71d..c0be7f5 100644
--- a/fuzzylite/src/imex/Importer.cpp
+++ b/fuzzylite/src/imex/Importer.cpp
@@ -1,46 +1,34 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/Importer.h"
#include "fl/Exception.h"
#include <fstream>
-#include <ostream>
namespace fl {
- Importer::Importer() {
- }
+ Importer::Importer() { }
- Importer::~Importer() {
-
- }
+ Importer::~Importer() { }
Engine* Importer::fromFile(const std::string& path) const {
std::ifstream reader(path.c_str());
if (not reader.is_open()) {
- throw fl::Exception("[file error] file <" + path + "> could not be opened", FL_AT);
+ throw Exception("[file error] file <" + path + "> could not be opened", FL_AT);
}
std::ostringstream textEngine;
std::string line;
diff --git a/fuzzylite/src/imex/JavaExporter.cpp b/fuzzylite/src/imex/JavaExporter.cpp
index a4948f8..6981dae 100644
--- a/fuzzylite/src/imex/JavaExporter.cpp
+++ b/fuzzylite/src/imex/JavaExporter.cpp
@@ -1,60 +1,59 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/imex/JavaExporter.h"
#include "fl/Headers.h"
-#include <algorithm>
namespace fl {
- JavaExporter::JavaExporter() : Exporter() {
- }
+ JavaExporter::JavaExporter(bool usingVariableNames) : Exporter(),
+ _usingVariableNames(usingVariableNames) { }
- JavaExporter::~JavaExporter() {
-
- }
+ JavaExporter::~JavaExporter() { }
std::string JavaExporter::name() const {
return "JavaExporter";
}
+ void JavaExporter::setUsingVariableNames(bool usingVariableNames) {
+ this->_usingVariableNames = usingVariableNames;
+ }
+
+ bool JavaExporter::isUsingVariableNames() const {
+ return this->_usingVariableNames;
+ }
+
std::string JavaExporter::toString(const Engine* engine) const {
std::ostringstream ss;
+ ss << "//Code automatically generated with " << fuzzylite::library() << ".\n\n";
ss << "Engine engine = new Engine();\n";
ss << "engine.setName(\"" << engine->getName() << "\");\n";
+ ss << "engine.setDescription(\"" << engine->getDescription() << "\");\n";
ss << "\n";
- for (int i = 0; i < engine->numberOfInputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfInputVariables(); ++i) {
ss << toString(engine->getInputVariable(i), engine) << "\n";
}
- for (int i = 0; i < engine->numberOfOutputVariables(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfOutputVariables(); ++i) {
ss << toString(engine->getOutputVariable(i), engine) << "\n";
}
- for (int i = 0; i < engine->numberOfRuleBlocks(); ++i) {
+ for (std::size_t i = 0; i < engine->numberOfRuleBlocks(); ++i) {
ss << toString(engine->getRuleBlock(i), engine) << "\n";
}
@@ -63,21 +62,28 @@ namespace fl {
std::string JavaExporter::toString(const InputVariable* inputVariable, const Engine* engine) const {
std::ostringstream ss;
- std::string name = "inputVariable";
- if (engine->numberOfInputVariables() > 1) {
- int index = std::distance(engine->inputVariables().begin(),
- std::find(engine->inputVariables().begin(),
- engine->inputVariables().end(), inputVariable));
- name += Op::str<int>(index + 1);
+ std::string name;
+ if (isUsingVariableNames()) {
+ name = Op::validName(inputVariable->getName());
+ } else {
+ name = "inputVariable";
+ if (engine->numberOfInputVariables() > 1) {
+ std::size_t index = std::distance(engine->inputVariables().begin(),
+ std::find(engine->inputVariables().begin(),
+ engine->inputVariables().end(), inputVariable));
+ name += Op::str(index + 1);
+ }
}
ss << "InputVariable " << name << " = new InputVariable();\n";
- ss << name << ".setEnabled(" << (inputVariable->isEnabled() ? "true" : "false") << ");\n";
ss << name << ".setName(\"" << inputVariable->getName() << "\");\n";
+ ss << name << ".setDescription(\"" << inputVariable->getDescription() << "\");\n";
+ ss << name << ".setEnabled(" << (inputVariable->isEnabled() ? "true" : "false") << ");\n";
ss << name << ".setRange("
<< toString(inputVariable->getMinimum()) << ", "
<< toString(inputVariable->getMaximum()) << ");\n";
-
- for (int i = 0; i < inputVariable->numberOfTerms(); ++i) {
+ ss << name << ".setLockValueInRange("
+ << (inputVariable->isLockValueInRange() ? "true" : "false") << ");\n";
+ for (std::size_t i = 0; i < inputVariable->numberOfTerms(); ++i) {
ss << name << ".addTerm(" <<
toString(inputVariable->getTerm(i)) << ");\n";
}
@@ -87,30 +93,36 @@ namespace fl {
std::string JavaExporter::toString(const OutputVariable* outputVariable, const Engine* engine) const {
std::ostringstream ss;
- std::string name = "outputVariable";
- if (engine->numberOfOutputVariables() > 1) {
- int index = std::distance(engine->outputVariables().begin(),
- std::find(engine->outputVariables().begin(),
- engine->outputVariables().end(), outputVariable));
- name += Op::str<int>(index + 1);
+ std::string name;
+ if (isUsingVariableNames()) {
+ name = Op::validName(outputVariable->getName());
+ } else {
+ name = "outputVariable";
+ if (engine->numberOfOutputVariables() > 1) {
+ std::size_t index = std::distance(engine->outputVariables().begin(),
+ std::find(engine->outputVariables().begin(),
+ engine->outputVariables().end(), outputVariable));
+ name += Op::str(index + 1);
+ }
}
ss << "OutputVariable " << name << " = new OutputVariable();\n";
- ss << name << ".setEnabled(" << (outputVariable->isEnabled() ? "true" : "false") << ");\n";
ss << name << ".setName(\"" << outputVariable->getName() << "\");\n";
+ ss << name << ".setDescription(\"" << outputVariable->getDescription() << "\");\n";
+ ss << name << ".setEnabled(" << (outputVariable->isEnabled() ? "true" : "false") << ");\n";
ss << name << ".setRange("
<< toString(outputVariable->getMinimum()) << ", "
<< toString(outputVariable->getMaximum()) << ");\n";
- ss << name << ".fuzzyOutput().setAccumulation(" <<
- toString(outputVariable->fuzzyOutput()->getAccumulation()) << ");\n";
+ ss << name << ".setLockValueInRange(" <<
+ (outputVariable->isLockValueInRange() ? "true" : "false") << ");\n";
+ ss << name << ".setAggregation(" <<
+ toString(outputVariable->fuzzyOutput()->getAggregation()) << ");\n";
ss << name << ".setDefuzzifier(" <<
toString(outputVariable->getDefuzzifier()) << ");\n";
ss << name << ".setDefaultValue(" <<
toString(outputVariable->getDefaultValue()) << ");\n";
- ss << name << ".setLockPreviousOutputValue(" <<
- (outputVariable->isLockedPreviousOutputValue() ? "true" : "false") << ");\n";
- ss << name << ".setLockOutputValueInRange(" <<
- (outputVariable->isLockedOutputValueInRange() ? "true" : "false") << ");\n";
- for (int i = 0; i < outputVariable->numberOfTerms(); ++i) {
+ ss << name << ".setLockPreviousValue(" <<
+ (outputVariable->isLockPreviousValue() ? "true" : "false") << ");\n";
+ for (std::size_t i = 0; i < outputVariable->numberOfTerms(); ++i) {
ss << name << ".addTerm(" <<
toString(outputVariable->getTerm(i)) << ");\n";
}
@@ -120,23 +132,33 @@ namespace fl {
std::string JavaExporter::toString(const RuleBlock* ruleBlock, const Engine* engine) const {
std::ostringstream ss;
- std::string name = "ruleBlock";
- if (engine->numberOfRuleBlocks() > 1) {
- int index = std::distance(engine->ruleBlocks().begin(),
- std::find(engine->ruleBlocks().begin(),
- engine->ruleBlocks().end(), ruleBlock));
- name += Op::str<int>(index + 1);
+ std::string name;
+
+ if (isUsingVariableNames() and not ruleBlock->getName().empty()) {
+ name = Op::validName(ruleBlock->getName());
+ } else {
+ name = "ruleBlock";
+ if (engine->numberOfRuleBlocks() > 1) {
+ std::size_t index = std::distance(engine->ruleBlocks().begin(),
+ std::find(engine->ruleBlocks().begin(),
+ engine->ruleBlocks().end(), ruleBlock));
+ name += Op::str(index + 1);
+ }
}
+
ss << "RuleBlock " << name << " = new RuleBlock();\n";
- ss << name << ".setEnabled(" << (ruleBlock->isEnabled() ? "true" : "false") << ");\n";
ss << name << ".setName(\"" << ruleBlock->getName() << "\");\n";
+ ss << name << ".setDescription(\"" << ruleBlock->getDescription() << "\");\n";
+ ss << name << ".setEnabled(" << (ruleBlock->isEnabled() ? "true" : "false") << ");\n";
ss << name << ".setConjunction("
<< toString(ruleBlock->getConjunction()) << ");\n";
ss << name << ".setDisjunction("
<< toString(ruleBlock->getDisjunction()) << ");\n";
+ ss << name << ".setImplication("
+ << toString(ruleBlock->getImplication()) << ");\n";
ss << name << ".setActivation("
<< toString(ruleBlock->getActivation()) << ");\n";
- for (int i = 0; i < ruleBlock->numberOfRules(); ++i) {
+ for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
Rule* rule = ruleBlock->getRule(i);
ss << name << ".addRule(Rule.parse(\"" << rule->getText() << "\", engine));\n";
}
@@ -183,7 +205,7 @@ namespace fl {
if (const IntegralDefuzzifier * integralDefuzzifier =
dynamic_cast<const IntegralDefuzzifier*> (defuzzifier)) {
return "new " + integralDefuzzifier->className() + "("
- + fl::Op::str(integralDefuzzifier->getResolution()) + ")";
+ + Op::str(integralDefuzzifier->getResolution()) + ")";
}
if (const WeightedDefuzzifier * weightedDefuzzifier =
dynamic_cast<const WeightedDefuzzifier*> (defuzzifier)) {
@@ -193,19 +215,22 @@ namespace fl {
return "new " + defuzzifier->className() + "()";
}
- std::string JavaExporter::toString(const Norm* norm) const{
- if (not norm) return "null";
- return "new " + norm->className() + "()";
- }
-
- std::string JavaExporter::toString(const TNorm* norm) const {
+ std::string JavaExporter::toString(const Norm* norm) const {
if (not norm) return "null";
return "new " + norm->className() + "()";
}
- std::string JavaExporter::toString(const SNorm* norm) const {
- if (not norm) return "null";
- return "new " + norm->className() + "()";
+ std::string JavaExporter::toString(const Activation* activation) const {
+ if (not activation) return "null";
+ std::string parameters = Op::trim(activation->parameters());
+ if (parameters.empty()) return "new " + activation->className() + "()";
+
+ std::vector<std::string> values = Op::split(parameters, " ");
+ for (std::size_t i = 0; i < values.size(); ++i) {
+ std::string parameter = values.at(i);
+ values.at(i) = (Op::isNumeric(parameter) ? parameter : ("\"" + parameter + "\""));
+ }
+ return "new " + activation->className() + "(" + Op::join(values, ", ") + ")";
}
std::string JavaExporter::toString(scalar value) const {
@@ -223,6 +248,4 @@ namespace fl {
return new JavaExporter(*this);
}
-
}
-
diff --git a/fuzzylite/src/imex/RScriptExporter.cpp b/fuzzylite/src/imex/RScriptExporter.cpp
new file mode 100644
index 0000000..5fe53c7
--- /dev/null
+++ b/fuzzylite/src/imex/RScriptExporter.cpp
@@ -0,0 +1,234 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/imex/RScriptExporter.h"
+
+#include "fl/Engine.h"
+#include "fl/imex/FllExporter.h"
+#include "fl/variable/InputVariable.h"
+#include "fl/variable/OutputVariable.h"
+
+#include <fstream>
+namespace fl {
+
+ RScriptExporter::RScriptExporter() : Exporter(),
+ _minimumColor("yellow"), _maximumColor("red"), _contourColor("black") { }
+
+ RScriptExporter::~RScriptExporter() { }
+
+ std::string RScriptExporter::name() const {
+ return "RScriptExporter";
+ }
+
+ void RScriptExporter::setMinimumColor(const std::string& minimumColor) {
+ this->_minimumColor = minimumColor;
+ }
+
+ std::string RScriptExporter::getMinimumColor() const {
+ return this->_minimumColor;
+ }
+
+ void RScriptExporter::setMaximumColor(const std::string& maximumColor) {
+ this->_maximumColor = maximumColor;
+ }
+
+ std::string RScriptExporter::getMaximumColor() const {
+ return _maximumColor;
+ }
+
+ void RScriptExporter::setContourColor(const std::string& contourColor) {
+ this->_contourColor = contourColor;
+ }
+
+ std::string RScriptExporter::getContourColor() const {
+ return this->_contourColor;
+ }
+
+ RScriptExporter* RScriptExporter::clone() const {
+ return new RScriptExporter(*this);
+ }
+
+ std::string RScriptExporter::toString(const Engine* engine) const {
+ if (engine->inputVariables().empty()) {
+ throw Exception("[exporter error] engine has no input variables to export the surface", FL_AT);
+ }
+ if (engine->outputVariables().empty()) {
+ throw Exception("[exporter error] engine has no output variables to export the surface", FL_AT);
+ }
+ InputVariable* a = engine->inputVariables().at(0);
+ InputVariable* b = engine->inputVariables().at(1 % engine->numberOfInputVariables());
+ return toString(const_cast<Engine*> (engine), a, b,
+ 1024, FldExporter::AllVariables, engine->outputVariables());
+ }
+
+ std::string RScriptExporter::toString(Engine* engine, InputVariable* a, InputVariable* b,
+ int values, FldExporter::ScopeOfValues scope,
+ const std::vector<OutputVariable*>& outputVariables) const {
+ std::ostringstream writer;
+ writeScriptExportingDataFrame(engine, writer, a, b, values, scope, outputVariables);
+ return writer.str();
+ }
+
+ std::string RScriptExporter::toString(Engine* engine, InputVariable* a, InputVariable* b,
+ std::istream& reader, const std::vector<OutputVariable*>& outputVariables) const {
+ std::ostringstream writer;
+ writeScriptExportingDataFrame(engine, writer, a, b, reader, outputVariables);
+ return writer.str();
+ }
+
+ void RScriptExporter::toFile(const std::string& filePath, const Engine* engine) const {
+ if (engine->inputVariables().empty()) {
+ throw Exception("[exporter error] engine has no input variables to export the surface", FL_AT);
+ }
+ if (engine->outputVariables().empty()) {
+ throw Exception("[exporter error] engine has no output variables to export the surface", FL_AT);
+ }
+ InputVariable* a = engine->inputVariables().at(0);
+ InputVariable* b = engine->inputVariables().at(1 % engine->numberOfInputVariables());
+
+ toFile(filePath, const_cast<Engine*> (engine), a, b,
+ 1024, FldExporter::AllVariables, engine->outputVariables());
+ }
+
+ void RScriptExporter::toFile(const std::string& filePath, Engine* engine,
+ InputVariable* a, InputVariable* b, int values, FldExporter::ScopeOfValues scope,
+ const std::vector<OutputVariable*>& outputVariables) const {
+ std::ofstream writer(filePath.c_str());
+ if (not writer.is_open()) {
+ throw Exception("[file error] file <" + filePath + "> could not be created", FL_AT);
+ }
+ writeScriptExportingDataFrame(engine, writer, a, b, values, scope, outputVariables);
+ writer.close();
+ }
+
+ void RScriptExporter::toFile(const std::string& filePath, Engine* engine,
+ InputVariable* a, InputVariable* b, std::istream& reader,
+ const std::vector<OutputVariable*>& outputVariables) const {
+ std::ofstream writer(filePath.c_str());
+ if (not writer.is_open()) {
+ throw Exception("[file error] file <" + filePath + "> could not be created", FL_AT);
+ }
+ writeScriptExportingDataFrame(engine, writer, a, b, reader, outputVariables);
+ writer.close();
+ }
+
+ void RScriptExporter::writeScriptImportingDataFrame(const Engine* engine, std::ostream& writer,
+ InputVariable* a, InputVariable* b, const std::string& dfPath,
+ const std::vector<OutputVariable*>& outputVariables) const {
+ writeScriptHeader(writer, engine);
+
+ writer << "engine.fldFile = \"" << dfPath << "\"\n";
+ writer << "if (require(data.table)) {\n"
+ << " engine.df = data.table::fread(engine.fldFile, sep=\"auto\", header=\"auto\")\n"
+ << "} else {\n"
+ << " engine.df = read.table(engine.fldFile, header=TRUE)\n"
+ << "}\n";
+ writer << "\n";
+
+ writeScriptPlots(writer, a, b, outputVariables);
+ }
+
+ void RScriptExporter::writeScriptExportingDataFrame(Engine* engine, std::ostream& writer,
+ InputVariable* a, InputVariable* b, int values, FldExporter::ScopeOfValues scope,
+ const std::vector<OutputVariable*>& outputVariables) const {
+ writeScriptHeader(writer, engine);
+
+ std::vector<InputVariable*> activeVariables = engine->inputVariables();
+ for (std::size_t i = 0; i < activeVariables.size(); ++i) {
+ if (activeVariables.at(i) != a and activeVariables.at(i) != b) {
+ activeVariables.at(i) = fl::null;
+ }
+ }
+ writer << "engine.fld = \"";
+ FldExporter().write(engine, writer, values, scope, activeVariables);
+ writer << "\"\n\n";
+ writer << "engine.df = read.delim(textConnection(engine.fld), header=TRUE, "
+ "sep=\" \", strip.white=TRUE)\n\n";
+
+ writeScriptPlots(writer, a, b, outputVariables);
+ }
+
+ void RScriptExporter::writeScriptExportingDataFrame(Engine* engine, std::ostream& writer,
+ InputVariable* a, InputVariable* b, std::istream& reader,
+ const std::vector<OutputVariable*>& outputVariables) const {
+ writeScriptHeader(writer, engine);
+
+ writer << "engine.fld = \"";
+ FldExporter().write(engine, writer, reader);
+ writer << "\"\n\n";
+
+ writer << "engine.df = read.delim(textConnection(engine.fld), header=TRUE, "
+ "sep=\" \", strip.white=TRUE)\n\n";
+
+ writeScriptPlots(writer, a, b, outputVariables);
+ }
+
+ void RScriptExporter::writeScriptHeader(std::ostream& writer, const Engine* engine) const {
+ writer << "#Code automatically generated with " << fuzzylite::library() << ".\n\n"
+ << "library(ggplot2);\n"
+ << "\n";
+ writer << "engine.name = \"" << engine->getName() << "\"\n";
+ if (not engine->getDescription().empty())
+ writer << "engine.description = \"" << engine->getDescription() << "\"\n";
+ writer << "engine.fll = \"" << FllExporter().toString(engine) << "\"\n\n";
+ }
+
+ void RScriptExporter::writeScriptPlots(std::ostream& writer,
+ InputVariable* a, InputVariable* b,
+ const std::vector<OutputVariable*>& outputVariables) const {
+ std::ostringstream arrangeGrob;
+ arrangeGrob << "arrangeGrob(";
+ for (std::size_t i = 0; i < outputVariables.size(); ++i) {
+ OutputVariable* z = outputVariables.at(i);
+ if (a != b) {
+ writer << "engine.plot.i1i2_o" << (i + 1) << " = ggplot(engine.df, aes(" << a->getName() << ", " << b->getName() << ")) + \n"
+ << " geom_tile(aes(fill=" << z->getName() << ")) + \n"
+ << " scale_fill_gradient(low=\"" << _minimumColor << "\", high=\"" << _maximumColor << "\") + \n"
+ << " stat_contour(aes(x=" << a->getName() << ", y=" << b->getName() << ", z=" << z->getName() << "), color=\"" << _contourColor << "\") + \n"
+ << " ggtitle(\"(" << a->getName() << ", " << b->getName() << ") = " << z->getName() << "\")\n\n";
+
+ writer << "engine.plot.i2i1_o" << (i + 1) << " = ggplot(engine.df, aes(" << b->getName() << ", " << a->getName() << ")) + \n"
+ << " geom_tile(aes(fill=" << z->getName() << ")) + \n"
+ << " scale_fill_gradient(low=\"" << _minimumColor << "\", high=\"" << _maximumColor << "\") + \n"
+ << " stat_contour(aes(x=" << b->getName() << ", y=" << a->getName() << ", z=" << z->getName() << "), color=\"" << _contourColor << "\") + \n"
+ << " ggtitle(\"(" << b->getName() << ", " << a->getName() << ") = " << z->getName() << "\")\n\n";
+ arrangeGrob << "engine.plot.i1i2_o" << (i + 1) << ", " << "engine.plot.i2i1_o" << (i + 1) << ", ";
+ } else {
+ writer << "engine.plot.i1_o" << (i + 1) << " = ggplot(engine.df, aes(" << a->getName() << ", " << z->getName() << ")) + \n"
+ << " geom_line(aes(color=" << z->getName() << "), size=3, lineend=\"round\", linejoin=\"mitre\") + \n"
+ << " scale_color_gradient(low=\"" << _minimumColor << "\", high=\"" << _maximumColor << "\") + \n"
+ << " ggtitle(\"" << a->getName() << " vs " << z->getName() << "\")\n\n";
+
+ writer << "engine.plot.o" << (i + 1) << "_i1 = ggplot(engine.df, aes(" << a->getName() << ", " << z->getName() << ")) + \n"
+ << " geom_line(aes(color=" << z->getName() << "), size=3, lineend=\"round\", linejoin=\"mitre\") + \n"
+ << " scale_color_gradient(low=\"" << _minimumColor << "\", high=\"" << _maximumColor << "\") + \n"
+ << " coord_flip() + \n"
+ << " ggtitle(\"" << z->getName() << " vs " << a->getName() << "\")\n\n";
+ arrangeGrob << "engine.plot.i1_o" << (i + 1) << ", " << "engine.plot.o" << (i + 1) << "_i1, ";
+ }
+
+ }
+ arrangeGrob << "ncol=2, top=engine.name)";
+ writer << "if (require(gridExtra)) {\n"
+ << " engine.plots = " << arrangeGrob.str() << "\n"
+ << " ggsave(paste0(engine.name, \".pdf\"), engine.plots)\n"
+ << " if (require(grid)) {\n"
+ << " grid.newpage()\n"
+ << " grid.draw(engine.plots)\n"
+ << " }\n"
+ << "}\n";
+ }
+}
diff --git a/fuzzylite/src/m/compare.m b/fuzzylite/src/m/compare.m
deleted file mode 100755
index 56da68d..0000000
--- a/fuzzylite/src/m/compare.m
+++ /dev/null
@@ -1,60 +0,0 @@
-%{/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
-
- This file is part of fuzzylite.
-
- fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzylite (R) is a registered trademark of FuzzyLite Limited.
- */
-}%
-
-function [engine] = compare(fisFile, fldFile, delimiter, hasMetadata)
-if (nargin < 3)
- delimiter = ' ';
-end
-if (nargin < 4)
- hasMetadata = true;
-end
-
-engine = readfis(fisFile);
-flMatrix = dlmread(fldFile, delimiter, hasMetadata ~ = 0, 0);
-
-if (length(engine.input) + length(engine.output) ~ = size(flMatrix, 2))
- error('fuzzylite:compare.m', 'Number of inputs and outputs in engine differ from FLD matrix');
-end
-
-if (isempty(engine.andMethod))
- engine.andMethod = 'min';
-end
-if (isempty(engine.orMethod))
- engine.orMethod = 'max';
-end
-
-engine.inputValues = flMatrix(1 : end, 1 : length(engine.input));
-engine.outputValues = evalfis(engine.inputValues, engine);
-engine.flOutputValues = flMatrix(1 : end, (length(engine.input) + 1) : (length(engine.input) + length(engine.output)));
-engine.outputDiff = engine.outputValues - engine.flOutputValues;
-engine.fld = [engine.inputValues engine.outputValues engine.flOutputValues engine.outputDiff];
-engine.nanfreeDiff = engine.outputDiff;
-engine.nanfreeDiff(find(isnan(engine.nanfreeDiff))) = 0;
-engine.mse = nansum(engine.outputDiff.^2) / size(engine.outputDiff, 1);
-engine.quantiles = prctile(engine.nanfreeDiff, 0 : 25 : 100);
-
-end
-
-
-
diff --git a/fuzzylite/src/m/compare_examples.m b/fuzzylite/src/m/compare_examples.m
deleted file mode 100755
index 1bf6818..0000000
--- a/fuzzylite/src/m/compare_examples.m
+++ /dev/null
@@ -1,45 +0,0 @@
-%{/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
-
- This file is part of fuzzylite.
-
- fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzylite (R) is a registered trademark of FuzzyLite Limited.
- */
-}%
-
-
-function [ engines ] = compare_examples(path, delimiter, hasMetadata)
-if (nargin < 2)
- delimiter = ' ';
-end
-if (nargin < 3)
- hasMetadata = true;
-end
-
-examples = {'\mamdani\SimpleDimmer', '\mamdani\matlab\mam21', '\mamdani\matlab\mam22', '\mamdani\matlab\shower', '\mamdani\matlab\tank', '\mamdani\matlab\tank2', '\mamdani\matlab\tipper', '\mamdani\matlab\tipper1', '\mamdani\octave\mamdani_tip_calculator', '\takagi-sugeno\SimpleDimmer', '\takagi-sugeno\matlab\fpeaks', '\takagi-sugeno\matlab\invkine1', '\takagi-sugeno\matlab\invkine2', '\takagi-sugeno\matlab\juggler', '\takagi-sugeno\matlab\membrn1', '\takagi-sugeno\matlab\membrn2', '\takagi-sugeno\matlab\slbb', '\takagi-sugeno\matlab\slcp', '\takagi-sugeno\matlab\slcp1', '\takagi-sugeno\matlab\slcpp1', '\takagi-sugeno\matlab\sltbu_fl', '\takagi-sugeno\matlab\sugeno1', '\takagi-sugeno\matlab\tanksg', '\takagi-sugeno\matlab\tippersg', '\takagi-sugeno\octave\cubic_approximator', '\takagi-sugeno\octave\heart_disease_risk', '\takagi-sugeno\octave\linear_tip_calculator'};
-pending = {'\mamdani\octave\investment_portfolio', '\takagi-sugeno\approximation', '\takagi-sugeno\octave\sugeno_tip_calculator', '\tsukamoto\tsukamoto'};
-engines = [];
-for i = 1 : length(examples)
- fisFile = strcat(path, examples{i}, '.fis')
- fldFile = strcat(path, examples{i}, '.fld');
- engines = [engines compare(fisFile, fldFile, delimiter, hasMetadata)];
- disp(strcat('Five number summary (', num2str(i), '): ', fisFile));
- engines(i).quantiles
-end
-end
-
diff --git a/fuzzylite/src/main.cpp b/fuzzylite/src/main.cpp
index 6d8d701..06ca139 100644
--- a/fuzzylite/src/main.cpp
+++ b/fuzzylite/src/main.cpp
@@ -1,70 +1,49 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/Headers.h"
-#include <cstdlib>
#include <fstream>
-#include <iomanip>
-#include <signal.h>
-#include <typeinfo>
-
-using namespace fl;
-
-/*
-#ifdef FL_WINDOWS
-#include <windows.h>
-BOOL WINAPI flSignalHandler(DWORD dwCtrlType)
-{
- FL_LOG("Signal: " << dwCtrlType);
- if (CTRL_C_EVENT == dwCtrlType){
- }
- //return FALSE;
- return TRUE;
-}
-#endif
- */
+#include <csignal>
-int main(int argc, char** argv) {
- (void) argc;
- (void) argv;
+int main(int argc, const char* argv[]) {
std::set_terminate(fl::Exception::terminate);
std::set_unexpected(fl::Exception::terminate);
- signal(SIGSEGV, fl::Exception::signalHandler);
- signal(SIGABRT, fl::Exception::signalHandler);
- signal(SIGILL, fl::Exception::signalHandler);
- signal(SIGSEGV, fl::Exception::signalHandler);
- signal(SIGFPE, fl::Exception::signalHandler);
+ ::signal(SIGSEGV, fl::Exception::signalHandler);
+ ::signal(SIGABRT, fl::Exception::signalHandler);
+ ::signal(SIGILL, fl::Exception::signalHandler);
+ ::signal(SIGSEGV, fl::Exception::signalHandler);
+ ::signal(SIGFPE, fl::Exception::signalHandler);
#ifdef FL_UNIX
- signal(SIGBUS, fl::Exception::signalHandler);
- signal(SIGPIPE, fl::Exception::signalHandler);
+ ::signal(SIGBUS, fl::Exception::signalHandler);
+ ::signal(SIGPIPE, fl::Exception::signalHandler);
#endif
#ifdef FL_WINDOWS
//SetConsoleCtrlHandler(flSignalHandler, TRUE);
#endif
- fuzzylite::setDebug(false);
- return Console::main(argc, argv);
+ fl::fuzzylite::setDebugging(false);
+
+ try {
+ fl::Console::main(argc, argv);
+ } catch (std::exception& ex) {
+ std::cout << ex.what() << "\nBACKTRACE:\n" <<
+ fl::Exception::btCallStack() << std::endl;
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
}
diff --git a/fuzzylite/src/norm/s/AlgebraicSum.cpp b/fuzzylite/src/norm/s/AlgebraicSum.cpp
index e96c1a7..0497f23 100644
--- a/fuzzylite/src/norm/s/AlgebraicSum.cpp
+++ b/fuzzylite/src/norm/s/AlgebraicSum.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/s/AlgebraicSum.h"
@@ -30,6 +22,10 @@ namespace fl {
return "AlgebraicSum";
}
+ Complexity AlgebraicSum::complexity() const {
+ return Complexity().arithmetic(3);
+ }
+
scalar AlgebraicSum::compute(scalar a, scalar b) const {
return a + b - (a * b);
}
diff --git a/fuzzylite/src/norm/s/BoundedSum.cpp b/fuzzylite/src/norm/s/BoundedSum.cpp
index 9c050c8..b1cb42b 100644
--- a/fuzzylite/src/norm/s/BoundedSum.cpp
+++ b/fuzzylite/src/norm/s/BoundedSum.cpp
@@ -1,35 +1,33 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/s/BoundedSum.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string BoundedSum::className() const {
return "BoundedSum";
}
+ Complexity BoundedSum::complexity() const {
+ return Complexity().arithmetic(1).function(1);
+ }
+
scalar BoundedSum::compute(scalar a, scalar b) const {
return Op::min(scalar(1.0), a + b);
}
diff --git a/fuzzylite/src/norm/s/DrasticSum.cpp b/fuzzylite/src/norm/s/DrasticSum.cpp
index c0629db..b0d9f1e 100644
--- a/fuzzylite/src/norm/s/DrasticSum.cpp
+++ b/fuzzylite/src/norm/s/DrasticSum.cpp
@@ -1,35 +1,33 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/s/DrasticSum.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string DrasticSum::className() const {
return "DrasticSum";
}
+ Complexity DrasticSum::complexity() const {
+ return Complexity().comparison(1).function(2);
+ }
+
scalar DrasticSum::compute(scalar a, scalar b) const {
if (Op::isEq(Op::min(a, b), 0.0)) {
return Op::max(a, b);
diff --git a/fuzzylite/src/norm/s/EinsteinSum.cpp b/fuzzylite/src/norm/s/EinsteinSum.cpp
index ec0fbd8..a638c7b 100644
--- a/fuzzylite/src/norm/s/EinsteinSum.cpp
+++ b/fuzzylite/src/norm/s/EinsteinSum.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/s/EinsteinSum.h"
@@ -30,6 +22,10 @@ namespace fl {
return "EinsteinSum";
}
+ Complexity EinsteinSum::complexity() const {
+ return Complexity().arithmetic(4);
+ }
+
scalar EinsteinSum::compute(scalar a, scalar b) const {
return (a + b) / (1.0 + a * b);
}
diff --git a/fuzzylite/src/norm/s/HamacherSum.cpp b/fuzzylite/src/norm/s/HamacherSum.cpp
index f9c0994..41242ee 100644
--- a/fuzzylite/src/norm/s/HamacherSum.cpp
+++ b/fuzzylite/src/norm/s/HamacherSum.cpp
@@ -1,36 +1,35 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/s/HamacherSum.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string HamacherSum::className() const {
return "HamacherSum";
}
+ Complexity HamacherSum::complexity() const {
+ return Complexity().arithmetic(7);
+ }
+
scalar HamacherSum::compute(scalar a, scalar b) const {
+ if (Op::isEq(a * b, 1.0)) return 1.0;
return (a + b - 2.0 * a * b) / (1.0 - a * b);
}
diff --git a/fuzzylite/src/norm/s/Maximum.cpp b/fuzzylite/src/norm/s/Maximum.cpp
index ed8a839..5277d49 100644
--- a/fuzzylite/src/norm/s/Maximum.cpp
+++ b/fuzzylite/src/norm/s/Maximum.cpp
@@ -1,35 +1,33 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/s/Maximum.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string Maximum::className() const {
return "Maximum";
}
+ Complexity Maximum::complexity() const {
+ return Complexity().function(1);
+ }
+
scalar Maximum::compute(scalar a, scalar b) const {
return Op::max(a, b);
}
diff --git a/fuzzylite/src/norm/s/NilpotentMaximum.cpp b/fuzzylite/src/norm/s/NilpotentMaximum.cpp
index 0a09136..7c63999 100644
--- a/fuzzylite/src/norm/s/NilpotentMaximum.cpp
+++ b/fuzzylite/src/norm/s/NilpotentMaximum.cpp
@@ -1,38 +1,36 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/s/NilpotentMaximum.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string NilpotentMaximum::className() const {
return "NilpotentMaximum";
}
+ Complexity NilpotentMaximum::complexity() const {
+ return Complexity().comparison(1).arithmetic(1).function(1);
+ }
+
scalar NilpotentMaximum::compute(scalar a, scalar b) const {
if (Op::isLt(a + b, 1.0)) {
- return std::max(a, b);
+ return Op::max(a, b);
}
return 1.0;
}
@@ -45,6 +43,4 @@ namespace fl {
return new NilpotentMaximum;
}
-
}
-
diff --git a/fuzzylite/src/norm/s/NormalizedSum.cpp b/fuzzylite/src/norm/s/NormalizedSum.cpp
index 94ad5ea..c420ed1 100644
--- a/fuzzylite/src/norm/s/NormalizedSum.cpp
+++ b/fuzzylite/src/norm/s/NormalizedSum.cpp
@@ -1,37 +1,35 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/s/NormalizedSum.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string NormalizedSum::className() const {
return "NormalizedSum";
}
+ Complexity NormalizedSum::complexity() const {
+ return Complexity().arithmetic(3).function(1);
+ }
+
scalar NormalizedSum::compute(scalar a, scalar b) const {
- return a + b / Op::max(scalar(1.0), Op::max(a, b));
+ return (a + b) / Op::max(scalar(1.0), a + b);
}
NormalizedSum* NormalizedSum::clone() const {
@@ -42,5 +40,4 @@ namespace fl {
return new NormalizedSum;
}
-
}
diff --git a/fuzzylite/src/norm/s/SNormFunction.cpp b/fuzzylite/src/norm/s/SNormFunction.cpp
new file mode 100644
index 0000000..f8d9e42
--- /dev/null
+++ b/fuzzylite/src/norm/s/SNormFunction.cpp
@@ -0,0 +1,65 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/norm/s/SNormFunction.h"
+
+namespace fl {
+
+ SNormFunction::SNormFunction(const std::string& formula) : SNorm() {
+ _function.variables["a"] = fl::nan;
+ _function.variables["b"] = fl::nan;
+ if (not formula.empty()) {
+ _function.load(formula);
+ }
+ }
+
+ std::string SNormFunction::className() const {
+ return "SNormFunction";
+ }
+
+ Complexity SNormFunction::complexity() const {
+ if (_function.root())
+ return _function.complexity().function(2 * std::log(scalar(_function.variables.size())));
+ return _function.complexity();
+ }
+
+ scalar SNormFunction::compute(scalar a, scalar b) const {
+ _function.variables["a"] = a;
+ _function.variables["b"] = b;
+ return _function.evaluate();
+ }
+
+ Function& SNormFunction::function() {
+ return this->_function;
+ }
+
+ void SNormFunction::setFormula(const std::string& formula) {
+ this->_function.load(formula);
+ }
+
+ std::string SNormFunction::getFormula() const {
+ return _function.getFormula();
+ }
+
+ SNormFunction* SNormFunction::clone() const {
+ return new SNormFunction(*this);
+ }
+
+ SNorm* SNormFunction::constructor() {
+ return new SNormFunction;
+ }
+
+}
diff --git a/fuzzylite/src/norm/s/UnboundedSum.cpp b/fuzzylite/src/norm/s/UnboundedSum.cpp
new file mode 100644
index 0000000..adee6ad
--- /dev/null
+++ b/fuzzylite/src/norm/s/UnboundedSum.cpp
@@ -0,0 +1,43 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/norm/s/UnboundedSum.h"
+
+#include "fl/Operation.h"
+
+namespace fl {
+
+ std::string UnboundedSum::className() const {
+ return "UnboundedSum";
+ }
+
+ Complexity UnboundedSum::complexity() const {
+ return Complexity().arithmetic(1);
+ }
+
+ scalar UnboundedSum::compute(scalar a, scalar b) const {
+ return a + b;
+ }
+
+ UnboundedSum* UnboundedSum::clone() const {
+ return new UnboundedSum(*this);
+ }
+
+ SNorm* UnboundedSum::constructor() {
+ return new UnboundedSum;
+ }
+
+}
diff --git a/fuzzylite/src/norm/t/AlgebraicProduct.cpp b/fuzzylite/src/norm/t/AlgebraicProduct.cpp
index eee1061..eefe309 100644
--- a/fuzzylite/src/norm/t/AlgebraicProduct.cpp
+++ b/fuzzylite/src/norm/t/AlgebraicProduct.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/t/AlgebraicProduct.h"
@@ -30,6 +22,10 @@ namespace fl {
return "AlgebraicProduct";
}
+ Complexity AlgebraicProduct::complexity() const {
+ return Complexity().arithmetic(1);
+ }
+
scalar AlgebraicProduct::compute(scalar a, scalar b) const {
return a * b;
}
diff --git a/fuzzylite/src/norm/t/BoundedDifference.cpp b/fuzzylite/src/norm/t/BoundedDifference.cpp
index aa4fead..3775aa4 100644
--- a/fuzzylite/src/norm/t/BoundedDifference.cpp
+++ b/fuzzylite/src/norm/t/BoundedDifference.cpp
@@ -1,29 +1,22 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/t/BoundedDifference.h"
+#include "fl/Operation.h"
namespace fl {
@@ -31,6 +24,10 @@ namespace fl {
return "BoundedDifference";
}
+ Complexity BoundedDifference::complexity() const {
+ return Complexity().arithmetic(2).function(1);
+ }
+
scalar BoundedDifference::compute(scalar a, scalar b) const {
return Op::max(scalar(0.0), a + b - scalar(1.0));
}
diff --git a/fuzzylite/src/norm/t/DrasticProduct.cpp b/fuzzylite/src/norm/t/DrasticProduct.cpp
index 124b79d..5bfdc87 100644
--- a/fuzzylite/src/norm/t/DrasticProduct.cpp
+++ b/fuzzylite/src/norm/t/DrasticProduct.cpp
@@ -1,35 +1,33 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/t/DrasticProduct.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string DrasticProduct::className() const {
return "DrasticProduct";
}
+ Complexity DrasticProduct::complexity() const {
+ return Complexity().comparison(1).function(2);
+ }
+
scalar DrasticProduct::compute(scalar a, scalar b) const {
if (Op::isEq(Op::max(a, b), 1.0)) {
return Op::min(a, b);
diff --git a/fuzzylite/src/norm/t/EinsteinProduct.cpp b/fuzzylite/src/norm/t/EinsteinProduct.cpp
index ea79188..bbb3966 100644
--- a/fuzzylite/src/norm/t/EinsteinProduct.cpp
+++ b/fuzzylite/src/norm/t/EinsteinProduct.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/t/EinsteinProduct.h"
@@ -30,6 +22,10 @@ namespace fl {
return "EinsteinProduct";
}
+ Complexity EinsteinProduct::complexity() const {
+ return Complexity().arithmetic(6);
+ }
+
scalar EinsteinProduct::compute(scalar a, scalar b) const {
return (a * b) / (2.0 - (a + b - a * b));
}
diff --git a/fuzzylite/src/norm/t/HamacherProduct.cpp b/fuzzylite/src/norm/t/HamacherProduct.cpp
index e3f093e..9416084 100644
--- a/fuzzylite/src/norm/t/HamacherProduct.cpp
+++ b/fuzzylite/src/norm/t/HamacherProduct.cpp
@@ -1,29 +1,22 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/t/HamacherProduct.h"
+#include "fl/Operation.h"
namespace fl {
@@ -31,7 +24,12 @@ namespace fl {
return "HamacherProduct";
}
+ Complexity HamacherProduct::complexity() const {
+ return Complexity().arithmetic(5);
+ }
+
scalar HamacherProduct::compute(scalar a, scalar b) const {
+ if (Op::isEq(a + b, 0.0)) return 0.0;
return (a * b) / (a + b - a * b);
}
diff --git a/fuzzylite/src/norm/t/Minimum.cpp b/fuzzylite/src/norm/t/Minimum.cpp
index 34f348f..1a63658 100644
--- a/fuzzylite/src/norm/t/Minimum.cpp
+++ b/fuzzylite/src/norm/t/Minimum.cpp
@@ -1,35 +1,33 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/t/Minimum.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string Minimum::className() const {
return "Minimum";
}
+ Complexity Minimum::complexity() const {
+ return Complexity().function(1);
+ }
+
scalar Minimum::compute(scalar a, scalar b) const {
return Op::min(a, b);
}
diff --git a/fuzzylite/src/norm/t/NilpotentMinimum.cpp b/fuzzylite/src/norm/t/NilpotentMinimum.cpp
index b52a2fc..7ab906b 100644
--- a/fuzzylite/src/norm/t/NilpotentMinimum.cpp
+++ b/fuzzylite/src/norm/t/NilpotentMinimum.cpp
@@ -1,35 +1,33 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/norm/t/NilpotentMinimum.h"
+#include "fl/Operation.h"
+
namespace fl {
std::string NilpotentMinimum::className() const {
return "NilpotentMinimum";
}
+ Complexity NilpotentMinimum::complexity() const {
+ return Complexity().comparison(1).arithmetic(1).function(1);
+ }
+
scalar NilpotentMinimum::compute(scalar a, scalar b) const {
if (Op::isGt(a + b, 1.0)) {
return Op::min(a, b);
@@ -47,4 +45,3 @@ namespace fl {
}
-
diff --git a/fuzzylite/src/norm/t/TNormFunction.cpp b/fuzzylite/src/norm/t/TNormFunction.cpp
new file mode 100644
index 0000000..1e0563e
--- /dev/null
+++ b/fuzzylite/src/norm/t/TNormFunction.cpp
@@ -0,0 +1,66 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/norm/t/TNormFunction.h"
+
+namespace fl {
+
+ TNormFunction::TNormFunction(const std::string& formula) : TNorm() {
+ _function.variables["a"] = fl::nan;
+ _function.variables["b"] = fl::nan;
+ if (not formula.empty()) {
+ _function.load(formula);
+ }
+ }
+
+ std::string TNormFunction::className() const {
+ return "TNormFunction";
+ }
+
+ Complexity TNormFunction::complexity() const {
+ if (_function.root())
+ return _function.complexity().function(2 * std::log(scalar(_function.variables.size())));
+ return _function.complexity();
+ }
+
+ scalar TNormFunction::compute(scalar a, scalar b) const {
+ _function.variables["a"] = a;
+ _function.variables["b"] = b;
+ return _function.evaluate();
+ }
+
+ Function& TNormFunction::function() {
+ return this->_function;
+ }
+
+ void TNormFunction::setFormula(const std::string& formula) {
+ this->_function.load(formula);
+ }
+
+ std::string TNormFunction::getFormula() const {
+ return _function.getFormula();
+ }
+
+ TNormFunction* TNormFunction::clone() const {
+ return new TNormFunction(*this);
+ }
+
+ TNorm* TNormFunction::constructor() {
+ return new TNormFunction;
+ }
+
+
+}
diff --git a/fuzzylite/src/rule/Antecedent.cpp b/fuzzylite/src/rule/Antecedent.cpp
index aa18a68..5f0b0be 100644
--- a/fuzzylite/src/rule/Antecedent.cpp
+++ b/fuzzylite/src/rule/Antecedent.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/rule/Antecedent.h"
@@ -28,29 +20,21 @@
#include "fl/factory/HedgeFactory.h"
#include "fl/factory/FactoryManager.h"
#include "fl/hedge/Any.h"
-#include "fl/hedge/Hedge.h"
-#include "fl/norm/SNorm.h"
-#include "fl/norm/TNorm.h"
#include "fl/rule/Expression.h"
#include "fl/rule/Rule.h"
-#include "fl/term/Accumulated.h"
-#include "fl/term/Function.h"
-#include "fl/term/Term.h"
+#include "fl/term/Aggregated.h"
#include "fl/variable/InputVariable.h"
#include "fl/variable/OutputVariable.h"
-#include <algorithm>
#include <stack>
-
namespace fl {
Antecedent::Antecedent()
- : _text(""), _expression(fl::null) {
- }
+ : _text(""), _expression(fl::null) { }
Antecedent::~Antecedent() {
- unload();
+ _expression.reset(fl::null);
}
void Antecedent::setText(const std::string& text) {
@@ -62,24 +46,29 @@ namespace fl {
}
Expression* Antecedent::getExpression() const {
- return this->_expression;
+ return this->_expression.get();
+ }
+
+ void Antecedent::setExpression(Expression* expression) {
+ this->_expression.reset(expression);
}
bool Antecedent::isLoaded() const {
- return this->_expression != fl::null;
+ return _expression.get() != fl::null;
}
scalar Antecedent::activationDegree(const TNorm* conjunction, const SNorm* disjunction) const {
- return this->activationDegree(conjunction, disjunction, this->_expression);
+ return this->activationDegree(conjunction, disjunction, _expression.get());
}
scalar Antecedent::activationDegree(const TNorm* conjunction, const SNorm* disjunction,
const Expression* node) const {
if (not isLoaded()) {
- throw fl::Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT);
+ throw Exception("[antecedent error] antecedent <" + getText() + "> is not loaded", FL_AT);
}
- const Proposition* proposition = dynamic_cast<const Proposition*> (node);
- if (proposition) {
+ const Expression::Type expression = node->type();
+ if (expression == Expression::Proposition) {
+ const Proposition* proposition = static_cast<const Proposition*> (node);
if (not proposition->variable->isEnabled()) {
return 0.0;
}
@@ -96,62 +85,147 @@ namespace fl {
}
}
scalar result = fl::nan;
- if (InputVariable * inputVariable = dynamic_cast<InputVariable*> (proposition->variable)) {
- result = proposition->term->membership(inputVariable->getInputValue());
- } else if (OutputVariable * outputVariable = dynamic_cast<OutputVariable*> (proposition->variable)) {
- result = outputVariable->fuzzyOutput()->activationDegree(proposition->term);
+ Variable::Type variableType = proposition->variable->type();
+ if (variableType == Variable::Input) {
+ result = proposition->term->membership(proposition->variable->getValue());
+ } else if (variableType == Variable::Output) {
+ result = static_cast<OutputVariable*> (proposition->variable)
+ ->fuzzyOutput()->activationDegree(proposition->term);
}
- for (std::vector<Hedge*>::const_reverse_iterator rit = proposition->hedges.rbegin();
- rit != proposition->hedges.rend(); ++rit) {
- result = (*rit)->hedge(result);
+
+ if (not proposition->hedges.empty()) {
+ for (std::vector<Hedge*>::const_reverse_iterator rit = proposition->hedges.rbegin();
+ rit != proposition->hedges.rend(); ++rit) {
+ result = (*rit)->hedge(result);
+ }
}
return result;
}
//if node is an operator
- const Operator* fuzzyOperator = dynamic_cast<const Operator*> (node);
- if (not (fuzzyOperator->left and fuzzyOperator->right)) {
+ if (expression == Expression::Operator) {
+ const Operator* fuzzyOperator = static_cast<const Operator*> (node);
+ if (not (fuzzyOperator->left and fuzzyOperator->right)) {
+ std::ostringstream ex;
+ ex << "[syntax error] left and right operands must exist";
+ throw Exception(ex.str(), FL_AT);
+ }
+ if (fuzzyOperator->name == Rule::andKeyword()) {
+ if (not conjunction) throw Exception("[conjunction error] "
+ "the following rule requires a conjunction operator:\n" + _text, FL_AT);
+ return conjunction->compute(
+ this->activationDegree(conjunction, disjunction, fuzzyOperator->left),
+ this->activationDegree(conjunction, disjunction, fuzzyOperator->right));
+ }
+
+ if (fuzzyOperator->name == Rule::orKeyword()) {
+ if (not disjunction) throw Exception("[disjunction error] "
+ "the following rule requires a disjunction operator:\n" + _text, FL_AT);
+ return disjunction->compute(
+ this->activationDegree(conjunction, disjunction, fuzzyOperator->left),
+ this->activationDegree(conjunction, disjunction, fuzzyOperator->right));
+ }
std::ostringstream ex;
- ex << "[syntax error] left and right operands must exist";
- throw fl::Exception(ex.str(), FL_AT);
+ ex << "[syntax error] operator <" << fuzzyOperator->name << "> not recognized";
+ throw Exception(ex.str(), FL_AT);
+
+ } else {
+ std::ostringstream ss;
+ ss << "[antecedent error] expected a Proposition or Operator, but found <";
+ if (node) ss << node->toString();
+ ss << ">";
+ throw Exception(ss.str(), FL_AT);
}
- if (fuzzyOperator->name == Rule::andKeyword()) {
- if (not conjunction) throw fl::Exception("[conjunction error] "
- "the following rule requires a conjunction operator:\n" + _text, FL_AT);
- return conjunction->compute(
- this->activationDegree(conjunction, disjunction, fuzzyOperator->left),
- this->activationDegree(conjunction, disjunction, fuzzyOperator->right));
+ }
+
+
+ Complexity Antecedent::complexity(const TNorm* conjunction, const SNorm* disjunction) const {
+ return complexity(conjunction, disjunction, _expression.get());
+ }
+
+ Complexity Antecedent::complexity(const TNorm* conjunction, const SNorm* disjunction,
+ const Expression* node) const {
+ if (not isLoaded()) {
+ return Complexity();
}
- if (fuzzyOperator->name == Rule::orKeyword()) {
- if (not disjunction) throw fl::Exception("[disjunction error] "
- "the following rule requires a disjunction operator:\n" + _text, FL_AT);
- return disjunction->compute(
- this->activationDegree(conjunction, disjunction, fuzzyOperator->left),
- this->activationDegree(conjunction, disjunction, fuzzyOperator->right));
+ Complexity result;
+ const Expression::Type expression = node->type();
+ if (expression == Expression::Proposition) {
+ const Proposition* proposition = static_cast<const Proposition*> (node);
+ if (not proposition->variable->isEnabled()) {
+ return result;
+ }
+
+ if (not proposition->hedges.empty()) {
+ //if last hedge is "Any", apply hedges in reverse order and return degree
+ std::vector<Hedge*>::const_reverse_iterator rit = proposition->hedges.rbegin();
+ if (dynamic_cast<Any*> (*rit)) {
+ result += (*rit)->complexity();
+ while (++rit != proposition->hedges.rend()) {
+ result = (*rit)->complexity();
+ }
+ return result;
+ }
+ }
+ Variable::Type variableType = proposition->variable->type();
+ if (variableType == Variable::Input) {
+ result += proposition->term->complexity();
+ } else if (variableType == Variable::Output) {
+ OutputVariable* outputVariable = static_cast<OutputVariable*> (proposition->variable);
+ result += outputVariable->fuzzyOutput()->complexityOfActivationDegree();
+ }
+
+ if (not proposition->hedges.empty()) {
+ for (std::vector<Hedge*>::const_reverse_iterator rit = proposition->hedges.rbegin();
+ rit != proposition->hedges.rend(); ++rit) {
+ result += (*rit)->complexity();
+ }
+ }
+ return result;
}
- std::ostringstream ex;
- ex << "[syntax error] operator <" << fuzzyOperator->name << "> not recognized";
- throw fl::Exception(ex.str(), FL_AT);
+ //if node is an operator
+ if (expression == Expression::Operator) {
+ const Operator* fuzzyOperator = static_cast<const Operator*> (node);
+ if (not (fuzzyOperator->left and fuzzyOperator->right)) {
+ std::ostringstream ex;
+ ex << "[syntax error] left and right operands must exist";
+ throw Exception(ex.str(), FL_AT);
+ }
+ if (fuzzyOperator->name == Rule::andKeyword()) {
+ if (conjunction) {
+ result += conjunction->complexity();
+ }
+ result += complexity(conjunction, disjunction, fuzzyOperator->left)
+ + complexity(conjunction, disjunction, fuzzyOperator->right);
+ return result;
+ }
+ if (fuzzyOperator->name == Rule::orKeyword()) {
+ if (disjunction) {
+ result += disjunction->complexity();
+ }
+ result += complexity(conjunction, disjunction, fuzzyOperator->left)
+ + complexity(conjunction, disjunction, fuzzyOperator->right);
+ return result;
+ }
+ }
+ return Complexity();
}
void Antecedent::unload() {
- if (_expression) {
- delete _expression;
- _expression = fl::null;
- }
+ _expression.reset(fl::null);
}
- void Antecedent::load(fl::Rule* rule, const Engine* engine) {
- load(_text, rule, engine);
+ void Antecedent::load(const Engine* engine) {
+ load(getText(), engine);
}
- void Antecedent::load(const std::string& antecedent, fl::Rule* rule, const Engine* engine) {
+ void Antecedent::load(const std::string& antecedent, const Engine* engine) {
FL_DBG("Antecedent: " << antecedent);
unload();
- this->_text = antecedent;
- if (fl::Op::trim(antecedent).empty()) {
- throw fl::Exception("[syntax error] antecedent is empty", FL_AT);
+ setText(antecedent);
+ if (Op::trim(antecedent).empty()) {
+ throw Exception("[syntax error] antecedent is empty", FL_AT);
}
/*
Builds an proposition tree from the antecedent of a fuzzy rule.
@@ -179,8 +253,10 @@ namespace fl {
while (tokenizer >> token) {
if (state bitand S_VARIABLE) {
Variable* variable = fl::null;
- if (engine->hasInputVariable(token)) variable = engine->getInputVariable(token);
- else if (engine->hasOutputVariable(token)) variable = engine->getOutputVariable(token);
+ if (engine->hasInputVariable(token))
+ variable = engine->getInputVariable(token);
+ else if (engine->hasOutputVariable(token))
+ variable = engine->getOutputVariable(token);
if (variable) {
proposition = new Proposition;
proposition->variable = variable;
@@ -201,15 +277,9 @@ namespace fl {
}
if (state bitand S_HEDGE) {
- Hedge* hedge = rule->getHedge(token);
- if (not hedge) {
- HedgeFactory* factory = FactoryManager::instance()->hedge();
- if (factory->hasConstructor(token)) {
- hedge = factory->constructObject(token);
- rule->addHedge(hedge);
- }
- }
- if (hedge) {
+ HedgeFactory* factory = FactoryManager::instance()->hedge();
+ if (factory->hasConstructor(token)) {
+ Hedge* hedge = factory->constructObject(token);
proposition->hedges.push_back(hedge);
if (dynamic_cast<Any*> (hedge)) {
state = S_VARIABLE bitor S_AND_OR;
@@ -236,7 +306,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] logical operator <" << token << "> expects two operands,"
<< "but found <" << expressionStack.size() << "> in antecedent";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
Operator* fuzzyOperator = new Operator;
fuzzyOperator->name = token;
@@ -258,33 +328,33 @@ namespace fl {
if ((state bitand S_VARIABLE) or (state bitand S_AND_OR)) {
std::ostringstream ex;
ex << "[syntax error] antecedent expected variable or logical operator, but found <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if (state bitand S_IS) {
std::ostringstream ex;
ex << "[syntax error] antecedent expected keyword <" << Rule::isKeyword() << ">, but found <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if ((state bitand S_HEDGE) or (state bitand S_TERM)) {
std::ostringstream ex;
ex << "[syntax error] antecedent expected hedge or term, but found <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
std::ostringstream ex;
ex << "[syntax error] unexpected token <" << token << "> in antecedent";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if (not ((state bitand S_VARIABLE) or (state bitand S_AND_OR))) { //only acceptable final state
if (state bitand S_IS) {
std::ostringstream ex;
ex << "[syntax error] antecedent expected keyword <" << Rule::isKeyword() << "> after <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if ((state bitand S_HEDGE) or (state bitand S_TERM)) {
std::ostringstream ex;
ex << "[syntax error] antecedent expected hedge or term after <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
}
@@ -299,7 +369,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] unable to parse the following expressions in antecedent <"
<< Op::join(errors, " ") << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
} catch (...) {
for (std::size_t i = 0; i < expressionStack.size(); ++i) {
@@ -308,59 +378,68 @@ namespace fl {
}
throw;
}
- this->_expression = expressionStack.top();
+ setExpression(expressionStack.top());
}
std::string Antecedent::toString() const {
- return toInfix(this->_expression);
+ return toInfix(getExpression());
}
std::string Antecedent::toPrefix(const Expression* node) const {
if (not isLoaded()) {
- throw fl::Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT);
+ throw Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT);
}
- if (not node) node = this->_expression;
+ if (not node) node = getExpression();
if (dynamic_cast<const Proposition*> (node)) {
return node->toString();
}
- const Operator* fuzzyOperator = dynamic_cast<const Operator*> (node);
std::stringstream ss;
- ss << fuzzyOperator->toString() << " "
- << toPrefix(fuzzyOperator->left) << " "
- << toPrefix(fuzzyOperator->right) << " ";
+ if (const Operator * fuzzyOperator = dynamic_cast<const Operator*> (node)) {
+ ss << fuzzyOperator->toString() << " "
+ << toPrefix(fuzzyOperator->left) << " "
+ << toPrefix(fuzzyOperator->right) << " ";
+ } else {
+ ss << "[antecedent error] unknown class of Expression <" << (node ? node->toString() : "null") << ">";
+ }
return ss.str();
}
std::string Antecedent::toInfix(const Expression* node) const {
if (not isLoaded()) {
- throw fl::Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT);
+ throw Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT);
}
- if (not node) node = this->_expression;
+ if (not node) node = getExpression();
if (dynamic_cast<const Proposition*> (node)) {
return node->toString();
}
- const Operator* fuzzyOperator = dynamic_cast<const Operator*> (node);
std::stringstream ss;
- ss << toInfix(fuzzyOperator->left) << " "
- << fuzzyOperator->toString() << " "
- << toInfix(fuzzyOperator->right) << " ";
+ if (const Operator * fuzzyOperator = dynamic_cast<const Operator*> (node)) {
+ ss << toInfix(fuzzyOperator->left) << " "
+ << fuzzyOperator->toString() << " "
+ << toInfix(fuzzyOperator->right) << " ";
+ } else {
+ ss << "[antecedent error] unknown class of Expression <" << (node ? node->toString() : "null") << ">";
+ }
return ss.str();
}
std::string Antecedent::toPostfix(const Expression* node) const {
if (not isLoaded()) {
- throw fl::Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT);
+ throw Exception("[antecedent error] antecedent <" + _text + "> is not loaded", FL_AT);
}
- if (not node) node = this->_expression;
+ if (not node) node = getExpression();
if (dynamic_cast<const Proposition*> (node)) {
return node->toString();
}
- const Operator* fuzzyOperator = dynamic_cast<const Operator*> (node);
std::stringstream ss;
- ss << toPostfix(fuzzyOperator->left) << " "
- << toPostfix(fuzzyOperator->right) << " "
- << fuzzyOperator->toString() << " ";
+ if (const Operator * fuzzyOperator = dynamic_cast<const Operator*> (node)) {
+ ss << toPostfix(fuzzyOperator->left) << " "
+ << toPostfix(fuzzyOperator->right) << " "
+ << fuzzyOperator->toString() << " ";
+ } else {
+ ss << "[antecedent error] unknown class of Expression <" << (node ? node->toString() : "null") << ">";
+ }
return ss.str();
}
diff --git a/fuzzylite/src/rule/Consequent.cpp b/fuzzylite/src/rule/Consequent.cpp
index 28d3390..a90b1a9 100644
--- a/fuzzylite/src/rule/Consequent.cpp
+++ b/fuzzylite/src/rule/Consequent.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/rule/Consequent.h"
@@ -27,24 +19,21 @@
#include "fl/Engine.h"
#include "fl/factory/HedgeFactory.h"
#include "fl/factory/FactoryManager.h"
-#include "fl/hedge/Hedge.h"
#include "fl/hedge/Any.h"
-#include "fl/norm/TNorm.h"
#include "fl/rule/Expression.h"
#include "fl/rule/Rule.h"
-#include "fl/term/Accumulated.h"
-#include "fl/term/Activated.h"
+#include "fl/term/Aggregated.h"
#include "fl/variable/OutputVariable.h"
-#include <algorithm>
-
namespace fl {
- Consequent::Consequent() {
- }
+ Consequent::Consequent() { }
Consequent::~Consequent() {
- unload();
+ for (std::size_t i = 0; i < _conclusions.size(); ++i) {
+ delete _conclusions.at(i);
+ }
+ _conclusions.clear();
}
std::string Consequent::getText() const {
@@ -59,9 +48,29 @@ namespace fl {
return this->_conclusions;
}
- void Consequent::modify(scalar activationDegree, const TNorm* activation) {
+ std::vector<Proposition*>& Consequent::conclusions() {
+ return this->_conclusions;
+ }
+
+ Complexity Consequent::complexity(const TNorm* implication) const {
+ Complexity result;
+ result.comparison(1);
+
+ for (std::size_t i = 0; i < _conclusions.size(); ++i) {
+ Proposition* proposition = _conclusions.at(i);
+ result.comparison(2);
+ for (std::size_t h = 0; h < proposition->hedges.size(); ++h) {
+ result += proposition->hedges.at(h)->complexity();
+ }
+ result += static_cast<OutputVariable*> (proposition->variable)
+ ->complexity(Activated(proposition->term, fl::nan, implication));
+ }
+ return result;
+ }
+
+ void Consequent::modify(scalar activationDegree, const TNorm* implication) {
if (not isLoaded()) {
- throw fl::Exception("[consequent error] consequent <" + _text + "> is not loaded", FL_AT);
+ throw Exception("[consequent error] consequent <" + getText() + "> is not loaded", FL_AT);
}
for (std::size_t i = 0; i < _conclusions.size(); ++i) {
Proposition* proposition = _conclusions.at(i);
@@ -72,10 +81,9 @@ namespace fl {
activationDegree = (*rit)->hedge(activationDegree);
}
}
- Activated* term = new Activated(_conclusions.at(i)->term, activationDegree, activation);
- OutputVariable* outputVariable = dynamic_cast<OutputVariable*> (proposition->variable);
- outputVariable->fuzzyOutput()->addTerm(term);
- FL_DBG("Accumulating " << term->toString());
+
+ static_cast<OutputVariable*> (proposition->variable)->fuzzyOutput()
+ ->addTerm(proposition->term, activationDegree, implication);
}
}
}
@@ -91,16 +99,16 @@ namespace fl {
_conclusions.clear();
}
- void Consequent::load(Rule* rule, const Engine* engine) {
- load(_text, rule, engine);
+ void Consequent::load(const Engine* engine) {
+ load(getText(), engine);
}
- void Consequent::load(const std::string& consequent, Rule* rule, const Engine* engine) {
+ void Consequent::load(const std::string& consequent, const Engine* engine) {
unload();
- this->_text = consequent;
+ setText(consequent);
- if (fl::Op::trim(consequent).empty()) {
- throw fl::Exception("[syntax error] consequent is empty", FL_AT);
+ if (Op::trim(consequent).empty()) {
+ throw Exception("[syntax error] consequent is empty", FL_AT);
}
/**
@@ -129,8 +137,7 @@ namespace fl {
if (engine->hasOutputVariable(token)) {
proposition = new Proposition;
proposition->variable = engine->getOutputVariable(token);
- _conclusions.push_back(proposition);
-
+ conclusions().push_back(proposition);
state = S_IS;
continue;
}
@@ -144,15 +151,9 @@ namespace fl {
}
if (state bitand S_HEDGE) {
- Hedge* hedge = rule->getHedge(token);
- if (not hedge) {
- HedgeFactory* factory = FactoryManager::instance()->hedge();
- if (factory->hasConstructor(token)){
- hedge = factory->constructObject(token);
- rule->addHedge(hedge);
- }
- }
- if (hedge) {
+ HedgeFactory* factory = FactoryManager::instance()->hedge();
+ if (factory->hasConstructor(token)) {
+ Hedge* hedge = factory->constructObject(token);
proposition->hedges.push_back(hedge);
state = S_HEDGE bitor S_TERM;
continue;
@@ -178,19 +179,19 @@ namespace fl {
if (state bitand S_VARIABLE) {
std::ostringstream ex;
ex << "[syntax error] consequent expected output variable, but found <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if (state bitand S_IS) {
std::ostringstream ex;
ex << "[syntax error] consequent expected keyword <" << Rule::isKeyword() << ">, "
"but found <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if ((state bitand S_HEDGE) or (state bitand S_TERM)) {
std::ostringstream ex;
ex << "[syntax error] consequent expected hedge or term, but found <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if ((state bitand S_AND) or (state bitand S_WITH)) {
@@ -198,30 +199,30 @@ namespace fl {
ex << "[syntax error] consequent expected operator <" << Rule::andKeyword() << "> "
<< "or keyword <" << Rule::withKeyword() << ">, "
<< "but found <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
std::ostringstream ex;
ex << "[syntax error] unexpected token <" << token << "> in consequent";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if (not ((state bitand S_AND) or (state bitand S_WITH))) { //only acceptable final state
if (state bitand S_VARIABLE) {
std::ostringstream ex;
ex << "[syntax error] consequent expected output variable after <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if (state bitand S_IS) {
std::ostringstream ex;
ex << "[syntax error] consequent expected keyword <" << Rule::isKeyword() << "> "
"after <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
if ((state bitand S_HEDGE) or (state bitand S_TERM)) {
std::ostringstream ex;
ex << "[syntax error] consequent expected hedge or term after <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
}
} catch (...) {
@@ -232,9 +233,9 @@ namespace fl {
std::string Consequent::toString() const {
std::stringstream ss;
- for (std::size_t i = 0; i < _conclusions.size(); ++i) {
- ss << _conclusions.at(i)->toString();
- if (i + 1 < _conclusions.size())
+ for (std::size_t i = 0; i < conclusions().size(); ++i) {
+ ss << conclusions().at(i)->toString();
+ if (i + 1 < conclusions().size())
ss << " " << Rule::andKeyword() << " ";
}
return ss.str();
diff --git a/fuzzylite/src/rule/Expression.cpp b/fuzzylite/src/rule/Expression.cpp
index ea7873e..9b0ab81 100644
--- a/fuzzylite/src/rule/Expression.cpp
+++ b/fuzzylite/src/rule/Expression.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/rule/Expression.h"
@@ -31,18 +23,22 @@
namespace fl {
- Expression::Expression() {
- }
+ Expression::Expression() { }
- Expression::~Expression() {
- }
+ Expression::~Expression() { }
- Proposition::Proposition()
- : Expression(), variable(fl::null), term(fl::null) {
- }
+ Proposition::Proposition() : Expression(),
+ variable(fl::null), term(fl::null) { }
Proposition::~Proposition() {
+ for (std::size_t i = 0; i < hedges.size(); ++i) {
+ delete hedges.at(i);
+ }
+ hedges.clear();
+ }
+ Expression::Type Proposition::type() const {
+ return Expression::Proposition;
}
std::string Proposition::toString() const {
@@ -68,14 +64,18 @@ namespace fl {
return ss.str();
}
- Operator::Operator() : Expression(), name(""), left(fl::null), right(fl::null) {
- }
+ Operator::Operator() : Expression(),
+ name(""), left(fl::null), right(fl::null) { }
Operator::~Operator() {
if (left) delete left;
if (right) delete right;
}
+ Expression::Type Operator::type() const {
+ return Expression::Operator;
+ }
+
std::string Operator::toString() const {
return name;
}
diff --git a/fuzzylite/src/rule/Rule.cpp b/fuzzylite/src/rule/Rule.cpp
index 446290b..0338cd9 100644
--- a/fuzzylite/src/rule/Rule.cpp
+++ b/fuzzylite/src/rule/Rule.cpp
@@ -1,55 +1,43 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/rule/Rule.h"
#include "fl/Exception.h"
-#include "fl/hedge/Hedge.h"
#include "fl/imex/FllExporter.h"
#include "fl/norm/Norm.h"
-#include "fl/rule/Antecedent.h"
-#include "fl/rule/Consequent.h"
-
-#include <sstream>
-#include <vector>
+#include "fl/Operation.h"
namespace fl {
Rule::Rule(const std::string& text, scalar weight)
- : _text(text), _weight(weight), _antecedent(new Antecedent), _consequent(new Consequent) {
- }
+ : _enabled(true), _text(text), _weight(weight), _activationDegree(0.0), _triggered(false),
+ _antecedent(new Antecedent), _consequent(new Consequent) { }
- Rule::Rule(const Rule& other) : _text(other._text), _weight(other._weight),
- _antecedent(new Antecedent), _consequent(new Consequent) {
- }
+ Rule::Rule(const Rule& other) : _enabled(other._enabled), _text(other._text),
+ _weight(other._weight), _activationDegree(other._activationDegree), _triggered(false),
+ _antecedent(new Antecedent), _consequent(new Consequent) { }
Rule& Rule::operator=(const Rule& other) {
if (this != &other) {
- unload();
-
+ _enabled = other._enabled;
_text = other._text;
_weight = other._weight;
+ _activationDegree = other._activationDegree;
+ _triggered = other._triggered;
_antecedent.reset(new Antecedent);
_consequent.reset(new Consequent);
}
@@ -57,7 +45,8 @@ namespace fl {
}
Rule::~Rule() {
- unload();
+ if (_antecedent.get()) _antecedent->unload();
+ if (_consequent.get()) _consequent->unload();
}
void Rule::setText(const std::string& text) {
@@ -92,87 +81,93 @@ namespace fl {
return this->_consequent.get();
}
- /**
- * Operations for std::vector _hedges
- */
- void Rule::addHedge(Hedge* hedge) {
- this->_hedges[hedge->name()] = hedge;
+ void Rule::setEnabled(bool active) {
+ this->_enabled = active;
}
- Hedge* Rule::getHedge(const std::string& name) const {
- std::map<std::string, Hedge*>::const_iterator it = this->_hedges.find(name);
- if (it != this->_hedges.end()) {
- if (it->second) return it->second;
- }
- return fl::null;
+ bool Rule::isEnabled() const {
+ return this->_enabled;
}
- Hedge* Rule::removeHedge(const std::string& name) {
- Hedge* result = fl::null;
- std::map<std::string, Hedge*>::iterator it = this->_hedges.find(name);
- if (it != this->_hedges.end()) {
- result = it->second;
- this->_hedges.erase(it);
- }
- return result;
+ void Rule::setActivationDegree(scalar activationDegree) {
+ this->_activationDegree = activationDegree;
}
- bool Rule::hasHedge(const std::string& name) const {
- std::map<std::string, Hedge*>::const_iterator it = this->_hedges.find(name);
- return (it != this->_hedges.end());
+ scalar Rule::getActivationDegree() const {
+ return this->_activationDegree;
}
- int Rule::numberOfHedges() const {
- return this->_hedges.size();
+ void Rule::deactivate() {
+ _activationDegree = 0.0;
+ _triggered = false;
}
- void Rule::setHedges(const std::map<std::string, Hedge*>& hedges) {
- this->_hedges = hedges;
+ scalar Rule::activateWith(const TNorm* conjunction, const SNorm* disjunction) {
+ if (not isLoaded()) {
+ throw Exception("[rule error] the following rule is not loaded: " + getText(), FL_AT);
+ }
+ _activationDegree = _weight * _antecedent->activationDegree(conjunction, disjunction);
+ return _activationDegree;
}
- const std::map<std::string, Hedge*>& Rule::hedges() const {
- return this->_hedges;
+ void Rule::trigger(const TNorm* implication) {
+ if (not isLoaded()) {
+ throw Exception("[rule error] the following rule is not loaded: " + getText(), FL_AT);
+ }
+ if (_enabled and Op::isGt(_activationDegree, 0.0)) {
+ FL_DBG("[firing with " << Op::str(_activationDegree) << "] " << toString());
+ _consequent->modify(_activationDegree, implication);
+ _triggered = true;
+ }
}
- std::map<std::string, Hedge*>& Rule::hedges() {
- return this->_hedges;
+ bool Rule::isTriggered() const {
+ return this->_triggered;
}
- scalar Rule::activationDegree(const TNorm* conjunction, const SNorm* disjunction) const {
- if (not isLoaded()) {
- throw fl::Exception("[rule error] the following rule is not loaded: " + _text, FL_AT);
+ Complexity Rule::complexityOfActivation(const TNorm* conjunction, const SNorm* disjunction) const {
+ Complexity result;
+ result.comparison(1).arithmetic(1);
+ if (isLoaded()) {
+ result += _antecedent->complexity(conjunction, disjunction);
}
- return _weight * getAntecedent()->activationDegree(conjunction, disjunction);
+ return result;
}
- void Rule::activate(scalar degree, const TNorm* activation) const {
- if (not isLoaded()) {
- throw fl::Exception("[rule error] the following rule is not loaded: " + _text, FL_AT);
+ Complexity Rule::complexityOfFiring(const TNorm* implication) const {
+ Complexity result;
+ result.comparison(3);
+ if (isLoaded()) {
+ result += _consequent->complexity(implication);
}
- _consequent->modify(degree, activation);
+ return result;
+ }
+
+ Complexity Rule::complexity(const TNorm* conjunction, const SNorm* disjunction,
+ const TNorm* implication) const {
+ return complexityOfActivation(conjunction, disjunction)
+ + complexityOfFiring(implication);
}
bool Rule::isLoaded() const {
- return _antecedent->isLoaded() and _consequent->isLoaded();
+ return _antecedent.get() and _consequent.get()
+ and _antecedent->isLoaded() and _consequent->isLoaded();
}
void Rule::unload() {
- _antecedent->unload();
- _consequent->unload();
-
- for (std::map<std::string, Hedge*>::const_iterator it = _hedges.begin();
- it != _hedges.end(); ++it) {
- delete it->second;
- }
- _hedges.clear();
+ deactivate();
+ if (getAntecedent()) getAntecedent()->unload();
+ if (getConsequent()) getConsequent()->unload();
}
void Rule::load(const Engine* engine) {
- load(_text, engine);
+ load(getText(), engine);
}
void Rule::load(const std::string& rule, const Engine* engine) {
- this->_text = rule;
+ deactivate();
+ setEnabled(true);
+ setText(rule);
std::istringstream tokenizer(rule.substr(0, rule.find_first_of('#')));
std::string token;
std::ostringstream ossAntecedent, ossConsequent;
@@ -192,7 +187,7 @@ namespace fl {
std::ostringstream ex;
ex << "[syntax error] expected keyword <" << Rule::ifKeyword() <<
">, but found <" << token << "> in rule: " << rule;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
break;
case S_IF:
@@ -205,39 +200,46 @@ namespace fl {
break;
case S_WITH:
try {
- weight = fl::Op::toScalar(token);
+ weight = Op::toScalar(token);
state = S_END;
- } catch (fl::Exception& e) {
+ } catch (Exception& e) {
std::ostringstream ex;
ex << "[syntax error] expected a numeric value as the weight of the rule: "
<< rule;
e.append(ex.str(), FL_AT);
- throw e;
+ throw;
}
break;
case S_END:
+ {
std::ostringstream ex;
ex << "[syntax error] unexpected token <" << token << "> at the end of rule";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
+ }
+
+ default:
+ std::ostringstream ex;
+ ex << "[syntax error] unexpected state <" << state << ">";
+ throw Exception(ex.str(), FL_AT);
}
}
if (state == S_NONE) {
std::ostringstream ex;
- ex << "[syntax error] " << (rule.empty() ? "empty rule" : "ignored rule: " + rule);
- throw fl::Exception(ex.str(), FL_AT);
+ ex << "[syntax error] " << (rule.empty() ? "empty rule" : ("ignored rule: " + rule));
+ throw Exception(ex.str(), FL_AT);
} else if (state == S_IF) {
std::ostringstream ex;
ex << "[syntax error] keyword <" << Rule::thenKeyword() << "> not found in rule: " << rule;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
} else if (state == S_WITH) {
std::ostringstream ex;
ex << "[syntax error] expected a numeric value as the weight of the rule: " << rule;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
- _antecedent->load(ossAntecedent.str(), this, engine);
- _consequent->load(ossConsequent.str(), this, engine);
- _weight = weight;
+ getAntecedent()->load(ossAntecedent.str(), engine);
+ getConsequent()->load(ossConsequent.str(), engine);
+ setWeight(weight);
} catch (...) {
unload();
diff --git a/fuzzylite/src/rule/RuleBlock.cpp b/fuzzylite/src/rule/RuleBlock.cpp
index 9ab813e..d4e2a82 100644
--- a/fuzzylite/src/rule/RuleBlock.cpp
+++ b/fuzzylite/src/rule/RuleBlock.cpp
@@ -1,44 +1,35 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/rule/RuleBlock.h"
+#include "fl/activation/General.h"
#include "fl/imex/FllExporter.h"
#include "fl/norm/TNorm.h"
#include "fl/norm/SNorm.h"
#include "fl/rule/Rule.h"
-
-#include <sstream>
+#include "fl/Operation.h"
namespace fl {
RuleBlock::RuleBlock(const std::string& name)
- : _name(name), _enabled(true) {
- }
+ : _enabled(true), _name(name), _description("") { }
- RuleBlock::RuleBlock(const RuleBlock& other) : _name(other._name),
- _enabled(true) {
+ RuleBlock::RuleBlock(const RuleBlock& other) : _enabled(true), _name(other._name),
+ _description(other._description) {
copyFrom(other);
}
@@ -50,6 +41,7 @@ namespace fl {
_rules.clear();
_conjunction.reset(fl::null);
_disjunction.reset(fl::null);
+ _implication.reset(fl::null);
_activation.reset(fl::null);
copyFrom(other);
@@ -58,11 +50,13 @@ namespace fl {
}
void RuleBlock::copyFrom(const RuleBlock& source) {
- _name = source._name;
_enabled = source._enabled;
- if (source._activation.get()) _activation.reset(source._activation->clone());
+ _name = source._name;
+ _description = source._description;
if (source._conjunction.get()) _conjunction.reset(source._conjunction->clone());
if (source._disjunction.get()) _disjunction.reset(source._disjunction->clone());
+ if (source._implication.get()) _implication.reset(source._implication->clone());
+ if (source._activation.get()) _activation.reset(source._activation->clone());
for (std::size_t i = 0; i < source._rules.size(); ++i) {
_rules.push_back(source._rules.at(i)->clone());
}
@@ -75,21 +69,25 @@ namespace fl {
_rules.clear();
}
- void RuleBlock::activate() {
- FL_DBG("===================");
- FL_DBG("ACTIVATING RULEBLOCK " << _name);
- for (std::size_t i = 0; i < _rules.size(); ++i) {
- Rule* rule = _rules.at(i);
- if (rule->isLoaded()) {
- scalar activationDegree = rule->activationDegree(_conjunction.get(), _disjunction.get());
- FL_DBG("[degree=" << Op::str(activationDegree) << "] " << rule->toString());
- if (Op::isGt(activationDegree, 0.0)) {
- rule->activate(activationDegree, _activation.get());
- }
- } else {
- FL_DBG("Rule not loaded: " << rule->toString());
+ Complexity RuleBlock::complexity() const {
+ Complexity result;
+ result.comparison(1);
+ if (_activation.get()) {
+ result += _activation->complexity(this);
+ } else {
+ for (std::size_t i = 0; i < _rules.size(); ++i) {
+ result += _rules.at(i)->complexity(
+ _conjunction.get(), _disjunction.get(), _implication.get());
}
}
+ return result;
+ }
+
+ void RuleBlock::activate() {
+ if (not _activation.get()) {
+ _activation.reset(new General);
+ }
+ _activation->activate(this);
}
void RuleBlock::unloadRules() const {
@@ -114,7 +112,7 @@ namespace fl {
}
}
if (throwException) {
- fl::Exception exception("[ruleblock error] the following "
+ Exception exception("[ruleblock error] the following "
"rules could not be loaded:\n" + exceptions.str(), FL_AT);
throw exception;
}
@@ -133,6 +131,14 @@ namespace fl {
return this->_name;
}
+ void RuleBlock::setDescription(const std::string& description) {
+ this->_description = description;
+ }
+
+ std::string RuleBlock::getDescription() const {
+ return this->_description;
+ }
+
void RuleBlock::setConjunction(TNorm* tnorm) {
this->_conjunction.reset(tnorm);
}
@@ -149,11 +155,19 @@ namespace fl {
return this->_disjunction.get();
}
- void RuleBlock::setActivation(TNorm* activation) {
+ void RuleBlock::setImplication(TNorm* implication) {
+ this->_implication.reset(implication);
+ }
+
+ TNorm* RuleBlock::getImplication() const {
+ return this->_implication.get();
+ }
+
+ void RuleBlock::setActivation(Activation* activation) {
this->_activation.reset(activation);
}
- TNorm* RuleBlock::getActivation() const {
+ Activation* RuleBlock::getActivation() const {
return this->_activation.get();
}
@@ -173,25 +187,25 @@ namespace fl {
* Operations for std::vector _rules
*/
void RuleBlock::addRule(Rule* rule) {
- this->_rules.push_back(rule);
+ _rules.push_back(rule);
}
- void RuleBlock::insertRule(Rule* rule, int index) {
- this->_rules.insert(this->_rules.begin() + index, rule);
+ void RuleBlock::insertRule(Rule* rule, std::size_t index) {
+ _rules.insert(_rules.begin() + index, rule);
}
- Rule* RuleBlock::getRule(int index) const {
- return this->_rules.at(index);
+ Rule* RuleBlock::getRule(std::size_t index) const {
+ return _rules.at(index);
}
- Rule* RuleBlock::removeRule(int index) {
- Rule* result = this->_rules.at(index);
- this->_rules.erase(this->_rules.begin() + index);
+ Rule* RuleBlock::removeRule(std::size_t index) {
+ Rule* result = _rules.at(index);
+ _rules.erase(_rules.begin() + index);
return result;
}
- int RuleBlock::numberOfRules() const {
- return this->_rules.size();
+ std::size_t RuleBlock::numberOfRules() const {
+ return _rules.size();
}
const std::vector<Rule*>& RuleBlock::rules() const {
@@ -206,5 +220,8 @@ namespace fl {
return this->_rules;
}
+ RuleBlock* RuleBlock::clone() const {
+ return new RuleBlock(*this);
+ }
}
diff --git a/fuzzylite/src/term/Accumulated.cpp b/fuzzylite/src/term/Accumulated.cpp
deleted file mode 100644
index 979af9f..0000000
--- a/fuzzylite/src/term/Accumulated.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
-
- This file is part of fuzzylite.
-
- fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
-
- */
-
-#include "fl/term/Accumulated.h"
-
-#include "fl/imex/FllExporter.h"
-#include "fl/norm/SNorm.h"
-#include "fl/norm/s/Maximum.h"
-#include "fl/term/Activated.h"
-
-
-namespace fl {
-
- Accumulated::Accumulated(const std::string& name, scalar minimum, scalar maximum,
- SNorm* accumulation)
- : Term(name), _minimum(minimum), _maximum(maximum), _accumulation(accumulation) {
- }
-
- Accumulated::Accumulated(const Accumulated& other) : Term(other) {
- copyFrom(other);
- }
-
- Accumulated& Accumulated::operator=(const Accumulated& other) {
- if (this != &other) {
- clear();
- _accumulation.reset(fl::null);
-
- Term::operator=(other);
- copyFrom(other);
- }
- return *this;
- }
-
- Accumulated::~Accumulated() {
- clear();
- }
-
- void Accumulated::copyFrom(const Accumulated& source) {
- _minimum = source._minimum;
- _maximum = source._maximum;
-
- if (source._accumulation.get())
- _accumulation.reset(source._accumulation->clone());
-
- for (std::size_t i = 0; i < source._terms.size(); ++i) {
- _terms.push_back(source._terms.at(i)->clone());
- }
- }
-
- std::string Accumulated::className() const {
- return "Accumulated";
- }
-
- scalar Accumulated::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (not (_terms.empty() or _accumulation.get())) { //Exception for IntegralDefuzzifiers
- throw fl::Exception("[accumulation error] "
- "accumulation operator needed to accumulate " + toString(), FL_AT);
- }
- scalar mu = 0.0;
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- mu = _accumulation->compute(mu, _terms.at(i)->membership(x));
- }
- return mu;
- }
-
- scalar Accumulated::activationDegree(const Term* forTerm) const {
- scalar result = 0.0;
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- Activated* activatedTerm = _terms.at(i);
- if (activatedTerm->getTerm() == forTerm) {
- if (_accumulation.get()) result = _accumulation->compute(result, activatedTerm->getDegree());
- else result += activatedTerm->getDegree(); //Default for WeightDefuzzifier
- }
- }
- return result;
- }
-
- std::string Accumulated::parameters() const {
- FllExporter exporter;
- std::ostringstream ss;
- ss << exporter.toString(_accumulation.get());
- ss << " " << Op::str(_minimum) << " " << Op::str(_maximum) << " ";
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- ss << " " << exporter.toString(_terms.at(i));
- }
- return ss.str();
- }
-
- void Accumulated::configure(const std::string& parameters) {
- (void) parameters;
- }
-
- Accumulated* Accumulated::clone() const {
- return new Accumulated(*this);
- }
-
- std::string Accumulated::toString() const {
- std::vector<std::string> accumulate;
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- accumulate.push_back(_terms.at(i)->toString());
- }
- FllExporter exporter;
- std::ostringstream ss;
- ss << _name << ": " << className() << " "
- << exporter.toString(_accumulation.get()) << "["
- << fl::Op::join(accumulate, ",") << "]";
- return ss.str();
- }
-
- void Accumulated::setMinimum(scalar minimum) {
- this->_minimum = minimum;
- }
-
- scalar Accumulated::getMinimum() const {
- return this->_minimum;
- }
-
- void Accumulated::setMaximum(scalar maximum) {
- this->_maximum = maximum;
- }
-
- scalar Accumulated::getMaximum() const {
- return this->_maximum;
- }
-
- void Accumulated::setRange(scalar minimum, scalar maximum) {
- setMinimum(minimum);
- setMaximum(maximum);
- }
-
- scalar Accumulated::range() const {
- return this->_maximum - this->_minimum;
- }
-
- void Accumulated::setAccumulation(SNorm* accumulation) {
- this->_accumulation.reset(accumulation);
- }
-
- SNorm* Accumulated::getAccumulation() const {
- return this->_accumulation.get();
- }
-
- /**
- * Operations for std::vector _terms
- */
-
-
- void Accumulated::addTerm(const Term* term, scalar degree, const TNorm* activation) {
- this->_terms.push_back(new Activated(term, degree, activation));
- }
-
- void Accumulated::addTerm(Activated* term) {
- this->_terms.push_back(term);
- }
-
- Activated* Accumulated::removeTerm(int index) {
- Activated* term = this->_terms.at(index);
- this->_terms.erase(this->_terms.begin() + index);
- return term;
- }
-
- void Accumulated::clear() {
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- delete _terms.at(i);
- }
- _terms.clear();
- }
-
- Activated* Accumulated::getTerm(int index) const {
- return this->_terms.at(index);
- }
-
- const std::vector<Activated*>& Accumulated::terms() const {
- return this->_terms;
- }
-
- std::vector<Activated*>& Accumulated::terms() {
- return this->_terms;
- }
-
- int Accumulated::numberOfTerms() const {
- return _terms.size();
- }
-
- bool Accumulated::isEmpty() const {
- return _terms.empty();
- }
-
-}
diff --git a/fuzzylite/src/term/Activated.cpp b/fuzzylite/src/term/Activated.cpp
index 9a27b4b..80eda6c 100644
--- a/fuzzylite/src/term/Activated.cpp
+++ b/fuzzylite/src/term/Activated.cpp
@@ -1,71 +1,81 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Activated.h"
#include "fl/imex/FllExporter.h"
-#include "fl/norm/TNorm.h"
namespace fl {
- Activated::Activated(const Term* term, scalar degree, const TNorm* activation)
- : Term(""), _term(term), _degree(degree), _activation(activation) {
- if (term) this->_name = term->getName();
+ Activated::Activated(const Term* term, scalar degree, const TNorm* implication)
+ : Term(""), _term(term), _degree(degree), _implication(implication) {
+ if (term) setName(term->getName());
}
- Activated::~Activated() {
- }
+ Activated::~Activated() { }
std::string Activated::className() const {
return "Activated";
}
+ Complexity Activated::complexity() const {
+ Complexity result;
+ result.comparison(3);
+ if (_implication) {
+ result += _implication->complexity();
+ }
+ if (_term) {
+ result += _term->complexity();
+ }
+ return result;
+ }
+
scalar Activated::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (not _activation) throw fl::Exception("[activation error] "
- "activation operator needed to activate " + _term->toString(), FL_AT);
- return _activation->compute(this->_term->membership(x), _degree);
+ if (Op::isNaN(x)) return fl::nan;
+ if (not _term)
+ throw Exception("[activation error] no term available to activate", FL_AT);
+ if (not _implication)
+ throw Exception("[implication error] implication operator needed "
+ "to activate " + getTerm()->toString(), FL_AT);
+ return _implication->compute(_term->membership(x), _degree);
}
std::string Activated::parameters() const {
FllExporter exporter;
std::ostringstream ss;
- ss << Op::str(_degree) << " " << exporter.toString(_activation) << " "
- << exporter.toString(_term);
+ ss << Op::str(getDegree()) << " " << exporter.toString(getImplication()) << " "
+ << exporter.toString(getTerm());
return ss.str();
}
void Activated::configure(const std::string& parameters) {
- (void) parameters;
+ FL_IUNUSED(parameters);
}
std::string Activated::toString() const {
FllExporter exporter;
std::ostringstream ss;
- ss << exporter.toString(_activation) << "("
- << Op::str(_degree) << ","
- << _term->getName() << ")";
+ if (getImplication()) {
+ ss << exporter.toString(getImplication()) << "("
+ << Op::str(getDegree()) << ","
+ << getTerm()->getName() << ")";
+ } else {
+ ss << "(" << Op::str(getDegree()) << "*" //"\u2297: (*)"
+ << getTerm()->getName() << ")";
+ }
return ss.str();
}
@@ -85,12 +95,12 @@ namespace fl {
return this->_degree;
}
- void Activated::setActivation(const TNorm* activation) {
- this->_activation = activation;
+ void Activated::setImplication(const TNorm* implication) {
+ this->_implication = implication;
}
- const TNorm* Activated::getActivation() const {
- return this->_activation;
+ const TNorm* Activated::getImplication() const {
+ return this->_implication;
}
Activated* Activated::clone() const {
diff --git a/fuzzylite/src/term/Aggregated.cpp b/fuzzylite/src/term/Aggregated.cpp
new file mode 100644
index 0000000..d1e2c89
--- /dev/null
+++ b/fuzzylite/src/term/Aggregated.cpp
@@ -0,0 +1,247 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/term/Aggregated.h"
+
+#include "fl/imex/FllExporter.h"
+#include "fl/norm/s/Maximum.h"
+
+namespace fl {
+
+ Aggregated::Aggregated(const std::string& name, scalar minimum, scalar maximum,
+ SNorm* aggregation)
+ : Term(name), _minimum(minimum), _maximum(maximum), _aggregation(aggregation) { }
+
+ Aggregated::Aggregated(const Aggregated& other) : Term(other) {
+ copyFrom(other);
+ }
+
+ Aggregated& Aggregated::operator=(const Aggregated& other) {
+ if (this != &other) {
+ clear();
+ _aggregation.reset(fl::null);
+
+ Term::operator=(other);
+ copyFrom(other);
+ }
+ return *this;
+ }
+
+ Aggregated::~Aggregated() { }
+
+ void Aggregated::copyFrom(const Aggregated& source) {
+ _minimum = source._minimum;
+ _maximum = source._maximum;
+
+ if (source._aggregation.get())
+ _aggregation.reset(source._aggregation->clone());
+
+ for (std::size_t i = 0; i < source._terms.size(); ++i) {
+ _terms.push_back(source._terms.at(i));
+ }
+ }
+
+ std::string Aggregated::className() const {
+ return "Aggregated";
+ }
+
+ Complexity Aggregated::complexity() const {
+ return complexityOfMembership();
+ }
+
+ Complexity Aggregated::complexityOfMembership() const {
+ Complexity result;
+ result.comparison(3);
+ if (_aggregation.get()) {
+ result += _aggregation->complexity().multiply(scalar(_terms.size()));
+ }
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ result += _terms.at(i).complexity();
+ }
+ return result;
+ }
+
+ scalar Aggregated::membership(scalar x) const {
+ if (Op::isNaN(x)) return fl::nan;
+ if (not (_terms.empty() or _aggregation.get())) { //Exception for IntegralDefuzzifiers
+ throw Exception("[aggregation error] "
+ "aggregation operator needed to aggregate variable "
+ "<" + getName() + ">", FL_AT);
+ }
+ scalar mu = 0.0;
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ mu = _aggregation->compute(mu, _terms.at(i).membership(x));
+ }
+ return mu;
+ }
+
+ Complexity Aggregated::complexityOfActivationDegree() const {
+ Complexity result;
+ result.comparison(2);
+ if (_aggregation.get()) {
+ result += _aggregation->complexity();
+ } else result.arithmetic(1);
+ result.multiply(scalar(_terms.size()));
+ return result;
+ }
+
+ scalar Aggregated::activationDegree(const Term* forTerm) const {
+ scalar result = 0.0;
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ const Activated& activatedTerm = _terms.at(i);
+ if (activatedTerm.getTerm() == forTerm) {
+ if (_aggregation.get())
+ result = _aggregation->compute(result, activatedTerm.getDegree());
+ else
+ result += activatedTerm.getDegree(); //Default for WeightDefuzzifier
+ }
+ }
+ return result;
+ }
+
+ const Activated* Aggregated::highestActivatedTerm() const {
+ const Activated* maximumTerm = fl::null;
+ scalar maximumActivation = -fl::inf;
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ const Activated& activated = _terms.at(i);
+ if (Op::isGt(activated.getDegree(), maximumActivation)) {
+ maximumActivation = activated.getDegree();
+ maximumTerm = &activated;
+ }
+ }
+ return maximumTerm;
+ }
+
+ std::string Aggregated::parameters() const {
+ FllExporter exporter;
+ std::ostringstream ss;
+ ss << exporter.toString(getAggregation());
+ ss << " " << Op::str(getMinimum()) << " " << Op::str(getMaximum()) << " ";
+ for (std::size_t i = 0; i < terms().size(); ++i) {
+ ss << " " << exporter.toString(&terms().at(i));
+ }
+ return ss.str();
+ }
+
+ void Aggregated::configure(const std::string& parameters) {
+ FL_IUNUSED(parameters);
+ }
+
+ Aggregated* Aggregated::clone() const {
+ return new Aggregated(*this);
+ }
+
+ std::string Aggregated::toString() const {
+ std::vector<std::string> aggregate;
+ for (std::size_t i = 0; i < terms().size(); ++i) {
+ aggregate.push_back(terms().at(i).toString());
+ }
+ FllExporter exporter;
+ std::ostringstream ss;
+ if (getAggregation()) {
+ ss << getName() << ": " << className() << " "
+ << exporter.toString(getAggregation()) << "["
+ << Op::join(aggregate, ",") << "]";
+ } else {
+ ss << getName() << ": " << className() << " " << "["
+ << Op::join(aggregate, "+") << "]"; //\u2295: (+)
+ }
+ return ss.str();
+ }
+
+ void Aggregated::setMinimum(scalar minimum) {
+ this->_minimum = minimum;
+ }
+
+ scalar Aggregated::getMinimum() const {
+ return this->_minimum;
+ }
+
+ void Aggregated::setMaximum(scalar maximum) {
+ this->_maximum = maximum;
+ }
+
+ scalar Aggregated::getMaximum() const {
+ return this->_maximum;
+ }
+
+ void Aggregated::setRange(scalar minimum, scalar maximum) {
+ setMinimum(minimum);
+ setMaximum(maximum);
+ }
+
+ scalar Aggregated::range() const {
+ return getMaximum() - getMinimum();
+ }
+
+ void Aggregated::setAggregation(SNorm* aggregation) {
+ this->_aggregation.reset(aggregation);
+ }
+
+ SNorm* Aggregated::getAggregation() const {
+ return this->_aggregation.get();
+ }
+
+ /**
+ * Operations for std::vector _terms
+ */
+
+
+ void Aggregated::addTerm(const Term* term, scalar degree, const TNorm* implication) {
+ _terms.push_back(Activated(term, degree, implication));
+ FL_DBG("Aggregating " << _terms.back().toString());
+ }
+
+ void Aggregated::addTerm(const Activated& term) {
+ _terms.push_back(term);
+ FL_DBG("Aggregating " << _terms.back().toString());
+ }
+
+ const Activated& Aggregated::removeTerm(std::size_t index) {
+ const Activated& term = _terms.at(index);
+ _terms.erase(_terms.begin() + index);
+ return term;
+ }
+
+ void Aggregated::clear() {
+ _terms.clear();
+ }
+
+ const Activated& Aggregated::getTerm(std::size_t index) const {
+ return _terms.at(index);
+ }
+
+ void Aggregated::setTerms(const std::vector<Activated>& terms) {
+ this->_terms = terms;
+ }
+
+ const std::vector<Activated>& Aggregated::terms() const {
+ return this->_terms;
+ }
+
+ std::vector<Activated>& Aggregated::terms() {
+ return this->_terms;
+ }
+
+ std::size_t Aggregated::numberOfTerms() const {
+ return _terms.size();
+ }
+
+ bool Aggregated::isEmpty() const {
+ return _terms.empty();
+ }
+
+}
diff --git a/fuzzylite/src/term/Bell.cpp b/fuzzylite/src/term/Bell.cpp
index fc0b215..bd63753 100644
--- a/fuzzylite/src/term/Bell.cpp
+++ b/fuzzylite/src/term/Bell.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Bell.h"
@@ -27,24 +19,26 @@
namespace fl {
Bell::Bell(const std::string& name, scalar center, scalar width, scalar slope, scalar height)
- : Term(name, height), _center(center), _width(width), _slope(slope) {
- }
+ : Term(name, height), _center(center), _width(width), _slope(slope) { }
- Bell::~Bell() {
- }
+ Bell::~Bell() { }
std::string Bell::className() const {
return "Bell";
}
+ Complexity Bell::complexity() const {
+ return Complexity().comparison(1).arithmetic(6).function(2);
+ }
+
scalar Bell::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- return _height * (1.0 / (1.0 + std::pow(std::abs((x - _center) / _width), 2 * _slope)));
+ if (Op::isNaN(x)) return fl::nan;
+ return Term::_height * (1.0 / (1.0 + std::pow(std::abs((x - _center) / _width), 2.0 * _slope)));
}
std::string Bell::parameters() const {
return Op::join(3, " ", _center, _width, _slope) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Bell::configure(const std::string& parameters) {
@@ -55,7 +49,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setCenter(Op::toScalar(values.at(0)));
setWidth(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Binary.cpp b/fuzzylite/src/term/Binary.cpp
new file mode 100644
index 0000000..368530b
--- /dev/null
+++ b/fuzzylite/src/term/Binary.cpp
@@ -0,0 +1,96 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/term/Binary.h"
+
+namespace fl {
+
+ Binary::Binary(const std::string& name, scalar start, scalar direction, scalar height)
+ : Term(name, height), _start(start), _direction(direction) { }
+
+ Binary::~Binary() { }
+
+ std::string Binary::className() const {
+ return "Binary";
+ }
+
+ Complexity Binary::complexity() const {
+ return Complexity().comparison(5).arithmetic(1);
+ }
+
+ scalar Binary::membership(scalar x) const {
+ if (Op::isNaN(x)) return fl::nan;
+ if (_direction > _start and Op::isGE(x, _start)) {
+ return Term::_height * 1.0;
+ }
+ if (_direction < _start and Op::isLE(x, _start)) {
+ return Term::_height * 1.0;
+ }
+ return Term::_height * 0.0;
+ }
+
+ std::string Binary::parameters() const {
+ return Op::join(2, " ", _start, _direction) +
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
+ }
+
+ void Binary::configure(const std::string& parameters) {
+ if (parameters.empty()) return;
+ std::vector<std::string> values = Op::split(parameters, " ");
+ std::size_t required = 2;
+ if (values.size() < required) {
+ std::ostringstream ex;
+ ex << "[configuration error] term <" << className() << ">"
+ << " requires <" << required << "> parameters";
+ throw Exception(ex.str(), FL_AT);
+ }
+ setStart(Op::toScalar(values.at(0)));
+ setDirection(Op::toScalar(values.at(1)));
+ if (values.size() > required)
+ setHeight(Op::toScalar(values.at(required)));
+ }
+
+ void Binary::setStart(scalar minimum) {
+ this->_start = minimum;
+ }
+
+ scalar Binary::getStart() const {
+ return this->_start;
+ }
+
+ void Binary::setDirection(scalar direction) {
+ this->_direction = direction;
+ }
+
+ scalar Binary::getDirection() const {
+ return this->_direction;
+ }
+
+ Binary::Direction Binary::direction() const {
+ if (this->_direction > _start) return Positive;
+ if (this->_direction < _start) return Negative;
+ return Undefined;
+ }
+
+ Binary* Binary::clone() const {
+ return new Binary(*this);
+ }
+
+ Term* Binary::constructor() {
+ return new Binary;
+ }
+
+}
diff --git a/fuzzylite/src/term/Concave.cpp b/fuzzylite/src/term/Concave.cpp
index 37679ae..c585edc 100644
--- a/fuzzylite/src/term/Concave.cpp
+++ b/fuzzylite/src/term/Concave.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Concave.h"
@@ -27,35 +19,47 @@
namespace fl {
Concave::Concave(const std::string& name, scalar inflection, scalar end, scalar height)
- : Term(name, height), _inflection(inflection), _end(end) {
-
- }
+ : Term(name, height), _inflection(inflection), _end(end) { }
- Concave::~Concave() {
-
- }
+ Concave::~Concave() { }
std::string Concave::className() const {
return "Concave";
}
+ Complexity Concave::complexity() const {
+ return Complexity().comparison(1 + 3).arithmetic(1 + 5);
+ }
+
scalar Concave::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (fl::Op::isLE(_inflection, _end)) { //Concave increasing
- if (fl::Op::isLt(x, _end)) {
- return _height * (_end - _inflection) / (2 * _end - _inflection - x);
+ if (Op::isNaN(x)) return fl::nan;
+ if (Op::isLE(_inflection, _end)) { //Concave increasing
+ if (Op::isLt(x, _end)) {
+ return Term::_height * (_end - _inflection) / (2.0 * _end - _inflection - x);
}
} else { //Concave decreasing
- if (fl::Op::isGt(x, _end)) {
- return _height * (_inflection - _end) / (_inflection - 2 * _end + x);
+ if (Op::isGt(x, _end)) {
+ return Term::_height * (_inflection - _end) / (_inflection - 2.0 * _end + x);
}
}
- return _height * 1.0;
+ return Term::_height * 1.0;
+ }
+
+ scalar Concave::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+ scalar i = _inflection;
+ scalar e = _end;
+ return (i - e) / membership(activationDegree) + 2 * e - i;
+ }
+
+ bool Concave::isMonotonic() const {
+ return true;
}
std::string Concave::parameters() const {
return Op::join(2, " ", _inflection, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
@@ -67,7 +71,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setInflection(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
@@ -100,8 +104,4 @@ namespace fl {
return new Concave;
}
-
-
-
-
}
diff --git a/fuzzylite/src/term/Constant.cpp b/fuzzylite/src/term/Constant.cpp
index d52f8ec..7c0422e 100644
--- a/fuzzylite/src/term/Constant.cpp
+++ b/fuzzylite/src/term/Constant.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Constant.h"
@@ -27,18 +19,20 @@
namespace fl {
Constant::Constant(const std::string& name, scalar value)
- : Term(name), _value(value) {
- }
+ : Term(name), _value(value) { }
- Constant::~Constant() {
- }
+ Constant::~Constant() { }
std::string Constant::className() const {
return "Constant";
}
+ Complexity Constant::complexity() const {
+ return Complexity();
+ }
+
scalar Constant::membership(scalar x) const {
- (void) x;
+ FL_IUNUSED(x);
return this->_value;
}
diff --git a/fuzzylite/src/term/Cosine.cpp b/fuzzylite/src/term/Cosine.cpp
index a1402ad..78162ea 100644
--- a/fuzzylite/src/term/Cosine.cpp
+++ b/fuzzylite/src/term/Cosine.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Cosine.h"
@@ -27,13 +19,9 @@
namespace fl {
Cosine::Cosine(const std::string& name, scalar center, scalar width, scalar height)
- : Term(name, height), _center(center), _width(width) {
+ : Term(name, height), _center(center), _width(width) { }
- }
-
- Cosine::~Cosine() {
-
- }
+ Cosine::~Cosine() { }
std::string Cosine::className() const {
return "Cosine";
@@ -41,7 +29,7 @@ namespace fl {
std::string Cosine::parameters() const {
return Op::join(2, " ", _center, _width) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Cosine::configure(const std::string& parameters) {
@@ -52,7 +40,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setCenter(Op::toScalar(values.at(0)));
setWidth(Op::toScalar(values.at(1)));
@@ -61,13 +49,17 @@ namespace fl {
}
+ Complexity Cosine::complexity() const {
+ return Complexity().comparison(3).arithmetic(4 + 1 + 7).function(2);
+ }
+
scalar Cosine::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (fl::Op::isLt(x, _center - _width / 2.0)
- or fl::Op::isGt(x, _center + _width / 2.0))
- return _height * 0.0;
+ if (Op::isNaN(x)) return fl::nan;
+ if (Op::isLt(x, _center - 0.5 * _width)
+ or Op::isGt(x, _center + 0.5 * _width))
+ return Term::_height * 0.0;
const scalar pi = 4.0 * std::atan(1.0);
- return _height * (0.5 * (1.0 + std::cos(2.0 / _width * pi * (x - _center))));
+ return Term::_height * (0.5 * (1.0 + std::cos(2.0 / _width * pi * (x - _center))));
}
void Cosine::setCenter(scalar center) {
@@ -93,4 +85,5 @@ namespace fl {
Term* Cosine::constructor() {
return new Cosine;
}
+
}
diff --git a/fuzzylite/src/term/Discrete.cpp b/fuzzylite/src/term/Discrete.cpp
index 212ada2..9951867 100644
--- a/fuzzylite/src/term/Discrete.cpp
+++ b/fuzzylite/src/term/Discrete.cpp
@@ -1,88 +1,89 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Discrete.h"
-#include <cstdarg>
-
namespace fl {
Discrete::Discrete(const std::string& name, const std::vector<Pair>& xy, scalar height)
- : Term(name, height), _xy(xy) {
- }
+ : Term(name, height), _xy(xy) { }
- Discrete::~Discrete() {
- }
+ Discrete::~Discrete() { }
std::string Discrete::className() const {
return "Discrete";
}
- scalar Discrete::membership(scalar _x_) const {
- if (fl::Op::isNaN(_x_)) return fl::nan;
+ bool compare(const Discrete::Pair& a, const Discrete::Pair& b) {
+ return a.first < b.first;
+ }
+
+ void Discrete::sort(std::vector<Pair>& pairs) {
+ std::sort(pairs.begin(), pairs.end(), compare);
+ }
+
+ void Discrete::sort() {
+ std::sort(_xy.begin(), _xy.end(), compare);
+ }
+
+ Complexity Discrete::complexity() const {
+ return Complexity().comparison(1 + 4).arithmetic(1 + 1 + 1).function(1)
+ .function(2 * std::log(scalar(_xy.size())));
+ }
+
+ scalar Discrete::membership(scalar x) const {
+ if (Op::isNaN(x)) return fl::nan;
if (_xy.empty())
- throw fl::Exception("[discrete error] term is empty", FL_AT);
+ throw Exception("[discrete error] term is empty", FL_AT);
/* ______________________
- * / \
- * / \
- * ____________/ \____________
- * x[0] x[n-1]
+ / \
+ / \
+ ____________/ \____________
+ x[0] x[n-1]
*/
+ if (Op::isLE(x, _xy.front().first))
+ return Term::_height * _xy.front().second;
+ if (Op::isGE(x, _xy.back().first))
+ return Term::_height * _xy.back().second;
- if (fl::Op::isLE(_x_, _xy.front().first)) return _height * _xy.front().second;
- if (fl::Op::isGE(_x_, _xy.back().first)) return _height * _xy.back().second;
-
- int lower = -1, upper = -1;
+ const Pair value(x, fl::nan);
+ typedef std::vector<Discrete::Pair>::const_iterator Bound;
+ //std::lower_bound finds the first number greater than or equal to x
+ Bound lowerBound(std::lower_bound(_xy.begin(), _xy.end(), value, compare));
- for (std::size_t i = 0; i < _xy.size(); ++i) {
- if (Op::isEq(_xy.at(i).first, _x_)) return _height * _xy.at(i).second;
- //approximate on the left
- if (Op::isLt(_xy.at(i).first, _x_)) {
- lower = i;
- }
- //get the immediate next one on the right
- if (Op::isGt(_xy.at(i).first, _x_)) {
- upper = i;
- break;
- }
+ //if the lower bound is equal to x
+ if (Op::isEq(x, lowerBound->first)) {
+ return Term::_height * lowerBound->second;
}
- if (upper < 0) upper = _xy.size() - 1;
- if (lower < 0) lower = 0;
-
- return _height * Op::scale(_x_, _xy.at(lower).first, _xy.at(upper).first,
- _xy.at(lower).second, _xy.at(upper).second);
+ //find the upper bound starting from a copy of lowerBound
+ const Bound upperBound(std::upper_bound(_xy.begin(), _xy.end(), value, compare));
+ --lowerBound; //One arithmetic
+ return Term::_height * Op::scale(x, lowerBound->first, upperBound->first,
+ lowerBound->second, upperBound->second);
}
std::string Discrete::parameters() const {
std::ostringstream ss;
for (std::size_t i = 0; i < _xy.size(); ++i) {
- ss << fl::Op::str(_xy.at(i).first) << " " << fl::Op::str(_xy.at(i).second);
+ ss << Op::str(_xy.at(i).first) << " " << Op::str(_xy.at(i).second);
if (i + 1 < _xy.size()) ss << " ";
}
- if (not Op::isEq(_height, 1.0)) ss << " " << Op::str(_height);
+ if (not Op::isEq(getHeight(), 1.0)) ss << " " << Op::str(getHeight());
return ss.str();
}
@@ -102,36 +103,8 @@ namespace fl {
this->_xy = toPairs(values);
}
- template <typename T>
- Discrete* Discrete::create(const std::string& name, int argc,
- T x1, T y1, ...) { // throw (fl::Exception) {
- std::vector<scalar> xy(argc);
- xy.at(0) = x1;
- xy.at(1) = y1;
- va_list args;
- va_start(args, y1);
- for (int i = 2; i < argc; ++i) {
- xy.at(i) = (scalar) va_arg(args, T);
- }
- va_end(args);
-
- FL_unique_ptr<Discrete> result(new Discrete(name));
- if (xy.size() % 2 != 0) {
- result->setHeight(xy.back());
- xy.pop_back();
- }
- result->setXY(toPairs(xy));
- return result.release();
- }
-
- template FL_API Discrete* Discrete::create(const std::string& name, int argc,
- double x1, double y1, ...); // throw (fl::Exception);
- //double, not scalar because variadic promotes floats to double
- template FL_API Discrete* Discrete::create(const std::string& name, int argc,
- int x1, int y1, ...); // throw (fl::Exception);
-
- void Discrete::setXY(const std::vector<Pair>& pairs) {
- this->_xy = pairs;
+ void Discrete::setXY(const std::vector<Pair>& xy) {
+ this->_xy = xy;
}
const std::vector<Discrete::Pair>& Discrete::xy() const {
@@ -142,19 +115,51 @@ namespace fl {
return this->_xy;
}
- const Discrete::Pair& Discrete::xy(int index) const {
+ const Discrete::Pair& Discrete::xy(std::size_t index) const {
return this->_xy.at(index);
}
- Discrete::Pair& Discrete::xy(int index) {
+ Discrete::Pair& Discrete::xy(std::size_t index) {
return this->_xy.at(index);
}
+ std::vector<scalar> Discrete::x() const {
+ std::vector<scalar> result(_xy.size());
+ for (std::size_t i = 0; i < result.size(); ++i) {
+ result.at(i) = _xy.at(i).first;
+ }
+ return result;
+ }
+
+ std::vector<scalar> Discrete::y() const {
+ std::vector<scalar> result(_xy.size());
+ for (std::size_t i = 0; i < result.size(); ++i) {
+ result.at(i) = _xy.at(i).second;
+ }
+ return result;
+ }
+
+ scalar Discrete::x(std::size_t index) const {
+ return _xy.at(index).first;
+ }
+
+ scalar& Discrete::x(std::size_t index) {
+ return _xy.at(index).first;
+ }
+
+ scalar Discrete::y(std::size_t index) const {
+ return _xy.at(index).second;
+ }
+
+ scalar& Discrete::y(std::size_t index) {
+ return _xy.at(index).second;
+ }
+
std::vector<Discrete::Pair> Discrete::toPairs(const std::vector<scalar>& xy) {
if (xy.size() % 2 != 0) {
std::ostringstream os;
os << "[discrete error] missing value in set of pairs (|xy|=" << xy.size() << ")";
- throw fl::Exception(os.str(), FL_AT);
+ throw Exception(os.str(), FL_AT);
}
std::vector<Pair> result((xy.size() + 1) / 2);
@@ -188,16 +193,32 @@ namespace fl {
return result;
}
- std::string Discrete::formatXY(const std::vector<Pair>& xy, const std::string& prefix, const std::string& innerSeparator, const std::string& postfix, const std::string& outerSeparator) {
+ std::string Discrete::formatXY(const std::vector<Pair>& xy, const std::string& prefix,
+ const std::string& innerSeparator, const std::string& suffix, const std::string& outerSeparator) {
std::ostringstream os;
for (std::size_t i = 0; i < xy.size(); ++i) {
- os << prefix << fl::Op::str(xy.at(i).first) << innerSeparator
- << fl::Op::str(xy.at(i).second) << postfix;
+ os << prefix << Op::str(xy.at(i).first) << innerSeparator
+ << Op::str(xy.at(i).second) << suffix;
if (i + 1 < xy.size()) os << outerSeparator;
}
return os.str();
}
+ Discrete* Discrete::discretize(const Term* term, scalar start, scalar end, int resolution,
+ bool boundedMembershipFunction) {
+ FL_unique_ptr<Discrete> result(new Discrete(term->getName()));
+ scalar dx = (end - start) / resolution;
+ scalar x, y;
+ for (int i = 0; i <= resolution; ++i) {
+ x = start + i * dx;
+ y = term->membership(x);
+ if (boundedMembershipFunction)
+ y = Op::bound(y, scalar(0.0), scalar(1.0));
+ result->xy().push_back(Discrete::Pair(x, y));
+ }
+ return result.release();
+ }
+
Discrete* Discrete::clone() const {
return new Discrete(*this);
}
@@ -206,5 +227,4 @@ namespace fl {
return new Discrete;
}
-
}
diff --git a/fuzzylite/src/term/Function.cpp b/fuzzylite/src/term/Function.cpp
index c0f54b8..42f4aaa 100644
--- a/fuzzylite/src/term/Function.cpp
+++ b/fuzzylite/src/term/Function.cpp
@@ -1,43 +1,30 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Function.h"
#include "fl/Engine.h"
#include "fl/factory/FactoryManager.h"
-#include "fl/factory/FunctionFactory.h"
#include "fl/rule/Rule.h"
#include "fl/variable/InputVariable.h"
#include "fl/variable/OutputVariable.h"
-#include <cctype>
-#include <functional>
#include <queue>
-#include <signal.h>
#include <stack>
-
namespace fl {
/**
@@ -47,32 +34,26 @@ namespace fl {
Function::Element::Element(const std::string& name, const std::string& description, Type type)
: name(name), description(description), type(type), unary(fl::null), binary(fl::null), arity(0),
- precedence(0), associativity(-1) {
-
- }
+ precedence(0), associativity(-1) { }
Function::Element::Element(const std::string& name, const std::string& description,
Type type, Unary unary, int precedence, int associativity)
: name(name), description(description), type(type), unary(unary), binary(fl::null), arity(1),
- precedence(precedence), associativity(associativity) {
- }
+ precedence(precedence), associativity(associativity) { }
Function::Element::Element(const std::string& name, const std::string& description,
Type type, Binary binary, int precedence, int associativity)
: name(name), description(description), type(type), unary(fl::null), binary(binary), arity(2),
- precedence(precedence), associativity(associativity) {
- }
+ precedence(precedence), associativity(associativity) { }
- Function::Element::~Element() {
-
- }
+ Function::Element::~Element() { }
bool Function::Element::isOperator() const {
- return type == OPERATOR;
+ return type == Operator;
}
bool Function::Element::isFunction() const {
- return type == FUNCTION;
+ return type == Function;
}
Function::Element* Function::Element::clone() const {
@@ -82,7 +63,7 @@ namespace fl {
std::string Function::Element::toString() const {
std::ostringstream ss;
- if (type == OPERATOR) {
+ if (type == Operator) {
ss << "Operator (name=" << name << ", "
<< "description=" << description << ", "
<< "precedence=" << precedence << ", "
@@ -92,7 +73,7 @@ namespace fl {
else if (arity == 2) ss << "pointer=" << binary;
else ss << "pointer=error";
ss << ")";
- } else if (type == FUNCTION) {
+ } else if (type == Function) {
ss << "Function (name=" << name << ", "
<< "description=" << description << ", "
<< "arity=" << arity << ", "
@@ -110,16 +91,13 @@ namespace fl {
******************************/
Function::Node::Node(Element* element, Node* left, Node* right)
- : element(element), left(left), right(right), variable(""), value(fl::nan) {
- }
+ : element(element), left(left), right(right), variable(""), value(fl::nan) { }
Function::Node::Node(const std::string& variable)
- : element(fl::null), left(fl::null), right(fl::null), variable(variable), value(fl::nan) {
- }
+ : element(fl::null), left(fl::null), right(fl::null), variable(variable), value(fl::nan) { }
Function::Node::Node(scalar value)
- : element(fl::null), left(fl::null), right(fl::null), variable(""), value(value) {
- }
+ : element(fl::null), left(fl::null), right(fl::null), variable(""), value(value) { }
Function::Node::Node(const Node& other)
: element(fl::null), left(fl::null), right(fl::null), variable(""), value(fl::nan) {
@@ -145,8 +123,7 @@ namespace fl {
value = other.value;
}
- Function::Node::~Node() {
- }
+ Function::Node::~Node() { }
scalar Function::Node::evaluate(const std::map<std::string, scalar>* variables) const {
scalar result = fl::nan;
@@ -160,17 +137,17 @@ namespace fl {
ex << "[function error] arity <" << element->arity << "> of "
<< (element->isOperator() ? "operator" : "function") <<
" <" << element->name << "> is fl::null";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
} else if (not variable.empty()) {
if (not variables) {
- throw fl::Exception("[function error] "
+ throw Exception("[function error] "
"expected a map of variables, but none was provided", FL_AT);
}
std::map<std::string, scalar>::const_iterator it = variables->find(variable);
if (it != variables->end()) result = it->second;
- else throw fl::Exception("[function error] "
+ else throw Exception("[function error] "
"unknown variable <" + variable + ">", FL_AT);
} else {
result = value;
@@ -178,6 +155,36 @@ namespace fl {
return result;
}
+ std::size_t Function::Node::treeSize(const Node* root) const {
+ if (not root) root = this;
+ std::size_t result = 0;
+ if (root->left.get()) {
+ result += treeSize(root->left.get());
+ }
+ if (root->right.get()) {
+ result += treeSize(root->right.get());
+ }
+ if (root->element.get()) {
+ result += 1;
+ }
+ return result;
+ }
+
+ std::size_t Function::Node::treeSize(Element::Type type, const Node* root) const {
+ if (not root) root = this;
+ std::size_t result = 0;
+ if (root->left.get()) {
+ result += treeSize(type, root->left.get());
+ }
+ if (root->right.get()) {
+ result += treeSize(type, root->right.get());
+ }
+ if (root->element.get() and root->element->type == type) {
+ result += 1;
+ }
+ return result;
+ }
+
Function::Node* Function::Node::clone() const {
return new Node(*this);
}
@@ -186,14 +193,14 @@ namespace fl {
std::ostringstream ss;
if (element.get()) ss << element->name;
else if (not variable.empty()) ss << variable;
- else ss << fl::Op::str(value);
+ else ss << Op::str(value);
return ss.str();
}
std::string Function::Node::toPrefix(const Node* node) const {
if (not node) node = this;
- if (not fl::Op::isNaN(node->value)) { //is terminal
- return fl::Op::str(node->value);
+ if (not Op::isNaN(node->value)) { //is terminal
+ return Op::str(node->value);
}
if (not node->variable.empty()) {
return node->variable;
@@ -210,8 +217,8 @@ namespace fl {
std::string Function::Node::toInfix(const Node* node) const {
if (not node) node = this;
- if (not fl::Op::isNaN(node->value)) { //is proposition
- return fl::Op::str(node->value);
+ if (not Op::isNaN(node->value)) { //is proposition
+ return Op::str(node->value);
}
if (not node->variable.empty()) {
return node->variable;
@@ -228,8 +235,8 @@ namespace fl {
std::string Function::Node::toPostfix(const Node* node) const {
if (not node) node = this;
- if (not fl::Op::isNaN(node->value)) { //is proposition
- return fl::Op::str(node->value);
+ if (not Op::isNaN(node->value)) { //is proposition
+ return Op::str(node->value);
}
if (not node->variable.empty()) {
return node->variable;
@@ -249,8 +256,7 @@ namespace fl {
**********************************/
Function::Function(const std::string& name,
const std::string& formula, const Engine* engine)
- : Term(name), _root(fl::null), _formula(formula), _engine(engine) {
- }
+ : Term(name), _root(fl::null), _formula(formula), _engine(engine) { }
Function::Function(const Function& other) : Term(other),
_root(fl::null), _formula(other._formula), _engine(other._engine) {
@@ -271,25 +277,41 @@ namespace fl {
return *this;
}
- Function::~Function() {
- }
+ Function::~Function() { }
std::string Function::className() const {
return "Function";
}
+ Complexity Function::complexity() const {
+ Complexity result;
+ result.comparison(2 + 2); //membership(scalar) + membership(std::map)
+ if (_engine) { //insert variables in map
+ const std::size_t engineVariables = _engine->variables().size();
+ result.function(engineVariables * std::log(scalar(variables.size() + engineVariables)));
+ result.function(1 * std::log(scalar(variables.size() + engineVariables)));
+ }
+ if (_root.get()) {
+ //Node::evaluate multiplies by tree size
+ const scalar treeSize = scalar(_root->treeSize());
+ result.comparison(3 * treeSize); //if element, unary, binary
+ result.function(treeSize * std::log(treeSize)); //only operands in tree
+ }
+ return result;
+ }
+
scalar Function::membership(scalar x) const {
- if (not this->_root.get()) {
- throw fl::Exception("[function error] function <" + _formula + "> not loaded.", FL_AT);
+ if (not _root.get()) {
+ throw Exception("[function error] function <" + _formula + "> not loaded.", FL_AT);
}
- if (this->_engine) {
- for (int i = 0; i < this->_engine->numberOfInputVariables(); ++i) {
- InputVariable* input = this->_engine->getInputVariable(i);
- this->variables[input->getName()] = input->getInputValue();
+ if (_engine) {
+ for (std::size_t i = 0; i < _engine->numberOfInputVariables(); ++i) {
+ InputVariable* input = _engine->getInputVariable(i);
+ this->variables[input->getName()] = input->getValue();
}
- for (int i = 0; i < this->_engine->numberOfOutputVariables(); ++i) {
- OutputVariable* output = this->_engine->getOutputVariable(i);
- this->variables[output->getName()] = output->getOutputValue();
+ for (std::size_t i = 0; i < _engine->numberOfOutputVariables(); ++i) {
+ OutputVariable* output = _engine->getOutputVariable(i);
+ this->variables[output->getName()] = output->getValue();
}
}
this->variables["x"] = x;
@@ -297,15 +319,15 @@ namespace fl {
}
scalar Function::evaluate(const std::map<std::string, scalar>* localVariables) const {
- if (not this->_root.get())
- throw fl::Exception("[function error] evaluation failed because the function is not loaded", FL_AT);
+ if (not _root.get())
+ throw Exception("[function error] evaluation failed because the function is not loaded", FL_AT);
if (localVariables)
- return this->_root->evaluate(localVariables);
- return this->_root->evaluate(&this->variables);
+ return _root->evaluate(localVariables);
+ return _root->evaluate(&this->variables);
}
std::string Function::parameters() const {
- return _formula;
+ return getFormula();
}
void Function::configure(const std::string& parameters) {
@@ -329,18 +351,17 @@ namespace fl {
}
void Function::load() {
- load(this->_formula);
+ load(getFormula());
}
void Function::load(const std::string& formula) {
- load(formula, this->_engine);
+ load(formula, getEngine());
}
void Function::load(const std::string& formula,
const Engine* engine) {
- unload();
- this->_formula = formula;
- this->_engine = engine;
+ setFormula(formula);
+ setEngine(engine);
this->_root.reset(parse(formula));
membership(0.0); //make sure function evaluates without throwing exception.
}
@@ -373,23 +394,32 @@ namespace fl {
return new Function;
}
+ void Function::updateReference(const Engine* engine) {
+ setEngine(engine);
+ try {
+ load();
+ } catch (...) {
+ //ignore
+ }
+ }
+
std::string Function::space(const std::string& formula) const {
std::vector<std::string> chars;
chars.push_back("(");
chars.push_back(")");
chars.push_back(",");
- std::vector<std::string> operators = fl::FactoryManager::instance()->function()->availableOperators();
+ std::vector<std::string> operators = FactoryManager::instance()->function()->availableOperators();
for (std::size_t i = 0; i < operators.size(); ++i) {
- if (not (operators.at(i) == fl::Rule::andKeyword() or
- operators.at(i) == fl::Rule::orKeyword())) {
+ if (not (operators.at(i) == Rule::andKeyword() or
+ operators.at(i) == Rule::orKeyword())) {
chars.push_back(operators.at(i));
}
}
std::string result = formula;
for (std::size_t i = 0; i < chars.size(); ++i) {
- result = fl::Op::findReplace(result, chars.at(i), " " + chars.at(i) + " ");
+ result = Op::findReplace(result, chars.at(i), " " + chars.at(i) + " ");
}
return result;
}
@@ -397,7 +427,7 @@ namespace fl {
/****************************************
* The Glorious Parser
* Shunting-yard algorithm
- * TODO: Maybe change it for http://en.wikipedia.org/wiki/Operator-precedence_parser
+ * @todo: maybe change it for http://en.wikipedia.org/wiki/Operator-precedence_parser
***************************************/
std::string Function::toPostfix(const std::string& formula) const {
@@ -408,7 +438,7 @@ namespace fl {
std::stringstream tokenizer(spacedFormula);
std::string token;
- FunctionFactory* factory = fl::FactoryManager::instance()->function();
+ FunctionFactory* factory = FactoryManager::instance()->function();
while (tokenizer >> token) {
Element* element = factory->getObject(token);
bool isOperand = not element and token != "(" and token != ")" and token != ",";
@@ -427,7 +457,7 @@ namespace fl {
if (stack.empty() or stack.top() != "(") {
std::ostringstream ex;
ex << "[parsing error] mismatching parentheses in: " << formula;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
} else if (element and element->isOperator()) {
@@ -457,7 +487,7 @@ namespace fl {
if (stack.empty() or stack.top() != "(") {
std::ostringstream ex;
ex << "[parsing error] mismatching parentheses in: " << formula;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
stack.pop(); //get rid of "("
@@ -470,7 +500,7 @@ namespace fl {
} else {
std::ostringstream ex;
ex << "[parsing error] unexpected error with token <" << token << ">";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
}
@@ -478,7 +508,7 @@ namespace fl {
if (stack.top() == "(" or stack.top() == ")") {
std::ostringstream ex;
ex << "[parsing error] mismatching parentheses in: " << formula;
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
queue.push(stack.top());
stack.pop();
@@ -490,43 +520,31 @@ namespace fl {
queue.pop();
if (not queue.empty()) ssPostfix << " ";
}
- // FL_DBG("postfix=" << ssPostfix.str());
return ssPostfix.str();
}
- // bool FunctionFactory::isOperand(const std::string& name) const {
- // //An operand is not a parenthesis...
- // if (name == "(" or name == ")" or name == ",") return false;
- // //nor an operator...
- // if (isOperator(name)) return false;
- // //nor a function...
- // if (isFunction(name)) return false;
- // //...it is everything else :)
- // return true;
- // }
-
Function::Node* Function::parse(const std::string& formula) {
if (formula.empty())
- throw fl::Exception("[function error] formula is empty", FL_AT);
+ throw Exception("[function error] formula is empty", FL_AT);
std::string postfix = toPostfix(formula);
std::stack<Node*> stack;
std::istringstream tokenizer(postfix);
std::string token;
- FunctionFactory* factory = fl::FactoryManager::instance()->function();
+ FunctionFactory* factory = FactoryManager::instance()->function();
while (tokenizer >> token) {
Element* element = factory->getObject(token);
bool isOperand = not element and token != "(" and token != ")" and token != ",";
if (element) {
- if (element->arity > (int) stack.size()) {
+ if (element->arity > static_cast<int> (stack.size())) {
std::ostringstream ss;
ss << "[function error] " << (element->isOperator() ? "operator" : "function") <<
" <" << element->name << "> has arity <" << element->arity << ">, "
"but found <" << stack.size() << "> element" <<
(stack.size() == 1 ? "" : "s");
- throw fl::Exception(ss.str(), FL_AT);
+ throw Exception(ss.str(), FL_AT);
}
Node* node = new Node(element->clone());
@@ -541,10 +559,10 @@ namespace fl {
} else if (isOperand) {
Node* node;
try {
- scalar value = fl::Op::toScalar(token);
+ scalar value = Op::toScalar(token);
node = new Node(value);
} catch (std::exception& ex) {
- (void) ex;
+ FL_IUNUSED(ex);
node = new Node(token);
}
stack.push(node);
@@ -552,49 +570,9 @@ namespace fl {
}
if (stack.size() != 1)
- throw fl::Exception("[function error] ill-formed formula <" + formula + ">", FL_AT);
+ throw Exception("[function error] ill-formed formula <" + formula + ">", FL_AT);
return stack.top();
}
- void Function::main() {
- Function f;
- std::string text = "3+4*2/(1-5)^2^3";
- FL_LOG(f.toPostfix(text));
- FL_LOG("P: " << f.parse(text)->toInfix());
- FL_LOG(">" << f.parse(text)->evaluate());
- //3 4 2 * 1 5 - 2 3 ^ ^ / +
-
- f.variables["y"] = 1.0;
- text = "sin(y*x)^2/x";
- FL_LOG("pre: " << f.parse(text)->toPrefix());
- FL_LOG("in: " << f.parse(text)->toInfix());
- FL_LOG("pos: " << f.parse(text)->toPostfix());
- f.load(text);
- FL_LOG("Result: " << f.membership(1));
- //y x * sin 2 ^ x /
-
-
- text = "(Temperature is High and Oxygen is Low) or "
- "(Temperature is Low and (Oxygen is Low or Oxygen is High))";
- FL_LOG(f.toPostfix(text));
-
- f.variables["pi"] = 3.14;
- text = "-5 *4/sin(-pi/2)";
- FL_LOG(f.toPostfix(text));
- try {
- FL_LOG(f.parse(text)->evaluate());
- } catch (std::exception& e) {
- FL_LOG(e.what());
- }
- f.variables["pi"] = 3.14;
- text = "~5 *4/sin(~pi/2)";
- FL_LOG(f.toPostfix(text));
- try {
- FL_LOG(f.parse(text)->evaluate(&f.variables));
- } catch (std::exception& e) {
- FL_LOG(e.what());
- }
- }
-
}
diff --git a/fuzzylite/src/term/Gaussian.cpp b/fuzzylite/src/term/Gaussian.cpp
index 5b709f9..8413b59 100644
--- a/fuzzylite/src/term/Gaussian.cpp
+++ b/fuzzylite/src/term/Gaussian.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Gaussian.h"
@@ -28,24 +20,26 @@ namespace fl {
Gaussian::Gaussian(const std::string& name,
scalar mean, scalar standardDeviation, scalar height)
- : Term(name, height), _mean(mean), _standardDeviation(standardDeviation) {
- }
+ : Term(name, height), _mean(mean), _standardDeviation(standardDeviation) { }
- Gaussian::~Gaussian() {
- }
+ Gaussian::~Gaussian() { }
std::string Gaussian::className() const {
return "Gaussian";
}
+ Complexity Gaussian::complexity() const {
+ return Complexity().comparison(1).arithmetic(7).function(1);
+ }
+
scalar Gaussian::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- return _height * std::exp((-(x - _mean) * (x - _mean)) / (2 * _standardDeviation * _standardDeviation));
+ if (Op::isNaN(x)) return fl::nan;
+ return Term::_height * std::exp((-(x - _mean) * (x - _mean)) / (2.0 * _standardDeviation * _standardDeviation));
}
std::string Gaussian::parameters() const {
return Op::join(2, " ", _mean, _standardDeviation) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Gaussian::configure(const std::string& parameters) {
@@ -56,7 +50,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setMean(Op::toScalar(values.at(0)));
setStandardDeviation(Op::toScalar(values.at(1)));
@@ -64,16 +58,16 @@ namespace fl {
setHeight(Op::toScalar(values.at(required)));
}
- void Gaussian::setMean(scalar c) {
- this->_mean = c;
+ void Gaussian::setMean(scalar mean) {
+ this->_mean = mean;
}
scalar Gaussian::getMean() const {
return this->_mean;
}
- void Gaussian::setStandardDeviation(scalar sigma) {
- this->_standardDeviation = sigma;
+ void Gaussian::setStandardDeviation(scalar standardDeviation) {
+ this->_standardDeviation = standardDeviation;
}
scalar Gaussian::getStandardDeviation() const {
diff --git a/fuzzylite/src/term/GaussianProduct.cpp b/fuzzylite/src/term/GaussianProduct.cpp
index b9652e1..791790c 100644
--- a/fuzzylite/src/term/GaussianProduct.cpp
+++ b/fuzzylite/src/term/GaussianProduct.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/GaussianProduct.h"
@@ -30,32 +22,37 @@ namespace fl {
scalar meanA, scalar standardDeviationA, scalar meanB, scalar standardDeviationB,
scalar height)
: Term(name, height), _meanA(meanA), _standardDeviationA(standardDeviationA),
- _meanB(meanB), _standardDeviationB(standardDeviationB) {
- }
+ _meanB(meanB), _standardDeviationB(standardDeviationB) { }
- GaussianProduct::~GaussianProduct() {
- }
+ GaussianProduct::~GaussianProduct() { }
std::string GaussianProduct::className() const {
return "GaussianProduct";
}
+ Complexity GaussianProduct::complexity() const {
+ return Complexity().comparison(1 + 2).arithmetic(9 + 9 + 2).function(2);
+ }
+
scalar GaussianProduct::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- bool xLEa = fl::Op::isLE(x, _meanA);
- scalar a = (1 - xLEa) + xLEa * std::exp(
- (-(x - _meanA) * (x - _meanA)) / (2 * _standardDeviationA * _standardDeviationA)
- );
- bool xGEb = fl::Op::isGE(x, _meanB);
- scalar b = (1 - xGEb) + xGEb * std::exp(
- (-(x - _meanB) * (x - _meanB)) / (2 * _standardDeviationB * _standardDeviationB)
- );
- return _height * a * b;
+ if (Op::isNaN(x)) return fl::nan;
+
+ scalar a = 1.0, b = 1.0;
+ if (Op::isLt(x, _meanA)) {
+ a = std::exp((-(x - _meanA) * (x - _meanA)) /
+ (2.0 * _standardDeviationA * _standardDeviationA));
+ }
+ if (Op::isGt(x, _meanB)) {
+ b = std::exp((-(x - _meanB) * (x - _meanB)) /
+ (2.0 * _standardDeviationB * _standardDeviationB));
+ }
+
+ return Term::_height * a * b;
}
std::string GaussianProduct::parameters() const {
return Op::join(4, " ", _meanA, _standardDeviationA, _meanB, _standardDeviationB) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void GaussianProduct::configure(const std::string& parameters) {
@@ -66,7 +63,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setMeanA(Op::toScalar(values.at(0)));
setStandardDeviationA(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Linear.cpp b/fuzzylite/src/term/Linear.cpp
index 4111a00..e6efb43 100644
--- a/fuzzylite/src/term/Linear.cpp
+++ b/fuzzylite/src/term/Linear.cpp
@@ -1,72 +1,72 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Linear.h"
-#include "fl/Engine.h"
#include "fl/variable/InputVariable.h"
-#include <cstdarg>
-
namespace fl {
Linear::Linear(const std::string& name,
const std::vector<scalar>& coefficients,
const Engine* engine)
- : Term(name), _coefficients(coefficients), _engine(engine) {
- }
+ : Term(name), _coefficients(coefficients), _engine(engine) { }
- Linear::~Linear() {
- }
+ Linear::~Linear() { }
std::string Linear::className() const {
return "Linear";
}
+ Complexity Linear::complexity() const {
+ Complexity result;
+ result.comparison(1 + 1);
+ if (_engine) {
+ result.arithmetic(scalar(_engine->variables().size()));
+ result.comparison(scalar(_engine->variables().size())); //if (i < coefficients)
+ }
+ return result;
+ }
+
scalar Linear::membership(scalar x) const {
- (void) x;
- if (not _engine) throw fl::Exception("[linear error] term <" + getName() + "> "
+ FL_IUNUSED(x);
+ if (not _engine)
+ throw Exception("[linear error] term <" + getName() + "> "
"is missing a reference to the engine", FL_AT);
scalar result = 0.0;
- for (std::size_t i = 0; i < _engine->inputVariables().size(); ++i) {
- if (i < _coefficients.size())
- result += _coefficients.at(i) * _engine->inputVariables().at(i)->getInputValue();
+ const std::size_t numberOfInputVariables = _engine->inputVariables().size();
+ const std::size_t numberOfCoefficients = _coefficients.size();
+ for (std::size_t i = 0; i < numberOfInputVariables; ++i) {
+ if (i < numberOfCoefficients)
+ result += _coefficients.at(i) * _engine->inputVariables().at(i)->getValue();
}
- if (_coefficients.size() > _engine->inputVariables().size()) {
+ if (numberOfCoefficients > numberOfInputVariables) {
result += _coefficients.back();
}
return result;
}
- void Linear::set(const std::vector<scalar>& coeffs, const Engine* engine) {
- setCoefficients(coeffs);
+ void Linear::set(const std::vector<scalar>& coefficients, const Engine* engine) {
+ setCoefficients(coefficients);
setEngine(engine);
}
- void Linear::setCoefficients(const std::vector<scalar>& coeffs) {
- this->_coefficients = coeffs;
+ void Linear::setCoefficients(const std::vector<scalar>& coefficients) {
+ this->_coefficients = coefficients;
}
const std::vector<scalar>& Linear::coefficients() const {
@@ -90,6 +90,7 @@ namespace fl {
}
void Linear::configure(const std::string& parameters) {
+ this->_coefficients.clear();
if (parameters.empty()) return;
std::vector<std::string> strValues = Op::split(parameters, " ");
std::vector<scalar> values;
@@ -103,33 +104,12 @@ namespace fl {
return new Linear(*this);
}
- Term* Linear::constructor() {
- return new Linear;
+ void Linear::updateReference(const Engine* engine) {
+ setEngine(engine);
}
- template <typename T>
- Linear* Linear::create(const std::string& name,
- const Engine* engine, T firstCoefficient, ...) {// throw (fl::Exception) {
- if (not engine) throw fl::Exception("[linear error] cannot create term <" + name + "> "
- "without a reference to the engine", FL_AT);
- std::vector<scalar> coefficients;
- coefficients.push_back(firstCoefficient);
-
- va_list args;
- va_start(args, firstCoefficient);
- for (std::size_t i = 0; i < engine->inputVariables().size(); ++i) {
- coefficients.push_back((scalar) va_arg(args, T));
- }
- va_end(args);
-
- return new Linear(name, coefficients, engine);
+ Term* Linear::constructor() {
+ return new Linear;
}
- template FL_API Linear* Linear::create(const std::string& name,
- const Engine* engine,
- double firstCoefficient, ...);
-
- template FL_API Linear* Linear::create(const std::string& name,
- const Engine* engine,
- int firstCoefficient, ...);
}
diff --git a/fuzzylite/src/term/PiShape.cpp b/fuzzylite/src/term/PiShape.cpp
index ba3e99f..6c91f54 100644
--- a/fuzzylite/src/term/PiShape.cpp
+++ b/fuzzylite/src/term/PiShape.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/PiShape.h"
@@ -29,47 +21,45 @@ namespace fl {
PiShape::PiShape(const std::string& name, scalar bottomLeft, scalar topLeft,
scalar topRight, scalar bottomRight, scalar height)
: Term(name, height), _bottomLeft(bottomLeft), _topLeft(topLeft),
- _topRight(topRight), _bottomRight(bottomRight) {
- }
+ _topRight(topRight), _bottomRight(bottomRight) { }
- PiShape::~PiShape() {
- }
+ PiShape::~PiShape() { }
std::string PiShape::className() const {
return "PiShape";
}
- scalar PiShape::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- //from Octave smf.m
- scalar a_b_ave = (_bottomLeft + _topLeft) / 2.0;
- scalar b_minus_a = _topLeft - _bottomLeft;
- scalar c_d_ave = (_topRight + _bottomRight) / 2.0;
- scalar d_minus_c = _bottomRight - _topRight;
-
- if (Op::isLE(x, _bottomLeft)) return _height * 0.0;
-
- if (Op::isLE(x, a_b_ave))
- return _height * (2.0 * std::pow((x - _bottomLeft) / b_minus_a, 2));
-
- if (Op::isLt(x, _topLeft))
- return _height * (1.0 - 2.0 * std::pow((x - _topLeft) / b_minus_a, 2));
+ Complexity PiShape::complexity() const {
+ return Complexity().comparison(1 + 6).arithmetic(1 + 5 + 5).function(1 + 1);
+ }
+ scalar PiShape::membership(scalar x) const {
+ if (Op::isNaN(x)) return fl::nan;
+
+ scalar sshape;
+ if (Op::isLE(x, _bottomLeft))
+ sshape = 0.0;
+ else if (Op::isLE(x, 0.5 * (_bottomLeft + _topLeft)))
+ sshape = 2.0 * std::pow((x - _bottomLeft) / (_topLeft - _bottomLeft), 2);
+ else if (Op::isLt(x, _topLeft))
+ sshape = 1.0 - 2.0 * std::pow((x - _topLeft) / (_topLeft - _bottomLeft), 2);
+ else sshape = 1.0;
+
+ scalar zshape;
if (Op::isLE(x, _topRight))
- return _height * 1.0;
-
- if (Op::isLE(x, c_d_ave))
- return _height * (1.0 - 2.0 * std::pow((x - _topRight) / d_minus_c, 2));
-
- if (Op::isLt(x, _bottomRight))
- return _height * (2.0 * std::pow((x - _bottomRight) / d_minus_c, 2));
+ zshape = 1.0;
+ else if (Op::isLE(x, 0.5 * (_topRight + _bottomRight)))
+ zshape = 1.0 - 2.0 * std::pow((x - _topRight) / (_bottomRight - _topRight), 2);
+ else if (Op::isLt(x, _bottomRight))
+ zshape = 2.0 * std::pow((x - _bottomRight) / (_bottomRight - _topRight), 2);
+ else zshape = 0.0;
- return _height * 0.0;
+ return Term::_height * sshape * zshape;
}
std::string PiShape::parameters() const {
return Op::join(4, " ", _bottomLeft, _topLeft, _topRight, _bottomRight) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void PiShape::configure(const std::string& parameters) {
@@ -80,7 +70,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setBottomLeft(Op::toScalar(values.at(0)));
setTopLeft(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Ramp.cpp b/fuzzylite/src/term/Ramp.cpp
index f224045..d29233d 100644
--- a/fuzzylite/src/term/Ramp.cpp
+++ b/fuzzylite/src/term/Ramp.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Ramp.h"
@@ -27,35 +19,52 @@
namespace fl {
Ramp::Ramp(const std::string& name, scalar start, scalar end, scalar height)
- : Term(name, height), _start(start), _end(end) {
- }
+ : Term(name, height), _start(start), _end(end) { }
- Ramp::~Ramp() {
- }
+ Ramp::~Ramp() { }
std::string Ramp::className() const {
return "Ramp";
}
+ Complexity Ramp::complexity() const {
+ return Complexity().comparison(1 + 4).arithmetic(1 + 3);
+ }
+
scalar Ramp::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
+ if (Op::isNaN(x)) return fl::nan;
- if (Op::isEq(_start, _end)) return _height * 0.0;
+ if (Op::isEq(_start, _end))
+ return Term::_height * 0.0;
if (Op::isLt(_start, _end)) {
- if (Op::isLE(x, _start)) return _height * 0.0;
- if (Op::isGE(x, _end)) return _height * 1.0;
- return _height * (x - _start) / (_end - _start);
+ if (Op::isLE(x, _start))
+ return Term::_height * 0.0;
+ if (Op::isGE(x, _end))
+ return Term::_height * 1.0;
+ return Term::_height * (x - _start) / (_end - _start);
} else {
- if (Op::isGE(x, _start)) return _height * 0.0;
- if (Op::isLE(x, _end)) return _height * 1.0;
- return _height * (_start - x) / (_start - _end);
+ if (Op::isGE(x, _start))
+ return Term::_height * 0.0;
+ if (Op::isLE(x, _end))
+ return Term::_height * 1.0;
+ return Term::_height * (_start - x) / (_start - _end);
}
}
+ scalar Ramp::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+ return Op::scale(activationDegree, 0, 1, _start, _end);
+ }
+
+ bool Ramp::isMonotonic() const {
+ return true;
+ }
+
std::string Ramp::parameters() const {
return Op::join(2, " ", _start, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Ramp::configure(const std::string& parameters) {
@@ -66,7 +75,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setStart(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
@@ -92,11 +101,11 @@ namespace fl {
Ramp::Direction Ramp::direction() const {
scalar range = this->_end - this->_start;
- if (not fl::Op::isFinite(range) or fl::Op::isEq(range, 0.0)) return ZERO;
+ if (not Op::isFinite(range) or Op::isEq(range, 0.0)) return Zero;
- if (fl::Op::isGt(range, 0.0)) return POSITIVE;
+ if (Op::isGt(range, 0.0)) return Positive;
- return NEGATIVE;
+ return Negative;
}
Ramp* Ramp::clone() const {
diff --git a/fuzzylite/src/term/Rectangle.cpp b/fuzzylite/src/term/Rectangle.cpp
index 363b15d..4f975d0 100644
--- a/fuzzylite/src/term/Rectangle.cpp
+++ b/fuzzylite/src/term/Rectangle.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Rectangle.h"
@@ -27,26 +19,28 @@
namespace fl {
Rectangle::Rectangle(const std::string& name, scalar start, scalar end, scalar height)
- : Term(name, height), _start(start), _end(end) {
- }
+ : Term(name, height), _start(start), _end(end) { }
- Rectangle::~Rectangle() {
- }
+ Rectangle::~Rectangle() { }
std::string Rectangle::className() const {
return "Rectangle";
}
+ Complexity Rectangle::complexity() const {
+ return Complexity().comparison(1 + 2).arithmetic(1);
+ }
+
scalar Rectangle::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- if (fl::Op::isLt(x, _start) or fl::Op::isGt(x, _end))
- return _height * 0.0;
- return _height * 1.0;
+ if (Op::isNaN(x)) return fl::nan;
+ if (Op::isGE(x, _start) and Op::isLE(x, _end))
+ return Term::_height * 1.0;
+ return Term::_height * 0.0;
}
std::string Rectangle::parameters() const {
return Op::join(2, " ", _start, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Rectangle::configure(const std::string& parameters) {
@@ -57,7 +51,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setStart(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/SShape.cpp b/fuzzylite/src/term/SShape.cpp
index cd02be1..65dfd2b 100644
--- a/fuzzylite/src/term/SShape.cpp
+++ b/fuzzylite/src/term/SShape.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/SShape.h"
@@ -27,36 +19,58 @@
namespace fl {
SShape::SShape(const std::string& name, scalar start, scalar end, scalar height)
- : Term(name, height), _start(start), _end(end) {
- }
+ : Term(name, height), _start(start), _end(end) { }
- SShape::~SShape() {
- }
+ SShape::~SShape() { }
std::string SShape::className() const {
return "SShape";
}
+ Complexity SShape::complexity() const {
+ return Complexity().comparison(1 + 3).arithmetic(1 + 3 + 4).function(1);
+ }
+
scalar SShape::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- //from Octave smf.m
- scalar average = (_start + _end) / 2.0;
- scalar difference = _end - _start;
+ if (Op::isNaN(x)) return fl::nan;
- if (Op::isLE(x, _start)) return _height * 0.0;
+ if (Op::isLE(x, _start))
+ return Term::_height * 0.0;
- if (Op::isLE(x, average))
- return _height * (2.0 * std::pow((x - _start) / difference, 2));
+ if (Op::isLE(x, 0.5 * (_start + _end)))
+ return Term::_height * (2.0 * std::pow((x - _start) / (_end - _start), 2));
if (Op::isLt(x, _end))
- return _height * (1.0 - 2.0 * std::pow((x - _end) / difference, 2));
+ return Term::_height * (1.0 - 2.0 * std::pow((x - _end) / (_end - _start), 2));
+
+ return Term::_height * 1.0;
+ }
+
+ scalar SShape::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+
+ scalar w = activationDegree;
+ scalar z = fl::nan;
+
+ scalar difference = _end - _start;
+ scalar a = _start + std::sqrt(0.5 * w * difference * difference);
+ scalar b = _end + std::sqrt(-0.5 * (w - 1.0) * difference * difference);
+ if (std::abs(w - membership(a)) < std::abs(w - membership(b))) {
+ z = a;
+ } else {
+ z = b;
+ }
+ return z;
+ }
- return _height * 1.0;
+ bool SShape::isMonotonic() const {
+ return true;
}
std::string SShape::parameters() const {
return Op::join(2, " ", _start, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void SShape::configure(const std::string& parameters) {
@@ -67,7 +81,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setStart(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Sigmoid.cpp b/fuzzylite/src/term/Sigmoid.cpp
index 77d7f82..fcf165e 100644
--- a/fuzzylite/src/term/Sigmoid.cpp
+++ b/fuzzylite/src/term/Sigmoid.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Sigmoid.h"
@@ -27,24 +19,58 @@
namespace fl {
Sigmoid::Sigmoid(const std::string& name, scalar inflection, scalar slope, scalar height)
- : Term(name, height), _inflection(inflection), _slope(slope) {
- }
+ : Term(name, height), _inflection(inflection), _slope(slope) { }
- Sigmoid::~Sigmoid() {
- }
+ Sigmoid::~Sigmoid() { }
std::string Sigmoid::className() const {
return "Sigmoid";
}
+ Complexity Sigmoid::complexity() const {
+ return Complexity().comparison(1).arithmetic(1 + 4).function(1);
+ }
+
scalar Sigmoid::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- return _height * 1.0 / (1.0 + std::exp(-_slope * (x - _inflection)));
+ if (Op::isNaN(x)) return fl::nan;
+ return Term::_height * 1.0 / (1.0 + std::exp(-_slope * (x - _inflection)));
+ }
+
+ scalar Sigmoid::tsukamoto(scalar activationDegree,
+ scalar minimum, scalar maximum) const {
+
+ scalar w = activationDegree;
+ scalar z = fl::nan;
+
+ if (Op::isEq(w, 1.0)) {
+ if (Op::isGE(_slope, 0.0)) {
+ z = maximum;
+ } else {
+ z = minimum;
+ }
+
+ } else if (Op::isEq(w, 0.0)) {
+ if (Op::isGE(_slope, 0.0)) {
+ z = minimum;
+ } else {
+ z = maximum;
+ }
+ } else {
+ scalar a = _slope;
+ scalar b = _inflection;
+ z = b + (std::log(1.0 / w - 1.0) / -a);
+ }
+
+ return z;
+ }
+
+ bool Sigmoid::isMonotonic() const {
+ return true;
}
std::string Sigmoid::parameters() const {
return Op::join(2, " ", _inflection, _slope) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Sigmoid::configure(const std::string& parameters) {
@@ -55,7 +81,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setInflection(Op::toScalar(values.at(0)));
setSlope(Op::toScalar(values.at(1)));
@@ -80,11 +106,11 @@ namespace fl {
}
Sigmoid::Direction Sigmoid::direction() const {
- if (not fl::Op::isFinite(_slope) or fl::Op::isEq(_slope, 0.0)) return ZERO;
+ if (not Op::isFinite(_slope) or Op::isEq(_slope, 0.0)) return Zero;
- if (fl::Op::isGt(_slope, 0.0)) return POSITIVE;
+ if (Op::isGt(_slope, 0.0)) return Positive;
- return NEGATIVE;
+ return Negative;
}
Sigmoid* Sigmoid::clone() const {
diff --git a/fuzzylite/src/term/SigmoidDifference.cpp b/fuzzylite/src/term/SigmoidDifference.cpp
index 55a586c..8f7ee80 100644
--- a/fuzzylite/src/term/SigmoidDifference.cpp
+++ b/fuzzylite/src/term/SigmoidDifference.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/SigmoidDifference.h"
@@ -29,27 +21,29 @@ namespace fl {
SigmoidDifference::SigmoidDifference(const std::string& name,
scalar left, scalar rising,
scalar falling, scalar right, scalar height)
- : Term(name, height), _left(left), _rising(rising), _falling(falling), _right(right) {
- }
+ : Term(name, height), _left(left), _rising(rising), _falling(falling), _right(right) { }
- SigmoidDifference::~SigmoidDifference() {
- }
+ SigmoidDifference::~SigmoidDifference() { }
std::string SigmoidDifference::className() const {
return "SigmoidDifference";
}
+ Complexity SigmoidDifference::complexity() const {
+ return Complexity().comparison(1).arithmetic(2 + 4 + 4).function(2 + 1);
+ }
+
scalar SigmoidDifference::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
+ if (Op::isNaN(x)) return fl::nan;
- scalar a = 1.0 / (1 + std::exp(-_rising * (x - _left)));
- scalar b = 1.0 / (1 + std::exp(-_falling * (x - _right)));
- return _height * std::abs(a - b);
+ const scalar a = 1.0 / (1.0 + std::exp(-_rising * (x - _left)));
+ const scalar b = 1.0 / (1.0 + std::exp(-_falling * (x - _right)));
+ return Term::_height * std::abs(a - b);
}
std::string SigmoidDifference::parameters() const {
return Op::join(4, " ", _left, _rising, _falling, _right) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void SigmoidDifference::configure(const std::string& parameters) {
@@ -60,7 +54,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setLeft(Op::toScalar(values.at(0)));
setRising(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/SigmoidProduct.cpp b/fuzzylite/src/term/SigmoidProduct.cpp
index 9e43ac9..5f35750 100644
--- a/fuzzylite/src/term/SigmoidProduct.cpp
+++ b/fuzzylite/src/term/SigmoidProduct.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/SigmoidProduct.h"
@@ -29,25 +21,28 @@ namespace fl {
SigmoidProduct::SigmoidProduct(const std::string& name,
scalar left, scalar rising,
scalar falling, scalar right, scalar height)
- : Term(name, height), _left(left), _rising(rising), _falling(falling), _right(right) {
- }
+ : Term(name, height), _left(left), _rising(rising), _falling(falling), _right(right) { }
- SigmoidProduct::~SigmoidProduct() {
- }
+ SigmoidProduct::~SigmoidProduct() { }
std::string SigmoidProduct::className() const {
return "SigmoidProduct";
}
+ Complexity SigmoidProduct::complexity() const {
+ return Complexity().comparison(1).arithmetic(2 + 4 + 4).function(2);
+ }
+
scalar SigmoidProduct::membership(scalar x) const {
- scalar a = 1.0 / (1 + std::exp(-_rising * (x - _left)));
- scalar b = 1.0 / (1 + std::exp(-_falling * (x - _right)));
- return _height * a * b;
+ if (Op::isNaN(x)) return fl::nan;
+ const scalar a = 1.0 + std::exp(-_rising * (x - _left));
+ const scalar b = 1.0 + std::exp(-_falling * (x - _right));
+ return Term::_height * 1.0 / (a * b);
}
std::string SigmoidProduct::parameters() const {
return Op::join(4, " ", _left, _rising, _falling, _right) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void SigmoidProduct::configure(const std::string& parameters) {
@@ -58,7 +53,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setLeft(Op::toScalar(values.at(0)));
setRising(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Spike.cpp b/fuzzylite/src/term/Spike.cpp
index f4b73bf..a19810d 100644
--- a/fuzzylite/src/term/Spike.cpp
+++ b/fuzzylite/src/term/Spike.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Spike.h"
@@ -27,25 +19,26 @@
namespace fl {
Spike::Spike(const std::string& name, scalar center, scalar width, scalar height)
- : Term(name, height), _center(center), _width(width) {
- }
-
- Spike::~Spike() {
+ : Term(name, height), _center(center), _width(width) { }
- }
+ Spike::~Spike() { }
std::string Spike::className() const {
return "Spike";
}
+ Complexity Spike::complexity() const {
+ return Complexity().comparison(1).arithmetic(1 + 3).function(2);
+ }
+
scalar Spike::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- return _height * std::exp(-std::fabs(10.0 / _width * (x - _center)));
+ if (Op::isNaN(x)) return fl::nan;
+ return Term::_height * std::exp(-std::abs(10.0 / _width * (x - _center)));
}
std::string Spike::parameters() const {
return Op::join(2, " ", _center, _width) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Spike::configure(const std::string& parameters) {
@@ -56,7 +49,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setCenter(Op::toScalar(values.at(0)));
setWidth(Op::toScalar(values.at(1)));
@@ -87,4 +80,5 @@ namespace fl {
Term* Spike::constructor() {
return new Spike;
}
+
}
diff --git a/fuzzylite/src/term/Term.cpp b/fuzzylite/src/term/Term.cpp
index 143a98f..bf7520d 100644
--- a/fuzzylite/src/term/Term.cpp
+++ b/fuzzylite/src/term/Term.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Term.h"
@@ -30,13 +22,9 @@
namespace fl {
- Term::Term(const std::string& name, scalar height) : _name(name), _height(height) {
-
- }
-
- Term::~Term() {
+ Term::Term(const std::string& name, scalar height) : _name(name), _height(height) { }
- }
+ Term::~Term() { }
void Term::setName(const std::string& name) {
this->_name = name;
@@ -58,17 +46,20 @@ namespace fl {
return FllExporter().toString(this);
}
- void Term::updateReference(Term* term, const Engine* engine) {
- if (Linear * linear = dynamic_cast<Linear*> (term)) {
- linear->setEngine(engine);
- } else if (Function * function = dynamic_cast<Function*> (term)) {
- function->setEngine(engine);
- try {
- function->load();
- } catch (...) {
- //ignore
- }
- }
+ void Term::updateReference(const Engine* engine) {
+ FL_IUNUSED(engine);
+ //do nothing
}
+ scalar Term::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+ return membership(activationDegree);
+ }
+
+ bool Term::isMonotonic() const {
+ return false;
+ }
+
+
}
diff --git a/fuzzylite/src/term/Trapezoid.cpp b/fuzzylite/src/term/Trapezoid.cpp
index 60abcc4..4773dbb 100644
--- a/fuzzylite/src/term/Trapezoid.cpp
+++ b/fuzzylite/src/term/Trapezoid.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Trapezoid.h"
@@ -30,7 +22,6 @@ namespace fl {
scalar vertexA, scalar vertexB, scalar vertexC, scalar vertexD, scalar height)
: Term(name, height), _vertexA(vertexA), _vertexB(vertexB), _vertexC(vertexC), _vertexD(vertexD) {
if (Op::isNaN(vertexC) and Op::isNaN(vertexD)) {
- //TODO: Modify FLL to allow passing two parameters only.
this->_vertexD = _vertexB;
scalar range = _vertexD - _vertexA;
this->_vertexB = _vertexA + range * 1.0 / 5.0;
@@ -38,34 +29,41 @@ namespace fl {
}
}
- Trapezoid::~Trapezoid() {
- }
+ Trapezoid::~Trapezoid() { }
std::string Trapezoid::className() const {
return "Trapezoid";
}
+ Complexity Trapezoid::complexity() const {
+ return Complexity().comparison(1 + 6).arithmetic(1 + 3).function(1);
+ }
+
scalar Trapezoid::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
+ if (Op::isNaN(x)) return fl::nan;
if (Op::isLt(x, _vertexA) or Op::isGt(x, _vertexD))
- return _height * 0.0;
-
- if (Op::isLt(x, _vertexB))
- return _height * Op::min(scalar(1.0), (x - _vertexA) / (_vertexB - _vertexA));
+ return Term::_height * 0.0;
+ if (Op::isLt(x, _vertexB)) {
+ if (_vertexA == -fl::inf) return Term::_height * 1.0;
+ return Term::_height * Op::min(scalar(1.0), (x - _vertexA) / (_vertexB - _vertexA));
+ }
if (Op::isLE(x, _vertexC))
- return _height * 1.0;
+ return Term::_height * 1.0;
- if (Op::isLt(x, _vertexD))
- return _height * (_vertexD - x) / (_vertexD - _vertexC);
+ if (Op::isLt(x, _vertexD)) {
+ if (_vertexD == fl::inf) return Term::_height * 1.0;
+ return Term::_height * (_vertexD - x) / (_vertexD - _vertexC);
+ }
- return _height * 0.0;
+ if (_vertexD == fl::inf) return Term::_height * 1.0;
+ return Term::_height * 0.0;
}
std::string Trapezoid::parameters() const {
return Op::join(4, " ", _vertexA, _vertexB, _vertexC, _vertexD)+
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Trapezoid::configure(const std::string& parameters) {
@@ -76,7 +74,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setVertexA(Op::toScalar(values.at(0)));
setVertexB(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/Triangle.cpp b/fuzzylite/src/term/Triangle.cpp
index 2fce1a6..9d1835c 100644
--- a/fuzzylite/src/term/Triangle.cpp
+++ b/fuzzylite/src/term/Triangle.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/Triangle.h"
@@ -28,38 +20,44 @@ namespace fl {
Triangle::Triangle(const std::string& name, scalar vertexA, scalar vertexB, scalar vertexC, scalar height)
: Term(name, height), _vertexA(vertexA), _vertexB(vertexB), _vertexC(vertexC) {
- if (fl::Op::isNaN(vertexC)) {
- //TODO: Modify FLL to allow passing two parameters only.
- this->_vertexC = vertexB;
- this->_vertexB = (vertexA + vertexB) / 2.0;
+ if (Op::isNaN(vertexC)) {
+ this->_vertexC = _vertexB;
+ this->_vertexB = 0.5 * (_vertexA + _vertexB);
}
}
- Triangle::~Triangle() {
- }
+ Triangle::~Triangle() { }
std::string Triangle::className() const {
return "Triangle";
}
+ Complexity Triangle::complexity() const {
+ return Complexity().comparison(1 + 5).arithmetic(4);
+ }
+
scalar Triangle::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
+ if (Op::isNaN(x)) return fl::nan;
if (Op::isLt(x, _vertexA) or Op::isGt(x, _vertexC))
- return _height * 0.0;
+ return Term::_height * 0.0;
if (Op::isEq(x, _vertexB))
- return _height * 1.0;
-
- if (Op::isLt(x, _vertexB))
- return _height * (x - _vertexA) / (_vertexB - _vertexA);
+ return Term::_height * 1.0;
- return _height * (_vertexC - x) / (_vertexC - _vertexB);
+ if (Op::isLt(x, _vertexB)) {
+ if (_vertexA == -fl::inf)
+ return Term::_height * 1.0;
+ return Term::_height * (x - _vertexA) / (_vertexB - _vertexA);
+ }
+ if (_vertexC == fl::inf)
+ return Term::_height * 1.0;
+ return Term::_height * (_vertexC - x) / (_vertexC - _vertexB);
}
std::string Triangle::parameters() const {
return Op::join(3, " ", _vertexA, _vertexB, _vertexC) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void Triangle::configure(const std::string& parameters) {
@@ -70,7 +68,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setVertexA(Op::toScalar(values.at(0)));
setVertexB(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/term/ZShape.cpp b/fuzzylite/src/term/ZShape.cpp
index 86668b6..9054b20 100644
--- a/fuzzylite/src/term/ZShape.cpp
+++ b/fuzzylite/src/term/ZShape.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/term/ZShape.h"
@@ -27,36 +19,58 @@
namespace fl {
ZShape::ZShape(const std::string& name, scalar start, scalar end, scalar height)
- : Term(name, height), _start(start), _end(end) {
- }
+ : Term(name, height), _start(start), _end(end) { }
- ZShape::~ZShape() {
- }
+ ZShape::~ZShape() { }
std::string ZShape::className() const {
return "ZShape";
}
+ Complexity ZShape::complexity() const {
+ return Complexity().comparison(1 + 3).arithmetic(3 + 4).function(1);
+ }
+
scalar ZShape::membership(scalar x) const {
- if (fl::Op::isNaN(x)) return fl::nan;
- //from Octave zmf.m
- scalar average = (_start + _end) / 2;
- scalar difference = _end - _start;
+ if (Op::isNaN(x)) return fl::nan;
- if (Op::isLE(x, _start)) return _height * 1.0;
+ if (Op::isLE(x, _start))
+ return Term::_height * 1.0;
- if (Op::isLE(x, average))
- return _height * (1.0 - 2.0 * std::pow((x - _start) / difference, 2));
+ if (Op::isLE(x, 0.5 * (_start + _end)))
+ return Term::_height * (1.0 - 2.0 * std::pow((x - _start) / (_end - _start), 2));
if (Op::isLt(x, _end))
- return _height * (2.0 * std::pow((x - _end) / difference, 2));
+ return Term::_height * (2.0 * std::pow((x - _end) / (_end - _start), 2));
+
+ return Term::_height * 0.0;
+ }
+
+ scalar ZShape::tsukamoto(scalar activationDegree, scalar minimum, scalar maximum) const {
+ FL_IUNUSED(minimum);
+ FL_IUNUSED(maximum);
+
+ scalar w = activationDegree;
+ scalar z = fl::nan;
+
+ scalar difference = _end - _start;
+ scalar a = _start + std::sqrt(-0.5 * (w - 1.0) * difference * difference);
+ scalar b = _end + std::sqrt(0.5 * w * difference * difference);
+ if (std::abs(w - membership(a)) < std::abs(w - membership(b))) {
+ z = a;
+ } else {
+ z = b;
+ }
+ return z;
+ }
- return _height * 0.0;
+ bool ZShape::isMonotonic() const {
+ return true;
}
std::string ZShape::parameters() const {
return Op::join(2, " ", _start, _end) +
- (not Op::isEq(_height, 1.0) ? " " + Op::str(_height) : "");
+ (not Op::isEq(getHeight(), 1.0) ? " " + Op::str(getHeight()) : "");
}
void ZShape::configure(const std::string& parameters) {
@@ -67,7 +81,7 @@ namespace fl {
std::ostringstream ex;
ex << "[configuration error] term <" << className() << ">"
<< " requires <" << required << "> parameters";
- throw fl::Exception(ex.str(), FL_AT);
+ throw Exception(ex.str(), FL_AT);
}
setStart(Op::toScalar(values.at(0)));
setEnd(Op::toScalar(values.at(1)));
diff --git a/fuzzylite/src/variable/InputVariable.cpp b/fuzzylite/src/variable/InputVariable.cpp
index 9fa2932..1364d8f 100644
--- a/fuzzylite/src/variable/InputVariable.cpp
+++ b/fuzzylite/src/variable/InputVariable.cpp
@@ -1,25 +1,17 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/variable/InputVariable.h"
@@ -29,26 +21,24 @@
namespace fl {
InputVariable::InputVariable(const std::string& name, scalar minimum, scalar maximum)
- : Variable(name, minimum, maximum), _inputValue(fl::nan) {
- }
-
- InputVariable::~InputVariable() {
- }
+ : Variable(name, minimum, maximum) { }
- void InputVariable::setInputValue(scalar inputValue) {
- this->_inputValue = inputValue;
- }
+ InputVariable::~InputVariable() { }
- scalar InputVariable::getInputValue() const {
- return this->_inputValue;
+ std::string InputVariable::fuzzyInputValue() const {
+ return fuzzify(getValue());
}
- std::string InputVariable::fuzzyInputValue() const {
- return fuzzify(_inputValue);
+ Variable::Type InputVariable::type() const {
+ return Variable::Input;
}
std::string InputVariable::toString() const {
return FllExporter().toString(this);
}
+ InputVariable* InputVariable::clone() const {
+ return new InputVariable(*this);
+ }
+
}
diff --git a/fuzzylite/src/variable/OutputVariable.cpp b/fuzzylite/src/variable/OutputVariable.cpp
index 6e1d906..0f85dc4 100644
--- a/fuzzylite/src/variable/OutputVariable.cpp
+++ b/fuzzylite/src/variable/OutputVariable.cpp
@@ -1,44 +1,31 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/variable/OutputVariable.h"
-#include "fl/defuzzifier/Defuzzifier.h"
#include "fl/imex/FllExporter.h"
-#include "fl/norm/SNorm.h"
-#include "fl/term/Accumulated.h"
-#include "fl/term/Activated.h"
namespace fl {
OutputVariable::OutputVariable(const std::string& name,
scalar minimum, scalar maximum)
: Variable(name, minimum, maximum),
- _fuzzyOutput(new Accumulated(name, minimum, maximum)), _outputValue(fl::nan),
- _previousOutputValue(fl::nan), _defaultValue(fl::nan),
- _lockOutputValueInRange(false), _lockPreviousOutputValue(false) {
- }
+ _fuzzyOutput(new Aggregated(name, minimum, maximum)),
+ _previousValue(fl::nan), _defaultValue(fl::nan),
+ _lockPreviousValue(false) { }
OutputVariable::OutputVariable(const OutputVariable& other) : Variable(other) {
copyFrom(other);
@@ -55,36 +42,33 @@ namespace fl {
return *this;
}
- OutputVariable::~OutputVariable() {
- }
+ OutputVariable::~OutputVariable() { }
void OutputVariable::copyFrom(const OutputVariable& other) {
_fuzzyOutput.reset(other._fuzzyOutput->clone());
if (other._defuzzifier.get()) _defuzzifier.reset(other._defuzzifier->clone());
- _outputValue = other._outputValue;
- _previousOutputValue = other._previousOutputValue;
+ _previousValue = other._previousValue;
_defaultValue = other._defaultValue;
- _lockOutputValueInRange = other._lockOutputValueInRange;
- _lockPreviousOutputValue = other._lockPreviousOutputValue;
+ _lockPreviousValue = other._lockPreviousValue;
}
void OutputVariable::setName(const std::string& name) {
Variable::setName(name);
- this->_fuzzyOutput->setName(name);
+ _fuzzyOutput->setName(name);
}
- Accumulated* OutputVariable::fuzzyOutput() const {
+ Aggregated* OutputVariable::fuzzyOutput() const {
return this->_fuzzyOutput.get();
}
void OutputVariable::setMinimum(scalar minimum) {
Variable::setMinimum(minimum);
- this->_fuzzyOutput->setMinimum(minimum);
+ _fuzzyOutput->setMinimum(minimum);
}
void OutputVariable::setMaximum(scalar maximum) {
Variable::setMaximum(maximum);
- this->_fuzzyOutput->setMaximum(maximum);
+ _fuzzyOutput->setMaximum(maximum);
}
void OutputVariable::setDefuzzifier(Defuzzifier* defuzzifier) {
@@ -95,20 +79,20 @@ namespace fl {
return this->_defuzzifier.get();
}
- void OutputVariable::setOutputValue(scalar outputValue) {
- this->_outputValue = outputValue;
+ void OutputVariable::setAggregation(SNorm* aggregation) {
+ this->_fuzzyOutput->setAggregation(aggregation);
}
- scalar OutputVariable::getOutputValue() const {
- return this->_outputValue;
+ SNorm* OutputVariable::getAggregation() const {
+ return this->_fuzzyOutput->getAggregation();
}
- void OutputVariable::setPreviousOutputValue(scalar previousOutputValue) {
- this->_previousOutputValue = previousOutputValue;
+ void OutputVariable::setPreviousValue(scalar previousOutputValue) {
+ this->_previousValue = previousOutputValue;
}
- scalar OutputVariable::getPreviousOutputValue() const {
- return this->_previousOutputValue;
+ scalar OutputVariable::getPreviousValue() const {
+ return this->_previousValue;
}
void OutputVariable::setDefaultValue(scalar defaultValue) {
@@ -119,77 +103,124 @@ namespace fl {
return this->_defaultValue;
}
- void OutputVariable::setLockOutputValueInRange(bool lockOutputValueInRange) {
- this->_lockOutputValueInRange = lockOutputValueInRange;
+ void OutputVariable::setLockPreviousValue(bool lockPreviousValue) {
+ this->_lockPreviousValue = lockPreviousValue;
}
- bool OutputVariable::isLockedOutputValueInRange() const {
- return this->_lockOutputValueInRange;
+ bool OutputVariable::isLockPreviousValue() const {
+ return this->_lockPreviousValue;
}
- void OutputVariable::setLockPreviousOutputValue(bool lockPreviousOutputValue) {
- this->_lockPreviousOutputValue = lockPreviousOutputValue;
+ Variable::Type OutputVariable::type() const {
+ return Variable::Output;
+ }
+
+ Complexity OutputVariable::complexity(const Activated& term) const {
+ Aggregated aggregated;
+ if (_fuzzyOutput->getAggregation()) {
+ aggregated.setAggregation(_fuzzyOutput->getAggregation()->clone());
+ }
+ aggregated.addTerm(term);
+ if (_defuzzifier.get()) {
+ return _defuzzifier->complexity(&aggregated);
+ }
+ return aggregated.complexityOfMembership();
+ }
+
+ Complexity OutputVariable::complexityOfDefuzzification() const {
+ Aggregated term;
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ term.addTerm(_terms.at(i), fl::nan, fl::null);
+ }
+ if (_defuzzifier.get()) {
+ return _defuzzifier->complexity(&term);
+ }
+ return term.complexityOfMembership();
}
- bool OutputVariable::isLockedPreviousOutputValue() const {
- return this->_lockPreviousOutputValue;
+ Complexity OutputVariable::currentComplexity() const {
+ if (_defuzzifier.get())
+ return _defuzzifier->complexity(_fuzzyOutput.get());
+ return _fuzzyOutput->complexity();
}
void OutputVariable::defuzzify() {
- if (fl::Op::isFinite(this->_outputValue)) {
- this->_previousOutputValue = this->_outputValue;
+ if (not _enabled) return;
+
+ if (Op::isFinite(_value)) {
+ _previousValue = _value;
}
+ std::string exception;
scalar result = fl::nan;
- bool isValid = this->_enabled and not this->_fuzzyOutput->isEmpty();
+ bool isValid = not _fuzzyOutput->isEmpty();
if (isValid) {
- if (not _defuzzifier.get()) {
- throw fl::Exception("[defuzzifier error] "
- "defuzzifier needed to defuzzify output variable <" + _name + ">", FL_AT);
+ /* Checks whether the variable can be defuzzified without exceptions.
+ * If it cannot be defuzzified, be that due to a missing defuzzifier
+ * or aggregation operator, the expected behaviour is to leave the
+ * variable in a state that reflects an invalid defuzzification,
+ * that is, apply logic of default values and previous values.*/
+ isValid = false;
+ if (_defuzzifier.get()) {
+ try {
+ result = _defuzzifier->defuzzify(_fuzzyOutput.get(), _minimum, _maximum);
+ isValid = true;
+ } catch (std::exception& ex) {
+ exception = ex.what();
+ }
+ } else {
+ exception = "[defuzzifier error] "
+ "defuzzifier needed to defuzzify output variable <" + getName() + ">";
}
- result = this->_defuzzifier->defuzzify(this->_fuzzyOutput.get(), _minimum, _maximum);
- } else {
+ }
+
+ if (not isValid) {
//if a previous defuzzification was successfully performed and
//and the output value is supposed not to change when the output is empty
- if (_lockPreviousOutputValue and not Op::isNaN(_previousOutputValue)) {
- result = _previousOutputValue;
+ if (_lockPreviousValue and not Op::isNaN(_previousValue)) {
+ result = _previousValue;
} else {
result = _defaultValue;
}
}
- if (_lockOutputValueInRange) {
- result = fl::Op::bound(result, _minimum, _maximum);
- }
+ setValue(result);
- this->_outputValue = result;
+ if (not exception.empty()) {
+ throw Exception(exception, FL_AT);
+ }
}
std::string OutputVariable::fuzzyOutputValue() const {
std::ostringstream ss;
- for (std::size_t i = 0; i < _terms.size(); ++i) {
- scalar degree = _fuzzyOutput->activationDegree(_terms.at(i));
- if (i == 0) {
- ss << fl::Op::str(degree);
- } else {
- if (fl::Op::isNaN(degree) or fl::Op::isGE(degree, 0.0))
- ss << " + " << fl::Op::str(degree);
- else
- ss << " - " << fl::Op::str(std::fabs(degree));
- }
- ss << "/" << _terms.at(i)->getName();
+ if (not _terms.empty()) {
+ Term* first = _terms.front();
+ ss << Op::str(fuzzyOutput()->activationDegree(first))
+ << "/" << first->getName();
+ }
+ for (std::size_t i = 1; i < _terms.size(); ++i) {
+ scalar degree = fuzzyOutput()->activationDegree(_terms.at(i));
+ if (Op::isNaN(degree) or Op::isGE(degree, 0.0))
+ ss << " + " << Op::str(degree);
+ else
+ ss << " - " << Op::str(std::abs(degree));
+ ss << "/" << terms().at(i)->getName();
}
return ss.str();
}
void OutputVariable::clear() {
- _fuzzyOutput->clear();
- setPreviousOutputValue(fl::nan);
- setOutputValue(fl::nan);
+ fuzzyOutput()->clear();
+ setValue(fl::nan);
+ setPreviousValue(fl::nan);
}
std::string OutputVariable::toString() const {
return FllExporter().toString(this);
}
+ OutputVariable* OutputVariable::clone() const {
+ return new OutputVariable(*this);
+ }
+
}
diff --git a/fuzzylite/src/variable/Variable.cpp b/fuzzylite/src/variable/Variable.cpp
index 37cf25c..516b466 100644
--- a/fuzzylite/src/variable/Variable.cpp
+++ b/fuzzylite/src/variable/Variable.cpp
@@ -1,45 +1,34 @@
/*
- Author: Juan Rada-Vilela, Ph.D.
- Copyright (C) 2010-2014 FuzzyLite Limited
- All rights reserved
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
This file is part of fuzzylite.
fuzzylite is free software: you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
+ the terms of the FuzzyLite License included with the software.
- fuzzylite is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with fuzzylite. If not, see <http://www.gnu.org/licenses/>.
-
- fuzzyliteâ„¢ is a trademark of FuzzyLite Limited.
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+ fuzzylite is a registered trademark of FuzzyLite Limited.
*/
#include "fl/variable/Variable.h"
-#include "fl/defuzzifier/Centroid.h"
#include "fl/imex/FllExporter.h"
#include "fl/norm/Norm.h"
#include "fl/term/Constant.h"
#include "fl/term/Linear.h"
-#include "fl/term/Term.h"
-#include <algorithm>
-#include <map>
-#include <sstream>
+#include <queue>
namespace fl {
Variable::Variable(const std::string& name, scalar minimum, scalar maximum)
- : _name(name), _minimum(minimum), _maximum(maximum), _enabled(true) {
- }
+ : _name(name), _description(""),
+ _value(fl::nan), _minimum(minimum), _maximum(maximum),
+ _enabled(true), _lockValueInRange(false) { }
Variable::Variable(const Variable& other) {
copyFrom(other);
@@ -58,9 +47,12 @@ namespace fl {
void Variable::copyFrom(const Variable& other) {
_name = other._name;
- _enabled = other._enabled;
+ _description = other._description;
+ _value = other._value;
_minimum = other._minimum;
_maximum = other._maximum;
+ _enabled = other._enabled;
+ _lockValueInRange = other._lockValueInRange;
for (std::size_t i = 0; i < other._terms.size(); ++i) {
_terms.push_back(other._terms.at(i)->clone());
}
@@ -80,13 +72,31 @@ namespace fl {
return this->_name;
}
+ void Variable::setDescription(const std::string& description) {
+ this->_description = description;
+ }
+
+ std::string Variable::getDescription() const {
+ return this->_description;
+ }
+
+ void Variable::setValue(scalar value) {
+ this->_value = _lockValueInRange
+ ? Op::bound(value, _minimum, _maximum)
+ : value;
+ }
+
+ scalar Variable::getValue() const {
+ return this->_value;
+ }
+
void Variable::setRange(scalar minimum, scalar maximum) {
setMinimum(minimum);
setMaximum(maximum);
}
scalar Variable::range() const {
- return this->_maximum - this->_minimum;
+ return getMaximum() - getMinimum();
}
void Variable::setMinimum(scalar minimum) {
@@ -113,24 +123,47 @@ namespace fl {
return this->_enabled;
}
+ void Variable::setLockValueInRange(bool lockValueInRange) {
+ this->_lockValueInRange = lockValueInRange;
+ }
+
+ bool Variable::isLockValueInRange() const {
+ return this->_lockValueInRange;
+ }
+
+ Variable::Type Variable::type() const {
+ return None;
+ }
+
+ Complexity Variable::complexity() const {
+ Complexity result;
+ if (isEnabled()) {
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ result += _terms.at(i)->complexity();
+ }
+ }
+ return result;
+ }
+
std::string Variable::fuzzify(scalar x) const {
std::ostringstream ss;
- for (std::size_t i = 0; i < _terms.size(); ++i) {
+ for (std::size_t i = 0; i < terms().size(); ++i) {
+ Term* term = _terms.at(i);
scalar fx = fl::nan;
try {
- fx = _terms.at(i)->membership(x);
+ fx = term->membership(x);
} catch (...) {
//ignore
}
if (i == 0) {
- ss << fl::Op::str(fx);
+ ss << Op::str(fx);
} else {
- if (fl::Op::isNaN(fx) or fl::Op::isGE(fx, 0.0))
- ss << " + " << fl::Op::str(fx);
+ if (Op::isNaN(fx) or Op::isGE(fx, 0.0))
+ ss << " + " << Op::str(fx);
else
- ss << " - " << fl::Op::str(std::fabs(fx));
+ ss << " - " << Op::str(std::abs(fx));
}
- ss << "/" << _terms.at(i)->getName();
+ ss << "/" << term->getName();
}
return ss.str();
}
@@ -140,14 +173,15 @@ namespace fl {
scalar ymax = 0.0;
for (std::size_t i = 0; i < _terms.size(); ++i) {
scalar y = fl::nan;
+ Term* term = _terms.at(i);
try {
- y = _terms.at(i)->membership(x);
+ y = term->membership(x);
} catch (...) {
//ignore
}
- if (fl::Op::isGt(y, ymax)) {
+ if (Op::isGt(y, ymax)) {
ymax = y;
- result = _terms.at(i);
+ result = term;
}
}
if (yhighest) *yhighest = ymax;
@@ -162,70 +196,83 @@ namespace fl {
* Operations for datatype _terms
*/
- struct SortByCoG {
- std::map<const Term*, scalar> centroids;
+ typedef std::pair<Term*, scalar> TermCentroid;
+
+ struct Ascending {
- bool operator()(const Term* a, const Term * b) {
- return fl::Op::isLt(
- centroids.find(a)->second,
- centroids.find(b)->second);
+ bool operator()(const TermCentroid& a, const TermCentroid& b) const {
+ return a.second > b.second;
}
};
void Variable::sort() {
+ std::priority_queue <TermCentroid, std::vector<TermCentroid>, Ascending> termCentroids;
Centroid defuzzifier;
- std::map<const Term*, scalar> centroids;
+ FL_DBG("Sorting...");
for (std::size_t i = 0; i < _terms.size(); ++i) {
Term* term = _terms.at(i);
+ scalar centroid = fl::inf;
try {
if (dynamic_cast<const Constant*> (term) or dynamic_cast<const Linear*> (term)) {
- centroids[term] = term->membership(0);
+ centroid = term->membership(0);
} else {
- centroids[term] = defuzzifier.defuzzify(term, _minimum, _maximum);
+ centroid = defuzzifier.defuzzify(term, getMinimum(), getMaximum());
}
} catch (...) { //ignore error possibly due to Function not loaded
- centroids[term] = fl::inf;
+ centroid = fl::inf;
}
+ termCentroids.push(TermCentroid(term, centroid));
+ FL_DBG(term->toString() << " -> " << centroid)
}
- SortByCoG criterion;
- criterion.centroids = centroids;
- std::sort(_terms.begin(), _terms.end(), criterion);
+
+ std::vector<Term*> sortedTerms;
+ while (termCentroids.size() > 0) {
+ sortedTerms.push_back(termCentroids.top().first);
+ FL_DBG(termCentroids.top().first->toString() << " -> " << termCentroids.top().second);
+ termCentroids.pop();
+ }
+ setTerms(sortedTerms);
}
void Variable::addTerm(Term* term) {
- this->_terms.push_back(term);
+ _terms.push_back(term);
}
- void Variable::insertTerm(Term* term, int index) {
- this->_terms.insert(this->_terms.begin() + index, term);
+ void Variable::insertTerm(Term* term, std::size_t index) {
+ _terms.insert(_terms.begin() + index, term);
}
- Term* Variable::getTerm(int index) const {
- return this->_terms.at(index);
+ Term* Variable::getTerm(std::size_t index) const {
+ return _terms.at(index);
}
Term* Variable::getTerm(const std::string& name) const {
- for (std::size_t i = 0; i < _terms.size(); ++i) {
+ for (std::size_t i = 0; i < terms().size(); ++i) {
if (_terms.at(i)->getName() == name) {
- return _terms.at(i);
+ return terms().at(i);
}
}
- throw fl::Exception("[variable error] term <" + name + "> "
- "not found in variable <" + this->_name + ">", FL_AT);
+ throw Exception("[variable error] term <" + name + "> "
+ "not found in variable <" + getName() + ">", FL_AT);
}
bool Variable::hasTerm(const std::string& name) const {
- return getTerm(name) != fl::null;
+ for (std::size_t i = 0; i < _terms.size(); ++i) {
+ if (_terms.at(i)->getName() == name) {
+ return true;
+ }
+ }
+ return false;
}
- Term* Variable::removeTerm(int index) {
- Term* result = this->_terms.at(index);
- this->_terms.erase(this->_terms.begin() + index);
+ Term* Variable::removeTerm(std::size_t index) {
+ Term* result = _terms.at(index);
+ _terms.erase(_terms.begin() + index);
return result;
}
- int Variable::numberOfTerms() const {
- return this->_terms.size();
+ std::size_t Variable::numberOfTerms() const {
+ return _terms.size();
}
const std::vector<Term*>& Variable::terms() const {
@@ -240,5 +287,9 @@ namespace fl {
return this->_terms;
}
+ Variable* Variable::clone() const {
+ return new Variable(*this);
+ }
+
}
diff --git a/fuzzylite/test/BenchmarkTest.cpp b/fuzzylite/test/BenchmarkTest.cpp
new file mode 100644
index 0000000..f868ec2
--- /dev/null
+++ b/fuzzylite/test/BenchmarkTest.cpp
@@ -0,0 +1,131 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "fl/Benchmark.h"
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+#include <vector>
+#include <fstream>
+
+namespace fl {
+
+ TEST_CASE("Benchmarks run from Console ", "[benchmark][console]") {
+ // const char* args[] = {"dummy-command", "benchmarks", "../../examples/", "1"};
+ // Console::main(4, args);
+ }
+
+ TEST_CASE("Benchmarks from FLD files", "[benchmark][fld]") {
+ std::string path = "../../examples/";
+ typedef std::pair<std::string, int > Example;
+ std::vector<Example> examples;
+ examples.push_back(Example("mamdani/AllTerms", int(1e4)));
+ examples.push_back(Example("mamdani/SimpleDimmer", int(1e5)));
+ examples.push_back(Example("mamdani/matlab/mam21", 128));
+ examples.push_back(Example("mamdani/matlab/mam22", 128));
+ examples.push_back(Example("mamdani/matlab/shower", 256));
+ examples.push_back(Example("mamdani/matlab/tank", 256));
+ examples.push_back(Example("mamdani/matlab/tank2", 512));
+ examples.push_back(Example("mamdani/matlab/tipper", 256));
+ examples.push_back(Example("mamdani/matlab/tipper1", int(1e5)));
+ examples.push_back(Example("mamdani/octave/investment_portfolio", 256));
+ examples.push_back(Example("mamdani/octave/mamdani_tip_calculator", 256));
+ examples.push_back(Example("takagi-sugeno/approximation", int(1e6)));
+ examples.push_back(Example("takagi-sugeno/SimpleDimmer", int(2e6)));
+ examples.push_back(Example("takagi-sugeno/matlab/fpeaks", 512));
+ examples.push_back(Example("takagi-sugeno/matlab/invkine1", 256));
+ examples.push_back(Example("takagi-sugeno/matlab/invkine2", 256));
+ examples.push_back(Example("takagi-sugeno/matlab/juggler", 512));
+ examples.push_back(Example("takagi-sugeno/matlab/membrn1", 1024));
+ examples.push_back(Example("takagi-sugeno/matlab/membrn2", 512));
+ examples.push_back(Example("takagi-sugeno/matlab/slbb", 20));
+ examples.push_back(Example("takagi-sugeno/matlab/slcp", 20));
+ examples.push_back(Example("takagi-sugeno/matlab/slcp1", 15));
+ examples.push_back(Example("takagi-sugeno/matlab/slcpp1", 9));
+ examples.push_back(Example("takagi-sugeno/matlab/sltbu_fl", 128));
+ examples.push_back(Example("takagi-sugeno/matlab/sugeno1", int(2e6)));
+ examples.push_back(Example("takagi-sugeno/matlab/tanksg", 1024));
+ examples.push_back(Example("takagi-sugeno/matlab/tippersg", 1024));
+ examples.push_back(Example("takagi-sugeno/octave/cubic_approximator", int(2e6)));
+ examples.push_back(Example("takagi-sugeno/octave/heart_disease_risk", 1024));
+ examples.push_back(Example("takagi-sugeno/octave/linear_tip_calculator", 1024));
+ examples.push_back(Example("takagi-sugeno/octave/sugeno_tip_calculator", 512));
+ examples.push_back(Example("tsukamoto/tsukamoto", int(1e6)));
+
+ std::ostringstream writer;
+ std::vector<int> errors = std::vector<int>(examples.size(), 0);
+ for (std::size_t i = 0; i < examples.size(); ++i) {
+ Example example = examples.at(i);
+ FL_LOG("Benchmark " << (i + 1) << "/" << examples.size() << ": "
+ << example.first << ".fll (" << example.second << " values)");
+
+ FL_unique_ptr<Engine> engine(FllImporter().fromFile(path + example.first + ".fll"));
+
+#ifdef FL_USE_FLOAT
+ scalar tolerance = 1e-3;
+#else
+ scalar tolerance = fuzzylite::macheps();
+#endif
+ Benchmark benchmark(example.first, engine.get(), tolerance);
+
+ std::ifstream reader(std::string(path + example.first + ".fld").c_str());
+ if (not reader.is_open()) {
+ throw Exception("File not found: " + path + example.first + ".fld");
+ }
+ benchmark.prepare(reader, 1024);
+ benchmark.run(1);
+ CHECK(benchmark.canComputeErrors() == true);
+ errors.at(i) = benchmark.accuracyErrors();
+
+ if (i == 0) {
+ writer << "\n" << benchmark.format(benchmark.results(),
+ Benchmark::Horizontal, Benchmark::HeaderAndBody) << "\n";
+ } else {
+ writer << benchmark.format(benchmark.results(),
+ Benchmark::Horizontal, Benchmark::Body) << "\n";
+ }
+ }
+ FL_LOG(writer.str());
+ for (std::size_t i = 0; i < errors.size(); ++i) {
+ FL_LOG("Checking for errors in: " << examples.at(i).first);
+ CHECK(errors.at(i) == 0);
+ }
+ }
+
+ TEST_CASE("Time conversions", "[benchmark][time]") {
+ CHECK(Op::isEq(1.0, Benchmark::convert(3600, Benchmark::Seconds, Benchmark::Hours)));
+ FL_LOG(Benchmark::convert(3600, Benchmark::Seconds, Benchmark::Hours));
+ CHECK(Op::isEq(3600, Benchmark::convert(1, Benchmark::Hours, Benchmark::Seconds)));
+ FL_LOG(Benchmark::convert(1, Benchmark::Hours, Benchmark::Seconds));
+
+ CHECK(Op::isEq(1000.0, Benchmark::convert(1.0, Benchmark::Seconds, Benchmark::MilliSeconds)));
+ FL_LOG(Benchmark::convert(1.0, Benchmark::Seconds, Benchmark::MilliSeconds));
+ CHECK(Op::isEq(1.0, Benchmark::convert(1000.0, Benchmark::MilliSeconds, Benchmark::Seconds)));
+ FL_LOG(Benchmark::convert(1000.0, Benchmark::MilliSeconds, Benchmark::Seconds));
+
+ CHECK(Op::isEq(35e9, Benchmark::convert(35, Benchmark::Seconds, Benchmark::NanoSeconds)));
+ CHECK(Op::isEq(35, Benchmark::convert(35e9, Benchmark::NanoSeconds, Benchmark::Seconds)));
+ }
+
+ TEST_CASE("Benchmark headers", "[benchmark][header]") {
+ FL_LOG(Op::join(Benchmark().header(10, true), "\t"));
+ CHECK(Benchmark().header(10).size() == 30);
+
+ FL_LOG(Op::join(Benchmark().header(10, false), "\t"));
+ CHECK(Benchmark().header(10, false).size() == 30 - 8);
+ }
+}
diff --git a/fuzzylite/test/Catch.License b/fuzzylite/test/Catch.License
new file mode 100644
index 0000000..36b7cd9
--- /dev/null
+++ b/fuzzylite/test/Catch.License
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/fuzzylite/test/MainTest.cpp b/fuzzylite/test/MainTest.cpp
new file mode 100644
index 0000000..c18740a
--- /dev/null
+++ b/fuzzylite/test/MainTest.cpp
@@ -0,0 +1,34 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#define CATCH_CONFIG_RUNNER
+
+#include "test/catch.hpp"
+
+#include "fl/Headers.h"
+
+int main(int argc, char** argv) {
+
+ // global setup...
+ fl::fuzzylite::setDebugging(false);
+ fl::fuzzylite::setLogging(true);
+
+ int result = Catch::Session().run(argc, argv);
+
+ // global clean-up...
+
+ return result;
+}
diff --git a/fuzzylite/test/QuickTest.cpp b/fuzzylite/test/QuickTest.cpp
new file mode 100644
index 0000000..9108fde
--- /dev/null
+++ b/fuzzylite/test/QuickTest.cpp
@@ -0,0 +1,128 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ TEST_CASE("Increment ", "[op][increment]") {
+ std::vector<int> sampleValues, minSampleValues, maxSampleValues;
+ for (std::size_t i = 0; i < 2; ++i) {
+ sampleValues.push_back(0);
+ minSampleValues.push_back(0);
+ if (i == 0)
+ maxSampleValues.push_back(10);
+ else maxSampleValues.push_back(0);
+ }
+ int times = 0;
+ do {
+ times++;
+ FL_LOG(times << " " << Op::join(sampleValues, ","));
+ } while (Op::increment(sampleValues, minSampleValues, maxSampleValues));
+
+ CHECK(times == 10 + 1);
+ }
+
+ TEST_CASE("Op::split splits multiline", "[op][split]") {
+ std::string multiline = "1\n2\n3\n4";
+ std::vector<std::string> split = Op::split(multiline, "\n");
+ CHECK(split.size() == 4);
+ }
+
+ TEST_CASE("Op::str produces correct numbers", "[op][str]") {
+ fuzzylite::setLogging(true);
+ fuzzylite::setDecimals(3);
+
+ FL_LOG(Op::str(1.0));
+ FL_LOG(Op::str((long) 5000));
+ FL_LOG(Op::str((int) 6000));
+ FL_LOG(Op::str(std::size_t(6000)));
+ FL_LOG(Op::str(scalar(0.333333)));
+ FL_LOG(Op::str(float(0.333333)));
+ FL_LOG(Op::str(double(0.333333)));
+ FL_LOG(Op::str(double(0.333333), 9));
+
+ CHECK(Op::str(0) == "0");
+ CHECK(Op::str(1) == "1");
+ CHECK(Op::str(1.0) == "1.000");
+ CHECK(Op::str((long) 5000) == "5000");
+ CHECK(Op::str((int) 6000) == "6000");
+ CHECK(Op::str(std::size_t(6000)) == "6000");
+ CHECK(Op::str(scalar(0.333333)) == "0.333");
+ CHECK(Op::str(float(0.333333)) == "0.333");
+ CHECK(Op::str(double(0.333333)) == "0.333");
+ CHECK(Op::str(double(0.0000333), 9) == "0.000033300");
+
+ CHECK(Op::str(fuzzylite::macheps()) == "0.000");
+ CHECK(Op::str(fuzzylite::macheps(), 6) == "0.000001");
+ CHECK(Op::str(1e-7) == "0.000");
+ CHECK(Op::str(1e-7, 6) == "0.000000");
+ CHECK(Op::str(1e-7, 7) == "0.0000001");
+
+ FL_LOG("scientific");
+ fuzzylite::setScalarFormat(std::ios_base::scientific);
+ FL_LOG(Op::str(1.0));
+ FL_LOG(Op::str((long) 5000));
+ FL_LOG(Op::str((int) 6000));
+ FL_LOG(Op::str(std::size_t(6000)));
+ FL_LOG(Op::str(scalar(0.333333)));
+ FL_LOG(Op::str(float(0.333333)));
+ FL_LOG(Op::str(double(0.333333)));
+ FL_LOG(Op::str(double(0.0000333), 9));
+
+ CHECK(Op::str(0) == "0");
+ CHECK(Op::str(1.0) == "1.000e+00");
+ CHECK(Op::str((long) 5000) == "5000");
+ CHECK(Op::str((int) 6000) == "6000");
+ CHECK(Op::str(std::size_t(6000)) == "6000");
+ CHECK(Op::str(scalar(0.333333)) == "3.333e-01");
+ CHECK(Op::str(float(0.333333)) == "3.333e-01");
+ CHECK(Op::str(double(0.333333)) == "3.333e-01");
+ CHECK(Op::str(double(0.0000333), 9) == "3.330000000e-05");
+
+ CHECK(Op::isEq(fuzzylite::macheps(), 0.0) == false);
+ CHECK(Op::isEq(fuzzylite::macheps(), 0.0, std::pow(10.0, -6)) == false);
+ CHECK(Op::str(fuzzylite::macheps()) == "0.000e+00");
+ CHECK(Op::str(fuzzylite::macheps(), -1) == "1.000000e-06");
+ CHECK(Op::str(fuzzylite::macheps(), -1, std::ios_base::fmtflags(0x0)) == "1e-06");
+ CHECK(Op::str(1e-7, 6) == "0.000000e+00");
+ CHECK(Op::str(1e-7, 7) == "1.0000000e-07");
+ CHECK(Op::str(1e-7, 7, std::ios_base::fmtflags(0x0)) == "1e-07");
+
+
+ fuzzylite::setScalarFormat(std::ios_base::fixed);
+
+ CHECK(Op::str(0.000001, 6, std::ios_base::fmtflags(0x0)) == "1e-06");
+ CHECK(Op::str(1e-6, 6, std::ios_base::fmtflags(0x0)) == "1e-06");
+ CHECK(Op::str(1e6, 3, std::ios_base::fmtflags(0x0)) == "1e+06");
+ CHECK(Op::str(1000000, 3, std::ios_base::fmtflags(0x0)) == "1000000");
+ CHECK(Op::str(1000000.0, 3, std::ios_base::fmtflags(0x0)) == "1e+06");
+ }
+
+ TEST_CASE("macro expansion does not evaluate parameter before expansion", "[op]") {
+ std::ostringstream os;
+#define FL_MACRO1(x) os << x * 5;
+ FL_MACRO1(4 + 10);
+ CHECK(os.str() == "54");
+
+#define xstr(s) str(s)
+#define str(s) #s
+ CHECK(xstr(4 + 10) == "4 + 10");
+ }
+
+
+}
diff --git a/fuzzylite/test/activation/ThresholdTest.cpp b/fuzzylite/test/activation/ThresholdTest.cpp
new file mode 100644
index 0000000..9f6a9e6
--- /dev/null
+++ b/fuzzylite/test/activation/ThresholdTest.cpp
@@ -0,0 +1,65 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ /**
+ * Tests: term/Function
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ TEST_CASE("Treshold can be clone ", "[activation][threshold]") {
+ Threshold* t = new Threshold("<", 1.0);
+ REQUIRE(t->getComparison() == Threshold::LessThan);
+ REQUIRE(Op::isEq(t->getValue(), 1.0));
+ FL_DBG(FllExporter().toString(t));
+
+ Threshold* clone = t->clone();
+ REQUIRE(clone->getComparison() == Threshold::LessThan);
+ REQUIRE(Op::isEq(clone->getValue(), 1.0));
+ FL_DBG(FllExporter().toString(clone));
+ }
+
+ TEST_CASE("Treshold can be copy-constructed", "[activation][threshold]") {
+ Threshold* t = new Threshold(">=", 1.0);
+ REQUIRE(t->getComparison() == Threshold::GreaterThanOrEqualTo);
+ REQUIRE(Op::isEq(t->getValue(), 1.0));
+ FL_DBG(FllExporter().toString(t));
+
+ Threshold clone(*t);
+ REQUIRE(clone.getComparison() == Threshold::GreaterThanOrEqualTo);
+ REQUIRE(Op::isEq(clone.getValue(), 1.0));
+ FL_DBG(FllExporter().toString(&clone));
+ }
+
+ TEST_CASE("Treshold can be assigned", "[activation][threshold]") {
+ Threshold* t = new Threshold(">=", 1.0);
+ REQUIRE(t->getComparison() == Threshold::GreaterThanOrEqualTo);
+ REQUIRE(Op::isEq(t->getValue(), 1.0));
+ FL_DBG(FllExporter().toString(t));
+
+ Threshold clone = *t;
+ REQUIRE(clone.getComparison() == Threshold::GreaterThanOrEqualTo);
+ REQUIRE(Op::isEq(clone.getValue(), 1.0));
+ FL_DBG(FllExporter().toString(&clone));
+ }
+
+}
diff --git a/fuzzylite/test/catch.hpp b/fuzzylite/test/catch.hpp
new file mode 100644
index 0000000..6f9334b
--- /dev/null
+++ b/fuzzylite/test/catch.hpp
@@ -0,0 +1,11282 @@
+/*
+ * Catch v1.8.1
+ * Generated: 2017-03-01 16:04:19.016511
+ * ----------------------------------------------------------
+ * This file has been merged from multiple headers. Please don't edit it directly
+ * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
+#define TWOBLUECUBES_CATCH_HPP_INCLUDED
+
+#ifdef __clang__
+# pragma clang system_header
+#elif defined __GNUC__
+# pragma GCC system_header
+#endif
+
+// #included from: internal/catch_suppress_warnings.h
+
+#ifdef __clang__
+# ifdef __ICC // icpc defines the __clang__ macro
+# pragma warning(push)
+# pragma warning(disable: 161 1682)
+# else // __ICC
+# pragma clang diagnostic ignored "-Wglobal-constructors"
+# pragma clang diagnostic ignored "-Wvariadic-macros"
+# pragma clang diagnostic ignored "-Wc99-extensions"
+# pragma clang diagnostic ignored "-Wunused-variable"
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wpadded"
+# pragma clang diagnostic ignored "-Wc++98-compat"
+# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
+# pragma clang diagnostic ignored "-Wswitch-enum"
+# pragma clang diagnostic ignored "-Wcovered-switch-default"
+# endif
+#elif defined __GNUC__
+# pragma GCC diagnostic ignored "-Wvariadic-macros"
+# pragma GCC diagnostic ignored "-Wunused-variable"
+
+ // For newer version we can use __Pragma to disable the warnings locally
+# if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ <= 7
+# pragma GCC diagnostic ignored "-Wparentheses"
+# endif
+
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wpadded"
+#endif
+#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
+# define CATCH_IMPL
+#endif
+
+#ifdef CATCH_IMPL
+# ifndef CLARA_CONFIG_MAIN
+# define CLARA_CONFIG_MAIN_NOT_DEFINED
+# define CLARA_CONFIG_MAIN
+# endif
+#endif
+
+// #included from: internal/catch_notimplemented_exception.h
+#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
+
+// #included from: catch_common.h
+#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
+
+// #included from: catch_compiler_capabilities.h
+#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
+
+// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
+// The following features are defined:
+//
+// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
+// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
+// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
+// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
+// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
+// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
+// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
+// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
+// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
+// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
+
+// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
+
+// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
+// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
+// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
+// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
+// ****************
+// Note to maintainers: if new toggles are added please document them
+// in configuration.md, too
+// ****************
+
+// In general each macro has a _NO_<feature name> form
+// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
+// Many features, at point of detection, define an _INTERNAL_ macro, so they
+// can be combined, en-mass, with the _NO_ forms later.
+
+// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
+
+#ifdef __cplusplus
+
+# if __cplusplus >= 201103L
+# define CATCH_CPP11_OR_GREATER
+# endif
+
+# if __cplusplus >= 201402L
+# define CATCH_CPP14_OR_GREATER
+# endif
+
+#endif
+
+#ifdef __clang__
+
+# if __has_feature(cxx_nullptr)
+# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+# endif
+
+# if __has_feature(cxx_noexcept)
+# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
+# endif
+
+# if defined(CATCH_CPP11_OR_GREATER)
+# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "clang diagnostic push" ) \
+ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
+# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "clang diagnostic pop" )
+# endif
+
+#endif // __clang__
+
+////////////////////////////////////////////////////////////////////////////////
+// Cygwin
+#ifdef __CYGWIN__
+
+# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
+# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
+# endif
+
+// Required for some versions of Cygwin to declare gettimeofday
+// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
+# define _BSD_SOURCE
+
+#endif // __CYGWIN__
+
+////////////////////////////////////////////////////////////////////////////////
+// Borland
+#ifdef __BORLANDC__
+
+#endif // __BORLANDC__
+
+////////////////////////////////////////////////////////////////////////////////
+// EDG
+#ifdef __EDG_VERSION__
+
+#endif // __EDG_VERSION__
+
+////////////////////////////////////////////////////////////////////////////////
+// Digital Mars
+#ifdef __DMC__
+
+#endif // __DMC__
+
+////////////////////////////////////////////////////////////////////////////////
+// GCC
+#ifdef __GNUC__
+
+# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+# define CATCH_GCC_HAS_NEW_PRAGMA
+# endif
+
+# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+# endif
+
+# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_GCC_HAS_NEW_PRAGMA)
+# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "GCC diagnostic push" ) \
+ _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
+# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "GCC diagnostic pop" )
+# endif
+
+// - otherwise more recent versions define __cplusplus >= 201103L
+// and will get picked up below
+
+#endif // __GNUC__
+
+////////////////////////////////////////////////////////////////////////////////
+// Visual C++
+#ifdef _MSC_VER
+
+#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
+
+#if (_MSC_VER >= 1600)
+# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+#endif
+
+#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
+#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
+#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
+#endif
+
+#endif // _MSC_VER
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Use variadic macros if the compiler supports them
+#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
+ ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
+ ( defined __GNUC__ && __GNUC__ >= 3 ) || \
+ ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
+
+#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
+
+#endif
+
+// Use __COUNTER__ if the compiler supports it
+#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
+ ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
+ ( defined __clang__ && __clang_major__ >= 3 )
+
+#define CATCH_INTERNAL_CONFIG_COUNTER
+
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// C++ language feature support
+
+// catch all support for C++11
+#if defined(CATCH_CPP11_OR_GREATER)
+
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
+# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+# endif
+
+# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
+# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
+# endif
+
+# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+# endif
+
+# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
+# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
+# endif
+
+# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
+# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
+# endif
+
+# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
+# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
+# endif
+
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
+# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
+# endif
+
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
+# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
+# endif
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
+# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+# endif
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
+# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
+# endif
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
+# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
+# endif
+
+#endif // __cplusplus >= 201103L
+
+// Now set the actual defines based on the above + anything the user has configured
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_NULLPTR
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_NOEXCEPT
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_GENERATED_METHODS
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_IS_ENUM
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_TUPLE
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
+# define CATCH_CONFIG_VARIADIC_MACROS
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_LONG_LONG
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_OVERRIDE
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_UNIQUE_PTR
+#endif
+// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
+// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
+// This does not affect compilation
+#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
+# define CATCH_CONFIG_COUNTER
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_SHUFFLE
+#endif
+# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_TYPE_TRAITS
+# endif
+#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
+# define CATCH_CONFIG_WINDOWS_SEH
+#endif
+// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
+#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
+# define CATCH_CONFIG_POSIX_SIGNALS
+#endif
+
+#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
+# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
+# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
+#endif
+
+// noexcept support:
+#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
+# define CATCH_NOEXCEPT noexcept
+# define CATCH_NOEXCEPT_IS(x) noexcept(x)
+#else
+# define CATCH_NOEXCEPT throw()
+# define CATCH_NOEXCEPT_IS(x)
+#endif
+
+// nullptr support
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+# define CATCH_NULL nullptr
+#else
+# define CATCH_NULL NULL
+#endif
+
+// override support
+#ifdef CATCH_CONFIG_CPP11_OVERRIDE
+# define CATCH_OVERRIDE override
+#else
+# define CATCH_OVERRIDE
+#endif
+
+// unique_ptr support
+#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
+# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
+#else
+# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
+#endif
+
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
+#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
+#ifdef CATCH_CONFIG_COUNTER
+# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
+#else
+# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
+#endif
+
+#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
+#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
+
+#include <sstream>
+#include <algorithm>
+
+namespace Catch {
+
+ struct IConfig;
+
+ struct CaseSensitive { enum Choice {
+ Yes,
+ No
+ }; };
+
+ class NonCopyable {
+#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ NonCopyable( NonCopyable const& ) = delete;
+ NonCopyable( NonCopyable && ) = delete;
+ NonCopyable& operator = ( NonCopyable const& ) = delete;
+ NonCopyable& operator = ( NonCopyable && ) = delete;
+#else
+ NonCopyable( NonCopyable const& info );
+ NonCopyable& operator = ( NonCopyable const& );
+#endif
+
+ protected:
+ NonCopyable() {}
+ virtual ~NonCopyable();
+ };
+
+ class SafeBool {
+ public:
+ typedef void (SafeBool::*type)() const;
+
+ static type makeSafe( bool value ) {
+ return value ? &SafeBool::trueValue : 0;
+ }
+ private:
+ void trueValue() const {}
+ };
+
+ template<typename ContainerT>
+ inline void deleteAll( ContainerT& container ) {
+ typename ContainerT::const_iterator it = container.begin();
+ typename ContainerT::const_iterator itEnd = container.end();
+ for(; it != itEnd; ++it )
+ delete *it;
+ }
+ template<typename AssociativeContainerT>
+ inline void deleteAllValues( AssociativeContainerT& container ) {
+ typename AssociativeContainerT::const_iterator it = container.begin();
+ typename AssociativeContainerT::const_iterator itEnd = container.end();
+ for(; it != itEnd; ++it )
+ delete it->second;
+ }
+
+ bool startsWith( std::string const& s, std::string const& prefix );
+ bool startsWith( std::string const& s, char prefix );
+ bool endsWith( std::string const& s, std::string const& suffix );
+ bool endsWith( std::string const& s, char suffix );
+ bool contains( std::string const& s, std::string const& infix );
+ void toLowerInPlace( std::string& s );
+ std::string toLower( std::string const& s );
+ std::string trim( std::string const& str );
+ bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
+
+ struct pluralise {
+ pluralise( std::size_t count, std::string const& label );
+
+ friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
+
+ std::size_t m_count;
+ std::string m_label;
+ };
+
+ struct SourceLineInfo {
+
+ SourceLineInfo();
+ SourceLineInfo( char const* _file, std::size_t _line );
+# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ SourceLineInfo(SourceLineInfo const& other) = default;
+ SourceLineInfo( SourceLineInfo && ) = default;
+ SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
+ SourceLineInfo& operator = ( SourceLineInfo && ) = default;
+# endif
+ bool empty() const;
+ bool operator == ( SourceLineInfo const& other ) const;
+ bool operator < ( SourceLineInfo const& other ) const;
+
+ char const* file;
+ std::size_t line;
+ };
+
+ std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
+
+ // This is just here to avoid compiler warnings with macro constants and boolean literals
+ inline bool isTrue( bool value ){ return value; }
+ inline bool alwaysTrue() { return true; }
+ inline bool alwaysFalse() { return false; }
+
+ void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
+
+ void seedRng( IConfig const& config );
+ unsigned int rngSeed();
+
+ // Use this in variadic streaming macros to allow
+ // >> +StreamEndStop
+ // as well as
+ // >> stuff +StreamEndStop
+ struct StreamEndStop {
+ std::string operator+() {
+ return std::string();
+ }
+ };
+ template<typename T>
+ T const& operator + ( T const& value, StreamEndStop ) {
+ return value;
+ }
+}
+
+#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
+#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
+
+namespace Catch {
+
+ class NotImplementedException : public std::exception
+ {
+ public:
+ NotImplementedException( SourceLineInfo const& lineInfo );
+ NotImplementedException( NotImplementedException const& ) {}
+
+ virtual ~NotImplementedException() CATCH_NOEXCEPT {}
+
+ virtual const char* what() const CATCH_NOEXCEPT;
+
+ private:
+ std::string m_what;
+ SourceLineInfo m_lineInfo;
+ };
+
+} // end namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
+
+// #included from: internal/catch_context.h
+#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
+
+// #included from: catch_interfaces_generators.h
+#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+ struct IGeneratorInfo {
+ virtual ~IGeneratorInfo();
+ virtual bool moveNext() = 0;
+ virtual std::size_t getCurrentIndex() const = 0;
+ };
+
+ struct IGeneratorsForTest {
+ virtual ~IGeneratorsForTest();
+
+ virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
+ virtual bool moveNext() = 0;
+ };
+
+ IGeneratorsForTest* createGeneratorsForTest();
+
+} // end namespace Catch
+
+// #included from: catch_ptr.hpp
+#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+ // An intrusive reference counting smart pointer.
+ // T must implement addRef() and release() methods
+ // typically implementing the IShared interface
+ template<typename T>
+ class Ptr {
+ public:
+ Ptr() : m_p( CATCH_NULL ){}
+ Ptr( T* p ) : m_p( p ){
+ if( m_p )
+ m_p->addRef();
+ }
+ Ptr( Ptr const& other ) : m_p( other.m_p ){
+ if( m_p )
+ m_p->addRef();
+ }
+ ~Ptr(){
+ if( m_p )
+ m_p->release();
+ }
+ void reset() {
+ if( m_p )
+ m_p->release();
+ m_p = CATCH_NULL;
+ }
+ Ptr& operator = ( T* p ){
+ Ptr temp( p );
+ swap( temp );
+ return *this;
+ }
+ Ptr& operator = ( Ptr const& other ){
+ Ptr temp( other );
+ swap( temp );
+ return *this;
+ }
+ void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
+ T* get() const{ return m_p; }
+ T& operator*() const { return *m_p; }
+ T* operator->() const { return m_p; }
+ bool operator !() const { return m_p == CATCH_NULL; }
+ operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
+
+ private:
+ T* m_p;
+ };
+
+ struct IShared : NonCopyable {
+ virtual ~IShared();
+ virtual void addRef() const = 0;
+ virtual void release() const = 0;
+ };
+
+ template<typename T = IShared>
+ struct SharedImpl : T {
+
+ SharedImpl() : m_rc( 0 ){}
+
+ virtual void addRef() const {
+ ++m_rc;
+ }
+ virtual void release() const {
+ if( --m_rc == 0 )
+ delete this;
+ }
+
+ mutable unsigned int m_rc;
+ };
+
+} // end namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+namespace Catch {
+
+ class TestCase;
+ class Stream;
+ struct IResultCapture;
+ struct IRunner;
+ struct IGeneratorsForTest;
+ struct IConfig;
+
+ struct IContext
+ {
+ virtual ~IContext();
+
+ virtual IResultCapture* getResultCapture() = 0;
+ virtual IRunner* getRunner() = 0;
+ virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
+ virtual bool advanceGeneratorsForCurrentTest() = 0;
+ virtual Ptr<IConfig const> getConfig() const = 0;
+ };
+
+ struct IMutableContext : IContext
+ {
+ virtual ~IMutableContext();
+ virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
+ virtual void setRunner( IRunner* runner ) = 0;
+ virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
+ };
+
+ IContext& getCurrentContext();
+ IMutableContext& getCurrentMutableContext();
+ void cleanUpContext();
+ Stream createStream( std::string const& streamName );
+
+}
+
+// #included from: internal/catch_test_registry.hpp
+#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
+
+// #included from: catch_interfaces_testcase.h
+#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
+
+#include <vector>
+
+namespace Catch {
+
+ class TestSpec;
+
+ struct ITestCase : IShared {
+ virtual void invoke () const = 0;
+ protected:
+ virtual ~ITestCase();
+ };
+
+ class TestCase;
+ struct IConfig;
+
+ struct ITestCaseRegistry {
+ virtual ~ITestCaseRegistry();
+ virtual std::vector<TestCase> const& getAllTests() const = 0;
+ virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
+ };
+
+ bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
+ std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
+ std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
+
+}
+
+namespace Catch {
+
+template<typename C>
+class MethodTestCase : public SharedImpl<ITestCase> {
+
+public:
+ MethodTestCase( void (C::*method)() ) : m_method( method ) {}
+
+ virtual void invoke() const {
+ C obj;
+ (obj.*m_method)();
+ }
+
+private:
+ virtual ~MethodTestCase() {}
+
+ void (C::*m_method)();
+};
+
+typedef void(*TestFunction)();
+
+struct NameAndDesc {
+ NameAndDesc( const char* _name = "", const char* _description= "" )
+ : name( _name ), description( _description )
+ {}
+
+ const char* name;
+ const char* description;
+};
+
+void registerTestCase
+ ( ITestCase* testCase,
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo );
+
+struct AutoReg {
+
+ AutoReg
+ ( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc );
+
+ template<typename C>
+ AutoReg
+ ( void (C::*method)(),
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo ) {
+
+ registerTestCase
+ ( new MethodTestCase<C>( method ),
+ className,
+ nameAndDesc,
+ lineInfo );
+ }
+
+ ~AutoReg();
+
+private:
+ AutoReg( AutoReg const& );
+ void operator= ( AutoReg const& );
+};
+
+void registerTestCaseFunction
+ ( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc );
+
+} // end namespace Catch
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
+ static void TestName(); \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
+ static void TestName()
+ #define INTERNAL_CATCH_TESTCASE( ... ) \
+ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
+ namespace{ \
+ struct TestName : ClassName{ \
+ void test(); \
+ }; \
+ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
+ } \
+ void TestName::test()
+ #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
+ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
+ Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
+
+#else
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
+ static void TestName(); \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
+ static void TestName()
+ #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
+ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
+ namespace{ \
+ struct TestCaseName : ClassName{ \
+ void test(); \
+ }; \
+ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
+ } \
+ void TestCaseName::test()
+ #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
+ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
+
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
+ Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
+#endif
+
+// #included from: internal/catch_capture.hpp
+#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
+
+// #included from: catch_result_builder.h
+#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
+
+// #included from: catch_result_type.h
+#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
+
+namespace Catch {
+
+ // ResultWas::OfType enum
+ struct ResultWas { enum OfType {
+ Unknown = -1,
+ Ok = 0,
+ Info = 1,
+ Warning = 2,
+
+ FailureBit = 0x10,
+
+ ExpressionFailed = FailureBit | 1,
+ ExplicitFailure = FailureBit | 2,
+
+ Exception = 0x100 | FailureBit,
+
+ ThrewException = Exception | 1,
+ DidntThrowException = Exception | 2,
+
+ FatalErrorCondition = 0x200 | FailureBit
+
+ }; };
+
+ inline bool isOk( ResultWas::OfType resultType ) {
+ return ( resultType & ResultWas::FailureBit ) == 0;
+ }
+ inline bool isJustInfo( int flags ) {
+ return flags == ResultWas::Info;
+ }
+
+ // ResultDisposition::Flags enum
+ struct ResultDisposition { enum Flags {
+ Normal = 0x01,
+
+ ContinueOnFailure = 0x02, // Failures fail test, but execution continues
+ FalseTest = 0x04, // Prefix expression with !
+ SuppressFail = 0x08 // Failures are reported but do not fail the test
+ }; };
+
+ inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
+ return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
+ }
+
+ inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
+ inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
+ inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
+
+} // end namespace Catch
+
+// #included from: catch_assertionresult.h
+#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+ struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
+
+ struct DecomposedExpression
+ {
+ virtual ~DecomposedExpression() {}
+ virtual bool isBinaryExpression() const {
+ return false;
+ }
+ virtual void reconstructExpression( std::string& dest ) const = 0;
+
+ // Only simple binary comparisons can be decomposed.
+ // If more complex check is required then wrap sub-expressions in parentheses.
+ template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
+ template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
+ template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
+ template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
+ template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
+ template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
+ template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
+
+ private:
+ DecomposedExpression& operator = (DecomposedExpression const&);
+ };
+
+ struct AssertionInfo
+ {
+ AssertionInfo() {}
+ AssertionInfo( std::string const& _macroName,
+ SourceLineInfo const& _lineInfo,
+ std::string const& _capturedExpression,
+ ResultDisposition::Flags _resultDisposition );
+
+ std::string macroName;
+ SourceLineInfo lineInfo;
+ std::string capturedExpression;
+ ResultDisposition::Flags resultDisposition;
+ };
+
+ struct AssertionResultData
+ {
+ AssertionResultData() : decomposedExpression( CATCH_NULL )
+ , resultType( ResultWas::Unknown )
+ , negated( false )
+ , parenthesized( false ) {}
+
+ void negate( bool parenthesize ) {
+ negated = !negated;
+ parenthesized = parenthesize;
+ if( resultType == ResultWas::Ok )
+ resultType = ResultWas::ExpressionFailed;
+ else if( resultType == ResultWas::ExpressionFailed )
+ resultType = ResultWas::Ok;
+ }
+
+ std::string const& reconstructExpression() const {
+ if( decomposedExpression != CATCH_NULL ) {
+ decomposedExpression->reconstructExpression( reconstructedExpression );
+ if( parenthesized ) {
+ reconstructedExpression.insert( 0, 1, '(' );
+ reconstructedExpression.append( 1, ')' );
+ }
+ if( negated ) {
+ reconstructedExpression.insert( 0, 1, '!' );
+ }
+ decomposedExpression = CATCH_NULL;
+ }
+ return reconstructedExpression;
+ }
+
+ mutable DecomposedExpression const* decomposedExpression;
+ mutable std::string reconstructedExpression;
+ std::string message;
+ ResultWas::OfType resultType;
+ bool negated;
+ bool parenthesized;
+ };
+
+ class AssertionResult {
+ public:
+ AssertionResult();
+ AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
+ ~AssertionResult();
+# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ AssertionResult( AssertionResult const& ) = default;
+ AssertionResult( AssertionResult && ) = default;
+ AssertionResult& operator = ( AssertionResult const& ) = default;
+ AssertionResult& operator = ( AssertionResult && ) = default;
+# endif
+
+ bool isOk() const;
+ bool succeeded() const;
+ ResultWas::OfType getResultType() const;
+ bool hasExpression() const;
+ bool hasMessage() const;
+ std::string getExpression() const;
+ std::string getExpressionInMacro() const;
+ bool hasExpandedExpression() const;
+ std::string getExpandedExpression() const;
+ std::string getMessage() const;
+ SourceLineInfo getSourceInfo() const;
+ std::string getTestMacroName() const;
+ void discardDecomposedExpression() const;
+ void expandDecomposedExpression() const;
+
+ protected:
+ AssertionInfo m_info;
+ AssertionResultData m_resultData;
+ };
+
+} // end namespace Catch
+
+// #included from: catch_matchers.hpp
+#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+ namespace Impl {
+
+ template<typename ArgT> struct MatchAllOf;
+ template<typename ArgT> struct MatchAnyOf;
+ template<typename ArgT> struct MatchNotOf;
+
+ class MatcherUntypedBase {
+ public:
+ std::string toString() const {
+ if( m_cachedToString.empty() )
+ m_cachedToString = describe();
+ return m_cachedToString;
+ }
+
+ protected:
+ virtual std::string describe() const = 0;
+ mutable std::string m_cachedToString;
+ private:
+ MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
+ };
+
+ template<typename ObjectT, typename ComparatorT = ObjectT>
+ struct MatcherBase : MatcherUntypedBase {
+
+ virtual bool match( ObjectT const& arg ) const = 0;
+
+ MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
+ MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
+ MatchNotOf<ComparatorT> operator ! () const;
+ };
+
+ template<typename ArgT>
+ struct MatchAllOf : MatcherBase<ArgT> {
+ virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+ for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+ if (!m_matchers[i]->match(arg))
+ return false;
+ }
+ return true;
+ }
+ virtual std::string describe() const CATCH_OVERRIDE {
+ std::string description;
+ description.reserve( 4 + m_matchers.size()*32 );
+ description += "( ";
+ for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+ if( i != 0 )
+ description += " and ";
+ description += m_matchers[i]->toString();
+ }
+ description += " )";
+ return description;
+ }
+
+ MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
+ m_matchers.push_back( &other );
+ return *this;
+ }
+
+ std::vector<MatcherBase<ArgT> const*> m_matchers;
+ };
+ template<typename ArgT>
+ struct MatchAnyOf : MatcherBase<ArgT> {
+
+ virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+ for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+ if (m_matchers[i]->match(arg))
+ return true;
+ }
+ return false;
+ }
+ virtual std::string describe() const CATCH_OVERRIDE {
+ std::string description;
+ description.reserve( 4 + m_matchers.size()*32 );
+ description += "( ";
+ for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+ if( i != 0 )
+ description += " or ";
+ description += m_matchers[i]->toString();
+ }
+ description += " )";
+ return description;
+ }
+
+ MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
+ m_matchers.push_back( &other );
+ return *this;
+ }
+
+ std::vector<MatcherBase<ArgT> const*> m_matchers;
+ };
+
+ template<typename ArgT>
+ struct MatchNotOf : MatcherBase<ArgT> {
+
+ MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
+
+ virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+ return !m_underlyingMatcher.match( arg );
+ }
+
+ virtual std::string describe() const CATCH_OVERRIDE {
+ return "not " + m_underlyingMatcher.toString();
+ }
+ MatcherBase<ArgT> const& m_underlyingMatcher;
+ };
+
+ template<typename ObjectT, typename ComparatorT>
+ MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
+ return MatchAllOf<ComparatorT>() && *this && other;
+ }
+ template<typename ObjectT, typename ComparatorT>
+ MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
+ return MatchAnyOf<ComparatorT>() || *this || other;
+ }
+ template<typename ObjectT, typename ComparatorT>
+ MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
+ return MatchNotOf<ComparatorT>( *this );
+ }
+
+ } // namespace Impl
+
+ // The following functions create the actual matcher objects.
+ // This allows the types to be inferred
+ // - deprecated: prefer ||, && and !
+ template<typename T>
+ inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
+ return Impl::MatchNotOf<T>( underlyingMatcher );
+ }
+ template<typename T>
+ inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
+ return Impl::MatchAllOf<T>() && m1 && m2;
+ }
+ template<typename T>
+ inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
+ return Impl::MatchAllOf<T>() && m1 && m2 && m3;
+ }
+ template<typename T>
+ inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
+ return Impl::MatchAnyOf<T>() || m1 || m2;
+ }
+ template<typename T>
+ inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
+ return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
+ }
+
+} // namespace Matchers
+
+using namespace Matchers;
+using Matchers::Impl::MatcherBase;
+
+} // namespace Catch
+
+namespace Catch {
+
+ struct TestFailureException{};
+
+ template<typename T> class ExpressionLhs;
+
+ struct CopyableStream {
+ CopyableStream() {}
+ CopyableStream( CopyableStream const& other ) {
+ oss << other.oss.str();
+ }
+ CopyableStream& operator=( CopyableStream const& other ) {
+ oss.str(std::string());
+ oss << other.oss.str();
+ return *this;
+ }
+ std::ostringstream oss;
+ };
+
+ class ResultBuilder : public DecomposedExpression {
+ public:
+ ResultBuilder( char const* macroName,
+ SourceLineInfo const& lineInfo,
+ char const* capturedExpression,
+ ResultDisposition::Flags resultDisposition,
+ char const* secondArg = "" );
+
+ template<typename T>
+ ExpressionLhs<T const&> operator <= ( T const& operand );
+ ExpressionLhs<bool> operator <= ( bool value );
+
+ template<typename T>
+ ResultBuilder& operator << ( T const& value ) {
+ m_stream.oss << value;
+ return *this;
+ }
+
+ ResultBuilder& setResultType( ResultWas::OfType result );
+ ResultBuilder& setResultType( bool result );
+
+ void endExpression( DecomposedExpression const& expr );
+
+ virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
+
+ AssertionResult build() const;
+ AssertionResult build( DecomposedExpression const& expr ) const;
+
+ void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
+ void captureResult( ResultWas::OfType resultType );
+ void captureExpression();
+ void captureExpectedException( std::string const& expectedMessage );
+ void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher );
+ void handleResult( AssertionResult const& result );
+ void react();
+ bool shouldDebugBreak() const;
+ bool allowThrows() const;
+
+ template<typename ArgT, typename MatcherT>
+ void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
+
+ private:
+ AssertionInfo m_assertionInfo;
+ AssertionResultData m_data;
+ CopyableStream m_stream;
+
+ bool m_shouldDebugBreak;
+ bool m_shouldThrow;
+ };
+
+} // namespace Catch
+
+// Include after due to circular dependency:
+// #included from: catch_expression_lhs.hpp
+#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
+
+// #included from: catch_evaluate.hpp
+#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
+#endif
+
+#include <cstddef>
+
+namespace Catch {
+namespace Internal {
+
+ enum Operator {
+ IsEqualTo,
+ IsNotEqualTo,
+ IsLessThan,
+ IsGreaterThan,
+ IsLessThanOrEqualTo,
+ IsGreaterThanOrEqualTo
+ };
+
+ template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
+ template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
+ template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
+ template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
+ template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
+ template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
+ template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
+
+ template<typename T>
+ inline T& opCast(T const& t) { return const_cast<T&>(t); }
+
+// nullptr_t support based on pull request #154 from Konstantin Baumann
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+ inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
+#endif // CATCH_CONFIG_CPP11_NULLPTR
+
+ // So the compare overloads can be operator agnostic we convey the operator as a template
+ // enum, which is used to specialise an Evaluator for doing the comparison.
+ template<typename T1, typename T2, Operator Op>
+ class Evaluator{};
+
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs) {
+ return bool( opCast( lhs ) == opCast( rhs ) );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsNotEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return bool( opCast( lhs ) != opCast( rhs ) );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsLessThan> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return bool( opCast( lhs ) < opCast( rhs ) );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsGreaterThan> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return bool( opCast( lhs ) > opCast( rhs ) );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return bool( opCast( lhs ) >= opCast( rhs ) );
+ }
+ };
+ template<typename T1, typename T2>
+ struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
+ static bool evaluate( T1 const& lhs, T2 const& rhs ) {
+ return bool( opCast( lhs ) <= opCast( rhs ) );
+ }
+ };
+
+ template<Operator Op, typename T1, typename T2>
+ bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+ }
+
+ // This level of indirection allows us to specialise for integer types
+ // to avoid signed/ unsigned warnings
+
+ // "base" overload
+ template<Operator Op, typename T1, typename T2>
+ bool compare( T1 const& lhs, T2 const& rhs ) {
+ return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
+ }
+
+ // unsigned X to int
+ template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
+ }
+
+ // unsigned X to long
+ template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+ template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
+ return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
+ }
+
+ // int to unsigned X
+ template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
+ }
+
+ // long to unsigned X
+ template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+
+ // pointer to long (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+
+ // pointer to int (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+ // long long to unsigned X
+ template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+
+ // unsigned long long to X
+ template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
+ return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
+ return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
+ return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
+ return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+ }
+
+ // pointer to long long (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+#endif // CATCH_CONFIG_CPP11_LONG_LONG
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+ // pointer to nullptr_t (when comparing against nullptr)
+ template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
+ }
+#endif // CATCH_CONFIG_CPP11_NULLPTR
+
+} // end of namespace Internal
+} // end of namespace Catch
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// #included from: catch_tostring.h
+#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
+
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <vector>
+#include <cstddef>
+
+#ifdef __OBJC__
+// #included from: catch_objc_arc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
+
+#import <Foundation/Foundation.h>
+
+#ifdef __has_feature
+#define CATCH_ARC_ENABLED __has_feature(objc_arc)
+#else
+#define CATCH_ARC_ENABLED 0
+#endif
+
+void arcSafeRelease( NSObject* obj );
+id performOptionalSelector( id obj, SEL sel );
+
+#if !CATCH_ARC_ENABLED
+inline void arcSafeRelease( NSObject* obj ) {
+ [obj release];
+}
+inline id performOptionalSelector( id obj, SEL sel ) {
+ if( [obj respondsToSelector: sel] )
+ return [obj performSelector: sel];
+ return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED
+#define CATCH_ARC_STRONG
+#else
+inline void arcSafeRelease( NSObject* ){}
+inline id performOptionalSelector( id obj, SEL sel ) {
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
+#endif
+ if( [obj respondsToSelector: sel] )
+ return [obj performSelector: sel];
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ return nil;
+}
+#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
+#define CATCH_ARC_STRONG __strong
+#endif
+
+#endif
+
+#ifdef CATCH_CONFIG_CPP11_TUPLE
+#include <tuple>
+#endif
+
+#ifdef CATCH_CONFIG_CPP11_IS_ENUM
+#include <type_traits>
+#endif
+
+namespace Catch {
+
+// Why we're here.
+template<typename T>
+std::string toString( T const& value );
+
+// Built in overloads
+
+std::string toString( std::string const& value );
+std::string toString( std::wstring const& value );
+std::string toString( const char* const value );
+std::string toString( char* const value );
+std::string toString( const wchar_t* const value );
+std::string toString( wchar_t* const value );
+std::string toString( int value );
+std::string toString( unsigned long value );
+std::string toString( unsigned int value );
+std::string toString( const double value );
+std::string toString( const float value );
+std::string toString( bool value );
+std::string toString( char value );
+std::string toString( signed char value );
+std::string toString( unsigned char value );
+
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+std::string toString( long long value );
+std::string toString( unsigned long long value );
+#endif
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+std::string toString( std::nullptr_t );
+#endif
+
+#ifdef __OBJC__
+ std::string toString( NSString const * const& nsstring );
+ std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
+ std::string toString( NSObject* const& nsObject );
+#endif
+
+namespace Detail {
+
+ extern const std::string unprintableString;
+
+ struct BorgType {
+ template<typename T> BorgType( T const& );
+ };
+
+ struct TrueType { char sizer[1]; };
+ struct FalseType { char sizer[2]; };
+
+ TrueType& testStreamable( std::ostream& );
+ FalseType testStreamable( FalseType );
+
+ FalseType operator<<( std::ostream const&, BorgType const& );
+
+ template<typename T>
+ struct IsStreamInsertable {
+ static std::ostream &s;
+ static T const&t;
+ enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
+ };
+
+#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
+ template<typename T,
+ bool IsEnum = std::is_enum<T>::value
+ >
+ struct EnumStringMaker
+ {
+ static std::string convert( T const& ) { return unprintableString; }
+ };
+
+ template<typename T>
+ struct EnumStringMaker<T,true>
+ {
+ static std::string convert( T const& v )
+ {
+ return ::Catch::toString(
+ static_cast<typename std::underlying_type<T>::type>(v)
+ );
+ }
+ };
+#endif
+ template<bool C>
+ struct StringMakerBase {
+#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
+ template<typename T>
+ static std::string convert( T const& v )
+ {
+ return EnumStringMaker<T>::convert( v );
+ }
+#else
+ template<typename T>
+ static std::string convert( T const& ) { return unprintableString; }
+#endif
+ };
+
+ template<>
+ struct StringMakerBase<true> {
+ template<typename T>
+ static std::string convert( T const& _value ) {
+ std::ostringstream oss;
+ oss << _value;
+ return oss.str();
+ }
+ };
+
+ std::string rawMemoryToString( const void *object, std::size_t size );
+
+ template<typename T>
+ inline std::string rawMemoryToString( const T& object ) {
+ return rawMemoryToString( &object, sizeof(object) );
+ }
+
+} // end namespace Detail
+
+template<typename T>
+struct StringMaker :
+ Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
+
+template<typename T>
+struct StringMaker<T*> {
+ template<typename U>
+ static std::string convert( U* p ) {
+ if( !p )
+ return "NULL";
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+template<typename R, typename C>
+struct StringMaker<R C::*> {
+ static std::string convert( R C::* p ) {
+ if( !p )
+ return "NULL";
+ else
+ return Detail::rawMemoryToString( p );
+ }
+};
+
+namespace Detail {
+ template<typename InputIterator>
+ std::string rangeToString( InputIterator first, InputIterator last );
+}
+
+//template<typename T, typename Allocator>
+//struct StringMaker<std::vector<T, Allocator> > {
+// static std::string convert( std::vector<T,Allocator> const& v ) {
+// return Detail::rangeToString( v.begin(), v.end() );
+// }
+//};
+
+template<typename T, typename Allocator>
+std::string toString( std::vector<T,Allocator> const& v ) {
+ return Detail::rangeToString( v.begin(), v.end() );
+}
+
+#ifdef CATCH_CONFIG_CPP11_TUPLE
+
+// toString for tuples
+namespace TupleDetail {
+ template<
+ typename Tuple,
+ std::size_t N = 0,
+ bool = (N < std::tuple_size<Tuple>::value)
+ >
+ struct ElementPrinter {
+ static void print( const Tuple& tuple, std::ostream& os )
+ {
+ os << ( N ? ", " : " " )
+ << Catch::toString(std::get<N>(tuple));
+ ElementPrinter<Tuple,N+1>::print(tuple,os);
+ }
+ };
+
+ template<
+ typename Tuple,
+ std::size_t N
+ >
+ struct ElementPrinter<Tuple,N,false> {
+ static void print( const Tuple&, std::ostream& ) {}
+ };
+
+}
+
+template<typename ...Types>
+struct StringMaker<std::tuple<Types...>> {
+
+ static std::string convert( const std::tuple<Types...>& tuple )
+ {
+ std::ostringstream os;
+ os << '{';
+ TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
+ os << " }";
+ return os.str();
+ }
+};
+#endif // CATCH_CONFIG_CPP11_TUPLE
+
+namespace Detail {
+ template<typename T>
+ std::string makeString( T const& value ) {
+ return StringMaker<T>::convert( value );
+ }
+} // end namespace Detail
+
+/// \brief converts any type to a string
+///
+/// The default template forwards on to ostringstream - except when an
+/// ostringstream overload does not exist - in which case it attempts to detect
+/// that and writes {?}.
+/// Overload (not specialise) this template for custom typs that you don't want
+/// to provide an ostream overload for.
+template<typename T>
+std::string toString( T const& value ) {
+ return StringMaker<T>::convert( value );
+}
+
+ namespace Detail {
+ template<typename InputIterator>
+ std::string rangeToString( InputIterator first, InputIterator last ) {
+ std::ostringstream oss;
+ oss << "{ ";
+ if( first != last ) {
+ oss << Catch::toString( *first );
+ for( ++first ; first != last ; ++first )
+ oss << ", " << Catch::toString( *first );
+ }
+ oss << " }";
+ return oss.str();
+ }
+}
+
+} // end namespace Catch
+
+namespace Catch {
+
+template<typename LhsT, Internal::Operator Op, typename RhsT>
+class BinaryExpression;
+
+template<typename ArgT, typename MatcherT>
+class MatchExpression;
+
+// Wraps the LHS of an expression and overloads comparison operators
+// for also capturing those and RHS (if any)
+template<typename T>
+class ExpressionLhs : public DecomposedExpression {
+public:
+ ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
+
+ ExpressionLhs& operator = ( const ExpressionLhs& );
+
+ template<typename RhsT>
+ BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
+ operator == ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
+ operator != ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsNotEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ BinaryExpression<T, Internal::IsLessThan, RhsT const&>
+ operator < ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsLessThan>( rhs );
+ }
+
+ template<typename RhsT>
+ BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
+ operator > ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsGreaterThan>( rhs );
+ }
+
+ template<typename RhsT>
+ BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
+ operator <= ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
+ }
+
+ template<typename RhsT>
+ BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
+ operator >= ( RhsT const& rhs ) {
+ return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
+ }
+
+ BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
+ return captureExpression<Internal::IsEqualTo>( rhs );
+ }
+
+ BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
+ return captureExpression<Internal::IsNotEqualTo>( rhs );
+ }
+
+ void endExpression() {
+ m_truthy = m_lhs ? true : false;
+ m_rb
+ .setResultType( m_truthy )
+ .endExpression( *this );
+ }
+
+ virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+ dest = Catch::toString( m_truthy );
+ }
+
+private:
+ template<Internal::Operator Op, typename RhsT>
+ BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
+ return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
+ }
+
+ template<Internal::Operator Op>
+ BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
+ return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
+ }
+
+private:
+ ResultBuilder& m_rb;
+ T m_lhs;
+ bool m_truthy;
+};
+
+template<typename LhsT, Internal::Operator Op, typename RhsT>
+class BinaryExpression : public DecomposedExpression {
+public:
+ BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
+ : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
+
+ BinaryExpression& operator = ( BinaryExpression& );
+
+ void endExpression() const {
+ m_rb
+ .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
+ .endExpression( *this );
+ }
+
+ virtual bool isBinaryExpression() const CATCH_OVERRIDE {
+ return true;
+ }
+
+ virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+ std::string lhs = Catch::toString( m_lhs );
+ std::string rhs = Catch::toString( m_rhs );
+ char delim = lhs.size() + rhs.size() < 40 &&
+ lhs.find('\n') == std::string::npos &&
+ rhs.find('\n') == std::string::npos ? ' ' : '\n';
+ dest.reserve( 7 + lhs.size() + rhs.size() );
+ // 2 for spaces around operator
+ // 2 for operator
+ // 2 for parentheses (conditionally added later)
+ // 1 for negation (conditionally added later)
+ dest = lhs;
+ dest += delim;
+ dest += Internal::OperatorTraits<Op>::getName();
+ dest += delim;
+ dest += rhs;
+ }
+
+private:
+ ResultBuilder& m_rb;
+ LhsT m_lhs;
+ RhsT m_rhs;
+};
+
+template<typename ArgT, typename MatcherT>
+class MatchExpression : public DecomposedExpression {
+public:
+ MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
+ : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
+
+ virtual bool isBinaryExpression() const CATCH_OVERRIDE {
+ return true;
+ }
+
+ virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+ std::string matcherAsString = m_matcher.toString();
+ dest = Catch::toString( m_arg );
+ dest += ' ';
+ if( matcherAsString == Detail::unprintableString )
+ dest += m_matcherString;
+ else
+ dest += matcherAsString;
+ }
+
+private:
+ ArgT m_arg;
+ MatcherT m_matcher;
+ char const* m_matcherString;
+};
+
+} // end namespace Catch
+
+
+namespace Catch {
+
+ template<typename T>
+ inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
+ return ExpressionLhs<T const&>( *this, operand );
+ }
+
+ inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
+ return ExpressionLhs<bool>( *this, value );
+ }
+
+ template<typename ArgT, typename MatcherT>
+ inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
+ char const* matcherString ) {
+ MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
+ setResultType( matcher.match( arg ) );
+ endExpression( expr );
+ }
+
+} // namespace Catch
+
+// #included from: catch_message.h
+#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+ struct MessageInfo {
+ MessageInfo( std::string const& _macroName,
+ SourceLineInfo const& _lineInfo,
+ ResultWas::OfType _type );
+
+ std::string macroName;
+ SourceLineInfo lineInfo;
+ ResultWas::OfType type;
+ std::string message;
+ unsigned int sequence;
+
+ bool operator == ( MessageInfo const& other ) const {
+ return sequence == other.sequence;
+ }
+ bool operator < ( MessageInfo const& other ) const {
+ return sequence < other.sequence;
+ }
+ private:
+ static unsigned int globalCount;
+ };
+
+ struct MessageBuilder {
+ MessageBuilder( std::string const& macroName,
+ SourceLineInfo const& lineInfo,
+ ResultWas::OfType type )
+ : m_info( macroName, lineInfo, type )
+ {}
+
+ template<typename T>
+ MessageBuilder& operator << ( T const& value ) {
+ m_stream << value;
+ return *this;
+ }
+
+ MessageInfo m_info;
+ std::ostringstream m_stream;
+ };
+
+ class ScopedMessage {
+ public:
+ ScopedMessage( MessageBuilder const& builder );
+ ScopedMessage( ScopedMessage const& other );
+ ~ScopedMessage();
+
+ MessageInfo m_info;
+ };
+
+} // end namespace Catch
+
+// #included from: catch_interfaces_capture.h
+#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+ class TestCase;
+ class AssertionResult;
+ struct AssertionInfo;
+ struct SectionInfo;
+ struct SectionEndInfo;
+ struct MessageInfo;
+ class ScopedMessageBuilder;
+ struct Counts;
+
+ struct IResultCapture {
+
+ virtual ~IResultCapture();
+
+ virtual void assertionEnded( AssertionResult const& result ) = 0;
+ virtual bool sectionStarted( SectionInfo const& sectionInfo,
+ Counts& assertions ) = 0;
+ virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
+ virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
+ virtual void pushScopedMessage( MessageInfo const& message ) = 0;
+ virtual void popScopedMessage( MessageInfo const& message ) = 0;
+
+ virtual std::string getCurrentTestName() const = 0;
+ virtual const AssertionResult* getLastResult() const = 0;
+
+ virtual void handleFatalErrorCondition( std::string const& message ) = 0;
+ };
+
+ IResultCapture& getResultCapture();
+}
+
+// #included from: catch_debugger.h
+#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
+
+// #included from: catch_platform.h
+#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
+
+#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
+# define CATCH_PLATFORM_MAC
+#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+# define CATCH_PLATFORM_IPHONE
+#elif defined(linux) || defined(__linux) || defined(__linux__)
+# define CATCH_PLATFORM_LINUX
+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
+# define CATCH_PLATFORM_WINDOWS
+# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
+# define CATCH_DEFINES_NOMINMAX
+# endif
+# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
+# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
+# endif
+#endif
+
+#include <string>
+
+namespace Catch{
+
+ bool isDebuggerActive();
+ void writeToDebugConsole( std::string const& text );
+}
+
+#ifdef CATCH_PLATFORM_MAC
+
+ // The following code snippet based on:
+ // http://cocoawithlove.com/2008/03/break-into-debugger.html
+ #if defined(__ppc64__) || defined(__ppc__)
+ #define CATCH_TRAP() \
+ __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
+ : : : "memory","r0","r3","r4" )
+ #else
+ #define CATCH_TRAP() __asm__("int $3\n" : : )
+ #endif
+
+#elif defined(CATCH_PLATFORM_LINUX)
+ // If we can use inline assembler, do it because this allows us to break
+ // directly at the location of the failing check instead of breaking inside
+ // raise() called from it, i.e. one stack frame below.
+ #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
+ #define CATCH_TRAP() asm volatile ("int $3")
+ #else // Fall back to the generic way.
+ #include <signal.h>
+
+ #define CATCH_TRAP() raise(SIGTRAP)
+ #endif
+#elif defined(_MSC_VER)
+ #define CATCH_TRAP() __debugbreak()
+#elif defined(__MINGW32__)
+ extern "C" __declspec(dllimport) void __stdcall DebugBreak();
+ #define CATCH_TRAP() DebugBreak()
+#endif
+
+#ifdef CATCH_TRAP
+ #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
+#else
+ #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
+#endif
+
+// #included from: catch_interfaces_runner.h
+#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
+
+namespace Catch {
+ class TestCase;
+
+ struct IRunner {
+ virtual ~IRunner();
+ virtual bool aborting() const = 0;
+ };
+}
+
+// #included from: catch_type_traits.hpp
+#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
+
+#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
+#include <type_traits>
+#endif
+
+namespace Catch {
+
+#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
+
+ template <typename T>
+ using add_lvalue_reference = std::add_lvalue_reference<T>;
+
+ template <typename T>
+ using add_const = std::add_const<T>;
+
+#else
+
+ template <typename T>
+ struct add_const {
+ typedef const T type;
+ };
+
+ template <typename T>
+ struct add_lvalue_reference {
+ typedef T& type;
+ };
+ template <typename T>
+ struct add_lvalue_reference<T&> {
+ typedef T& type;
+ };
+ // No && overload, because that is C++11, in which case we have
+ // proper type_traits implementation from the standard library
+
+#endif
+
+}
+
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+///////////////////////////////////////////////////////////////////////////////
+// We can speedup compilation significantly by breaking into debugger lower in
+// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
+// macro in each assertion
+#define INTERNAL_CATCH_REACT( resultBuilder ) \
+ resultBuilder.react();
+#else
+///////////////////////////////////////////////////////////////////////////////
+// In the event of a failure works out if the debugger needs to be invoked
+// and/or an exception thrown and takes appropriate action.
+// This needs to be done as a macro so the debugger will stop in the user
+// source code rather than in Catch library code
+#define INTERNAL_CATCH_REACT( resultBuilder ) \
+ if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
+ resultBuilder.react();
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
+ do { \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+ try { \
+ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+ ( __catchResult <= expr ).endExpression(); \
+ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+ } \
+ catch( ... ) { \
+ __catchResult.useActiveException( resultDisposition ); \
+ } \
+ INTERNAL_CATCH_REACT( __catchResult ) \
+ } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
+ // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
+ INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
+ if( Catch::getResultCapture().getLastResult()->succeeded() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
+ INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
+ if( !Catch::getResultCapture().getLastResult()->succeeded() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
+ do { \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+ try { \
+ static_cast<void>(expr); \
+ __catchResult.captureResult( Catch::ResultWas::Ok ); \
+ } \
+ catch( ... ) { \
+ __catchResult.useActiveException( resultDisposition ); \
+ } \
+ INTERNAL_CATCH_REACT( __catchResult ) \
+ } while( Catch::alwaysFalse() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
+ do { \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
+ if( __catchResult.allowThrows() ) \
+ try { \
+ static_cast<void>(expr); \
+ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
+ } \
+ catch( ... ) { \
+ __catchResult.captureExpectedException( matcher ); \
+ } \
+ else \
+ __catchResult.captureResult( Catch::ResultWas::Ok ); \
+ INTERNAL_CATCH_REACT( __catchResult ) \
+ } while( Catch::alwaysFalse() )
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
+ do { \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
+ if( __catchResult.allowThrows() ) \
+ try { \
+ static_cast<void>(expr); \
+ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
+ } \
+ catch( Catch::add_const<Catch::add_lvalue_reference<exceptionType>::type>::type ) { \
+ __catchResult.captureResult( Catch::ResultWas::Ok ); \
+ } \
+ catch( ... ) { \
+ __catchResult.useActiveException( resultDisposition ); \
+ } \
+ else \
+ __catchResult.captureResult( Catch::ResultWas::Ok ); \
+ INTERNAL_CATCH_REACT( __catchResult ) \
+ } while( Catch::alwaysFalse() )
+
+///////////////////////////////////////////////////////////////////////////////
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+ #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
+ do { \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+ __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
+ __catchResult.captureResult( messageType ); \
+ INTERNAL_CATCH_REACT( __catchResult ) \
+ } while( Catch::alwaysFalse() )
+#else
+ #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
+ do { \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
+ __catchResult << log + ::Catch::StreamEndStop(); \
+ __catchResult.captureResult( messageType ); \
+ INTERNAL_CATCH_REACT( __catchResult ) \
+ } while( Catch::alwaysFalse() )
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_INFO( log, macroName ) \
+ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
+ do { \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
+ try { \
+ __catchResult.captureMatch( arg, matcher, #matcher ); \
+ } catch( ... ) { \
+ __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
+ } \
+ INTERNAL_CATCH_REACT( __catchResult ) \
+ } while( Catch::alwaysFalse() )
+
+// #included from: internal/catch_section.h
+#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
+
+// #included from: catch_section_info.h
+#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
+
+// #included from: catch_totals.hpp
+#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
+
+#include <cstddef>
+
+namespace Catch {
+
+ struct Counts {
+ Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
+
+ Counts operator - ( Counts const& other ) const {
+ Counts diff;
+ diff.passed = passed - other.passed;
+ diff.failed = failed - other.failed;
+ diff.failedButOk = failedButOk - other.failedButOk;
+ return diff;
+ }
+ Counts& operator += ( Counts const& other ) {
+ passed += other.passed;
+ failed += other.failed;
+ failedButOk += other.failedButOk;
+ return *this;
+ }
+
+ std::size_t total() const {
+ return passed + failed + failedButOk;
+ }
+ bool allPassed() const {
+ return failed == 0 && failedButOk == 0;
+ }
+ bool allOk() const {
+ return failed == 0;
+ }
+
+ std::size_t passed;
+ std::size_t failed;
+ std::size_t failedButOk;
+ };
+
+ struct Totals {
+
+ Totals operator - ( Totals const& other ) const {
+ Totals diff;
+ diff.assertions = assertions - other.assertions;
+ diff.testCases = testCases - other.testCases;
+ return diff;
+ }
+
+ Totals delta( Totals const& prevTotals ) const {
+ Totals diff = *this - prevTotals;
+ if( diff.assertions.failed > 0 )
+ ++diff.testCases.failed;
+ else if( diff.assertions.failedButOk > 0 )
+ ++diff.testCases.failedButOk;
+ else
+ ++diff.testCases.passed;
+ return diff;
+ }
+
+ Totals& operator += ( Totals const& other ) {
+ assertions += other.assertions;
+ testCases += other.testCases;
+ return *this;
+ }
+
+ Counts assertions;
+ Counts testCases;
+ };
+}
+
+#include <string>
+
+namespace Catch {
+
+ struct SectionInfo {
+ SectionInfo
+ ( SourceLineInfo const& _lineInfo,
+ std::string const& _name,
+ std::string const& _description = std::string() );
+
+ std::string name;
+ std::string description;
+ SourceLineInfo lineInfo;
+ };
+
+ struct SectionEndInfo {
+ SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
+ : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
+ {}
+
+ SectionInfo sectionInfo;
+ Counts prevAssertions;
+ double durationInSeconds;
+ };
+
+} // end namespace Catch
+
+// #included from: catch_timer.h
+#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
+
+#ifdef CATCH_PLATFORM_WINDOWS
+typedef unsigned long long uint64_t;
+#else
+#include <stdint.h>
+#endif
+
+namespace Catch {
+
+ class Timer {
+ public:
+ Timer() : m_ticks( 0 ) {}
+ void start();
+ unsigned int getElapsedMicroseconds() const;
+ unsigned int getElapsedMilliseconds() const;
+ double getElapsedSeconds() const;
+
+ private:
+ uint64_t m_ticks;
+ };
+
+} // namespace Catch
+
+#include <string>
+
+namespace Catch {
+
+ class Section : NonCopyable {
+ public:
+ Section( SectionInfo const& info );
+ ~Section();
+
+ // This indicates whether the section should be executed or not
+ operator bool() const;
+
+ private:
+ SectionInfo m_info;
+
+ std::string m_name;
+ Counts m_assertions;
+ bool m_sectionIncluded;
+ Timer m_timer;
+ };
+
+} // end namespace Catch
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+ #define INTERNAL_CATCH_SECTION( ... ) \
+ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
+#else
+ #define INTERNAL_CATCH_SECTION( name, desc ) \
+ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
+#endif
+
+// #included from: internal/catch_generators.hpp
+#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
+
+#include <iterator>
+#include <vector>
+#include <string>
+#include <stdlib.h>
+
+namespace Catch {
+
+template<typename T>
+struct IGenerator {
+ virtual ~IGenerator() {}
+ virtual T getValue( std::size_t index ) const = 0;
+ virtual std::size_t size () const = 0;
+};
+
+template<typename T>
+class BetweenGenerator : public IGenerator<T> {
+public:
+ BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
+
+ virtual T getValue( std::size_t index ) const {
+ return m_from+static_cast<int>( index );
+ }
+
+ virtual std::size_t size() const {
+ return static_cast<std::size_t>( 1+m_to-m_from );
+ }
+
+private:
+
+ T m_from;
+ T m_to;
+};
+
+template<typename T>
+class ValuesGenerator : public IGenerator<T> {
+public:
+ ValuesGenerator(){}
+
+ void add( T value ) {
+ m_values.push_back( value );
+ }
+
+ virtual T getValue( std::size_t index ) const {
+ return m_values[index];
+ }
+
+ virtual std::size_t size() const {
+ return m_values.size();
+ }
+
+private:
+ std::vector<T> m_values;
+};
+
+template<typename T>
+class CompositeGenerator {
+public:
+ CompositeGenerator() : m_totalSize( 0 ) {}
+
+ // *** Move semantics, similar to auto_ptr ***
+ CompositeGenerator( CompositeGenerator& other )
+ : m_fileInfo( other.m_fileInfo ),
+ m_totalSize( 0 )
+ {
+ move( other );
+ }
+
+ CompositeGenerator& setFileInfo( const char* fileInfo ) {
+ m_fileInfo = fileInfo;
+ return *this;
+ }
+
+ ~CompositeGenerator() {
+ deleteAll( m_composed );
+ }
+
+ operator T () const {
+ size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
+
+ typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
+ typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
+ for( size_t index = 0; it != itEnd; ++it )
+ {
+ const IGenerator<T>* generator = *it;
+ if( overallIndex >= index && overallIndex < index + generator->size() )
+ {
+ return generator->getValue( overallIndex-index );
+ }
+ index += generator->size();
+ }
+ CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
+ return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
+ }
+
+ void add( const IGenerator<T>* generator ) {
+ m_totalSize += generator->size();
+ m_composed.push_back( generator );
+ }
+
+ CompositeGenerator& then( CompositeGenerator& other ) {
+ move( other );
+ return *this;
+ }
+
+ CompositeGenerator& then( T value ) {
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( value );
+ add( valuesGen );
+ return *this;
+ }
+
+private:
+
+ void move( CompositeGenerator& other ) {
+ std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
+ m_totalSize += other.m_totalSize;
+ other.m_composed.clear();
+ }
+
+ std::vector<const IGenerator<T>*> m_composed;
+ std::string m_fileInfo;
+ size_t m_totalSize;
+};
+
+namespace Generators
+{
+ template<typename T>
+ CompositeGenerator<T> between( T from, T to ) {
+ CompositeGenerator<T> generators;
+ generators.add( new BetweenGenerator<T>( from, to ) );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2 ) {
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2, T val3 ){
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ valuesGen->add( val3 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+ template<typename T>
+ CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
+ CompositeGenerator<T> generators;
+ ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
+ valuesGen->add( val1 );
+ valuesGen->add( val2 );
+ valuesGen->add( val3 );
+ valuesGen->add( val4 );
+ generators.add( valuesGen );
+ return generators;
+ }
+
+} // end namespace Generators
+
+using namespace Generators;
+
+} // end namespace Catch
+
+#define INTERNAL_CATCH_LINESTR2( line ) #line
+#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
+
+#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
+
+// #included from: internal/catch_interfaces_exception.h
+#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
+
+#include <string>
+#include <vector>
+
+// #included from: catch_interfaces_registry_hub.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+ class TestCase;
+ struct ITestCaseRegistry;
+ struct IExceptionTranslatorRegistry;
+ struct IExceptionTranslator;
+ struct IReporterRegistry;
+ struct IReporterFactory;
+
+ struct IRegistryHub {
+ virtual ~IRegistryHub();
+
+ virtual IReporterRegistry const& getReporterRegistry() const = 0;
+ virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
+ virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
+ };
+
+ struct IMutableRegistryHub {
+ virtual ~IMutableRegistryHub();
+ virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
+ virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
+ virtual void registerTest( TestCase const& testInfo ) = 0;
+ virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
+ };
+
+ IRegistryHub& getRegistryHub();
+ IMutableRegistryHub& getMutableRegistryHub();
+ void cleanUp();
+ std::string translateActiveException();
+
+}
+
+namespace Catch {
+
+ typedef std::string(*exceptionTranslateFunction)();
+
+ struct IExceptionTranslator;
+ typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
+
+ struct IExceptionTranslator {
+ virtual ~IExceptionTranslator();
+ virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
+ };
+
+ struct IExceptionTranslatorRegistry {
+ virtual ~IExceptionTranslatorRegistry();
+
+ virtual std::string translateActiveException() const = 0;
+ };
+
+ class ExceptionTranslatorRegistrar {
+ template<typename T>
+ class ExceptionTranslator : public IExceptionTranslator {
+ public:
+
+ ExceptionTranslator( std::string(*translateFunction)( T& ) )
+ : m_translateFunction( translateFunction )
+ {}
+
+ virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
+ try {
+ if( it == itEnd )
+ throw;
+ else
+ return (*it)->translate( it+1, itEnd );
+ }
+ catch( T& ex ) {
+ return m_translateFunction( ex );
+ }
+ }
+
+ protected:
+ std::string(*m_translateFunction)( T& );
+ };
+
+ public:
+ template<typename T>
+ ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
+ getMutableRegistryHub().registerTranslator
+ ( new ExceptionTranslator<T>( translateFunction ) );
+ }
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
+ static std::string translatorName( signature ); \
+ namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
+ static std::string translatorName( signature )
+
+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
+
+// #included from: internal/catch_approx.hpp
+#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
+
+#include <cmath>
+#include <limits>
+
+#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
+#include <type_traits>
+#endif
+
+namespace Catch {
+namespace Detail {
+
+ class Approx {
+ public:
+ explicit Approx ( double value )
+ : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
+ m_margin( 0.0 ),
+ m_scale( 1.0 ),
+ m_value( value )
+ {}
+
+ Approx( Approx const& other )
+ : m_epsilon( other.m_epsilon ),
+ m_margin( other.m_margin ),
+ m_scale( other.m_scale ),
+ m_value( other.m_value )
+ {}
+
+ static Approx custom() {
+ return Approx( 0 );
+ }
+
+ Approx operator()( double value ) {
+ Approx approx( value );
+ approx.epsilon( m_epsilon );
+ approx.margin( m_margin );
+ approx.scale( m_scale );
+ return approx;
+ }
+
+#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator == ( const T& lhs, Approx const& rhs ) {
+ // Thanks to Richard Harris for his help refining this formula
+ auto lhs_v = double(lhs);
+ bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value)));
+ if (relativeOK) {
+ return true;
+ }
+ return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator == ( Approx const& lhs, const T& rhs ) {
+ return operator==( rhs, lhs );
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator != ( T lhs, Approx const& rhs ) {
+ return !operator==( lhs, rhs );
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator != ( Approx const& lhs, T rhs ) {
+ return !operator==( rhs, lhs );
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator <= ( T lhs, Approx const& rhs )
+ {
+ return double(lhs) < rhs.m_value || lhs == rhs;
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator <= ( Approx const& lhs, T rhs )
+ {
+ return lhs.m_value < double(rhs) || lhs == rhs;
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator >= ( T lhs, Approx const& rhs )
+ {
+ return double(lhs) > rhs.m_value || lhs == rhs;
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator >= ( Approx const& lhs, T rhs )
+ {
+ return lhs.m_value > double(rhs) || lhs == rhs;
+ }
+#else
+ friend bool operator == ( double lhs, Approx const& rhs ) {
+ // Thanks to Richard Harris for his help refining this formula
+ bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
+ if (relativeOK) {
+ return true;
+ }
+ return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
+ }
+
+ friend bool operator == ( Approx const& lhs, double rhs ) {
+ return operator==( rhs, lhs );
+ }
+
+ friend bool operator != ( double lhs, Approx const& rhs ) {
+ return !operator==( lhs, rhs );
+ }
+
+ friend bool operator != ( Approx const& lhs, double rhs ) {
+ return !operator==( rhs, lhs );
+ }
+
+ friend bool operator <= ( double lhs, Approx const& rhs )
+ {
+ return lhs < rhs.m_value || lhs == rhs;
+ }
+
+ friend bool operator <= ( Approx const& lhs, double rhs )
+ {
+ return lhs.m_value < rhs || lhs == rhs;
+ }
+
+ friend bool operator >= ( double lhs, Approx const& rhs )
+ {
+ return lhs > rhs.m_value || lhs == rhs;
+ }
+
+ friend bool operator >= ( Approx const& lhs, double rhs )
+ {
+ return lhs.m_value > rhs || lhs == rhs;
+ }
+#endif
+
+ Approx& epsilon( double newEpsilon ) {
+ m_epsilon = newEpsilon;
+ return *this;
+ }
+
+ Approx& margin( double newMargin ) {
+ m_margin = newMargin;
+ return *this;
+ }
+
+ Approx& scale( double newScale ) {
+ m_scale = newScale;
+ return *this;
+ }
+
+ std::string toString() const {
+ std::ostringstream oss;
+ oss << "Approx( " << Catch::toString( m_value ) << " )";
+ return oss.str();
+ }
+
+ private:
+ double m_epsilon;
+ double m_margin;
+ double m_scale;
+ double m_value;
+ };
+}
+
+template<>
+inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
+ return value.toString();
+}
+
+} // end namespace Catch
+
+// #included from: internal/catch_matchers_string.h
+#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+
+ namespace StdString {
+
+ struct CasedString
+ {
+ CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
+ std::string adjustString( std::string const& str ) const;
+ std::string caseSensitivitySuffix() const;
+
+ CaseSensitive::Choice m_caseSensitivity;
+ std::string m_str;
+ };
+
+ struct StringMatcherBase : MatcherBase<std::string> {
+ StringMatcherBase( std::string operation, CasedString const& comparator );
+ virtual std::string describe() const CATCH_OVERRIDE;
+
+ CasedString m_comparator;
+ std::string m_operation;
+ };
+
+ struct EqualsMatcher : StringMatcherBase {
+ EqualsMatcher( CasedString const& comparator );
+ virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+ };
+ struct ContainsMatcher : StringMatcherBase {
+ ContainsMatcher( CasedString const& comparator );
+ virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+ };
+ struct StartsWithMatcher : StringMatcherBase {
+ StartsWithMatcher( CasedString const& comparator );
+ virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+ };
+ struct EndsWithMatcher : StringMatcherBase {
+ EndsWithMatcher( CasedString const& comparator );
+ virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+ };
+
+ } // namespace StdString
+
+ // The following functions create the actual matcher objects.
+ // This allows the types to be inferred
+
+ StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+ StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+ StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+ StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+
+} // namespace Matchers
+} // namespace Catch
+
+// #included from: internal/catch_matchers_vector.h
+#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+
+ namespace Vector {
+
+ template<typename T>
+ struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> {
+
+ ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
+
+ bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
+ return std::find(v.begin(), v.end(), m_comparator) != v.end();
+ }
+
+ virtual std::string describe() const CATCH_OVERRIDE {
+ return "Contains: " + Catch::toString( m_comparator );
+ }
+
+ T const& m_comparator;
+ };
+
+ template<typename T>
+ struct ContainsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
+
+ ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
+
+ bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
+ // !TBD: see note in EqualsMatcher
+ if (m_comparator.size() > v.size())
+ return false;
+ for (size_t i = 0; i < m_comparator.size(); ++i)
+ if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end())
+ return false;
+ return true;
+ }
+ virtual std::string describe() const CATCH_OVERRIDE {
+ return "Contains: " + Catch::toString( m_comparator );
+ }
+
+ std::vector<T> const& m_comparator;
+ };
+
+ template<typename T>
+ struct EqualsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
+
+ EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
+
+ bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
+ // !TBD: This currently works if all elements can be compared using !=
+ // - a more general approach would be via a compare template that defaults
+ // to using !=. but could be specialised for, e.g. std::vector<T> etc
+ // - then just call that directly
+ if (m_comparator.size() != v.size())
+ return false;
+ for (size_t i = 0; i < v.size(); ++i)
+ if (m_comparator[i] != v[i])
+ return false;
+ return true;
+ }
+ virtual std::string describe() const CATCH_OVERRIDE {
+ return "Equals: " + Catch::toString( m_comparator );
+ }
+ std::vector<T> const& m_comparator;
+ };
+
+ } // namespace Vector
+
+ // The following functions create the actual matcher objects.
+ // This allows the types to be inferred
+
+ template<typename T>
+ Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
+ return Vector::ContainsMatcher<T>( comparator );
+ }
+
+ template<typename T>
+ Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
+ return Vector::ContainsElementMatcher<T>( comparator );
+ }
+
+ template<typename T>
+ Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
+ return Vector::EqualsMatcher<T>( comparator );
+ }
+
+} // namespace Matchers
+} // namespace Catch
+
+// #included from: internal/catch_interfaces_tag_alias_registry.h
+#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
+
+// #included from: catch_tag_alias.h
+#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
+
+#include <string>
+
+namespace Catch {
+
+ struct TagAlias {
+ TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
+
+ std::string tag;
+ SourceLineInfo lineInfo;
+ };
+
+ struct RegistrarForTagAliases {
+ RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
+ };
+
+} // end namespace Catch
+
+#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
+// #included from: catch_option.hpp
+#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
+
+namespace Catch {
+
+ // An optional type
+ template<typename T>
+ class Option {
+ public:
+ Option() : nullableValue( CATCH_NULL ) {}
+ Option( T const& _value )
+ : nullableValue( new( storage ) T( _value ) )
+ {}
+ Option( Option const& _other )
+ : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
+ {}
+
+ ~Option() {
+ reset();
+ }
+
+ Option& operator= ( Option const& _other ) {
+ if( &_other != this ) {
+ reset();
+ if( _other )
+ nullableValue = new( storage ) T( *_other );
+ }
+ return *this;
+ }
+ Option& operator = ( T const& _value ) {
+ reset();
+ nullableValue = new( storage ) T( _value );
+ return *this;
+ }
+
+ void reset() {
+ if( nullableValue )
+ nullableValue->~T();
+ nullableValue = CATCH_NULL;
+ }
+
+ T& operator*() { return *nullableValue; }
+ T const& operator*() const { return *nullableValue; }
+ T* operator->() { return nullableValue; }
+ const T* operator->() const { return nullableValue; }
+
+ T valueOr( T const& defaultValue ) const {
+ return nullableValue ? *nullableValue : defaultValue;
+ }
+
+ bool some() const { return nullableValue != CATCH_NULL; }
+ bool none() const { return nullableValue == CATCH_NULL; }
+
+ bool operator !() const { return nullableValue == CATCH_NULL; }
+ operator SafeBool::type() const {
+ return SafeBool::makeSafe( some() );
+ }
+
+ private:
+ T* nullableValue;
+ char storage[sizeof(T)];
+ };
+
+} // end namespace Catch
+
+namespace Catch {
+
+ struct ITagAliasRegistry {
+ virtual ~ITagAliasRegistry();
+ virtual Option<TagAlias> find( std::string const& alias ) const = 0;
+ virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
+
+ static ITagAliasRegistry const& get();
+ };
+
+} // end namespace Catch
+
+// These files are included here so the single_include script doesn't put them
+// in the conditionally compiled sections
+// #included from: internal/catch_test_case_info.h
+#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
+
+#include <string>
+#include <set>
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+namespace Catch {
+
+ struct ITestCase;
+
+ struct TestCaseInfo {
+ enum SpecialProperties{
+ None = 0,
+ IsHidden = 1 << 1,
+ ShouldFail = 1 << 2,
+ MayFail = 1 << 3,
+ Throws = 1 << 4,
+ NonPortable = 1 << 5
+ };
+
+ TestCaseInfo( std::string const& _name,
+ std::string const& _className,
+ std::string const& _description,
+ std::set<std::string> const& _tags,
+ SourceLineInfo const& _lineInfo );
+
+ TestCaseInfo( TestCaseInfo const& other );
+
+ friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
+
+ bool isHidden() const;
+ bool throws() const;
+ bool okToFail() const;
+ bool expectedToFail() const;
+
+ std::string name;
+ std::string className;
+ std::string description;
+ std::set<std::string> tags;
+ std::set<std::string> lcaseTags;
+ std::string tagsAsString;
+ SourceLineInfo lineInfo;
+ SpecialProperties properties;
+ };
+
+ class TestCase : public TestCaseInfo {
+ public:
+
+ TestCase( ITestCase* testCase, TestCaseInfo const& info );
+ TestCase( TestCase const& other );
+
+ TestCase withName( std::string const& _newName ) const;
+
+ void invoke() const;
+
+ TestCaseInfo const& getTestCaseInfo() const;
+
+ void swap( TestCase& other );
+ bool operator == ( TestCase const& other ) const;
+ bool operator < ( TestCase const& other ) const;
+ TestCase& operator = ( TestCase const& other );
+
+ private:
+ Ptr<ITestCase> test;
+ };
+
+ TestCase makeTestCase( ITestCase* testCase,
+ std::string const& className,
+ std::string const& name,
+ std::string const& description,
+ SourceLineInfo const& lineInfo );
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+
+#ifdef __OBJC__
+// #included from: internal/catch_objc.hpp
+#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
+
+#import <objc/runtime.h>
+
+#include <string>
+
+// NB. Any general catch headers included here must be included
+// in catch.hpp first to make sure they are included by the single
+// header for non obj-usage
+
+///////////////////////////////////////////////////////////////////////////////
+// This protocol is really only here for (self) documenting purposes, since
+// all its methods are optional.
+@protocol OcFixture
+
+@optional
+
+-(void) setUp;
+-(void) tearDown;
+
+@end
+
+namespace Catch {
+
+ class OcMethod : public SharedImpl<ITestCase> {
+
+ public:
+ OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
+
+ virtual void invoke() const {
+ id obj = [[m_cls alloc] init];
+
+ performOptionalSelector( obj, @selector(setUp) );
+ performOptionalSelector( obj, m_sel );
+ performOptionalSelector( obj, @selector(tearDown) );
+
+ arcSafeRelease( obj );
+ }
+ private:
+ virtual ~OcMethod() {}
+
+ Class m_cls;
+ SEL m_sel;
+ };
+
+ namespace Detail{
+
+ inline std::string getAnnotation( Class cls,
+ std::string const& annotationName,
+ std::string const& testCaseName ) {
+ NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
+ SEL sel = NSSelectorFromString( selStr );
+ arcSafeRelease( selStr );
+ id value = performOptionalSelector( cls, sel );
+ if( value )
+ return [(NSString*)value UTF8String];
+ return "";
+ }
+ }
+
+ inline size_t registerTestMethods() {
+ size_t noTestMethods = 0;
+ int noClasses = objc_getClassList( CATCH_NULL, 0 );
+
+ Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
+ objc_getClassList( classes, noClasses );
+
+ for( int c = 0; c < noClasses; c++ ) {
+ Class cls = classes[c];
+ {
+ u_int count;
+ Method* methods = class_copyMethodList( cls, &count );
+ for( u_int m = 0; m < count ; m++ ) {
+ SEL selector = method_getName(methods[m]);
+ std::string methodName = sel_getName(selector);
+ if( startsWith( methodName, "Catch_TestCase_" ) ) {
+ std::string testCaseName = methodName.substr( 15 );
+ std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
+ std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
+ const char* className = class_getName( cls );
+
+ getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
+ noTestMethods++;
+ }
+ }
+ free(methods);
+ }
+ }
+ return noTestMethods;
+ }
+
+ namespace Matchers {
+ namespace Impl {
+ namespace NSStringMatchers {
+
+ template<typename MatcherT>
+ struct StringHolder : MatcherImpl<MatcherT, NSString*>{
+ StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
+ StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
+ StringHolder() {
+ arcSafeRelease( m_substr );
+ }
+
+ NSString* m_substr;
+ };
+
+ struct Equals : StringHolder<Equals> {
+ Equals( NSString* substr ) : StringHolder( substr ){}
+
+ virtual bool match( ExpressionType const& str ) const {
+ return (str != nil || m_substr == nil ) &&
+ [str isEqualToString:m_substr];
+ }
+
+ virtual std::string toString() const {
+ return "equals string: " + Catch::toString( m_substr );
+ }
+ };
+
+ struct Contains : StringHolder<Contains> {
+ Contains( NSString* substr ) : StringHolder( substr ){}
+
+ virtual bool match( ExpressionType const& str ) const {
+ return (str != nil || m_substr == nil ) &&
+ [str rangeOfString:m_substr].location != NSNotFound;
+ }
+
+ virtual std::string toString() const {
+ return "contains string: " + Catch::toString( m_substr );
+ }
+ };
+
+ struct StartsWith : StringHolder<StartsWith> {
+ StartsWith( NSString* substr ) : StringHolder( substr ){}
+
+ virtual bool match( ExpressionType const& str ) const {
+ return (str != nil || m_substr == nil ) &&
+ [str rangeOfString:m_substr].location == 0;
+ }
+
+ virtual std::string toString() const {
+ return "starts with: " + Catch::toString( m_substr );
+ }
+ };
+ struct EndsWith : StringHolder<EndsWith> {
+ EndsWith( NSString* substr ) : StringHolder( substr ){}
+
+ virtual bool match( ExpressionType const& str ) const {
+ return (str != nil || m_substr == nil ) &&
+ [str rangeOfString:m_substr].location == [str length] - [m_substr length];
+ }
+
+ virtual std::string toString() const {
+ return "ends with: " + Catch::toString( m_substr );
+ }
+ };
+
+ } // namespace NSStringMatchers
+ } // namespace Impl
+
+ inline Impl::NSStringMatchers::Equals
+ Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
+
+ inline Impl::NSStringMatchers::Contains
+ Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
+
+ inline Impl::NSStringMatchers::StartsWith
+ StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
+
+ inline Impl::NSStringMatchers::EndsWith
+ EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
+
+ } // namespace Matchers
+
+ using namespace Matchers;
+
+} // namespace Catch
+
+///////////////////////////////////////////////////////////////////////////////
+#define OC_TEST_CASE( name, desc )\
++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
+{\
+return @ name; \
+}\
++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
+{ \
+return @ desc; \
+} \
+-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
+
+#endif
+
+#ifdef CATCH_IMPL
+
+// !TBD: Move the leak detector code into a separate header
+#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
+#include <crtdbg.h>
+class LeakDetector {
+public:
+ LeakDetector() {
+ int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+ flag |= _CRTDBG_LEAK_CHECK_DF;
+ flag |= _CRTDBG_ALLOC_MEM_DF;
+ _CrtSetDbgFlag(flag);
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ // Change this to leaking allocation's number to break there
+ _CrtSetBreakAlloc(-1);
+ }
+};
+#else
+class LeakDetector {};
+#endif
+
+LeakDetector leakDetector;
+
+// #included from: internal/catch_impl.hpp
+#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
+
+// Collect all the implementation files together here
+// These are the equivalent of what would usually be cpp files
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#endif
+
+// #included from: ../catch_session.hpp
+#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
+
+// #included from: internal/catch_commandline.hpp
+#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
+
+// #included from: catch_config.hpp
+#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
+
+// #included from: catch_test_spec_parser.hpp
+#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+// #included from: catch_test_spec.hpp
+#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#endif
+
+// #included from: catch_wildcard_pattern.hpp
+#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
+
+#include <stdexcept>
+
+namespace Catch
+{
+ class WildcardPattern {
+ enum WildcardPosition {
+ NoWildcard = 0,
+ WildcardAtStart = 1,
+ WildcardAtEnd = 2,
+ WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
+ };
+
+ public:
+
+ WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
+ : m_caseSensitivity( caseSensitivity ),
+ m_wildcard( NoWildcard ),
+ m_pattern( adjustCase( pattern ) )
+ {
+ if( startsWith( m_pattern, '*' ) ) {
+ m_pattern = m_pattern.substr( 1 );
+ m_wildcard = WildcardAtStart;
+ }
+ if( endsWith( m_pattern, '*' ) ) {
+ m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
+ m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
+ }
+ }
+ virtual ~WildcardPattern();
+ virtual bool matches( std::string const& str ) const {
+ switch( m_wildcard ) {
+ case NoWildcard:
+ return m_pattern == adjustCase( str );
+ case WildcardAtStart:
+ return endsWith( adjustCase( str ), m_pattern );
+ case WildcardAtEnd:
+ return startsWith( adjustCase( str ), m_pattern );
+ case WildcardAtBothEnds:
+ return contains( adjustCase( str ), m_pattern );
+ }
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code"
+#endif
+ throw std::logic_error( "Unknown enum" );
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ }
+ private:
+ std::string adjustCase( std::string const& str ) const {
+ return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
+ }
+ CaseSensitive::Choice m_caseSensitivity;
+ WildcardPosition m_wildcard;
+ std::string m_pattern;
+ };
+}
+
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+ class TestSpec {
+ struct Pattern : SharedImpl<> {
+ virtual ~Pattern();
+ virtual bool matches( TestCaseInfo const& testCase ) const = 0;
+ };
+ class NamePattern : public Pattern {
+ public:
+ NamePattern( std::string const& name )
+ : m_wildcardPattern( toLower( name ), CaseSensitive::No )
+ {}
+ virtual ~NamePattern();
+ virtual bool matches( TestCaseInfo const& testCase ) const {
+ return m_wildcardPattern.matches( toLower( testCase.name ) );
+ }
+ private:
+ WildcardPattern m_wildcardPattern;
+ };
+
+ class TagPattern : public Pattern {
+ public:
+ TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
+ virtual ~TagPattern();
+ virtual bool matches( TestCaseInfo const& testCase ) const {
+ return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
+ }
+ private:
+ std::string m_tag;
+ };
+
+ class ExcludedPattern : public Pattern {
+ public:
+ ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
+ virtual ~ExcludedPattern();
+ virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
+ private:
+ Ptr<Pattern> m_underlyingPattern;
+ };
+
+ struct Filter {
+ std::vector<Ptr<Pattern> > m_patterns;
+
+ bool matches( TestCaseInfo const& testCase ) const {
+ // All patterns in a filter must match for the filter to be a match
+ for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
+ if( !(*it)->matches( testCase ) )
+ return false;
+ }
+ return true;
+ }
+ };
+
+ public:
+ bool hasFilters() const {
+ return !m_filters.empty();
+ }
+ bool matches( TestCaseInfo const& testCase ) const {
+ // A TestSpec matches if any filter matches
+ for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
+ if( it->matches( testCase ) )
+ return true;
+ return false;
+ }
+
+ private:
+ std::vector<Filter> m_filters;
+
+ friend class TestSpecParser;
+ };
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+namespace Catch {
+
+ class TestSpecParser {
+ enum Mode{ None, Name, QuotedName, Tag, EscapedName };
+ Mode m_mode;
+ bool m_exclusion;
+ std::size_t m_start, m_pos;
+ std::string m_arg;
+ std::vector<std::size_t> m_escapeChars;
+ TestSpec::Filter m_currentFilter;
+ TestSpec m_testSpec;
+ ITagAliasRegistry const* m_tagAliases;
+
+ public:
+ TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
+
+ TestSpecParser& parse( std::string const& arg ) {
+ m_mode = None;
+ m_exclusion = false;
+ m_start = std::string::npos;
+ m_arg = m_tagAliases->expandAliases( arg );
+ m_escapeChars.clear();
+ for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
+ visitChar( m_arg[m_pos] );
+ if( m_mode == Name )
+ addPattern<TestSpec::NamePattern>();
+ return *this;
+ }
+ TestSpec testSpec() {
+ addFilter();
+ return m_testSpec;
+ }
+ private:
+ void visitChar( char c ) {
+ if( m_mode == None ) {
+ switch( c ) {
+ case ' ': return;
+ case '~': m_exclusion = true; return;
+ case '[': return startNewMode( Tag, ++m_pos );
+ case '"': return startNewMode( QuotedName, ++m_pos );
+ case '\\': return escape();
+ default: startNewMode( Name, m_pos ); break;
+ }
+ }
+ if( m_mode == Name ) {
+ if( c == ',' ) {
+ addPattern<TestSpec::NamePattern>();
+ addFilter();
+ }
+ else if( c == '[' ) {
+ if( subString() == "exclude:" )
+ m_exclusion = true;
+ else
+ addPattern<TestSpec::NamePattern>();
+ startNewMode( Tag, ++m_pos );
+ }
+ else if( c == '\\' )
+ escape();
+ }
+ else if( m_mode == EscapedName )
+ m_mode = Name;
+ else if( m_mode == QuotedName && c == '"' )
+ addPattern<TestSpec::NamePattern>();
+ else if( m_mode == Tag && c == ']' )
+ addPattern<TestSpec::TagPattern>();
+ }
+ void startNewMode( Mode mode, std::size_t start ) {
+ m_mode = mode;
+ m_start = start;
+ }
+ void escape() {
+ if( m_mode == None )
+ m_start = m_pos;
+ m_mode = EscapedName;
+ m_escapeChars.push_back( m_pos );
+ }
+ std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
+ template<typename T>
+ void addPattern() {
+ std::string token = subString();
+ for( size_t i = 0; i < m_escapeChars.size(); ++i )
+ token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
+ m_escapeChars.clear();
+ if( startsWith( token, "exclude:" ) ) {
+ m_exclusion = true;
+ token = token.substr( 8 );
+ }
+ if( !token.empty() ) {
+ Ptr<TestSpec::Pattern> pattern = new T( token );
+ if( m_exclusion )
+ pattern = new TestSpec::ExcludedPattern( pattern );
+ m_currentFilter.m_patterns.push_back( pattern );
+ }
+ m_exclusion = false;
+ m_mode = None;
+ }
+ void addFilter() {
+ if( !m_currentFilter.m_patterns.empty() ) {
+ m_testSpec.m_filters.push_back( m_currentFilter );
+ m_currentFilter = TestSpec::Filter();
+ }
+ }
+ };
+ inline TestSpec parseTestSpec( std::string const& arg ) {
+ return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
+ }
+
+} // namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// #included from: catch_interfaces_config.h
+#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
+
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+namespace Catch {
+
+ struct Verbosity { enum Level {
+ NoOutput = 0,
+ Quiet,
+ Normal
+ }; };
+
+ struct WarnAbout { enum What {
+ Nothing = 0x00,
+ NoAssertions = 0x01
+ }; };
+
+ struct ShowDurations { enum OrNot {
+ DefaultForReporter,
+ Always,
+ Never
+ }; };
+ struct RunTests { enum InWhatOrder {
+ InDeclarationOrder,
+ InLexicographicalOrder,
+ InRandomOrder
+ }; };
+ struct UseColour { enum YesOrNo {
+ Auto,
+ Yes,
+ No
+ }; };
+
+ class TestSpec;
+
+ struct IConfig : IShared {
+
+ virtual ~IConfig();
+
+ virtual bool allowThrows() const = 0;
+ virtual std::ostream& stream() const = 0;
+ virtual std::string name() const = 0;
+ virtual bool includeSuccessfulResults() const = 0;
+ virtual bool shouldDebugBreak() const = 0;
+ virtual bool warnAboutMissingAssertions() const = 0;
+ virtual int abortAfter() const = 0;
+ virtual bool showInvisibles() const = 0;
+ virtual ShowDurations::OrNot showDurations() const = 0;
+ virtual TestSpec const& testSpec() const = 0;
+ virtual RunTests::InWhatOrder runOrder() const = 0;
+ virtual unsigned int rngSeed() const = 0;
+ virtual UseColour::YesOrNo useColour() const = 0;
+ virtual std::vector<std::string> const& getSectionsToRun() const = 0;
+
+ };
+}
+
+// #included from: catch_stream.h
+#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
+
+// #included from: catch_streambuf.h
+#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
+
+#include <streambuf>
+
+namespace Catch {
+
+ class StreamBufBase : public std::streambuf {
+ public:
+ virtual ~StreamBufBase() CATCH_NOEXCEPT;
+ };
+}
+
+#include <streambuf>
+#include <ostream>
+#include <fstream>
+#include <memory>
+
+namespace Catch {
+
+ std::ostream& cout();
+ std::ostream& cerr();
+
+ struct IStream {
+ virtual ~IStream() CATCH_NOEXCEPT;
+ virtual std::ostream& stream() const = 0;
+ };
+
+ class FileStream : public IStream {
+ mutable std::ofstream m_ofs;
+ public:
+ FileStream( std::string const& filename );
+ virtual ~FileStream() CATCH_NOEXCEPT;
+ public: // IStream
+ virtual std::ostream& stream() const CATCH_OVERRIDE;
+ };
+
+ class CoutStream : public IStream {
+ mutable std::ostream m_os;
+ public:
+ CoutStream();
+ virtual ~CoutStream() CATCH_NOEXCEPT;
+
+ public: // IStream
+ virtual std::ostream& stream() const CATCH_OVERRIDE;
+ };
+
+ class DebugOutStream : public IStream {
+ CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
+ mutable std::ostream m_os;
+ public:
+ DebugOutStream();
+ virtual ~DebugOutStream() CATCH_NOEXCEPT;
+
+ public: // IStream
+ virtual std::ostream& stream() const CATCH_OVERRIDE;
+ };
+}
+
+#include <memory>
+#include <vector>
+#include <string>
+#include <stdexcept>
+
+#ifndef CATCH_CONFIG_CONSOLE_WIDTH
+#define CATCH_CONFIG_CONSOLE_WIDTH 80
+#endif
+
+namespace Catch {
+
+ struct ConfigData {
+
+ ConfigData()
+ : listTests( false ),
+ listTags( false ),
+ listReporters( false ),
+ listTestNamesOnly( false ),
+ showSuccessfulTests( false ),
+ shouldDebugBreak( false ),
+ noThrow( false ),
+ showHelp( false ),
+ showInvisibles( false ),
+ filenamesAsTags( false ),
+ abortAfter( -1 ),
+ rngSeed( 0 ),
+ verbosity( Verbosity::Normal ),
+ warnings( WarnAbout::Nothing ),
+ showDurations( ShowDurations::DefaultForReporter ),
+ runOrder( RunTests::InDeclarationOrder ),
+ useColour( UseColour::Auto )
+ {}
+
+ bool listTests;
+ bool listTags;
+ bool listReporters;
+ bool listTestNamesOnly;
+
+ bool showSuccessfulTests;
+ bool shouldDebugBreak;
+ bool noThrow;
+ bool showHelp;
+ bool showInvisibles;
+ bool filenamesAsTags;
+
+ int abortAfter;
+ unsigned int rngSeed;
+
+ Verbosity::Level verbosity;
+ WarnAbout::What warnings;
+ ShowDurations::OrNot showDurations;
+ RunTests::InWhatOrder runOrder;
+ UseColour::YesOrNo useColour;
+
+ std::string outputFilename;
+ std::string name;
+ std::string processName;
+
+ std::vector<std::string> reporterNames;
+ std::vector<std::string> testsOrTags;
+ std::vector<std::string> sectionsToRun;
+ };
+
+ class Config : public SharedImpl<IConfig> {
+ private:
+ Config( Config const& other );
+ Config& operator = ( Config const& other );
+ virtual void dummy();
+ public:
+
+ Config()
+ {}
+
+ Config( ConfigData const& data )
+ : m_data( data ),
+ m_stream( openStream() )
+ {
+ if( !data.testsOrTags.empty() ) {
+ TestSpecParser parser( ITagAliasRegistry::get() );
+ for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
+ parser.parse( data.testsOrTags[i] );
+ m_testSpec = parser.testSpec();
+ }
+ }
+
+ virtual ~Config() {}
+
+ std::string const& getFilename() const {
+ return m_data.outputFilename ;
+ }
+
+ bool listTests() const { return m_data.listTests; }
+ bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
+ bool listTags() const { return m_data.listTags; }
+ bool listReporters() const { return m_data.listReporters; }
+
+ std::string getProcessName() const { return m_data.processName; }
+
+ std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
+ std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
+
+ virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; }
+
+ bool showHelp() const { return m_data.showHelp; }
+
+ // IConfig interface
+ virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; }
+ virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); }
+ virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; }
+ virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; }
+ virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; }
+ virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; }
+ virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; }
+ virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; }
+ virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; }
+ virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; }
+ virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; }
+ virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; }
+
+ private:
+
+ IStream const* openStream() {
+ if( m_data.outputFilename.empty() )
+ return new CoutStream();
+ else if( m_data.outputFilename[0] == '%' ) {
+ if( m_data.outputFilename == "%debug" )
+ return new DebugOutStream();
+ else
+ throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
+ }
+ else
+ return new FileStream( m_data.outputFilename );
+ }
+ ConfigData m_data;
+
+ CATCH_AUTO_PTR( IStream const ) m_stream;
+ TestSpec m_testSpec;
+ };
+
+} // end namespace Catch
+
+// #included from: catch_clara.h
+#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
+
+// Use Catch's value for console width (store Clara's off to the side, if present)
+#ifdef CLARA_CONFIG_CONSOLE_WIDTH
+#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
+#undef CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
+
+// Declare Clara inside the Catch namespace
+#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
+// #included from: ../external/clara.h
+
+// Version 0.0.2.4
+
+// Only use header guard if we are not using an outer namespace
+#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
+
+#ifndef STITCH_CLARA_OPEN_NAMESPACE
+#define TWOBLUECUBES_CLARA_H_INCLUDED
+#define STITCH_CLARA_OPEN_NAMESPACE
+#define STITCH_CLARA_CLOSE_NAMESPACE
+#else
+#define STITCH_CLARA_CLOSE_NAMESPACE }
+#endif
+
+#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
+
+// ----------- #included from tbc_text_format.h -----------
+
+// Only use header guard if we are not using an outer namespace
+#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
+#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+#define TBC_TEXT_FORMAT_H_INCLUDED
+#endif
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+
+// Use optional outer namespace
+#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
+#endif
+
+namespace Tbc {
+
+#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
+ const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
+#else
+ const unsigned int consoleWidth = 80;
+#endif
+
+ struct TextAttributes {
+ TextAttributes()
+ : initialIndent( std::string::npos ),
+ indent( 0 ),
+ width( consoleWidth-1 ),
+ tabChar( '\t' )
+ {}
+
+ TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
+ TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
+ TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
+ TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
+
+ std::size_t initialIndent; // indent of first line, or npos
+ std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
+ std::size_t width; // maximum width of text, including indent. Longer text will wrap
+ char tabChar; // If this char is seen the indent is changed to current pos
+ };
+
+ class Text {
+ public:
+ Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
+ : attr( _attr )
+ {
+ std::string wrappableChars = " [({.,/|\\-";
+ std::size_t indent = _attr.initialIndent != std::string::npos
+ ? _attr.initialIndent
+ : _attr.indent;
+ std::string remainder = _str;
+
+ while( !remainder.empty() ) {
+ if( lines.size() >= 1000 ) {
+ lines.push_back( "... message truncated due to excessive size" );
+ return;
+ }
+ std::size_t tabPos = std::string::npos;
+ std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
+ std::size_t pos = remainder.find_first_of( '\n' );
+ if( pos <= width ) {
+ width = pos;
+ }
+ pos = remainder.find_last_of( _attr.tabChar, width );
+ if( pos != std::string::npos ) {
+ tabPos = pos;
+ if( remainder[width] == '\n' )
+ width--;
+ remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
+ }
+
+ if( width == remainder.size() ) {
+ spliceLine( indent, remainder, width );
+ }
+ else if( remainder[width] == '\n' ) {
+ spliceLine( indent, remainder, width );
+ if( width <= 1 || remainder.size() != 1 )
+ remainder = remainder.substr( 1 );
+ indent = _attr.indent;
+ }
+ else {
+ pos = remainder.find_last_of( wrappableChars, width );
+ if( pos != std::string::npos && pos > 0 ) {
+ spliceLine( indent, remainder, pos );
+ if( remainder[0] == ' ' )
+ remainder = remainder.substr( 1 );
+ }
+ else {
+ spliceLine( indent, remainder, width-1 );
+ lines.back() += "-";
+ }
+ if( lines.size() == 1 )
+ indent = _attr.indent;
+ if( tabPos != std::string::npos )
+ indent += tabPos;
+ }
+ }
+ }
+
+ void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
+ lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
+ _remainder = _remainder.substr( _pos );
+ }
+
+ typedef std::vector<std::string>::const_iterator const_iterator;
+
+ const_iterator begin() const { return lines.begin(); }
+ const_iterator end() const { return lines.end(); }
+ std::string const& last() const { return lines.back(); }
+ std::size_t size() const { return lines.size(); }
+ std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
+ std::string toString() const {
+ std::ostringstream oss;
+ oss << *this;
+ return oss.str();
+ }
+
+ inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
+ for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
+ it != itEnd; ++it ) {
+ if( it != _text.begin() )
+ _stream << "\n";
+ _stream << *it;
+ }
+ return _stream;
+ }
+
+ private:
+ std::string str;
+ TextAttributes attr;
+ std::vector<std::string> lines;
+ };
+
+} // end namespace Tbc
+
+#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+} // end outer namespace
+#endif
+
+#endif // TBC_TEXT_FORMAT_H_INCLUDED
+
+// ----------- end of #include from tbc_text_format.h -----------
+// ........... back in clara.h
+
+#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
+
+// ----------- #included from clara_compilers.h -----------
+
+#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
+#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
+
+// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
+// The following features are defined:
+//
+// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
+// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
+// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
+// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
+// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
+
+// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
+
+// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
+
+// In general each macro has a _NO_<feature name> form
+// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
+// Many features, at point of detection, define an _INTERNAL_ macro, so they
+// can be combined, en-mass, with the _NO_ forms later.
+
+// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
+
+#ifdef __clang__
+
+#if __has_feature(cxx_nullptr)
+#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
+#endif
+
+#if __has_feature(cxx_noexcept)
+#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#endif
+
+#endif // __clang__
+
+////////////////////////////////////////////////////////////////////////////////
+// GCC
+#ifdef __GNUC__
+
+#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
+#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
+#endif
+
+// - otherwise more recent versions define __cplusplus >= 201103L
+// and will get picked up below
+
+#endif // __GNUC__
+
+////////////////////////////////////////////////////////////////////////////////
+// Visual C++
+#ifdef _MSC_VER
+
+#if (_MSC_VER >= 1600)
+#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
+#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+#endif
+
+#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
+#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#endif
+
+#endif // _MSC_VER
+
+////////////////////////////////////////////////////////////////////////////////
+// C++ language feature support
+
+// catch all support for C++11
+#if defined(__cplusplus) && __cplusplus >= 201103L
+
+#define CLARA_CPP11_OR_GREATER
+
+#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
+#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
+#endif
+
+#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
+#endif
+
+#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
+#endif
+
+#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
+#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
+#endif
+#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
+#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+#endif
+
+#endif // __cplusplus >= 201103L
+
+// Now set the actual defines based on the above + anything the user has configured
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_NULLPTR
+#endif
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_NOEXCEPT
+#endif
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_GENERATED_METHODS
+#endif
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_OVERRIDE
+#endif
+#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
+#define CLARA_CONFIG_CPP11_UNIQUE_PTR
+#endif
+
+// noexcept support:
+#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
+#define CLARA_NOEXCEPT noexcept
+# define CLARA_NOEXCEPT_IS(x) noexcept(x)
+#else
+#define CLARA_NOEXCEPT throw()
+# define CLARA_NOEXCEPT_IS(x)
+#endif
+
+// nullptr support
+#ifdef CLARA_CONFIG_CPP11_NULLPTR
+#define CLARA_NULL nullptr
+#else
+#define CLARA_NULL NULL
+#endif
+
+// override support
+#ifdef CLARA_CONFIG_CPP11_OVERRIDE
+#define CLARA_OVERRIDE override
+#else
+#define CLARA_OVERRIDE
+#endif
+
+// unique_ptr support
+#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
+# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
+#else
+# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
+#endif
+
+#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
+
+// ----------- end of #include from clara_compilers.h -----------
+// ........... back in clara.h
+
+#include <map>
+#include <stdexcept>
+#include <memory>
+
+#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
+#define CLARA_PLATFORM_WINDOWS
+#endif
+
+// Use optional outer namespace
+#ifdef STITCH_CLARA_OPEN_NAMESPACE
+STITCH_CLARA_OPEN_NAMESPACE
+#endif
+
+namespace Clara {
+
+ struct UnpositionalTag {};
+
+ extern UnpositionalTag _;
+
+#ifdef CLARA_CONFIG_MAIN
+ UnpositionalTag _;
+#endif
+
+ namespace Detail {
+
+#ifdef CLARA_CONSOLE_WIDTH
+ const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
+#else
+ const unsigned int consoleWidth = 80;
+#endif
+
+ using namespace Tbc;
+
+ inline bool startsWith( std::string const& str, std::string const& prefix ) {
+ return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
+ }
+
+ template<typename T> struct RemoveConstRef{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
+ template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
+
+ template<typename T> struct IsBool { static const bool value = false; };
+ template<> struct IsBool<bool> { static const bool value = true; };
+
+ template<typename T>
+ void convertInto( std::string const& _source, T& _dest ) {
+ std::stringstream ss;
+ ss << _source;
+ ss >> _dest;
+ if( ss.fail() )
+ throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
+ }
+ inline void convertInto( std::string const& _source, std::string& _dest ) {
+ _dest = _source;
+ }
+ char toLowerCh(char c) {
+ return static_cast<char>( ::tolower( c ) );
+ }
+ inline void convertInto( std::string const& _source, bool& _dest ) {
+ std::string sourceLC = _source;
+ std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
+ if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
+ _dest = true;
+ else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
+ _dest = false;
+ else
+ throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
+ }
+
+ template<typename ConfigT>
+ struct IArgFunction {
+ virtual ~IArgFunction() {}
+#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
+ IArgFunction() = default;
+ IArgFunction( IArgFunction const& ) = default;
+#endif
+ virtual void set( ConfigT& config, std::string const& value ) const = 0;
+ virtual bool takesArg() const = 0;
+ virtual IArgFunction* clone() const = 0;
+ };
+
+ template<typename ConfigT>
+ class BoundArgFunction {
+ public:
+ BoundArgFunction() : functionObj( CLARA_NULL ) {}
+ BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
+ BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
+ BoundArgFunction& operator = ( BoundArgFunction const& other ) {
+ IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
+ delete functionObj;
+ functionObj = newFunctionObj;
+ return *this;
+ }
+ ~BoundArgFunction() { delete functionObj; }
+
+ void set( ConfigT& config, std::string const& value ) const {
+ functionObj->set( config, value );
+ }
+ bool takesArg() const { return functionObj->takesArg(); }
+
+ bool isSet() const {
+ return functionObj != CLARA_NULL;
+ }
+ private:
+ IArgFunction<ConfigT>* functionObj;
+ };
+
+ template<typename C>
+ struct NullBinder : IArgFunction<C>{
+ virtual void set( C&, std::string const& ) const {}
+ virtual bool takesArg() const { return true; }
+ virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
+ };
+
+ template<typename C, typename M>
+ struct BoundDataMember : IArgFunction<C>{
+ BoundDataMember( M C::* _member ) : member( _member ) {}
+ virtual void set( C& p, std::string const& stringValue ) const {
+ convertInto( stringValue, p.*member );
+ }
+ virtual bool takesArg() const { return !IsBool<M>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
+ M C::* member;
+ };
+ template<typename C, typename M>
+ struct BoundUnaryMethod : IArgFunction<C>{
+ BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
+ virtual void set( C& p, std::string const& stringValue ) const {
+ typename RemoveConstRef<M>::type value;
+ convertInto( stringValue, value );
+ (p.*member)( value );
+ }
+ virtual bool takesArg() const { return !IsBool<M>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
+ void (C::*member)( M );
+ };
+ template<typename C>
+ struct BoundNullaryMethod : IArgFunction<C>{
+ BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
+ virtual void set( C& p, std::string const& stringValue ) const {
+ bool value;
+ convertInto( stringValue, value );
+ if( value )
+ (p.*member)();
+ }
+ virtual bool takesArg() const { return false; }
+ virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
+ void (C::*member)();
+ };
+
+ template<typename C>
+ struct BoundUnaryFunction : IArgFunction<C>{
+ BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
+ virtual void set( C& obj, std::string const& stringValue ) const {
+ bool value;
+ convertInto( stringValue, value );
+ if( value )
+ function( obj );
+ }
+ virtual bool takesArg() const { return false; }
+ virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
+ void (*function)( C& );
+ };
+
+ template<typename C, typename T>
+ struct BoundBinaryFunction : IArgFunction<C>{
+ BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
+ virtual void set( C& obj, std::string const& stringValue ) const {
+ typename RemoveConstRef<T>::type value;
+ convertInto( stringValue, value );
+ function( obj, value );
+ }
+ virtual bool takesArg() const { return !IsBool<T>::value; }
+ virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
+ void (*function)( C&, T );
+ };
+
+ } // namespace Detail
+
+ inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
+ std::vector<std::string> args( static_cast<std::size_t>( argc ) );
+ for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
+ args[i] = argv[i];
+
+ return args;
+ }
+
+ class Parser {
+ enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
+ Mode mode;
+ std::size_t from;
+ bool inQuotes;
+ public:
+
+ struct Token {
+ enum Type { Positional, ShortOpt, LongOpt };
+ Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
+ Type type;
+ std::string data;
+ };
+
+ Parser() : mode( None ), from( 0 ), inQuotes( false ){}
+
+ void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
+ const std::string doubleDash = "--";
+ for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
+ parseIntoTokens( args[i], tokens);
+ }
+
+ void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
+ for( std::size_t i = 0; i <= arg.size(); ++i ) {
+ char c = arg[i];
+ if( c == '"' )
+ inQuotes = !inQuotes;
+ mode = handleMode( i, c, arg, tokens );
+ }
+ }
+ Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
+ switch( mode ) {
+ case None: return handleNone( i, c );
+ case MaybeShortOpt: return handleMaybeShortOpt( i, c );
+ case ShortOpt:
+ case LongOpt:
+ case SlashOpt: return handleOpt( i, c, arg, tokens );
+ case Positional: return handlePositional( i, c, arg, tokens );
+ default: throw std::logic_error( "Unknown mode" );
+ }
+ }
+
+ Mode handleNone( std::size_t i, char c ) {
+ if( inQuotes ) {
+ from = i;
+ return Positional;
+ }
+ switch( c ) {
+ case '-': return MaybeShortOpt;
+#ifdef CLARA_PLATFORM_WINDOWS
+ case '/': from = i+1; return SlashOpt;
+#endif
+ default: from = i; return Positional;
+ }
+ }
+ Mode handleMaybeShortOpt( std::size_t i, char c ) {
+ switch( c ) {
+ case '-': from = i+1; return LongOpt;
+ default: from = i; return ShortOpt;
+ }
+ }
+ Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
+ if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
+ return mode;
+
+ std::string optName = arg.substr( from, i-from );
+ if( mode == ShortOpt )
+ for( std::size_t j = 0; j < optName.size(); ++j )
+ tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
+ else if( mode == SlashOpt && optName.size() == 1 )
+ tokens.push_back( Token( Token::ShortOpt, optName ) );
+ else
+ tokens.push_back( Token( Token::LongOpt, optName ) );
+ return None;
+ }
+ Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
+ if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
+ return mode;
+
+ std::string data = arg.substr( from, i-from );
+ tokens.push_back( Token( Token::Positional, data ) );
+ return None;
+ }
+ };
+
+ template<typename ConfigT>
+ struct CommonArgProperties {
+ CommonArgProperties() {}
+ CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
+
+ Detail::BoundArgFunction<ConfigT> boundField;
+ std::string description;
+ std::string detail;
+ std::string placeholder; // Only value if boundField takes an arg
+
+ bool takesArg() const {
+ return !placeholder.empty();
+ }
+ void validate() const {
+ if( !boundField.isSet() )
+ throw std::logic_error( "option not bound" );
+ }
+ };
+ struct OptionArgProperties {
+ std::vector<std::string> shortNames;
+ std::string longName;
+
+ bool hasShortName( std::string const& shortName ) const {
+ return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
+ }
+ bool hasLongName( std::string const& _longName ) const {
+ return _longName == longName;
+ }
+ };
+ struct PositionalArgProperties {
+ PositionalArgProperties() : position( -1 ) {}
+ int position; // -1 means non-positional (floating)
+
+ bool isFixedPositional() const {
+ return position != -1;
+ }
+ };
+
+ template<typename ConfigT>
+ class CommandLine {
+
+ struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
+ Arg() {}
+ Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
+
+ using CommonArgProperties<ConfigT>::placeholder; // !TBD
+
+ std::string dbgName() const {
+ if( !longName.empty() )
+ return "--" + longName;
+ if( !shortNames.empty() )
+ return "-" + shortNames[0];
+ return "positional args";
+ }
+ std::string commands() const {
+ std::ostringstream oss;
+ bool first = true;
+ std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
+ for(; it != itEnd; ++it ) {
+ if( first )
+ first = false;
+ else
+ oss << ", ";
+ oss << "-" << *it;
+ }
+ if( !longName.empty() ) {
+ if( !first )
+ oss << ", ";
+ oss << "--" << longName;
+ }
+ if( !placeholder.empty() )
+ oss << " <" << placeholder << ">";
+ return oss.str();
+ }
+ };
+
+ typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
+
+ friend void addOptName( Arg& arg, std::string const& optName )
+ {
+ if( optName.empty() )
+ return;
+ if( Detail::startsWith( optName, "--" ) ) {
+ if( !arg.longName.empty() )
+ throw std::logic_error( "Only one long opt may be specified. '"
+ + arg.longName
+ + "' already specified, now attempting to add '"
+ + optName + "'" );
+ arg.longName = optName.substr( 2 );
+ }
+ else if( Detail::startsWith( optName, "-" ) )
+ arg.shortNames.push_back( optName.substr( 1 ) );
+ else
+ throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
+ }
+ friend void setPositionalArg( Arg& arg, int position )
+ {
+ arg.position = position;
+ }
+
+ class ArgBuilder {
+ public:
+ ArgBuilder( Arg* arg ) : m_arg( arg ) {}
+
+ // Bind a non-boolean data member (requires placeholder string)
+ template<typename C, typename M>
+ void bind( M C::* field, std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
+ m_arg->placeholder = placeholder;
+ }
+ // Bind a boolean data member (no placeholder required)
+ template<typename C>
+ void bind( bool C::* field ) {
+ m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
+ }
+
+ // Bind a method taking a single, non-boolean argument (requires a placeholder string)
+ template<typename C, typename M>
+ void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
+ m_arg->placeholder = placeholder;
+ }
+
+ // Bind a method taking a single, boolean argument (no placeholder string required)
+ template<typename C>
+ void bind( void (C::* unaryMethod)( bool ) ) {
+ m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
+ }
+
+ // Bind a method that takes no arguments (will be called if opt is present)
+ template<typename C>
+ void bind( void (C::* nullaryMethod)() ) {
+ m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
+ template<typename C>
+ void bind( void (* unaryFunction)( C& ) ) {
+ m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
+ }
+
+ // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
+ template<typename C, typename T>
+ void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
+ m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
+ m_arg->placeholder = placeholder;
+ }
+
+ ArgBuilder& describe( std::string const& description ) {
+ m_arg->description = description;
+ return *this;
+ }
+ ArgBuilder& detail( std::string const& detail ) {
+ m_arg->detail = detail;
+ return *this;
+ }
+
+ protected:
+ Arg* m_arg;
+ };
+
+ class OptBuilder : public ArgBuilder {
+ public:
+ OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
+ OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
+
+ OptBuilder& operator[]( std::string const& optName ) {
+ addOptName( *ArgBuilder::m_arg, optName );
+ return *this;
+ }
+ };
+
+ public:
+
+ CommandLine()
+ : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
+ m_highestSpecifiedArgPosition( 0 ),
+ m_throwOnUnrecognisedTokens( false )
+ {}
+ CommandLine( CommandLine const& other )
+ : m_boundProcessName( other.m_boundProcessName ),
+ m_options ( other.m_options ),
+ m_positionalArgs( other.m_positionalArgs ),
+ m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
+ m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
+ {
+ if( other.m_floatingArg.get() )
+ m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
+ }
+
+ CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
+ m_throwOnUnrecognisedTokens = shouldThrow;
+ return *this;
+ }
+
+ OptBuilder operator[]( std::string const& optName ) {
+ m_options.push_back( Arg() );
+ addOptName( m_options.back(), optName );
+ OptBuilder builder( &m_options.back() );
+ return builder;
+ }
+
+ ArgBuilder operator[]( int position ) {
+ m_positionalArgs.insert( std::make_pair( position, Arg() ) );
+ if( position > m_highestSpecifiedArgPosition )
+ m_highestSpecifiedArgPosition = position;
+ setPositionalArg( m_positionalArgs[position], position );
+ ArgBuilder builder( &m_positionalArgs[position] );
+ return builder;
+ }
+
+ // Invoke this with the _ instance
+ ArgBuilder operator[]( UnpositionalTag ) {
+ if( m_floatingArg.get() )
+ throw std::logic_error( "Only one unpositional argument can be added" );
+ m_floatingArg.reset( new Arg() );
+ ArgBuilder builder( m_floatingArg.get() );
+ return builder;
+ }
+
+ template<typename C, typename M>
+ void bindProcessName( M C::* field ) {
+ m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
+ }
+ template<typename C, typename M>
+ void bindProcessName( void (C::*_unaryMethod)( M ) ) {
+ m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
+ }
+
+ void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
+ typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
+ std::size_t maxWidth = 0;
+ for( it = itBegin; it != itEnd; ++it )
+ maxWidth = (std::max)( maxWidth, it->commands().size() );
+
+ for( it = itBegin; it != itEnd; ++it ) {
+ Detail::Text usage( it->commands(), Detail::TextAttributes()
+ .setWidth( maxWidth+indent )
+ .setIndent( indent ) );
+ Detail::Text desc( it->description, Detail::TextAttributes()
+ .setWidth( width - maxWidth - 3 ) );
+
+ for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
+ std::string usageCol = i < usage.size() ? usage[i] : "";
+ os << usageCol;
+
+ if( i < desc.size() && !desc[i].empty() )
+ os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
+ << desc[i];
+ os << "\n";
+ }
+ }
+ }
+ std::string optUsage() const {
+ std::ostringstream oss;
+ optUsage( oss );
+ return oss.str();
+ }
+
+ void argSynopsis( std::ostream& os ) const {
+ for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
+ if( i > 1 )
+ os << " ";
+ typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
+ if( it != m_positionalArgs.end() )
+ os << "<" << it->second.placeholder << ">";
+ else if( m_floatingArg.get() )
+ os << "<" << m_floatingArg->placeholder << ">";
+ else
+ throw std::logic_error( "non consecutive positional arguments with no floating args" );
+ }
+ // !TBD No indication of mandatory args
+ if( m_floatingArg.get() ) {
+ if( m_highestSpecifiedArgPosition > 1 )
+ os << " ";
+ os << "[<" << m_floatingArg->placeholder << "> ...]";
+ }
+ }
+ std::string argSynopsis() const {
+ std::ostringstream oss;
+ argSynopsis( oss );
+ return oss.str();
+ }
+
+ void usage( std::ostream& os, std::string const& procName ) const {
+ validate();
+ os << "usage:\n " << procName << " ";
+ argSynopsis( os );
+ if( !m_options.empty() ) {
+ os << " [options]\n\nwhere options are: \n";
+ optUsage( os, 2 );
+ }
+ os << "\n";
+ }
+ std::string usage( std::string const& procName ) const {
+ std::ostringstream oss;
+ usage( oss, procName );
+ return oss.str();
+ }
+
+ ConfigT parse( std::vector<std::string> const& args ) const {
+ ConfigT config;
+ parseInto( args, config );
+ return config;
+ }
+
+ std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
+ std::string processName = args[0];
+ std::size_t lastSlash = processName.find_last_of( "/\\" );
+ if( lastSlash != std::string::npos )
+ processName = processName.substr( lastSlash+1 );
+ m_boundProcessName.set( config, processName );
+ std::vector<Parser::Token> tokens;
+ Parser parser;
+ parser.parseIntoTokens( args, tokens );
+ return populate( tokens, config );
+ }
+
+ std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ validate();
+ std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
+ unusedTokens = populateFixedArgs( unusedTokens, config );
+ unusedTokens = populateFloatingArgs( unusedTokens, config );
+ return unusedTokens;
+ }
+
+ std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ std::vector<Parser::Token> unusedTokens;
+ std::vector<std::string> errors;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
+ for(; it != itEnd; ++it ) {
+ Arg const& arg = *it;
+
+ try {
+ if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
+ ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
+ if( arg.takesArg() ) {
+ if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
+ errors.push_back( "Expected argument to option: " + token.data );
+ else
+ arg.boundField.set( config, tokens[++i].data );
+ }
+ else {
+ arg.boundField.set( config, "true" );
+ }
+ break;
+ }
+ }
+ catch( std::exception& ex ) {
+ errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
+ }
+ }
+ if( it == itEnd ) {
+ if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
+ unusedTokens.push_back( token );
+ else if( errors.empty() && m_throwOnUnrecognisedTokens )
+ errors.push_back( "unrecognised option: " + token.data );
+ }
+ }
+ if( !errors.empty() ) {
+ std::ostringstream oss;
+ for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
+ it != itEnd;
+ ++it ) {
+ if( it != errors.begin() )
+ oss << "\n";
+ oss << *it;
+ }
+ throw std::runtime_error( oss.str() );
+ }
+ return unusedTokens;
+ }
+ std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ std::vector<Parser::Token> unusedTokens;
+ int position = 1;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
+ if( it != m_positionalArgs.end() )
+ it->second.boundField.set( config, token.data );
+ else
+ unusedTokens.push_back( token );
+ if( token.type == Parser::Token::Positional )
+ position++;
+ }
+ return unusedTokens;
+ }
+ std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
+ if( !m_floatingArg.get() )
+ return tokens;
+ std::vector<Parser::Token> unusedTokens;
+ for( std::size_t i = 0; i < tokens.size(); ++i ) {
+ Parser::Token const& token = tokens[i];
+ if( token.type == Parser::Token::Positional )
+ m_floatingArg->boundField.set( config, token.data );
+ else
+ unusedTokens.push_back( token );
+ }
+ return unusedTokens;
+ }
+
+ void validate() const
+ {
+ if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
+ throw std::logic_error( "No options or arguments specified" );
+
+ for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
+ itEnd = m_options.end();
+ it != itEnd; ++it )
+ it->validate();
+ }
+
+ private:
+ Detail::BoundArgFunction<ConfigT> m_boundProcessName;
+ std::vector<Arg> m_options;
+ std::map<int, Arg> m_positionalArgs;
+ ArgAutoPtr m_floatingArg;
+ int m_highestSpecifiedArgPosition;
+ bool m_throwOnUnrecognisedTokens;
+ };
+
+} // end namespace Clara
+
+STITCH_CLARA_CLOSE_NAMESPACE
+#undef STITCH_CLARA_OPEN_NAMESPACE
+#undef STITCH_CLARA_CLOSE_NAMESPACE
+
+#endif // TWOBLUECUBES_CLARA_H_INCLUDED
+#undef STITCH_CLARA_OPEN_NAMESPACE
+
+// Restore Clara's value for console width, if present
+#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
+#endif
+
+#include <fstream>
+#include <ctime>
+
+namespace Catch {
+
+ inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
+ inline void abortAfterX( ConfigData& config, int x ) {
+ if( x < 1 )
+ throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
+ config.abortAfter = x;
+ }
+ inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
+ inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
+ inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
+
+ inline void addWarning( ConfigData& config, std::string const& _warning ) {
+ if( _warning == "NoAssertions" )
+ config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
+ else
+ throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
+ }
+ inline void setOrder( ConfigData& config, std::string const& order ) {
+ if( startsWith( "declared", order ) )
+ config.runOrder = RunTests::InDeclarationOrder;
+ else if( startsWith( "lexical", order ) )
+ config.runOrder = RunTests::InLexicographicalOrder;
+ else if( startsWith( "random", order ) )
+ config.runOrder = RunTests::InRandomOrder;
+ else
+ throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
+ }
+ inline void setRngSeed( ConfigData& config, std::string const& seed ) {
+ if( seed == "time" ) {
+ config.rngSeed = static_cast<unsigned int>( std::time(0) );
+ }
+ else {
+ std::stringstream ss;
+ ss << seed;
+ ss >> config.rngSeed;
+ if( ss.fail() )
+ throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" );
+ }
+ }
+ inline void setVerbosity( ConfigData& config, int level ) {
+ // !TBD: accept strings?
+ config.verbosity = static_cast<Verbosity::Level>( level );
+ }
+ inline void setShowDurations( ConfigData& config, bool _showDurations ) {
+ config.showDurations = _showDurations
+ ? ShowDurations::Always
+ : ShowDurations::Never;
+ }
+ inline void setUseColour( ConfigData& config, std::string const& value ) {
+ std::string mode = toLower( value );
+
+ if( mode == "yes" )
+ config.useColour = UseColour::Yes;
+ else if( mode == "no" )
+ config.useColour = UseColour::No;
+ else if( mode == "auto" )
+ config.useColour = UseColour::Auto;
+ else
+ throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
+ }
+ inline void forceColour( ConfigData& config ) {
+ config.useColour = UseColour::Yes;
+ }
+ inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
+ std::ifstream f( _filename.c_str() );
+ if( !f.is_open() )
+ throw std::domain_error( "Unable to load input file: " + _filename );
+
+ std::string line;
+ while( std::getline( f, line ) ) {
+ line = trim(line);
+ if( !line.empty() && !startsWith( line, '#' ) ) {
+ if( !startsWith( line, '"' ) )
+ line = '"' + line + '"';
+ addTestOrTags( config, line + ',' );
+ }
+ }
+ }
+
+ inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
+
+ using namespace Clara;
+ CommandLine<ConfigData> cli;
+
+ cli.bindProcessName( &ConfigData::processName );
+
+ cli["-?"]["-h"]["--help"]
+ .describe( "display usage information" )
+ .bind( &ConfigData::showHelp );
+
+ cli["-l"]["--list-tests"]
+ .describe( "list all/matching test cases" )
+ .bind( &ConfigData::listTests );
+
+ cli["-t"]["--list-tags"]
+ .describe( "list all/matching tags" )
+ .bind( &ConfigData::listTags );
+
+ cli["-s"]["--success"]
+ .describe( "include successful tests in output" )
+ .bind( &ConfigData::showSuccessfulTests );
+
+ cli["-b"]["--break"]
+ .describe( "break into debugger on failure" )
+ .bind( &ConfigData::shouldDebugBreak );
+
+ cli["-e"]["--nothrow"]
+ .describe( "skip exception tests" )
+ .bind( &ConfigData::noThrow );
+
+ cli["-i"]["--invisibles"]
+ .describe( "show invisibles (tabs, newlines)" )
+ .bind( &ConfigData::showInvisibles );
+
+ cli["-o"]["--out"]
+ .describe( "output filename" )
+ .bind( &ConfigData::outputFilename, "filename" );
+
+ cli["-r"]["--reporter"]
+// .placeholder( "name[:filename]" )
+ .describe( "reporter to use (defaults to console)" )
+ .bind( &addReporterName, "name" );
+
+ cli["-n"]["--name"]
+ .describe( "suite name" )
+ .bind( &ConfigData::name, "name" );
+
+ cli["-a"]["--abort"]
+ .describe( "abort at first failure" )
+ .bind( &abortAfterFirst );
+
+ cli["-x"]["--abortx"]
+ .describe( "abort after x failures" )
+ .bind( &abortAfterX, "no. failures" );
+
+ cli["-w"]["--warn"]
+ .describe( "enable warnings" )
+ .bind( &addWarning, "warning name" );
+
+// - needs updating if reinstated
+// cli.into( &setVerbosity )
+// .describe( "level of verbosity (0=no output)" )
+// .shortOpt( "v")
+// .longOpt( "verbosity" )
+// .placeholder( "level" );
+
+ cli[_]
+ .describe( "which test or tests to use" )
+ .bind( &addTestOrTags, "test name, pattern or tags" );
+
+ cli["-d"]["--durations"]
+ .describe( "show test durations" )
+ .bind( &setShowDurations, "yes|no" );
+
+ cli["-f"]["--input-file"]
+ .describe( "load test names to run from a file" )
+ .bind( &loadTestNamesFromFile, "filename" );
+
+ cli["-#"]["--filenames-as-tags"]
+ .describe( "adds a tag for the filename" )
+ .bind( &ConfigData::filenamesAsTags );
+
+ cli["-c"]["--section"]
+ .describe( "specify section to run" )
+ .bind( &addSectionToRun, "section name" );
+
+ // Less common commands which don't have a short form
+ cli["--list-test-names-only"]
+ .describe( "list all/matching test cases names only" )
+ .bind( &ConfigData::listTestNamesOnly );
+
+ cli["--list-reporters"]
+ .describe( "list all reporters" )
+ .bind( &ConfigData::listReporters );
+
+ cli["--order"]
+ .describe( "test case order (defaults to decl)" )
+ .bind( &setOrder, "decl|lex|rand" );
+
+ cli["--rng-seed"]
+ .describe( "set a specific seed for random numbers" )
+ .bind( &setRngSeed, "'time'|number" );
+
+ cli["--force-colour"]
+ .describe( "force colourised output (deprecated)" )
+ .bind( &forceColour );
+
+ cli["--use-colour"]
+ .describe( "should output be colourised" )
+ .bind( &setUseColour, "yes|no" );
+
+ return cli;
+ }
+
+} // end namespace Catch
+
+// #included from: internal/catch_list.hpp
+#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
+
+// #included from: catch_text.h
+#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
+
+#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
+
+#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
+// #included from: ../external/tbc_text_format.h
+// Only use header guard if we are not using an outer namespace
+#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
+# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+# endif
+# else
+# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
+# endif
+#endif
+#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#include <string>
+#include <vector>
+#include <sstream>
+
+// Use optional outer namespace
+#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
+#endif
+
+namespace Tbc {
+
+#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
+ const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
+#else
+ const unsigned int consoleWidth = 80;
+#endif
+
+ struct TextAttributes {
+ TextAttributes()
+ : initialIndent( std::string::npos ),
+ indent( 0 ),
+ width( consoleWidth-1 )
+ {}
+
+ TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
+ TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
+ TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
+
+ std::size_t initialIndent; // indent of first line, or npos
+ std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
+ std::size_t width; // maximum width of text, including indent. Longer text will wrap
+ };
+
+ class Text {
+ public:
+ Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
+ : attr( _attr )
+ {
+ const std::string wrappableBeforeChars = "[({<\t";
+ const std::string wrappableAfterChars = "])}>-,./|\\";
+ const std::string wrappableInsteadOfChars = " \n\r";
+ std::string indent = _attr.initialIndent != std::string::npos
+ ? std::string( _attr.initialIndent, ' ' )
+ : std::string( _attr.indent, ' ' );
+
+ typedef std::string::const_iterator iterator;
+ iterator it = _str.begin();
+ const iterator strEnd = _str.end();
+
+ while( it != strEnd ) {
+
+ if( lines.size() >= 1000 ) {
+ lines.push_back( "... message truncated due to excessive size" );
+ return;
+ }
+
+ std::string suffix;
+ std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
+ iterator itEnd = it+width;
+ iterator itNext = _str.end();
+
+ iterator itNewLine = std::find( it, itEnd, '\n' );
+ if( itNewLine != itEnd )
+ itEnd = itNewLine;
+
+ if( itEnd != strEnd ) {
+ bool foundWrapPoint = false;
+ iterator findIt = itEnd;
+ do {
+ if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
+ itEnd = findIt+1;
+ itNext = findIt+1;
+ foundWrapPoint = true;
+ }
+ else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
+ itEnd = findIt;
+ itNext = findIt;
+ foundWrapPoint = true;
+ }
+ else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
+ itNext = findIt+1;
+ itEnd = findIt;
+ foundWrapPoint = true;
+ }
+ if( findIt == it )
+ break;
+ else
+ --findIt;
+ }
+ while( !foundWrapPoint );
+
+ if( !foundWrapPoint ) {
+ // No good wrap char, so we'll break mid word and add a hyphen
+ --itEnd;
+ itNext = itEnd;
+ suffix = "-";
+ }
+ else {
+ while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
+ --itEnd;
+ }
+ }
+ lines.push_back( indent + std::string( it, itEnd ) + suffix );
+
+ if( indent.size() != _attr.indent )
+ indent = std::string( _attr.indent, ' ' );
+ it = itNext;
+ }
+ }
+
+ typedef std::vector<std::string>::const_iterator const_iterator;
+
+ const_iterator begin() const { return lines.begin(); }
+ const_iterator end() const { return lines.end(); }
+ std::string const& last() const { return lines.back(); }
+ std::size_t size() const { return lines.size(); }
+ std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
+ std::string toString() const {
+ std::ostringstream oss;
+ oss << *this;
+ return oss.str();
+ }
+
+ inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
+ for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
+ it != itEnd; ++it ) {
+ if( it != _text.begin() )
+ _stream << "\n";
+ _stream << *it;
+ }
+ return _stream;
+ }
+
+ private:
+ std::string str;
+ TextAttributes attr;
+ std::vector<std::string> lines;
+ };
+
+} // end namespace Tbc
+
+#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+} // end outer namespace
+#endif
+
+#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
+#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
+
+namespace Catch {
+ using Tbc::Text;
+ using Tbc::TextAttributes;
+}
+
+// #included from: catch_console_colour.hpp
+#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
+
+namespace Catch {
+
+ struct Colour {
+ enum Code {
+ None = 0,
+
+ White,
+ Red,
+ Green,
+ Blue,
+ Cyan,
+ Yellow,
+ Grey,
+
+ Bright = 0x10,
+
+ BrightRed = Bright | Red,
+ BrightGreen = Bright | Green,
+ LightGrey = Bright | Grey,
+ BrightWhite = Bright | White,
+
+ // By intention
+ FileName = LightGrey,
+ Warning = Yellow,
+ ResultError = BrightRed,
+ ResultSuccess = BrightGreen,
+ ResultExpectedFailure = Warning,
+
+ Error = BrightRed,
+ Success = Green,
+
+ OriginalExpression = Cyan,
+ ReconstructedExpression = Yellow,
+
+ SecondaryText = LightGrey,
+ Headers = White
+ };
+
+ // Use constructed object for RAII guard
+ Colour( Code _colourCode );
+ Colour( Colour const& other );
+ ~Colour();
+
+ // Use static method for one-shot changes
+ static void use( Code _colourCode );
+
+ private:
+ bool m_moved;
+ };
+
+ inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
+
+} // end namespace Catch
+
+// #included from: catch_interfaces_reporter.h
+#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
+
+#include <string>
+#include <ostream>
+#include <map>
+
+namespace Catch
+{
+ struct ReporterConfig {
+ explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
+ : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
+
+ ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
+ : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
+
+ std::ostream& stream() const { return *m_stream; }
+ Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
+
+ private:
+ std::ostream* m_stream;
+ Ptr<IConfig const> m_fullConfig;
+ };
+
+ struct ReporterPreferences {
+ ReporterPreferences()
+ : shouldRedirectStdOut( false )
+ {}
+
+ bool shouldRedirectStdOut;
+ };
+
+ template<typename T>
+ struct LazyStat : Option<T> {
+ LazyStat() : used( false ) {}
+ LazyStat& operator=( T const& _value ) {
+ Option<T>::operator=( _value );
+ used = false;
+ return *this;
+ }
+ void reset() {
+ Option<T>::reset();
+ used = false;
+ }
+ bool used;
+ };
+
+ struct TestRunInfo {
+ TestRunInfo( std::string const& _name ) : name( _name ) {}
+ std::string name;
+ };
+ struct GroupInfo {
+ GroupInfo( std::string const& _name,
+ std::size_t _groupIndex,
+ std::size_t _groupsCount )
+ : name( _name ),
+ groupIndex( _groupIndex ),
+ groupsCounts( _groupsCount )
+ {}
+
+ std::string name;
+ std::size_t groupIndex;
+ std::size_t groupsCounts;
+ };
+
+ struct AssertionStats {
+ AssertionStats( AssertionResult const& _assertionResult,
+ std::vector<MessageInfo> const& _infoMessages,
+ Totals const& _totals )
+ : assertionResult( _assertionResult ),
+ infoMessages( _infoMessages ),
+ totals( _totals )
+ {
+ if( assertionResult.hasMessage() ) {
+ // Copy message into messages list.
+ // !TBD This should have been done earlier, somewhere
+ MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
+ builder << assertionResult.getMessage();
+ builder.m_info.message = builder.m_stream.str();
+
+ infoMessages.push_back( builder.m_info );
+ }
+ }
+ virtual ~AssertionStats();
+
+# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ AssertionStats( AssertionStats const& ) = default;
+ AssertionStats( AssertionStats && ) = default;
+ AssertionStats& operator = ( AssertionStats const& ) = default;
+ AssertionStats& operator = ( AssertionStats && ) = default;
+# endif
+
+ AssertionResult assertionResult;
+ std::vector<MessageInfo> infoMessages;
+ Totals totals;
+ };
+
+ struct SectionStats {
+ SectionStats( SectionInfo const& _sectionInfo,
+ Counts const& _assertions,
+ double _durationInSeconds,
+ bool _missingAssertions )
+ : sectionInfo( _sectionInfo ),
+ assertions( _assertions ),
+ durationInSeconds( _durationInSeconds ),
+ missingAssertions( _missingAssertions )
+ {}
+ virtual ~SectionStats();
+# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ SectionStats( SectionStats const& ) = default;
+ SectionStats( SectionStats && ) = default;
+ SectionStats& operator = ( SectionStats const& ) = default;
+ SectionStats& operator = ( SectionStats && ) = default;
+# endif
+
+ SectionInfo sectionInfo;
+ Counts assertions;
+ double durationInSeconds;
+ bool missingAssertions;
+ };
+
+ struct TestCaseStats {
+ TestCaseStats( TestCaseInfo const& _testInfo,
+ Totals const& _totals,
+ std::string const& _stdOut,
+ std::string const& _stdErr,
+ bool _aborting )
+ : testInfo( _testInfo ),
+ totals( _totals ),
+ stdOut( _stdOut ),
+ stdErr( _stdErr ),
+ aborting( _aborting )
+ {}
+ virtual ~TestCaseStats();
+
+# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ TestCaseStats( TestCaseStats const& ) = default;
+ TestCaseStats( TestCaseStats && ) = default;
+ TestCaseStats& operator = ( TestCaseStats const& ) = default;
+ TestCaseStats& operator = ( TestCaseStats && ) = default;
+# endif
+
+ TestCaseInfo testInfo;
+ Totals totals;
+ std::string stdOut;
+ std::string stdErr;
+ bool aborting;
+ };
+
+ struct TestGroupStats {
+ TestGroupStats( GroupInfo const& _groupInfo,
+ Totals const& _totals,
+ bool _aborting )
+ : groupInfo( _groupInfo ),
+ totals( _totals ),
+ aborting( _aborting )
+ {}
+ TestGroupStats( GroupInfo const& _groupInfo )
+ : groupInfo( _groupInfo ),
+ aborting( false )
+ {}
+ virtual ~TestGroupStats();
+
+# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ TestGroupStats( TestGroupStats const& ) = default;
+ TestGroupStats( TestGroupStats && ) = default;
+ TestGroupStats& operator = ( TestGroupStats const& ) = default;
+ TestGroupStats& operator = ( TestGroupStats && ) = default;
+# endif
+
+ GroupInfo groupInfo;
+ Totals totals;
+ bool aborting;
+ };
+
+ struct TestRunStats {
+ TestRunStats( TestRunInfo const& _runInfo,
+ Totals const& _totals,
+ bool _aborting )
+ : runInfo( _runInfo ),
+ totals( _totals ),
+ aborting( _aborting )
+ {}
+ virtual ~TestRunStats();
+
+# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ TestRunStats( TestRunStats const& _other )
+ : runInfo( _other.runInfo ),
+ totals( _other.totals ),
+ aborting( _other.aborting )
+ {}
+# else
+ TestRunStats( TestRunStats const& ) = default;
+ TestRunStats( TestRunStats && ) = default;
+ TestRunStats& operator = ( TestRunStats const& ) = default;
+ TestRunStats& operator = ( TestRunStats && ) = default;
+# endif
+
+ TestRunInfo runInfo;
+ Totals totals;
+ bool aborting;
+ };
+
+ class MultipleReporters;
+
+ struct IStreamingReporter : IShared {
+ virtual ~IStreamingReporter();
+
+ // Implementing class must also provide the following static method:
+ // static std::string getDescription();
+
+ virtual ReporterPreferences getPreferences() const = 0;
+
+ virtual void noMatchingTestCases( std::string const& spec ) = 0;
+
+ virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
+
+ virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
+
+ virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
+
+ // The return value indicates if the messages buffer should be cleared:
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
+
+ virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
+ virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
+
+ virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
+
+ virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
+ };
+
+ struct IReporterFactory : IShared {
+ virtual ~IReporterFactory();
+ virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
+ virtual std::string getDescription() const = 0;
+ };
+
+ struct IReporterRegistry {
+ typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
+ typedef std::vector<Ptr<IReporterFactory> > Listeners;
+
+ virtual ~IReporterRegistry();
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
+ virtual FactoryMap const& getFactories() const = 0;
+ virtual Listeners const& getListeners() const = 0;
+ };
+
+ Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
+
+}
+
+#include <limits>
+#include <algorithm>
+
+namespace Catch {
+
+ inline std::size_t listTests( Config const& config ) {
+
+ TestSpec testSpec = config.testSpec();
+ if( config.testSpec().hasFilters() )
+ Catch::cout() << "Matching test cases:\n";
+ else {
+ Catch::cout() << "All available test cases:\n";
+ testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
+ }
+
+ std::size_t matchedTests = 0;
+ TextAttributes nameAttr, tagsAttr;
+ nameAttr.setInitialIndent( 2 ).setIndent( 4 );
+ tagsAttr.setIndent( 6 );
+
+ std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+ it != itEnd;
+ ++it ) {
+ matchedTests++;
+ TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+ Colour::Code colour = testCaseInfo.isHidden()
+ ? Colour::SecondaryText
+ : Colour::None;
+ Colour colourGuard( colour );
+
+ Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
+ if( !testCaseInfo.tags.empty() )
+ Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
+ }
+
+ if( !config.testSpec().hasFilters() )
+ Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
+ else
+ Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
+ return matchedTests;
+ }
+
+ inline std::size_t listTestsNamesOnly( Config const& config ) {
+ TestSpec testSpec = config.testSpec();
+ if( !config.testSpec().hasFilters() )
+ testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
+ std::size_t matchedTests = 0;
+ std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+ it != itEnd;
+ ++it ) {
+ matchedTests++;
+ TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+ if( startsWith( testCaseInfo.name, '#' ) )
+ Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
+ else
+ Catch::cout() << testCaseInfo.name << std::endl;
+ }
+ return matchedTests;
+ }
+
+ struct TagInfo {
+ TagInfo() : count ( 0 ) {}
+ void add( std::string const& spelling ) {
+ ++count;
+ spellings.insert( spelling );
+ }
+ std::string all() const {
+ std::string out;
+ for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
+ it != itEnd;
+ ++it )
+ out += "[" + *it + "]";
+ return out;
+ }
+ std::set<std::string> spellings;
+ std::size_t count;
+ };
+
+ inline std::size_t listTags( Config const& config ) {
+ TestSpec testSpec = config.testSpec();
+ if( config.testSpec().hasFilters() )
+ Catch::cout() << "Tags for matching test cases:\n";
+ else {
+ Catch::cout() << "All available tags:\n";
+ testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
+ }
+
+ std::map<std::string, TagInfo> tagCounts;
+
+ std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
+ for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
+ it != itEnd;
+ ++it ) {
+ for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
+ tagItEnd = it->getTestCaseInfo().tags.end();
+ tagIt != tagItEnd;
+ ++tagIt ) {
+ std::string tagName = *tagIt;
+ std::string lcaseTagName = toLower( tagName );
+ std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
+ if( countIt == tagCounts.end() )
+ countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
+ countIt->second.add( tagName );
+ }
+ }
+
+ for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
+ countItEnd = tagCounts.end();
+ countIt != countItEnd;
+ ++countIt ) {
+ std::ostringstream oss;
+ oss << " " << std::setw(2) << countIt->second.count << " ";
+ Text wrapper( countIt->second.all(), TextAttributes()
+ .setInitialIndent( 0 )
+ .setIndent( oss.str().size() )
+ .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
+ Catch::cout() << oss.str() << wrapper << '\n';
+ }
+ Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
+ return tagCounts.size();
+ }
+
+ inline std::size_t listReporters( Config const& /*config*/ ) {
+ Catch::cout() << "Available reporters:\n";
+ IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
+ IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
+ std::size_t maxNameLen = 0;
+ for(it = itBegin; it != itEnd; ++it )
+ maxNameLen = (std::max)( maxNameLen, it->first.size() );
+
+ for(it = itBegin; it != itEnd; ++it ) {
+ Text wrapper( it->second->getDescription(), TextAttributes()
+ .setInitialIndent( 0 )
+ .setIndent( 7+maxNameLen )
+ .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
+ Catch::cout() << " "
+ << it->first
+ << ':'
+ << std::string( maxNameLen - it->first.size() + 2, ' ' )
+ << wrapper << '\n';
+ }
+ Catch::cout() << std::endl;
+ return factories.size();
+ }
+
+ inline Option<std::size_t> list( Config const& config ) {
+ Option<std::size_t> listedCount;
+ if( config.listTests() )
+ listedCount = listedCount.valueOr(0) + listTests( config );
+ if( config.listTestNamesOnly() )
+ listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
+ if( config.listTags() )
+ listedCount = listedCount.valueOr(0) + listTags( config );
+ if( config.listReporters() )
+ listedCount = listedCount.valueOr(0) + listReporters( config );
+ return listedCount;
+ }
+
+} // end namespace Catch
+
+// #included from: internal/catch_run_context.hpp
+#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
+
+// #included from: catch_test_case_tracker.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
+
+#include <map>
+#include <string>
+#include <assert.h>
+#include <vector>
+#include <iterator>
+#include <stdexcept>
+
+namespace Catch {
+namespace TestCaseTracking {
+
+ struct NameAndLocation {
+ std::string name;
+ SourceLineInfo location;
+
+ NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
+ : name( _name ),
+ location( _location )
+ {}
+ };
+
+ struct ITracker : SharedImpl<> {
+ virtual ~ITracker();
+
+ // static queries
+ virtual NameAndLocation const& nameAndLocation() const = 0;
+
+ // dynamic queries
+ virtual bool isComplete() const = 0; // Successfully completed or failed
+ virtual bool isSuccessfullyCompleted() const = 0;
+ virtual bool isOpen() const = 0; // Started but not complete
+ virtual bool hasChildren() const = 0;
+
+ virtual ITracker& parent() = 0;
+
+ // actions
+ virtual void close() = 0; // Successfully complete
+ virtual void fail() = 0;
+ virtual void markAsNeedingAnotherRun() = 0;
+
+ virtual void addChild( Ptr<ITracker> const& child ) = 0;
+ virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
+ virtual void openChild() = 0;
+
+ // Debug/ checking
+ virtual bool isSectionTracker() const = 0;
+ virtual bool isIndexTracker() const = 0;
+ };
+
+ class TrackerContext {
+
+ enum RunState {
+ NotStarted,
+ Executing,
+ CompletedCycle
+ };
+
+ Ptr<ITracker> m_rootTracker;
+ ITracker* m_currentTracker;
+ RunState m_runState;
+
+ public:
+
+ static TrackerContext& instance() {
+ static TrackerContext s_instance;
+ return s_instance;
+ }
+
+ TrackerContext()
+ : m_currentTracker( CATCH_NULL ),
+ m_runState( NotStarted )
+ {}
+
+ ITracker& startRun();
+
+ void endRun() {
+ m_rootTracker.reset();
+ m_currentTracker = CATCH_NULL;
+ m_runState = NotStarted;
+ }
+
+ void startCycle() {
+ m_currentTracker = m_rootTracker.get();
+ m_runState = Executing;
+ }
+ void completeCycle() {
+ m_runState = CompletedCycle;
+ }
+
+ bool completedCycle() const {
+ return m_runState == CompletedCycle;
+ }
+ ITracker& currentTracker() {
+ return *m_currentTracker;
+ }
+ void setCurrentTracker( ITracker* tracker ) {
+ m_currentTracker = tracker;
+ }
+ };
+
+ class TrackerBase : public ITracker {
+ protected:
+ enum CycleState {
+ NotStarted,
+ Executing,
+ ExecutingChildren,
+ NeedsAnotherRun,
+ CompletedSuccessfully,
+ Failed
+ };
+ class TrackerHasName {
+ NameAndLocation m_nameAndLocation;
+ public:
+ TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
+ bool operator ()( Ptr<ITracker> const& tracker ) {
+ return
+ tracker->nameAndLocation().name == m_nameAndLocation.name &&
+ tracker->nameAndLocation().location == m_nameAndLocation.location;
+ }
+ };
+ typedef std::vector<Ptr<ITracker> > Children;
+ NameAndLocation m_nameAndLocation;
+ TrackerContext& m_ctx;
+ ITracker* m_parent;
+ Children m_children;
+ CycleState m_runState;
+ public:
+ TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+ : m_nameAndLocation( nameAndLocation ),
+ m_ctx( ctx ),
+ m_parent( parent ),
+ m_runState( NotStarted )
+ {}
+ virtual ~TrackerBase();
+
+ virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
+ return m_nameAndLocation;
+ }
+ virtual bool isComplete() const CATCH_OVERRIDE {
+ return m_runState == CompletedSuccessfully || m_runState == Failed;
+ }
+ virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
+ return m_runState == CompletedSuccessfully;
+ }
+ virtual bool isOpen() const CATCH_OVERRIDE {
+ return m_runState != NotStarted && !isComplete();
+ }
+ virtual bool hasChildren() const CATCH_OVERRIDE {
+ return !m_children.empty();
+ }
+
+ virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
+ m_children.push_back( child );
+ }
+
+ virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
+ Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
+ return( it != m_children.end() )
+ ? it->get()
+ : CATCH_NULL;
+ }
+ virtual ITracker& parent() CATCH_OVERRIDE {
+ assert( m_parent ); // Should always be non-null except for root
+ return *m_parent;
+ }
+
+ virtual void openChild() CATCH_OVERRIDE {
+ if( m_runState != ExecutingChildren ) {
+ m_runState = ExecutingChildren;
+ if( m_parent )
+ m_parent->openChild();
+ }
+ }
+
+ virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
+ virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
+
+ void open() {
+ m_runState = Executing;
+ moveToThis();
+ if( m_parent )
+ m_parent->openChild();
+ }
+
+ virtual void close() CATCH_OVERRIDE {
+
+ // Close any still open children (e.g. generators)
+ while( &m_ctx.currentTracker() != this )
+ m_ctx.currentTracker().close();
+
+ switch( m_runState ) {
+ case NotStarted:
+ case CompletedSuccessfully:
+ case Failed:
+ throw std::logic_error( "Illogical state" );
+
+ case NeedsAnotherRun:
+ break;;
+
+ case Executing:
+ m_runState = CompletedSuccessfully;
+ break;
+ case ExecutingChildren:
+ if( m_children.empty() || m_children.back()->isComplete() )
+ m_runState = CompletedSuccessfully;
+ break;
+
+ default:
+ throw std::logic_error( "Unexpected state" );
+ }
+ moveToParent();
+ m_ctx.completeCycle();
+ }
+ virtual void fail() CATCH_OVERRIDE {
+ m_runState = Failed;
+ if( m_parent )
+ m_parent->markAsNeedingAnotherRun();
+ moveToParent();
+ m_ctx.completeCycle();
+ }
+ virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
+ m_runState = NeedsAnotherRun;
+ }
+ private:
+ void moveToParent() {
+ assert( m_parent );
+ m_ctx.setCurrentTracker( m_parent );
+ }
+ void moveToThis() {
+ m_ctx.setCurrentTracker( this );
+ }
+ };
+
+ class SectionTracker : public TrackerBase {
+ std::vector<std::string> m_filters;
+ public:
+ SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
+ : TrackerBase( nameAndLocation, ctx, parent )
+ {
+ if( parent ) {
+ while( !parent->isSectionTracker() )
+ parent = &parent->parent();
+
+ SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
+ addNextFilters( parentSection.m_filters );
+ }
+ }
+ virtual ~SectionTracker();
+
+ virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
+
+ static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
+ SectionTracker* section = CATCH_NULL;
+
+ ITracker& currentTracker = ctx.currentTracker();
+ if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
+ assert( childTracker );
+ assert( childTracker->isSectionTracker() );
+ section = static_cast<SectionTracker*>( childTracker );
+ }
+ else {
+ section = new SectionTracker( nameAndLocation, ctx, &currentTracker );
+ currentTracker.addChild( section );
+ }
+ if( !ctx.completedCycle() )
+ section->tryOpen();
+ return *section;
+ }
+
+ void tryOpen() {
+ if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
+ open();
+ }
+
+ void addInitialFilters( std::vector<std::string> const& filters ) {
+ if( !filters.empty() ) {
+ m_filters.push_back(""); // Root - should never be consulted
+ m_filters.push_back(""); // Test Case - not a section filter
+ std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) );
+ }
+ }
+ void addNextFilters( std::vector<std::string> const& filters ) {
+ if( filters.size() > 1 )
+ std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) );
+ }
+ };
+
+ class IndexTracker : public TrackerBase {
+ int m_size;
+ int m_index;
+ public:
+ IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
+ : TrackerBase( nameAndLocation, ctx, parent ),
+ m_size( size ),
+ m_index( -1 )
+ {}
+ virtual ~IndexTracker();
+
+ virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
+
+ static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
+ IndexTracker* tracker = CATCH_NULL;
+
+ ITracker& currentTracker = ctx.currentTracker();
+ if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
+ assert( childTracker );
+ assert( childTracker->isIndexTracker() );
+ tracker = static_cast<IndexTracker*>( childTracker );
+ }
+ else {
+ tracker = new IndexTracker( nameAndLocation, ctx, &currentTracker, size );
+ currentTracker.addChild( tracker );
+ }
+
+ if( !ctx.completedCycle() && !tracker->isComplete() ) {
+ if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
+ tracker->moveNext();
+ tracker->open();
+ }
+
+ return *tracker;
+ }
+
+ int index() const { return m_index; }
+
+ void moveNext() {
+ m_index++;
+ m_children.clear();
+ }
+
+ virtual void close() CATCH_OVERRIDE {
+ TrackerBase::close();
+ if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
+ m_runState = Executing;
+ }
+ };
+
+ inline ITracker& TrackerContext::startRun() {
+ m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
+ m_currentTracker = CATCH_NULL;
+ m_runState = Executing;
+ return *m_rootTracker;
+ }
+
+} // namespace TestCaseTracking
+
+using TestCaseTracking::ITracker;
+using TestCaseTracking::TrackerContext;
+using TestCaseTracking::SectionTracker;
+using TestCaseTracking::IndexTracker;
+
+} // namespace Catch
+
+// #included from: catch_fatal_condition.hpp
+#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
+
+namespace Catch {
+
+ // Report the error condition
+ inline void reportFatal( std::string const& message ) {
+ IContext& context = Catch::getCurrentContext();
+ IResultCapture* resultCapture = context.getResultCapture();
+ resultCapture->handleFatalErrorCondition( message );
+ }
+
+} // namespace Catch
+
+#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
+// #included from: catch_windows_h_proxy.h
+
+#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
+
+#ifdef CATCH_DEFINES_NOMINMAX
+# define NOMINMAX
+#endif
+#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifdef __AFXDLL
+#include <AfxWin.h>
+#else
+#include <windows.h>
+#endif
+
+#ifdef CATCH_DEFINES_NOMINMAX
+# undef NOMINMAX
+#endif
+#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
+# undef WIN32_LEAN_AND_MEAN
+#endif
+
+
+# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
+
+namespace Catch {
+ struct FatalConditionHandler {
+ void reset() {}
+ };
+}
+
+# else // CATCH_CONFIG_WINDOWS_SEH is defined
+
+namespace Catch {
+
+ struct SignalDefs { DWORD id; const char* name; };
+ extern SignalDefs signalDefs[];
+ // There is no 1-1 mapping between signals and windows exceptions.
+ // Windows can easily distinguish between SO and SigSegV,
+ // but SigInt, SigTerm, etc are handled differently.
+ SignalDefs signalDefs[] = {
+ { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
+ { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
+ { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
+ { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
+ };
+
+ struct FatalConditionHandler {
+
+ static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
+ for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
+ if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
+ reset();
+ reportFatal(signalDefs[i].name);
+ }
+ }
+ // If its not an exception we care about, pass it along.
+ // This stops us from eating debugger breaks etc.
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ FatalConditionHandler() {
+ isSet = true;
+ // 32k seems enough for Catch to handle stack overflow,
+ // but the value was found experimentally, so there is no strong guarantee
+ guaranteeSize = 32 * 1024;
+ exceptionHandlerHandle = CATCH_NULL;
+ // Register as first handler in current chain
+ exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
+ // Pass in guarantee size to be filled
+ SetThreadStackGuarantee(&guaranteeSize);
+ }
+
+ static void reset() {
+ if (isSet) {
+ // Unregister handler and restore the old guarantee
+ RemoveVectoredExceptionHandler(exceptionHandlerHandle);
+ SetThreadStackGuarantee(&guaranteeSize);
+ exceptionHandlerHandle = CATCH_NULL;
+ isSet = false;
+ }
+ }
+
+ ~FatalConditionHandler() {
+ reset();
+ }
+ private:
+ static bool isSet;
+ static ULONG guaranteeSize;
+ static PVOID exceptionHandlerHandle;
+ };
+
+ bool FatalConditionHandler::isSet = false;
+ ULONG FatalConditionHandler::guaranteeSize = 0;
+ PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
+
+} // namespace Catch
+
+# endif // CATCH_CONFIG_WINDOWS_SEH
+
+#else // Not Windows - assumed to be POSIX compatible //////////////////////////
+
+# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
+
+namespace Catch {
+ struct FatalConditionHandler {
+ void reset() {}
+ };
+}
+
+# else // CATCH_CONFIG_POSIX_SIGNALS is defined
+
+#include <signal.h>
+
+namespace Catch {
+
+ struct SignalDefs {
+ int id;
+ const char* name;
+ };
+ extern SignalDefs signalDefs[];
+ SignalDefs signalDefs[] = {
+ { SIGINT, "SIGINT - Terminal interrupt signal" },
+ { SIGILL, "SIGILL - Illegal instruction signal" },
+ { SIGFPE, "SIGFPE - Floating point error signal" },
+ { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
+ { SIGTERM, "SIGTERM - Termination request signal" },
+ { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
+ };
+
+ struct FatalConditionHandler {
+
+ static bool isSet;
+ static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
+ static stack_t oldSigStack;
+ static char altStackMem[SIGSTKSZ];
+
+ static void handleSignal( int sig ) {
+ std::string name = "<unknown signal>";
+ for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
+ SignalDefs &def = signalDefs[i];
+ if (sig == def.id) {
+ name = def.name;
+ break;
+ }
+ }
+ reset();
+ reportFatal(name);
+ raise( sig );
+ }
+
+ FatalConditionHandler() {
+ isSet = true;
+ stack_t sigStack;
+ sigStack.ss_sp = altStackMem;
+ sigStack.ss_size = SIGSTKSZ;
+ sigStack.ss_flags = 0;
+ sigaltstack(&sigStack, &oldSigStack);
+ struct sigaction sa = { 0 };
+
+ sa.sa_handler = handleSignal;
+ sa.sa_flags = SA_ONSTACK;
+ for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
+ sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
+ }
+ }
+
+ ~FatalConditionHandler() {
+ reset();
+ }
+ static void reset() {
+ if( isSet ) {
+ // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
+ for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
+ sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
+ }
+ // Return the old stack
+ sigaltstack(&oldSigStack, CATCH_NULL);
+ isSet = false;
+ }
+ }
+ };
+
+ bool FatalConditionHandler::isSet = false;
+ struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
+ stack_t FatalConditionHandler::oldSigStack = {};
+ char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
+
+} // namespace Catch
+
+# endif // CATCH_CONFIG_POSIX_SIGNALS
+
+#endif // not Windows
+
+#include <set>
+#include <string>
+
+namespace Catch {
+
+ class StreamRedirect {
+
+ public:
+ StreamRedirect( std::ostream& stream, std::string& targetString )
+ : m_stream( stream ),
+ m_prevBuf( stream.rdbuf() ),
+ m_targetString( targetString )
+ {
+ stream.rdbuf( m_oss.rdbuf() );
+ }
+
+ ~StreamRedirect() {
+ m_targetString += m_oss.str();
+ m_stream.rdbuf( m_prevBuf );
+ }
+
+ private:
+ std::ostream& m_stream;
+ std::streambuf* m_prevBuf;
+ std::ostringstream m_oss;
+ std::string& m_targetString;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ class RunContext : public IResultCapture, public IRunner {
+
+ RunContext( RunContext const& );
+ void operator =( RunContext const& );
+
+ public:
+
+ explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
+ : m_runInfo( _config->name() ),
+ m_context( getCurrentMutableContext() ),
+ m_activeTestCase( CATCH_NULL ),
+ m_config( _config ),
+ m_reporter( reporter )
+ {
+ m_context.setRunner( this );
+ m_context.setConfig( m_config );
+ m_context.setResultCapture( this );
+ m_reporter->testRunStarting( m_runInfo );
+ }
+
+ virtual ~RunContext() {
+ m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
+ }
+
+ void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
+ m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
+ }
+ void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
+ m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
+ }
+
+ Totals runTest( TestCase const& testCase ) {
+ Totals prevTotals = m_totals;
+
+ std::string redirectedCout;
+ std::string redirectedCerr;
+
+ TestCaseInfo testInfo = testCase.getTestCaseInfo();
+
+ m_reporter->testCaseStarting( testInfo );
+
+ m_activeTestCase = &testCase;
+
+ do {
+ ITracker& rootTracker = m_trackerContext.startRun();
+ assert( rootTracker.isSectionTracker() );
+ static_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
+ do {
+ m_trackerContext.startCycle();
+ m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
+ runCurrentTest( redirectedCout, redirectedCerr );
+ }
+ while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
+ }
+ // !TBD: deprecated - this will be replaced by indexed trackers
+ while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
+
+ Totals deltaTotals = m_totals.delta( prevTotals );
+ if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
+ deltaTotals.assertions.failed++;
+ deltaTotals.testCases.passed--;
+ deltaTotals.testCases.failed++;
+ }
+ m_totals.testCases += deltaTotals.testCases;
+ m_reporter->testCaseEnded( TestCaseStats( testInfo,
+ deltaTotals,
+ redirectedCout,
+ redirectedCerr,
+ aborting() ) );
+
+ m_activeTestCase = CATCH_NULL;
+ m_testCaseTracker = CATCH_NULL;
+
+ return deltaTotals;
+ }
+
+ Ptr<IConfig const> config() const {
+ return m_config;
+ }
+
+ private: // IResultCapture
+
+ virtual void assertionEnded( AssertionResult const& result ) {
+ if( result.getResultType() == ResultWas::Ok ) {
+ m_totals.assertions.passed++;
+ }
+ else if( !result.isOk() ) {
+ m_totals.assertions.failed++;
+ }
+
+ if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
+ m_messages.clear();
+
+ // Reset working state
+ m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
+ m_lastResult = result;
+ }
+
+ virtual bool sectionStarted (
+ SectionInfo const& sectionInfo,
+ Counts& assertions
+ )
+ {
+ ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
+ if( !sectionTracker.isOpen() )
+ return false;
+ m_activeSections.push_back( &sectionTracker );
+
+ m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
+
+ m_reporter->sectionStarting( sectionInfo );
+
+ assertions = m_totals.assertions;
+
+ return true;
+ }
+ bool testForMissingAssertions( Counts& assertions ) {
+ if( assertions.total() != 0 )
+ return false;
+ if( !m_config->warnAboutMissingAssertions() )
+ return false;
+ if( m_trackerContext.currentTracker().hasChildren() )
+ return false;
+ m_totals.assertions.failed++;
+ assertions.failed++;
+ return true;
+ }
+
+ virtual void sectionEnded( SectionEndInfo const& endInfo ) {
+ Counts assertions = m_totals.assertions - endInfo.prevAssertions;
+ bool missingAssertions = testForMissingAssertions( assertions );
+
+ if( !m_activeSections.empty() ) {
+ m_activeSections.back()->close();
+ m_activeSections.pop_back();
+ }
+
+ m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
+ m_messages.clear();
+ }
+
+ virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
+ if( m_unfinishedSections.empty() )
+ m_activeSections.back()->fail();
+ else
+ m_activeSections.back()->close();
+ m_activeSections.pop_back();
+
+ m_unfinishedSections.push_back( endInfo );
+ }
+
+ virtual void pushScopedMessage( MessageInfo const& message ) {
+ m_messages.push_back( message );
+ }
+
+ virtual void popScopedMessage( MessageInfo const& message ) {
+ m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
+ }
+
+ virtual std::string getCurrentTestName() const {
+ return m_activeTestCase
+ ? m_activeTestCase->getTestCaseInfo().name
+ : std::string();
+ }
+
+ virtual const AssertionResult* getLastResult() const {
+ return &m_lastResult;
+ }
+
+ virtual void handleFatalErrorCondition( std::string const& message ) {
+ ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
+ resultBuilder.setResultType( ResultWas::FatalErrorCondition );
+ resultBuilder << message;
+ resultBuilder.captureExpression();
+
+ handleUnfinishedSections();
+
+ // Recreate section for test case (as we will lose the one that was in scope)
+ TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
+ SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
+
+ Counts assertions;
+ assertions.failed = 1;
+ SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
+ m_reporter->sectionEnded( testCaseSectionStats );
+
+ TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
+
+ Totals deltaTotals;
+ deltaTotals.testCases.failed = 1;
+ m_reporter->testCaseEnded( TestCaseStats( testInfo,
+ deltaTotals,
+ std::string(),
+ std::string(),
+ false ) );
+ m_totals.testCases.failed++;
+ testGroupEnded( std::string(), m_totals, 1, 1 );
+ m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
+ }
+
+ public:
+ // !TBD We need to do this another way!
+ bool aborting() const {
+ return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
+ }
+
+ private:
+
+ void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
+ TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
+ SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
+ m_reporter->sectionStarting( testCaseSection );
+ Counts prevAssertions = m_totals.assertions;
+ double duration = 0;
+ try {
+ m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
+
+ seedRng( *m_config );
+
+ Timer timer;
+ timer.start();
+ if( m_reporter->getPreferences().shouldRedirectStdOut ) {
+ StreamRedirect coutRedir( Catch::cout(), redirectedCout );
+ StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
+ invokeActiveTestCase();
+ }
+ else {
+ invokeActiveTestCase();
+ }
+ duration = timer.getElapsedSeconds();
+ }
+ catch( TestFailureException& ) {
+ // This just means the test was aborted due to failure
+ }
+ catch(...) {
+ makeUnexpectedResultBuilder().useActiveException();
+ }
+ m_testCaseTracker->close();
+ handleUnfinishedSections();
+ m_messages.clear();
+
+ Counts assertions = m_totals.assertions - prevAssertions;
+ bool missingAssertions = testForMissingAssertions( assertions );
+
+ if( testCaseInfo.okToFail() ) {
+ std::swap( assertions.failedButOk, assertions.failed );
+ m_totals.assertions.failed -= assertions.failedButOk;
+ m_totals.assertions.failedButOk += assertions.failedButOk;
+ }
+
+ SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
+ m_reporter->sectionEnded( testCaseSectionStats );
+ }
+
+ void invokeActiveTestCase() {
+ FatalConditionHandler fatalConditionHandler; // Handle signals
+ m_activeTestCase->invoke();
+ fatalConditionHandler.reset();
+ }
+
+ private:
+
+ ResultBuilder makeUnexpectedResultBuilder() const {
+ return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
+ m_lastAssertionInfo.lineInfo,
+ m_lastAssertionInfo.capturedExpression.c_str(),
+ m_lastAssertionInfo.resultDisposition );
+ }
+
+ void handleUnfinishedSections() {
+ // If sections ended prematurely due to an exception we stored their
+ // infos here so we can tear them down outside the unwind process.
+ for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
+ itEnd = m_unfinishedSections.rend();
+ it != itEnd;
+ ++it )
+ sectionEnded( *it );
+ m_unfinishedSections.clear();
+ }
+
+ TestRunInfo m_runInfo;
+ IMutableContext& m_context;
+ TestCase const* m_activeTestCase;
+ ITracker* m_testCaseTracker;
+ ITracker* m_currentSectionTracker;
+ AssertionResult m_lastResult;
+
+ Ptr<IConfig const> m_config;
+ Totals m_totals;
+ Ptr<IStreamingReporter> m_reporter;
+ std::vector<MessageInfo> m_messages;
+ AssertionInfo m_lastAssertionInfo;
+ std::vector<SectionEndInfo> m_unfinishedSections;
+ std::vector<ITracker*> m_activeSections;
+ TrackerContext m_trackerContext;
+ };
+
+ IResultCapture& getResultCapture() {
+ if( IResultCapture* capture = getCurrentContext().getResultCapture() )
+ return *capture;
+ else
+ throw std::logic_error( "No result capture instance" );
+ }
+
+} // end namespace Catch
+
+// #included from: internal/catch_version.h
+#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
+
+namespace Catch {
+
+ // Versioning information
+ struct Version {
+ Version( unsigned int _majorVersion,
+ unsigned int _minorVersion,
+ unsigned int _patchNumber,
+ std::string const& _branchName,
+ unsigned int _buildNumber );
+
+ unsigned int const majorVersion;
+ unsigned int const minorVersion;
+ unsigned int const patchNumber;
+
+ // buildNumber is only used if branchName is not null
+ std::string const branchName;
+ unsigned int const buildNumber;
+
+ friend std::ostream& operator << ( std::ostream& os, Version const& version );
+
+ private:
+ void operator=( Version const& );
+ };
+
+ extern Version libraryVersion;
+}
+
+#include <fstream>
+#include <stdlib.h>
+#include <limits>
+
+namespace Catch {
+
+ Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
+ Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
+ if( !reporter ) {
+ std::ostringstream oss;
+ oss << "No reporter registered with name: '" << reporterName << "'";
+ throw std::domain_error( oss.str() );
+ }
+ return reporter;
+ }
+
+ Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
+ std::vector<std::string> reporters = config->getReporterNames();
+ if( reporters.empty() )
+ reporters.push_back( "console" );
+
+ Ptr<IStreamingReporter> reporter;
+ for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
+ it != itEnd;
+ ++it )
+ reporter = addReporter( reporter, createReporter( *it, config ) );
+ return reporter;
+ }
+ Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
+ IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
+ for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
+ it != itEnd;
+ ++it )
+ reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
+ return reporters;
+ }
+
+ Totals runTests( Ptr<Config> const& config ) {
+
+ Ptr<IConfig const> iconfig = config.get();
+
+ Ptr<IStreamingReporter> reporter = makeReporter( config );
+ reporter = addListeners( iconfig, reporter );
+
+ RunContext context( iconfig, reporter );
+
+ Totals totals;
+
+ context.testGroupStarting( config->name(), 1, 1 );
+
+ TestSpec testSpec = config->testSpec();
+ if( !testSpec.hasFilters() )
+ testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
+
+ std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
+ for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
+ it != itEnd;
+ ++it ) {
+ if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
+ totals += context.runTest( *it );
+ else
+ reporter->skipTest( *it );
+ }
+
+ context.testGroupEnded( iconfig->name(), totals, 1, 1 );
+ return totals;
+ }
+
+ void applyFilenamesAsTags( IConfig const& config ) {
+ std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
+ for(std::size_t i = 0; i < tests.size(); ++i ) {
+ TestCase& test = const_cast<TestCase&>( tests[i] );
+ std::set<std::string> tags = test.tags;
+
+ std::string filename = test.lineInfo.file;
+ std::string::size_type lastSlash = filename.find_last_of( "\\/" );
+ if( lastSlash != std::string::npos )
+ filename = filename.substr( lastSlash+1 );
+
+ std::string::size_type lastDot = filename.find_last_of( "." );
+ if( lastDot != std::string::npos )
+ filename = filename.substr( 0, lastDot );
+
+ tags.insert( "#" + filename );
+ setTags( test, tags );
+ }
+ }
+
+ class Session : NonCopyable {
+ static bool alreadyInstantiated;
+
+ public:
+
+ struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
+
+ Session()
+ : m_cli( makeCommandLineParser() ) {
+ if( alreadyInstantiated ) {
+ std::string msg = "Only one instance of Catch::Session can ever be used";
+ Catch::cerr() << msg << std::endl;
+ throw std::logic_error( msg );
+ }
+ alreadyInstantiated = true;
+ }
+ ~Session() {
+ Catch::cleanUp();
+ }
+
+ void showHelp( std::string const& processName ) {
+ Catch::cout() << "\nCatch v" << libraryVersion << "\n";
+
+ m_cli.usage( Catch::cout(), processName );
+ Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
+ }
+
+ int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
+ try {
+ m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
+ m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
+ if( m_configData.showHelp )
+ showHelp( m_configData.processName );
+ m_config.reset();
+ }
+ catch( std::exception& ex ) {
+ {
+ Colour colourGuard( Colour::Red );
+ Catch::cerr()
+ << "\nError(s) in input:\n"
+ << Text( ex.what(), TextAttributes().setIndent(2) )
+ << "\n\n";
+ }
+ m_cli.usage( Catch::cout(), m_configData.processName );
+ return (std::numeric_limits<int>::max)();
+ }
+ return 0;
+ }
+
+ void useConfigData( ConfigData const& _configData ) {
+ m_configData = _configData;
+ m_config.reset();
+ }
+
+ int run( int argc, char const* const* const argv ) {
+
+ int returnCode = applyCommandLine( argc, argv );
+ if( returnCode == 0 )
+ returnCode = run();
+ return returnCode;
+ }
+
+ int run() {
+ if( m_configData.showHelp )
+ return 0;
+
+ try
+ {
+ config(); // Force config to be constructed
+
+ seedRng( *m_config );
+
+ if( m_configData.filenamesAsTags )
+ applyFilenamesAsTags( *m_config );
+
+ // Handle list request
+ if( Option<std::size_t> listed = list( config() ) )
+ return static_cast<int>( *listed );
+
+ return static_cast<int>( runTests( m_config ).assertions.failed );
+ }
+ catch( std::exception& ex ) {
+ Catch::cerr() << ex.what() << std::endl;
+ return (std::numeric_limits<int>::max)();
+ }
+ }
+
+ Clara::CommandLine<ConfigData> const& cli() const {
+ return m_cli;
+ }
+ std::vector<Clara::Parser::Token> const& unusedTokens() const {
+ return m_unusedTokens;
+ }
+ ConfigData& configData() {
+ return m_configData;
+ }
+ Config& config() {
+ if( !m_config )
+ m_config = new Config( m_configData );
+ return *m_config;
+ }
+ private:
+ Clara::CommandLine<ConfigData> m_cli;
+ std::vector<Clara::Parser::Token> m_unusedTokens;
+ ConfigData m_configData;
+ Ptr<Config> m_config;
+ };
+
+ bool Session::alreadyInstantiated = false;
+
+} // end namespace Catch
+
+// #included from: catch_registry_hub.hpp
+#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
+
+// #included from: catch_test_case_registry_impl.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
+
+#include <vector>
+#include <set>
+#include <sstream>
+#include <algorithm>
+
+namespace Catch {
+
+ struct RandomNumberGenerator {
+ typedef std::ptrdiff_t result_type;
+
+ result_type operator()( result_type n ) const { return std::rand() % n; }
+
+#ifdef CATCH_CONFIG_CPP11_SHUFFLE
+ static constexpr result_type min() { return 0; }
+ static constexpr result_type max() { return 1000000; }
+ result_type operator()() const { return std::rand() % max(); }
+#endif
+ template<typename V>
+ static void shuffle( V& vector ) {
+ RandomNumberGenerator rng;
+#ifdef CATCH_CONFIG_CPP11_SHUFFLE
+ std::shuffle( vector.begin(), vector.end(), rng );
+#else
+ std::random_shuffle( vector.begin(), vector.end(), rng );
+#endif
+ }
+ };
+
+ inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
+
+ std::vector<TestCase> sorted = unsortedTestCases;
+
+ switch( config.runOrder() ) {
+ case RunTests::InLexicographicalOrder:
+ std::sort( sorted.begin(), sorted.end() );
+ break;
+ case RunTests::InRandomOrder:
+ {
+ seedRng( config );
+ RandomNumberGenerator::shuffle( sorted );
+ }
+ break;
+ case RunTests::InDeclarationOrder:
+ // already in declaration order
+ break;
+ }
+ return sorted;
+ }
+ bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
+ return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
+ }
+
+ void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
+ std::set<TestCase> seenFunctions;
+ for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
+ it != itEnd;
+ ++it ) {
+ std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
+ if( !prev.second ) {
+ std::ostringstream ss;
+
+ ss << Colour( Colour::Red )
+ << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
+ << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
+ << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
+
+ throw std::runtime_error(ss.str());
+ }
+ }
+ }
+
+ std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
+ std::vector<TestCase> filtered;
+ filtered.reserve( testCases.size() );
+ for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
+ it != itEnd;
+ ++it )
+ if( matchTest( *it, testSpec, config ) )
+ filtered.push_back( *it );
+ return filtered;
+ }
+ std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
+ return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
+ }
+
+ class TestRegistry : public ITestCaseRegistry {
+ public:
+ TestRegistry()
+ : m_currentSortOrder( RunTests::InDeclarationOrder ),
+ m_unnamedCount( 0 )
+ {}
+ virtual ~TestRegistry();
+
+ virtual void registerTest( TestCase const& testCase ) {
+ std::string name = testCase.getTestCaseInfo().name;
+ if( name.empty() ) {
+ std::ostringstream oss;
+ oss << "Anonymous test case " << ++m_unnamedCount;
+ return registerTest( testCase.withName( oss.str() ) );
+ }
+ m_functions.push_back( testCase );
+ }
+
+ virtual std::vector<TestCase> const& getAllTests() const {
+ return m_functions;
+ }
+ virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
+ if( m_sortedFunctions.empty() )
+ enforceNoDuplicateTestCases( m_functions );
+
+ if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
+ m_sortedFunctions = sortTests( config, m_functions );
+ m_currentSortOrder = config.runOrder();
+ }
+ return m_sortedFunctions;
+ }
+
+ private:
+ std::vector<TestCase> m_functions;
+ mutable RunTests::InWhatOrder m_currentSortOrder;
+ mutable std::vector<TestCase> m_sortedFunctions;
+ size_t m_unnamedCount;
+ std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ class FreeFunctionTestCase : public SharedImpl<ITestCase> {
+ public:
+
+ FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
+
+ virtual void invoke() const {
+ m_fun();
+ }
+
+ private:
+ virtual ~FreeFunctionTestCase();
+
+ TestFunction m_fun;
+ };
+
+ inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
+ std::string className = classOrQualifiedMethodName;
+ if( startsWith( className, '&' ) )
+ {
+ std::size_t lastColons = className.rfind( "::" );
+ std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
+ if( penultimateColons == std::string::npos )
+ penultimateColons = 1;
+ className = className.substr( penultimateColons, lastColons-penultimateColons );
+ }
+ return className;
+ }
+
+ void registerTestCase
+ ( ITestCase* testCase,
+ char const* classOrQualifiedMethodName,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo ) {
+
+ getMutableRegistryHub().registerTest
+ ( makeTestCase
+ ( testCase,
+ extractClassName( classOrQualifiedMethodName ),
+ nameAndDesc.name,
+ nameAndDesc.description,
+ lineInfo ) );
+ }
+ void registerTestCaseFunction
+ ( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc ) {
+ registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ AutoReg::AutoReg
+ ( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc ) {
+ registerTestCaseFunction( function, lineInfo, nameAndDesc );
+ }
+
+ AutoReg::~AutoReg() {}
+
+} // end namespace Catch
+
+// #included from: catch_reporter_registry.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
+
+#include <map>
+
+namespace Catch {
+
+ class ReporterRegistry : public IReporterRegistry {
+
+ public:
+
+ virtual ~ReporterRegistry() CATCH_OVERRIDE {}
+
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
+ FactoryMap::const_iterator it = m_factories.find( name );
+ if( it == m_factories.end() )
+ return CATCH_NULL;
+ return it->second->create( ReporterConfig( config ) );
+ }
+
+ void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
+ m_factories.insert( std::make_pair( name, factory ) );
+ }
+ void registerListener( Ptr<IReporterFactory> const& factory ) {
+ m_listeners.push_back( factory );
+ }
+
+ virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
+ return m_factories;
+ }
+ virtual Listeners const& getListeners() const CATCH_OVERRIDE {
+ return m_listeners;
+ }
+
+ private:
+ FactoryMap m_factories;
+ Listeners m_listeners;
+ };
+}
+
+// #included from: catch_exception_translator_registry.hpp
+#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
+
+#ifdef __OBJC__
+#import "Foundation/Foundation.h"
+#endif
+
+namespace Catch {
+
+ class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
+ public:
+ ~ExceptionTranslatorRegistry() {
+ deleteAll( m_translators );
+ }
+
+ virtual void registerTranslator( const IExceptionTranslator* translator ) {
+ m_translators.push_back( translator );
+ }
+
+ virtual std::string translateActiveException() const {
+ try {
+#ifdef __OBJC__
+ // In Objective-C try objective-c exceptions first
+ @try {
+ return tryTranslators();
+ }
+ @catch (NSException *exception) {
+ return Catch::toString( [exception description] );
+ }
+#else
+ return tryTranslators();
+#endif
+ }
+ catch( TestFailureException& ) {
+ throw;
+ }
+ catch( std::exception& ex ) {
+ return ex.what();
+ }
+ catch( std::string& msg ) {
+ return msg;
+ }
+ catch( const char* msg ) {
+ return msg;
+ }
+ catch(...) {
+ return "Unknown exception";
+ }
+ }
+
+ std::string tryTranslators() const {
+ if( m_translators.empty() )
+ throw;
+ else
+ return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
+ }
+
+ private:
+ std::vector<const IExceptionTranslator*> m_translators;
+ };
+}
+
+namespace Catch {
+
+ namespace {
+
+ class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
+
+ RegistryHub( RegistryHub const& );
+ void operator=( RegistryHub const& );
+
+ public: // IRegistryHub
+ RegistryHub() {
+ }
+ virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
+ return m_reporterRegistry;
+ }
+ virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
+ return m_testCaseRegistry;
+ }
+ virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
+ return m_exceptionTranslatorRegistry;
+ }
+
+ public: // IMutableRegistryHub
+ virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
+ m_reporterRegistry.registerReporter( name, factory );
+ }
+ virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
+ m_reporterRegistry.registerListener( factory );
+ }
+ virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
+ m_testCaseRegistry.registerTest( testInfo );
+ }
+ virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
+ m_exceptionTranslatorRegistry.registerTranslator( translator );
+ }
+
+ private:
+ TestRegistry m_testCaseRegistry;
+ ReporterRegistry m_reporterRegistry;
+ ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
+ };
+
+ // Single, global, instance
+ inline RegistryHub*& getTheRegistryHub() {
+ static RegistryHub* theRegistryHub = CATCH_NULL;
+ if( !theRegistryHub )
+ theRegistryHub = new RegistryHub();
+ return theRegistryHub;
+ }
+ }
+
+ IRegistryHub& getRegistryHub() {
+ return *getTheRegistryHub();
+ }
+ IMutableRegistryHub& getMutableRegistryHub() {
+ return *getTheRegistryHub();
+ }
+ void cleanUp() {
+ delete getTheRegistryHub();
+ getTheRegistryHub() = CATCH_NULL;
+ cleanUpContext();
+ }
+ std::string translateActiveException() {
+ return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
+ }
+
+} // end namespace Catch
+
+// #included from: catch_notimplemented_exception.hpp
+#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
+
+#include <sstream>
+
+namespace Catch {
+
+ NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
+ : m_lineInfo( lineInfo ) {
+ std::ostringstream oss;
+ oss << lineInfo << ": function ";
+ oss << "not implemented";
+ m_what = oss.str();
+ }
+
+ const char* NotImplementedException::what() const CATCH_NOEXCEPT {
+ return m_what.c_str();
+ }
+
+} // end namespace Catch
+
+// #included from: catch_context_impl.hpp
+#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
+
+// #included from: catch_stream.hpp
+#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
+
+#include <stdexcept>
+#include <cstdio>
+#include <iostream>
+
+namespace Catch {
+
+ template<typename WriterF, size_t bufferSize=256>
+ class StreamBufImpl : public StreamBufBase {
+ char data[bufferSize];
+ WriterF m_writer;
+
+ public:
+ StreamBufImpl() {
+ setp( data, data + sizeof(data) );
+ }
+
+ ~StreamBufImpl() CATCH_NOEXCEPT {
+ sync();
+ }
+
+ private:
+ int overflow( int c ) {
+ sync();
+
+ if( c != EOF ) {
+ if( pbase() == epptr() )
+ m_writer( std::string( 1, static_cast<char>( c ) ) );
+ else
+ sputc( static_cast<char>( c ) );
+ }
+ return 0;
+ }
+
+ int sync() {
+ if( pbase() != pptr() ) {
+ m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
+ setp( pbase(), epptr() );
+ }
+ return 0;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ FileStream::FileStream( std::string const& filename ) {
+ m_ofs.open( filename.c_str() );
+ if( m_ofs.fail() ) {
+ std::ostringstream oss;
+ oss << "Unable to open file: '" << filename << '\'';
+ throw std::domain_error( oss.str() );
+ }
+ }
+
+ std::ostream& FileStream::stream() const {
+ return m_ofs;
+ }
+
+ struct OutputDebugWriter {
+
+ void operator()( std::string const&str ) {
+ writeToDebugConsole( str );
+ }
+ };
+
+ DebugOutStream::DebugOutStream()
+ : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
+ m_os( m_streamBuf.get() )
+ {}
+
+ std::ostream& DebugOutStream::stream() const {
+ return m_os;
+ }
+
+ // Store the streambuf from cout up-front because
+ // cout may get redirected when running tests
+ CoutStream::CoutStream()
+ : m_os( Catch::cout().rdbuf() )
+ {}
+
+ std::ostream& CoutStream::stream() const {
+ return m_os;
+ }
+
+#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
+ std::ostream& cout() {
+ return std::cout;
+ }
+ std::ostream& cerr() {
+ return std::cerr;
+ }
+#endif
+}
+
+namespace Catch {
+
+ class Context : public IMutableContext {
+
+ Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
+ Context( Context const& );
+ void operator=( Context const& );
+
+ public:
+ virtual ~Context() {
+ deleteAllValues( m_generatorsByTestName );
+ }
+
+ public: // IContext
+ virtual IResultCapture* getResultCapture() {
+ return m_resultCapture;
+ }
+ virtual IRunner* getRunner() {
+ return m_runner;
+ }
+ virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
+ return getGeneratorsForCurrentTest()
+ .getGeneratorInfo( fileInfo, totalSize )
+ .getCurrentIndex();
+ }
+ virtual bool advanceGeneratorsForCurrentTest() {
+ IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
+ return generators && generators->moveNext();
+ }
+
+ virtual Ptr<IConfig const> getConfig() const {
+ return m_config;
+ }
+
+ public: // IMutableContext
+ virtual void setResultCapture( IResultCapture* resultCapture ) {
+ m_resultCapture = resultCapture;
+ }
+ virtual void setRunner( IRunner* runner ) {
+ m_runner = runner;
+ }
+ virtual void setConfig( Ptr<IConfig const> const& config ) {
+ m_config = config;
+ }
+
+ friend IMutableContext& getCurrentMutableContext();
+
+ private:
+ IGeneratorsForTest* findGeneratorsForCurrentTest() {
+ std::string testName = getResultCapture()->getCurrentTestName();
+
+ std::map<std::string, IGeneratorsForTest*>::const_iterator it =
+ m_generatorsByTestName.find( testName );
+ return it != m_generatorsByTestName.end()
+ ? it->second
+ : CATCH_NULL;
+ }
+
+ IGeneratorsForTest& getGeneratorsForCurrentTest() {
+ IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
+ if( !generators ) {
+ std::string testName = getResultCapture()->getCurrentTestName();
+ generators = createGeneratorsForTest();
+ m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
+ }
+ return *generators;
+ }
+
+ private:
+ Ptr<IConfig const> m_config;
+ IRunner* m_runner;
+ IResultCapture* m_resultCapture;
+ std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
+ };
+
+ namespace {
+ Context* currentContext = CATCH_NULL;
+ }
+ IMutableContext& getCurrentMutableContext() {
+ if( !currentContext )
+ currentContext = new Context();
+ return *currentContext;
+ }
+ IContext& getCurrentContext() {
+ return getCurrentMutableContext();
+ }
+
+ void cleanUpContext() {
+ delete currentContext;
+ currentContext = CATCH_NULL;
+ }
+}
+
+// #included from: catch_console_colour_impl.hpp
+#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
+
+namespace Catch {
+ namespace {
+
+ struct IColourImpl {
+ virtual ~IColourImpl() {}
+ virtual void use( Colour::Code _colourCode ) = 0;
+ };
+
+ struct NoColourImpl : IColourImpl {
+ void use( Colour::Code ) {}
+
+ static IColourImpl* instance() {
+ static NoColourImpl s_instance;
+ return &s_instance;
+ }
+ };
+
+ } // anon namespace
+} // namespace Catch
+
+#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
+# ifdef CATCH_PLATFORM_WINDOWS
+# define CATCH_CONFIG_COLOUR_WINDOWS
+# else
+# define CATCH_CONFIG_COLOUR_ANSI
+# endif
+#endif
+
+#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
+
+namespace Catch {
+namespace {
+
+ class Win32ColourImpl : public IColourImpl {
+ public:
+ Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
+ {
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+ GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
+ originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
+ originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
+ }
+
+ virtual void use( Colour::Code _colourCode ) {
+ switch( _colourCode ) {
+ case Colour::None: return setTextAttribute( originalForegroundAttributes );
+ case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
+ case Colour::Red: return setTextAttribute( FOREGROUND_RED );
+ case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
+ case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
+ case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
+ case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
+ case Colour::Grey: return setTextAttribute( 0 );
+
+ case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
+ case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
+ case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
+ case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
+
+ case Colour::Bright: throw std::logic_error( "not a colour" );
+ }
+ }
+
+ private:
+ void setTextAttribute( WORD _textAttribute ) {
+ SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
+ }
+ HANDLE stdoutHandle;
+ WORD originalForegroundAttributes;
+ WORD originalBackgroundAttributes;
+ };
+
+ IColourImpl* platformColourInstance() {
+ static Win32ColourImpl s_instance;
+
+ Ptr<IConfig const> config = getCurrentContext().getConfig();
+ UseColour::YesOrNo colourMode = config
+ ? config->useColour()
+ : UseColour::Auto;
+ if( colourMode == UseColour::Auto )
+ colourMode = !isDebuggerActive()
+ ? UseColour::Yes
+ : UseColour::No;
+ return colourMode == UseColour::Yes
+ ? &s_instance
+ : NoColourImpl::instance();
+ }
+
+} // end anon namespace
+} // end namespace Catch
+
+#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
+
+#include <unistd.h>
+
+namespace Catch {
+namespace {
+
+ // use POSIX/ ANSI console terminal codes
+ // Thanks to Adam Strzelecki for original contribution
+ // (http://github.com/nanoant)
+ // https://github.com/philsquared/Catch/pull/131
+ class PosixColourImpl : public IColourImpl {
+ public:
+ virtual void use( Colour::Code _colourCode ) {
+ switch( _colourCode ) {
+ case Colour::None:
+ case Colour::White: return setColour( "[0m" );
+ case Colour::Red: return setColour( "[0;31m" );
+ case Colour::Green: return setColour( "[0;32m" );
+ case Colour::Blue: return setColour( "[0;34m" );
+ case Colour::Cyan: return setColour( "[0;36m" );
+ case Colour::Yellow: return setColour( "[0;33m" );
+ case Colour::Grey: return setColour( "[1;30m" );
+
+ case Colour::LightGrey: return setColour( "[0;37m" );
+ case Colour::BrightRed: return setColour( "[1;31m" );
+ case Colour::BrightGreen: return setColour( "[1;32m" );
+ case Colour::BrightWhite: return setColour( "[1;37m" );
+
+ case Colour::Bright: throw std::logic_error( "not a colour" );
+ }
+ }
+ static IColourImpl* instance() {
+ static PosixColourImpl s_instance;
+ return &s_instance;
+ }
+
+ private:
+ void setColour( const char* _escapeCode ) {
+ Catch::cout() << '\033' << _escapeCode;
+ }
+ };
+
+ IColourImpl* platformColourInstance() {
+ Ptr<IConfig const> config = getCurrentContext().getConfig();
+ UseColour::YesOrNo colourMode = config
+ ? config->useColour()
+ : UseColour::Auto;
+ if( colourMode == UseColour::Auto )
+ colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
+ ? UseColour::Yes
+ : UseColour::No;
+ return colourMode == UseColour::Yes
+ ? PosixColourImpl::instance()
+ : NoColourImpl::instance();
+ }
+
+} // end anon namespace
+} // end namespace Catch
+
+#else // not Windows or ANSI ///////////////////////////////////////////////
+
+namespace Catch {
+
+ static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
+
+} // end namespace Catch
+
+#endif // Windows/ ANSI/ None
+
+namespace Catch {
+
+ Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
+ Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
+ Colour::~Colour(){ if( !m_moved ) use( None ); }
+
+ void Colour::use( Code _colourCode ) {
+ static IColourImpl* impl = platformColourInstance();
+ impl->use( _colourCode );
+ }
+
+} // end namespace Catch
+
+// #included from: catch_generators_impl.hpp
+#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
+
+#include <vector>
+#include <string>
+#include <map>
+
+namespace Catch {
+
+ struct GeneratorInfo : IGeneratorInfo {
+
+ GeneratorInfo( std::size_t size )
+ : m_size( size ),
+ m_currentIndex( 0 )
+ {}
+
+ bool moveNext() {
+ if( ++m_currentIndex == m_size ) {
+ m_currentIndex = 0;
+ return false;
+ }
+ return true;
+ }
+
+ std::size_t getCurrentIndex() const {
+ return m_currentIndex;
+ }
+
+ std::size_t m_size;
+ std::size_t m_currentIndex;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ class GeneratorsForTest : public IGeneratorsForTest {
+
+ public:
+ ~GeneratorsForTest() {
+ deleteAll( m_generatorsInOrder );
+ }
+
+ IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
+ std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
+ if( it == m_generatorsByName.end() ) {
+ IGeneratorInfo* info = new GeneratorInfo( size );
+ m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
+ m_generatorsInOrder.push_back( info );
+ return *info;
+ }
+ return *it->second;
+ }
+
+ bool moveNext() {
+ std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
+ std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
+ for(; it != itEnd; ++it ) {
+ if( (*it)->moveNext() )
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ std::map<std::string, IGeneratorInfo*> m_generatorsByName;
+ std::vector<IGeneratorInfo*> m_generatorsInOrder;
+ };
+
+ IGeneratorsForTest* createGeneratorsForTest()
+ {
+ return new GeneratorsForTest();
+ }
+
+} // end namespace Catch
+
+// #included from: catch_assertionresult.hpp
+#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
+
+namespace Catch {
+
+ AssertionInfo::AssertionInfo( std::string const& _macroName,
+ SourceLineInfo const& _lineInfo,
+ std::string const& _capturedExpression,
+ ResultDisposition::Flags _resultDisposition )
+ : macroName( _macroName ),
+ lineInfo( _lineInfo ),
+ capturedExpression( _capturedExpression ),
+ resultDisposition( _resultDisposition )
+ {}
+
+ AssertionResult::AssertionResult() {}
+
+ AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
+ : m_info( info ),
+ m_resultData( data )
+ {}
+
+ AssertionResult::~AssertionResult() {}
+
+ // Result was a success
+ bool AssertionResult::succeeded() const {
+ return Catch::isOk( m_resultData.resultType );
+ }
+
+ // Result was a success, or failure is suppressed
+ bool AssertionResult::isOk() const {
+ return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
+ }
+
+ ResultWas::OfType AssertionResult::getResultType() const {
+ return m_resultData.resultType;
+ }
+
+ bool AssertionResult::hasExpression() const {
+ return !m_info.capturedExpression.empty();
+ }
+
+ bool AssertionResult::hasMessage() const {
+ return !m_resultData.message.empty();
+ }
+
+ std::string AssertionResult::getExpression() const {
+ if( isFalseTest( m_info.resultDisposition ) )
+ return '!' + m_info.capturedExpression;
+ else
+ return m_info.capturedExpression;
+ }
+ std::string AssertionResult::getExpressionInMacro() const {
+ if( m_info.macroName.empty() )
+ return m_info.capturedExpression;
+ else
+ return m_info.macroName + "( " + m_info.capturedExpression + " )";
+ }
+
+ bool AssertionResult::hasExpandedExpression() const {
+ return hasExpression() && getExpandedExpression() != getExpression();
+ }
+
+ std::string AssertionResult::getExpandedExpression() const {
+ return m_resultData.reconstructExpression();
+ }
+
+ std::string AssertionResult::getMessage() const {
+ return m_resultData.message;
+ }
+ SourceLineInfo AssertionResult::getSourceInfo() const {
+ return m_info.lineInfo;
+ }
+
+ std::string AssertionResult::getTestMacroName() const {
+ return m_info.macroName;
+ }
+
+ void AssertionResult::discardDecomposedExpression() const {
+ m_resultData.decomposedExpression = CATCH_NULL;
+ }
+
+ void AssertionResult::expandDecomposedExpression() const {
+ m_resultData.reconstructExpression();
+ }
+
+} // end namespace Catch
+
+// #included from: catch_test_case_info.hpp
+#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
+
+#include <cctype>
+
+namespace Catch {
+
+ inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
+ if( startsWith( tag, '.' ) ||
+ tag == "hide" ||
+ tag == "!hide" )
+ return TestCaseInfo::IsHidden;
+ else if( tag == "!throws" )
+ return TestCaseInfo::Throws;
+ else if( tag == "!shouldfail" )
+ return TestCaseInfo::ShouldFail;
+ else if( tag == "!mayfail" )
+ return TestCaseInfo::MayFail;
+ else if( tag == "!nonportable" )
+ return TestCaseInfo::NonPortable;
+ else
+ return TestCaseInfo::None;
+ }
+ inline bool isReservedTag( std::string const& tag ) {
+ return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
+ }
+ inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
+ if( isReservedTag( tag ) ) {
+ {
+ Colour colourGuard( Colour::Red );
+ Catch::cerr()
+ << "Tag name [" << tag << "] not allowed.\n"
+ << "Tag names starting with non alpha-numeric characters are reserved\n";
+ }
+ {
+ Colour colourGuard( Colour::FileName );
+ Catch::cerr() << _lineInfo << std::endl;
+ }
+ exit(1);
+ }
+ }
+
+ TestCase makeTestCase( ITestCase* _testCase,
+ std::string const& _className,
+ std::string const& _name,
+ std::string const& _descOrTags,
+ SourceLineInfo const& _lineInfo )
+ {
+ bool isHidden( startsWith( _name, "./" ) ); // Legacy support
+
+ // Parse out tags
+ std::set<std::string> tags;
+ std::string desc, tag;
+ bool inTag = false;
+ for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
+ char c = _descOrTags[i];
+ if( !inTag ) {
+ if( c == '[' )
+ inTag = true;
+ else
+ desc += c;
+ }
+ else {
+ if( c == ']' ) {
+ TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
+ if( prop == TestCaseInfo::IsHidden )
+ isHidden = true;
+ else if( prop == TestCaseInfo::None )
+ enforceNotReservedTag( tag, _lineInfo );
+
+ tags.insert( tag );
+ tag.clear();
+ inTag = false;
+ }
+ else
+ tag += c;
+ }
+ }
+ if( isHidden ) {
+ tags.insert( "hide" );
+ tags.insert( "." );
+ }
+
+ TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
+ return TestCase( _testCase, info );
+ }
+
+ void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
+ {
+ testCaseInfo.tags = tags;
+ testCaseInfo.lcaseTags.clear();
+
+ std::ostringstream oss;
+ for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
+ oss << '[' << *it << ']';
+ std::string lcaseTag = toLower( *it );
+ testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
+ testCaseInfo.lcaseTags.insert( lcaseTag );
+ }
+ testCaseInfo.tagsAsString = oss.str();
+ }
+
+ TestCaseInfo::TestCaseInfo( std::string const& _name,
+ std::string const& _className,
+ std::string const& _description,
+ std::set<std::string> const& _tags,
+ SourceLineInfo const& _lineInfo )
+ : name( _name ),
+ className( _className ),
+ description( _description ),
+ lineInfo( _lineInfo ),
+ properties( None )
+ {
+ setTags( *this, _tags );
+ }
+
+ TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
+ : name( other.name ),
+ className( other.className ),
+ description( other.description ),
+ tags( other.tags ),
+ lcaseTags( other.lcaseTags ),
+ tagsAsString( other.tagsAsString ),
+ lineInfo( other.lineInfo ),
+ properties( other.properties )
+ {}
+
+ bool TestCaseInfo::isHidden() const {
+ return ( properties & IsHidden ) != 0;
+ }
+ bool TestCaseInfo::throws() const {
+ return ( properties & Throws ) != 0;
+ }
+ bool TestCaseInfo::okToFail() const {
+ return ( properties & (ShouldFail | MayFail ) ) != 0;
+ }
+ bool TestCaseInfo::expectedToFail() const {
+ return ( properties & (ShouldFail ) ) != 0;
+ }
+
+ TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
+
+ TestCase::TestCase( TestCase const& other )
+ : TestCaseInfo( other ),
+ test( other.test )
+ {}
+
+ TestCase TestCase::withName( std::string const& _newName ) const {
+ TestCase other( *this );
+ other.name = _newName;
+ return other;
+ }
+
+ void TestCase::swap( TestCase& other ) {
+ test.swap( other.test );
+ name.swap( other.name );
+ className.swap( other.className );
+ description.swap( other.description );
+ tags.swap( other.tags );
+ lcaseTags.swap( other.lcaseTags );
+ tagsAsString.swap( other.tagsAsString );
+ std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
+ std::swap( lineInfo, other.lineInfo );
+ }
+
+ void TestCase::invoke() const {
+ test->invoke();
+ }
+
+ bool TestCase::operator == ( TestCase const& other ) const {
+ return test.get() == other.test.get() &&
+ name == other.name &&
+ className == other.className;
+ }
+
+ bool TestCase::operator < ( TestCase const& other ) const {
+ return name < other.name;
+ }
+ TestCase& TestCase::operator = ( TestCase const& other ) {
+ TestCase temp( other );
+ swap( temp );
+ return *this;
+ }
+
+ TestCaseInfo const& TestCase::getTestCaseInfo() const
+ {
+ return *this;
+ }
+
+} // end namespace Catch
+
+// #included from: catch_version.hpp
+#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
+
+namespace Catch {
+
+ Version::Version
+ ( unsigned int _majorVersion,
+ unsigned int _minorVersion,
+ unsigned int _patchNumber,
+ std::string const& _branchName,
+ unsigned int _buildNumber )
+ : majorVersion( _majorVersion ),
+ minorVersion( _minorVersion ),
+ patchNumber( _patchNumber ),
+ branchName( _branchName ),
+ buildNumber( _buildNumber )
+ {}
+
+ std::ostream& operator << ( std::ostream& os, Version const& version ) {
+ os << version.majorVersion << '.'
+ << version.minorVersion << '.'
+ << version.patchNumber;
+
+ if( !version.branchName.empty() ) {
+ os << '-' << version.branchName
+ << '.' << version.buildNumber;
+ }
+ return os;
+ }
+
+ Version libraryVersion( 1, 8, 1, "", 0 );
+
+}
+
+// #included from: catch_message.hpp
+#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
+
+namespace Catch {
+
+ MessageInfo::MessageInfo( std::string const& _macroName,
+ SourceLineInfo const& _lineInfo,
+ ResultWas::OfType _type )
+ : macroName( _macroName ),
+ lineInfo( _lineInfo ),
+ type( _type ),
+ sequence( ++globalCount )
+ {}
+
+ // This may need protecting if threading support is added
+ unsigned int MessageInfo::globalCount = 0;
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ ScopedMessage::ScopedMessage( MessageBuilder const& builder )
+ : m_info( builder.m_info )
+ {
+ m_info.message = builder.m_stream.str();
+ getResultCapture().pushScopedMessage( m_info );
+ }
+ ScopedMessage::ScopedMessage( ScopedMessage const& other )
+ : m_info( other.m_info )
+ {}
+
+ ScopedMessage::~ScopedMessage() {
+ getResultCapture().popScopedMessage( m_info );
+ }
+
+} // end namespace Catch
+
+// #included from: catch_legacy_reporter_adapter.hpp
+#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
+
+// #included from: catch_legacy_reporter_adapter.h
+#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
+
+namespace Catch
+{
+ // Deprecated
+ struct IReporter : IShared {
+ virtual ~IReporter();
+
+ virtual bool shouldRedirectStdout() const = 0;
+
+ virtual void StartTesting() = 0;
+ virtual void EndTesting( Totals const& totals ) = 0;
+ virtual void StartGroup( std::string const& groupName ) = 0;
+ virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
+ virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
+ virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
+ virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
+ virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
+ virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
+ virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
+ virtual void Aborted() = 0;
+ virtual void Result( AssertionResult const& result ) = 0;
+ };
+
+ class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
+ {
+ public:
+ LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
+ virtual ~LegacyReporterAdapter();
+
+ virtual ReporterPreferences getPreferences() const;
+ virtual void noMatchingTestCases( std::string const& );
+ virtual void testRunStarting( TestRunInfo const& );
+ virtual void testGroupStarting( GroupInfo const& groupInfo );
+ virtual void testCaseStarting( TestCaseInfo const& testInfo );
+ virtual void sectionStarting( SectionInfo const& sectionInfo );
+ virtual void assertionStarting( AssertionInfo const& );
+ virtual bool assertionEnded( AssertionStats const& assertionStats );
+ virtual void sectionEnded( SectionStats const& sectionStats );
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats );
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats );
+ virtual void testRunEnded( TestRunStats const& testRunStats );
+ virtual void skipTest( TestCaseInfo const& );
+
+ private:
+ Ptr<IReporter> m_legacyReporter;
+ };
+}
+
+namespace Catch
+{
+ LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
+ : m_legacyReporter( legacyReporter )
+ {}
+ LegacyReporterAdapter::~LegacyReporterAdapter() {}
+
+ ReporterPreferences LegacyReporterAdapter::getPreferences() const {
+ ReporterPreferences prefs;
+ prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
+ return prefs;
+ }
+
+ void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
+ void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
+ m_legacyReporter->StartTesting();
+ }
+ void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
+ m_legacyReporter->StartGroup( groupInfo.name );
+ }
+ void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
+ m_legacyReporter->StartTestCase( testInfo );
+ }
+ void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
+ m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
+ }
+ void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
+ // Not on legacy interface
+ }
+
+ bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
+ if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
+ for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
+ it != itEnd;
+ ++it ) {
+ if( it->type == ResultWas::Info ) {
+ ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
+ rb << it->message;
+ rb.setResultType( ResultWas::Info );
+ AssertionResult result = rb.build();
+ m_legacyReporter->Result( result );
+ }
+ }
+ }
+ m_legacyReporter->Result( assertionStats.assertionResult );
+ return true;
+ }
+ void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
+ if( sectionStats.missingAssertions )
+ m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
+ m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
+ }
+ void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
+ m_legacyReporter->EndTestCase
+ ( testCaseStats.testInfo,
+ testCaseStats.totals,
+ testCaseStats.stdOut,
+ testCaseStats.stdErr );
+ }
+ void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
+ if( testGroupStats.aborting )
+ m_legacyReporter->Aborted();
+ m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
+ }
+ void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
+ m_legacyReporter->EndTesting( testRunStats.totals );
+ }
+ void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
+ }
+}
+
+// #included from: catch_timer.hpp
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++11-long-long"
+#endif
+
+#ifdef CATCH_PLATFORM_WINDOWS
+
+#else
+
+#include <sys/time.h>
+
+#endif
+
+namespace Catch {
+
+ namespace {
+#ifdef CATCH_PLATFORM_WINDOWS
+ uint64_t getCurrentTicks() {
+ static uint64_t hz=0, hzo=0;
+ if (!hz) {
+ QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
+ QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
+ }
+ uint64_t t;
+ QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
+ return ((t-hzo)*1000000)/hz;
+ }
+#else
+ uint64_t getCurrentTicks() {
+ timeval t;
+ gettimeofday(&t,CATCH_NULL);
+ return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
+ }
+#endif
+ }
+
+ void Timer::start() {
+ m_ticks = getCurrentTicks();
+ }
+ unsigned int Timer::getElapsedMicroseconds() const {
+ return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
+ }
+ unsigned int Timer::getElapsedMilliseconds() const {
+ return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
+ }
+ double Timer::getElapsedSeconds() const {
+ return getElapsedMicroseconds()/1000000.0;
+ }
+
+} // namespace Catch
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+// #included from: catch_common.hpp
+#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
+
+#include <cstring>
+#include <cctype>
+
+namespace Catch {
+
+ bool startsWith( std::string const& s, std::string const& prefix ) {
+ return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
+ }
+ bool startsWith( std::string const& s, char prefix ) {
+ return !s.empty() && s[0] == prefix;
+ }
+ bool endsWith( std::string const& s, std::string const& suffix ) {
+ return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
+ }
+ bool endsWith( std::string const& s, char suffix ) {
+ return !s.empty() && s[s.size()-1] == suffix;
+ }
+ bool contains( std::string const& s, std::string const& infix ) {
+ return s.find( infix ) != std::string::npos;
+ }
+ char toLowerCh(char c) {
+ return static_cast<char>( std::tolower( c ) );
+ }
+ void toLowerInPlace( std::string& s ) {
+ std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
+ }
+ std::string toLower( std::string const& s ) {
+ std::string lc = s;
+ toLowerInPlace( lc );
+ return lc;
+ }
+ std::string trim( std::string const& str ) {
+ static char const* whitespaceChars = "\n\r\t ";
+ std::string::size_type start = str.find_first_not_of( whitespaceChars );
+ std::string::size_type end = str.find_last_not_of( whitespaceChars );
+
+ return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
+ }
+
+ bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
+ bool replaced = false;
+ std::size_t i = str.find( replaceThis );
+ while( i != std::string::npos ) {
+ replaced = true;
+ str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
+ if( i < str.size()-withThis.size() )
+ i = str.find( replaceThis, i+withThis.size() );
+ else
+ i = std::string::npos;
+ }
+ return replaced;
+ }
+
+ pluralise::pluralise( std::size_t count, std::string const& label )
+ : m_count( count ),
+ m_label( label )
+ {}
+
+ std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
+ os << pluraliser.m_count << ' ' << pluraliser.m_label;
+ if( pluraliser.m_count != 1 )
+ os << 's';
+ return os;
+ }
+
+ SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
+ SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
+ : file( _file ),
+ line( _line )
+ {}
+ bool SourceLineInfo::empty() const {
+ return file[0] == '\0';
+ }
+ bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
+ return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
+ }
+ bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
+ return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
+ }
+
+ void seedRng( IConfig const& config ) {
+ if( config.rngSeed() != 0 )
+ std::srand( config.rngSeed() );
+ }
+ unsigned int rngSeed() {
+ return getCurrentContext().getConfig()->rngSeed();
+ }
+
+ std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
+#ifndef __GNUG__
+ os << info.file << '(' << info.line << ')';
+#else
+ os << info.file << ':' << info.line;
+#endif
+ return os;
+ }
+
+ void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
+ std::ostringstream oss;
+ oss << locationInfo << ": Internal Catch error: '" << message << '\'';
+ if( alwaysTrue() )
+ throw std::logic_error( oss.str() );
+ }
+}
+
+// #included from: catch_section.hpp
+#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
+
+namespace Catch {
+
+ SectionInfo::SectionInfo
+ ( SourceLineInfo const& _lineInfo,
+ std::string const& _name,
+ std::string const& _description )
+ : name( _name ),
+ description( _description ),
+ lineInfo( _lineInfo )
+ {}
+
+ Section::Section( SectionInfo const& info )
+ : m_info( info ),
+ m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
+ {
+ m_timer.start();
+ }
+
+ Section::~Section() {
+ if( m_sectionIncluded ) {
+ SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
+ if( std::uncaught_exception() )
+ getResultCapture().sectionEndedEarly( endInfo );
+ else
+ getResultCapture().sectionEnded( endInfo );
+ }
+ }
+
+ // This indicates whether the section should be executed or not
+ Section::operator bool() const {
+ return m_sectionIncluded;
+ }
+
+} // end namespace Catch
+
+// #included from: catch_debugger.hpp
+#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
+
+#ifdef CATCH_PLATFORM_MAC
+
+ #include <assert.h>
+ #include <stdbool.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/sysctl.h>
+
+ namespace Catch{
+
+ // The following function is taken directly from the following technical note:
+ // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
+
+ // Returns true if the current process is being debugged (either
+ // running under the debugger or has a debugger attached post facto).
+ bool isDebuggerActive(){
+
+ int mib[4];
+ struct kinfo_proc info;
+ size_t size;
+
+ // Initialize the flags so that, if sysctl fails for some bizarre
+ // reason, we get a predictable result.
+
+ info.kp_proc.p_flag = 0;
+
+ // Initialize mib, which tells sysctl the info we want, in this case
+ // we're looking for information about a specific process ID.
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid();
+
+ // Call sysctl.
+
+ size = sizeof(info);
+ if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
+ Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
+ return false;
+ }
+
+ // We're being debugged if the P_TRACED flag is set.
+
+ return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
+ }
+ } // namespace Catch
+
+#elif defined(CATCH_PLATFORM_LINUX)
+ #include <fstream>
+ #include <string>
+
+ namespace Catch{
+ // The standard POSIX way of detecting a debugger is to attempt to
+ // ptrace() the process, but this needs to be done from a child and not
+ // this process itself to still allow attaching to this process later
+ // if wanted, so is rather heavy. Under Linux we have the PID of the
+ // "debugger" (which doesn't need to be gdb, of course, it could also
+ // be strace, for example) in /proc/$PID/status, so just get it from
+ // there instead.
+ bool isDebuggerActive(){
+ std::ifstream in("/proc/self/status");
+ for( std::string line; std::getline(in, line); ) {
+ static const int PREFIX_LEN = 11;
+ if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
+ // We're traced if the PID is not 0 and no other PID starts
+ // with 0 digit, so it's enough to check for just a single
+ // character.
+ return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
+ }
+ }
+
+ return false;
+ }
+ } // namespace Catch
+#elif defined(_MSC_VER)
+ extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+ namespace Catch {
+ bool isDebuggerActive() {
+ return IsDebuggerPresent() != 0;
+ }
+ }
+#elif defined(__MINGW32__)
+ extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
+ namespace Catch {
+ bool isDebuggerActive() {
+ return IsDebuggerPresent() != 0;
+ }
+ }
+#else
+ namespace Catch {
+ inline bool isDebuggerActive() { return false; }
+ }
+#endif // Platform
+
+#ifdef CATCH_PLATFORM_WINDOWS
+
+ namespace Catch {
+ void writeToDebugConsole( std::string const& text ) {
+ ::OutputDebugStringA( text.c_str() );
+ }
+ }
+#else
+ namespace Catch {
+ void writeToDebugConsole( std::string const& text ) {
+ // !TBD: Need a version for Mac/ XCode and other IDEs
+ Catch::cout() << text;
+ }
+ }
+#endif // Platform
+
+// #included from: catch_tostring.hpp
+#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
+
+namespace Catch {
+
+namespace Detail {
+
+ const std::string unprintableString = "{?}";
+
+ namespace {
+ const int hexThreshold = 255;
+
+ struct Endianness {
+ enum Arch { Big, Little };
+
+ static Arch which() {
+ union _{
+ int asInt;
+ char asChar[sizeof (int)];
+ } u;
+
+ u.asInt = 1;
+ return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
+ }
+ };
+ }
+
+ std::string rawMemoryToString( const void *object, std::size_t size )
+ {
+ // Reverse order for little endian architectures
+ int i = 0, end = static_cast<int>( size ), inc = 1;
+ if( Endianness::which() == Endianness::Little ) {
+ i = end-1;
+ end = inc = -1;
+ }
+
+ unsigned char const *bytes = static_cast<unsigned char const *>(object);
+ std::ostringstream os;
+ os << "0x" << std::setfill('0') << std::hex;
+ for( ; i != end; i += inc )
+ os << std::setw(2) << static_cast<unsigned>(bytes[i]);
+ return os.str();
+ }
+}
+
+std::string toString( std::string const& value ) {
+ std::string s = value;
+ if( getCurrentContext().getConfig()->showInvisibles() ) {
+ for(size_t i = 0; i < s.size(); ++i ) {
+ std::string subs;
+ switch( s[i] ) {
+ case '\n': subs = "\\n"; break;
+ case '\t': subs = "\\t"; break;
+ default: break;
+ }
+ if( !subs.empty() ) {
+ s = s.substr( 0, i ) + subs + s.substr( i+1 );
+ ++i;
+ }
+ }
+ }
+ return '"' + s + '"';
+}
+std::string toString( std::wstring const& value ) {
+
+ std::string s;
+ s.reserve( value.size() );
+ for(size_t i = 0; i < value.size(); ++i )
+ s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
+ return Catch::toString( s );
+}
+
+std::string toString( const char* const value ) {
+ return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
+}
+
+std::string toString( char* const value ) {
+ return Catch::toString( static_cast<const char*>( value ) );
+}
+
+std::string toString( const wchar_t* const value )
+{
+ return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
+}
+
+std::string toString( wchar_t* const value )
+{
+ return Catch::toString( static_cast<const wchar_t*>( value ) );
+}
+
+std::string toString( int value ) {
+ std::ostringstream oss;
+ oss << value;
+ if( value > Detail::hexThreshold )
+ oss << " (0x" << std::hex << value << ')';
+ return oss.str();
+}
+
+std::string toString( unsigned long value ) {
+ std::ostringstream oss;
+ oss << value;
+ if( value > Detail::hexThreshold )
+ oss << " (0x" << std::hex << value << ')';
+ return oss.str();
+}
+
+std::string toString( unsigned int value ) {
+ return Catch::toString( static_cast<unsigned long>( value ) );
+}
+
+template<typename T>
+std::string fpToString( T value, int precision ) {
+ std::ostringstream oss;
+ oss << std::setprecision( precision )
+ << std::fixed
+ << value;
+ std::string d = oss.str();
+ std::size_t i = d.find_last_not_of( '0' );
+ if( i != std::string::npos && i != d.size()-1 ) {
+ if( d[i] == '.' )
+ i++;
+ d = d.substr( 0, i+1 );
+ }
+ return d;
+}
+
+std::string toString( const double value ) {
+ return fpToString( value, 10 );
+}
+std::string toString( const float value ) {
+ return fpToString( value, 5 ) + 'f';
+}
+
+std::string toString( bool value ) {
+ return value ? "true" : "false";
+}
+
+std::string toString( char value ) {
+ if ( value == '\r' )
+ return "'\\r'";
+ if ( value == '\f' )
+ return "'\\f'";
+ if ( value == '\n' )
+ return "'\\n'";
+ if ( value == '\t' )
+ return "'\\t'";
+ if ( '\0' <= value && value < ' ' )
+ return toString( static_cast<unsigned int>( value ) );
+ char chstr[] = "' '";
+ chstr[1] = value;
+ return chstr;
+}
+
+std::string toString( signed char value ) {
+ return toString( static_cast<char>( value ) );
+}
+
+std::string toString( unsigned char value ) {
+ return toString( static_cast<char>( value ) );
+}
+
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+std::string toString( long long value ) {
+ std::ostringstream oss;
+ oss << value;
+ if( value > Detail::hexThreshold )
+ oss << " (0x" << std::hex << value << ')';
+ return oss.str();
+}
+std::string toString( unsigned long long value ) {
+ std::ostringstream oss;
+ oss << value;
+ if( value > Detail::hexThreshold )
+ oss << " (0x" << std::hex << value << ')';
+ return oss.str();
+}
+#endif
+
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+std::string toString( std::nullptr_t ) {
+ return "nullptr";
+}
+#endif
+
+#ifdef __OBJC__
+ std::string toString( NSString const * const& nsstring ) {
+ if( !nsstring )
+ return "nil";
+ return "@" + toString([nsstring UTF8String]);
+ }
+ std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
+ if( !nsstring )
+ return "nil";
+ return "@" + toString([nsstring UTF8String]);
+ }
+ std::string toString( NSObject* const& nsObject ) {
+ return toString( [nsObject description] );
+ }
+#endif
+
+} // end namespace Catch
+
+// #included from: catch_result_builder.hpp
+#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
+
+namespace Catch {
+
+ std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
+ return secondArg.empty() || secondArg == "\"\""
+ ? capturedExpression
+ : capturedExpression + ", " + secondArg;
+ }
+ ResultBuilder::ResultBuilder( char const* macroName,
+ SourceLineInfo const& lineInfo,
+ char const* capturedExpression,
+ ResultDisposition::Flags resultDisposition,
+ char const* secondArg )
+ : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
+ m_shouldDebugBreak( false ),
+ m_shouldThrow( false )
+ {}
+
+ ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
+ m_data.resultType = result;
+ return *this;
+ }
+ ResultBuilder& ResultBuilder::setResultType( bool result ) {
+ m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
+ return *this;
+ }
+
+ void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
+ AssertionResult result = build( expr );
+ handleResult( result );
+ }
+
+ void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
+ m_assertionInfo.resultDisposition = resultDisposition;
+ m_stream.oss << Catch::translateActiveException();
+ captureResult( ResultWas::ThrewException );
+ }
+
+ void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
+ setResultType( resultType );
+ captureExpression();
+ }
+
+ void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
+ if( expectedMessage.empty() )
+ captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() );
+ else
+ captureExpectedException( Matchers::Equals( expectedMessage ) );
+ }
+
+ void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) {
+
+ assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
+ AssertionResultData data = m_data;
+ data.resultType = ResultWas::Ok;
+ data.reconstructedExpression = m_assertionInfo.capturedExpression;
+
+ std::string actualMessage = Catch::translateActiveException();
+ if( !matcher.match( actualMessage ) ) {
+ data.resultType = ResultWas::ExpressionFailed;
+ data.reconstructedExpression = actualMessage;
+ }
+ AssertionResult result( m_assertionInfo, data );
+ handleResult( result );
+ }
+
+ void ResultBuilder::captureExpression() {
+ AssertionResult result = build();
+ handleResult( result );
+ }
+
+ void ResultBuilder::handleResult( AssertionResult const& result )
+ {
+ getResultCapture().assertionEnded( result );
+
+ if( !result.isOk() ) {
+ if( getCurrentContext().getConfig()->shouldDebugBreak() )
+ m_shouldDebugBreak = true;
+ if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
+ m_shouldThrow = true;
+ }
+ }
+
+ void ResultBuilder::react() {
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+ if (m_shouldDebugBreak) {
+ ///////////////////////////////////////////////////////////////////
+ // To inspect the state during test, you need to go one level up the callstack
+ // To go back to the test and change execution, jump over the throw statement
+ ///////////////////////////////////////////////////////////////////
+ CATCH_BREAK_INTO_DEBUGGER();
+ }
+#endif
+ if( m_shouldThrow )
+ throw Catch::TestFailureException();
+ }
+
+ bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
+ bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
+
+ AssertionResult ResultBuilder::build() const
+ {
+ return build( *this );
+ }
+
+ // CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
+ // a temporary DecomposedExpression, which in turn holds references to
+ // operands, possibly temporary as well.
+ // It should immediately be passed to handleResult; if the expression
+ // needs to be reported, its string expansion must be composed before
+ // the temporaries are destroyed.
+ AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
+ {
+ assert( m_data.resultType != ResultWas::Unknown );
+ AssertionResultData data = m_data;
+
+ // Flip bool results if FalseTest flag is set
+ if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
+ data.negate( expr.isBinaryExpression() );
+ }
+
+ data.message = m_stream.oss.str();
+ data.decomposedExpression = &expr; // for lazy reconstruction
+ return AssertionResult( m_assertionInfo, data );
+ }
+
+ void ResultBuilder::reconstructExpression( std::string& dest ) const {
+ dest = m_assertionInfo.capturedExpression;
+ }
+
+} // end namespace Catch
+
+// #included from: catch_tag_alias_registry.hpp
+#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
+
+// #included from: catch_tag_alias_registry.h
+#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
+
+#include <map>
+
+namespace Catch {
+
+ class TagAliasRegistry : public ITagAliasRegistry {
+ public:
+ virtual ~TagAliasRegistry();
+ virtual Option<TagAlias> find( std::string const& alias ) const;
+ virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
+ void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
+ static TagAliasRegistry& get();
+
+ private:
+ std::map<std::string, TagAlias> m_registry;
+ };
+
+} // end namespace Catch
+
+namespace Catch {
+
+ TagAliasRegistry::~TagAliasRegistry() {}
+
+ Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
+ std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
+ if( it != m_registry.end() )
+ return it->second;
+ else
+ return Option<TagAlias>();
+ }
+
+ std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
+ std::string expandedTestSpec = unexpandedTestSpec;
+ for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
+ it != itEnd;
+ ++it ) {
+ std::size_t pos = expandedTestSpec.find( it->first );
+ if( pos != std::string::npos ) {
+ expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
+ it->second.tag +
+ expandedTestSpec.substr( pos + it->first.size() );
+ }
+ }
+ return expandedTestSpec;
+ }
+
+ void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
+
+ if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
+ std::ostringstream oss;
+ oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
+ throw std::domain_error( oss.str().c_str() );
+ }
+ if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
+ std::ostringstream oss;
+ oss << "error: tag alias, \"" << alias << "\" already registered.\n"
+ << "\tFirst seen at " << find(alias)->lineInfo << '\n'
+ << "\tRedefined at " << lineInfo;
+ throw std::domain_error( oss.str().c_str() );
+ }
+ }
+
+ TagAliasRegistry& TagAliasRegistry::get() {
+ static TagAliasRegistry instance;
+ return instance;
+
+ }
+
+ ITagAliasRegistry::~ITagAliasRegistry() {}
+ ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); }
+
+ RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
+ try {
+ TagAliasRegistry::get().add( alias, tag, lineInfo );
+ }
+ catch( std::exception& ex ) {
+ Colour colourGuard( Colour::Red );
+ Catch::cerr() << ex.what() << std::endl;
+ exit(1);
+ }
+ }
+
+} // end namespace Catch
+
+// #included from: catch_matchers_string.hpp
+
+namespace Catch {
+namespace Matchers {
+
+ namespace StdString {
+
+ CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
+ : m_caseSensitivity( caseSensitivity ),
+ m_str( adjustString( str ) )
+ {}
+ std::string CasedString::adjustString( std::string const& str ) const {
+ return m_caseSensitivity == CaseSensitive::No
+ ? toLower( str )
+ : str;
+ }
+ std::string CasedString::caseSensitivitySuffix() const {
+ return m_caseSensitivity == CaseSensitive::No
+ ? " (case insensitive)"
+ : std::string();
+ }
+
+ StringMatcherBase::StringMatcherBase( std::string operation, CasedString const& comparator )
+ : m_comparator( comparator ),
+ m_operation( operation ) {
+ }
+
+ std::string StringMatcherBase::describe() const {
+ std::string description;
+ description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
+ m_comparator.caseSensitivitySuffix().size());
+ description += m_operation;
+ description += ": \"";
+ description += m_comparator.m_str;
+ description += "\"";
+ description += m_comparator.caseSensitivitySuffix();
+ return description;
+ }
+
+ EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
+
+ bool EqualsMatcher::match( std::string const& source ) const {
+ return m_comparator.adjustString( source ) == m_comparator.m_str;
+ }
+
+ ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
+
+ bool ContainsMatcher::match( std::string const& source ) const {
+ return contains( m_comparator.adjustString( source ), m_comparator.m_str );
+ }
+
+ StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
+
+ bool StartsWithMatcher::match( std::string const& source ) const {
+ return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
+ }
+
+ EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
+
+ bool EndsWithMatcher::match( std::string const& source ) const {
+ return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
+ }
+
+ } // namespace StdString
+
+ StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+ return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
+ }
+ StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+ return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
+ }
+ StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+ return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
+ }
+ StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
+ return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
+ }
+
+} // namespace Matchers
+} // namespace Catch
+// #included from: ../reporters/catch_reporter_multi.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
+
+namespace Catch {
+
+class MultipleReporters : public SharedImpl<IStreamingReporter> {
+ typedef std::vector<Ptr<IStreamingReporter> > Reporters;
+ Reporters m_reporters;
+
+public:
+ void add( Ptr<IStreamingReporter> const& reporter ) {
+ m_reporters.push_back( reporter );
+ }
+
+public: // IStreamingReporter
+
+ virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+ return m_reporters[0]->getPreferences();
+ }
+
+ virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->noMatchingTestCases( spec );
+ }
+
+ virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testRunStarting( testRunInfo );
+ }
+
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testGroupStarting( groupInfo );
+ }
+
+ virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testCaseStarting( testInfo );
+ }
+
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->sectionStarting( sectionInfo );
+ }
+
+ virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->assertionStarting( assertionInfo );
+ }
+
+ // The return value indicates if the messages buffer should be cleared:
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+ bool clearBuffer = false;
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ clearBuffer |= (*it)->assertionEnded( assertionStats );
+ return clearBuffer;
+ }
+
+ virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->sectionEnded( sectionStats );
+ }
+
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testCaseEnded( testCaseStats );
+ }
+
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testGroupEnded( testGroupStats );
+ }
+
+ virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testRunEnded( testRunStats );
+ }
+
+ virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->skipTest( testInfo );
+ }
+
+ virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
+ return this;
+ }
+
+};
+
+Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
+ Ptr<IStreamingReporter> resultingReporter;
+
+ if( existingReporter ) {
+ MultipleReporters* multi = existingReporter->tryAsMulti();
+ if( !multi ) {
+ multi = new MultipleReporters;
+ resultingReporter = Ptr<IStreamingReporter>( multi );
+ if( existingReporter )
+ multi->add( existingReporter );
+ }
+ else
+ resultingReporter = existingReporter;
+ multi->add( additionalReporter );
+ }
+ else
+ resultingReporter = additionalReporter;
+
+ return resultingReporter;
+}
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_xml.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
+
+// #included from: catch_reporter_bases.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
+
+#include <cstring>
+#include <assert.h>
+
+namespace Catch {
+
+ struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
+
+ StreamingReporterBase( ReporterConfig const& _config )
+ : m_config( _config.fullConfig() ),
+ stream( _config.stream() )
+ {
+ m_reporterPrefs.shouldRedirectStdOut = false;
+ }
+
+ virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+ return m_reporterPrefs;
+ }
+
+ virtual ~StreamingReporterBase() CATCH_OVERRIDE;
+
+ virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
+
+ virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
+ currentTestRunInfo = _testRunInfo;
+ }
+ virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
+ currentGroupInfo = _groupInfo;
+ }
+
+ virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
+ currentTestCaseInfo = _testInfo;
+ }
+ virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
+ m_sectionStack.push_back( _sectionInfo );
+ }
+
+ virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
+ m_sectionStack.pop_back();
+ }
+ virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
+ currentTestCaseInfo.reset();
+ }
+ virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
+ currentGroupInfo.reset();
+ }
+ virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
+ currentTestCaseInfo.reset();
+ currentGroupInfo.reset();
+ currentTestRunInfo.reset();
+ }
+
+ virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
+ // Don't do anything with this by default.
+ // It can optionally be overridden in the derived class.
+ }
+
+ Ptr<IConfig const> m_config;
+ std::ostream& stream;
+
+ LazyStat<TestRunInfo> currentTestRunInfo;
+ LazyStat<GroupInfo> currentGroupInfo;
+ LazyStat<TestCaseInfo> currentTestCaseInfo;
+
+ std::vector<SectionInfo> m_sectionStack;
+ ReporterPreferences m_reporterPrefs;
+ };
+
+ struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
+ template<typename T, typename ChildNodeT>
+ struct Node : SharedImpl<> {
+ explicit Node( T const& _value ) : value( _value ) {}
+ virtual ~Node() {}
+
+ typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
+ T value;
+ ChildNodes children;
+ };
+ struct SectionNode : SharedImpl<> {
+ explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
+ virtual ~SectionNode();
+
+ bool operator == ( SectionNode const& other ) const {
+ return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
+ }
+ bool operator == ( Ptr<SectionNode> const& other ) const {
+ return operator==( *other );
+ }
+
+ SectionStats stats;
+ typedef std::vector<Ptr<SectionNode> > ChildSections;
+ typedef std::vector<AssertionStats> Assertions;
+ ChildSections childSections;
+ Assertions assertions;
+ std::string stdOut;
+ std::string stdErr;
+ };
+
+ struct BySectionInfo {
+ BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
+ BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
+ bool operator() ( Ptr<SectionNode> const& node ) const {
+ return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
+ }
+ private:
+ void operator=( BySectionInfo const& );
+ SectionInfo const& m_other;
+ };
+
+ typedef Node<TestCaseStats, SectionNode> TestCaseNode;
+ typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
+ typedef Node<TestRunStats, TestGroupNode> TestRunNode;
+
+ CumulativeReporterBase( ReporterConfig const& _config )
+ : m_config( _config.fullConfig() ),
+ stream( _config.stream() )
+ {
+ m_reporterPrefs.shouldRedirectStdOut = false;
+ }
+ ~CumulativeReporterBase();
+
+ virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+ return m_reporterPrefs;
+ }
+
+ virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
+ virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
+
+ virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
+
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
+ SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
+ Ptr<SectionNode> node;
+ if( m_sectionStack.empty() ) {
+ if( !m_rootSection )
+ m_rootSection = new SectionNode( incompleteStats );
+ node = m_rootSection;
+ }
+ else {
+ SectionNode& parentNode = *m_sectionStack.back();
+ SectionNode::ChildSections::const_iterator it =
+ std::find_if( parentNode.childSections.begin(),
+ parentNode.childSections.end(),
+ BySectionInfo( sectionInfo ) );
+ if( it == parentNode.childSections.end() ) {
+ node = new SectionNode( incompleteStats );
+ parentNode.childSections.push_back( node );
+ }
+ else
+ node = *it;
+ }
+ m_sectionStack.push_back( node );
+ m_deepestSection = node;
+ }
+
+ virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
+
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+ assert( !m_sectionStack.empty() );
+ SectionNode& sectionNode = *m_sectionStack.back();
+ sectionNode.assertions.push_back( assertionStats );
+ // AssertionResult holds a pointer to a temporary DecomposedExpression,
+ // which getExpandedExpression() calls to build the expression string.
+ // Our section stack copy of the assertionResult will likely outlive the
+ // temporary, so it must be expanded or discarded now to avoid calling
+ // a destroyed object later.
+ prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
+ return true;
+ }
+ virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
+ assert( !m_sectionStack.empty() );
+ SectionNode& node = *m_sectionStack.back();
+ node.stats = sectionStats;
+ m_sectionStack.pop_back();
+ }
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+ Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
+ assert( m_sectionStack.size() == 0 );
+ node->children.push_back( m_rootSection );
+ m_testCases.push_back( node );
+ m_rootSection.reset();
+
+ assert( m_deepestSection );
+ m_deepestSection->stdOut = testCaseStats.stdOut;
+ m_deepestSection->stdErr = testCaseStats.stdErr;
+ }
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+ Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
+ node->children.swap( m_testCases );
+ m_testGroups.push_back( node );
+ }
+ virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
+ Ptr<TestRunNode> node = new TestRunNode( testRunStats );
+ node->children.swap( m_testGroups );
+ m_testRuns.push_back( node );
+ testRunEndedCumulative();
+ }
+ virtual void testRunEndedCumulative() = 0;
+
+ virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
+
+ virtual void prepareExpandedExpression( AssertionResult& result ) const {
+ if( result.isOk() )
+ result.discardDecomposedExpression();
+ else
+ result.expandDecomposedExpression();
+ }
+
+ Ptr<IConfig const> m_config;
+ std::ostream& stream;
+ std::vector<AssertionStats> m_assertions;
+ std::vector<std::vector<Ptr<SectionNode> > > m_sections;
+ std::vector<Ptr<TestCaseNode> > m_testCases;
+ std::vector<Ptr<TestGroupNode> > m_testGroups;
+
+ std::vector<Ptr<TestRunNode> > m_testRuns;
+
+ Ptr<SectionNode> m_rootSection;
+ Ptr<SectionNode> m_deepestSection;
+ std::vector<Ptr<SectionNode> > m_sectionStack;
+ ReporterPreferences m_reporterPrefs;
+
+ };
+
+ template<char C>
+ char const* getLineOfChars() {
+ static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
+ if( !*line ) {
+ std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
+ line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
+ }
+ return line;
+ }
+
+ struct TestEventListenerBase : StreamingReporterBase {
+ TestEventListenerBase( ReporterConfig const& _config )
+ : StreamingReporterBase( _config )
+ {}
+
+ virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
+ virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
+ return false;
+ }
+ };
+
+} // end namespace Catch
+
+// #included from: ../internal/catch_reporter_registrars.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
+
+namespace Catch {
+
+ template<typename T>
+ class LegacyReporterRegistrar {
+
+ class ReporterFactory : public IReporterFactory {
+ virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+ return new LegacyReporterAdapter( new T( config ) );
+ }
+
+ virtual std::string getDescription() const {
+ return T::getDescription();
+ }
+ };
+
+ public:
+
+ LegacyReporterRegistrar( std::string const& name ) {
+ getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
+ }
+ };
+
+ template<typename T>
+ class ReporterRegistrar {
+
+ class ReporterFactory : public SharedImpl<IReporterFactory> {
+
+ // *** Please Note ***:
+ // - If you end up here looking at a compiler error because it's trying to register
+ // your custom reporter class be aware that the native reporter interface has changed
+ // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
+ // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
+ // However please consider updating to the new interface as the old one is now
+ // deprecated and will probably be removed quite soon!
+ // Please contact me via github if you have any questions at all about this.
+ // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
+ // no idea who is actually using custom reporters at all (possibly no-one!).
+ // The new interface is designed to minimise exposure to interface changes in the future.
+ virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+ return new T( config );
+ }
+
+ virtual std::string getDescription() const {
+ return T::getDescription();
+ }
+ };
+
+ public:
+
+ ReporterRegistrar( std::string const& name ) {
+ getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
+ }
+ };
+
+ template<typename T>
+ class ListenerRegistrar {
+
+ class ListenerFactory : public SharedImpl<IReporterFactory> {
+
+ virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+ return new T( config );
+ }
+ virtual std::string getDescription() const {
+ return std::string();
+ }
+ };
+
+ public:
+
+ ListenerRegistrar() {
+ getMutableRegistryHub().registerListener( new ListenerFactory() );
+ }
+ };
+}
+
+#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
+ namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
+#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
+ namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
+#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
+ namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
+
+// #included from: ../internal/catch_xmlwriter.hpp
+#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
+
+#include <sstream>
+#include <string>
+#include <vector>
+#include <iomanip>
+
+namespace Catch {
+
+ class XmlEncode {
+ public:
+ enum ForWhat { ForTextNodes, ForAttributes };
+
+ XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
+ : m_str( str ),
+ m_forWhat( forWhat )
+ {}
+
+ void encodeTo( std::ostream& os ) const {
+
+ // Apostrophe escaping not necessary if we always use " to write attributes
+ // (see: http://www.w3.org/TR/xml/#syntax)
+
+ for( std::size_t i = 0; i < m_str.size(); ++ i ) {
+ char c = m_str[i];
+ switch( c ) {
+ case '<': os << "&lt;"; break;
+ case '&': os << "&amp;"; break;
+
+ case '>':
+ // See: http://www.w3.org/TR/xml/#syntax
+ if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
+ os << "&gt;";
+ else
+ os << c;
+ break;
+
+ case '\"':
+ if( m_forWhat == ForAttributes )
+ os << "&quot;";
+ else
+ os << c;
+ break;
+
+ default:
+ // Escape control chars - based on contribution by @espenalb in PR #465 and
+ // by @mrpi PR #588
+ if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
+ // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
+ os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
+ << static_cast<int>( c );
+ }
+ else
+ os << c;
+ }
+ }
+ }
+
+ friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
+ xmlEncode.encodeTo( os );
+ return os;
+ }
+
+ private:
+ std::string m_str;
+ ForWhat m_forWhat;
+ };
+
+ class XmlWriter {
+ public:
+
+ class ScopedElement {
+ public:
+ ScopedElement( XmlWriter* writer )
+ : m_writer( writer )
+ {}
+
+ ScopedElement( ScopedElement const& other )
+ : m_writer( other.m_writer ){
+ other.m_writer = CATCH_NULL;
+ }
+
+ ~ScopedElement() {
+ if( m_writer )
+ m_writer->endElement();
+ }
+
+ ScopedElement& writeText( std::string const& text, bool indent = true ) {
+ m_writer->writeText( text, indent );
+ return *this;
+ }
+
+ template<typename T>
+ ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
+ m_writer->writeAttribute( name, attribute );
+ return *this;
+ }
+
+ private:
+ mutable XmlWriter* m_writer;
+ };
+
+ XmlWriter()
+ : m_tagIsOpen( false ),
+ m_needsNewline( false ),
+ m_os( Catch::cout() )
+ {
+ writeDeclaration();
+ }
+
+ XmlWriter( std::ostream& os )
+ : m_tagIsOpen( false ),
+ m_needsNewline( false ),
+ m_os( os )
+ {
+ writeDeclaration();
+ }
+
+ ~XmlWriter() {
+ while( !m_tags.empty() )
+ endElement();
+ }
+
+ XmlWriter& startElement( std::string const& name ) {
+ ensureTagClosed();
+ newlineIfNecessary();
+ m_os << m_indent << '<' << name;
+ m_tags.push_back( name );
+ m_indent += " ";
+ m_tagIsOpen = true;
+ return *this;
+ }
+
+ ScopedElement scopedElement( std::string const& name ) {
+ ScopedElement scoped( this );
+ startElement( name );
+ return scoped;
+ }
+
+ XmlWriter& endElement() {
+ newlineIfNecessary();
+ m_indent = m_indent.substr( 0, m_indent.size()-2 );
+ if( m_tagIsOpen ) {
+ m_os << "/>";
+ m_tagIsOpen = false;
+ }
+ else {
+ m_os << m_indent << "</" << m_tags.back() << ">";
+ }
+ m_os << std::endl;
+ m_tags.pop_back();
+ return *this;
+ }
+
+ XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
+ if( !name.empty() && !attribute.empty() )
+ m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
+ return *this;
+ }
+
+ XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
+ m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
+ return *this;
+ }
+
+ template<typename T>
+ XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
+ std::ostringstream oss;
+ oss << attribute;
+ return writeAttribute( name, oss.str() );
+ }
+
+ XmlWriter& writeText( std::string const& text, bool indent = true ) {
+ if( !text.empty() ){
+ bool tagWasOpen = m_tagIsOpen;
+ ensureTagClosed();
+ if( tagWasOpen && indent )
+ m_os << m_indent;
+ m_os << XmlEncode( text );
+ m_needsNewline = true;
+ }
+ return *this;
+ }
+
+ XmlWriter& writeComment( std::string const& text ) {
+ ensureTagClosed();
+ m_os << m_indent << "<!--" << text << "-->";
+ m_needsNewline = true;
+ return *this;
+ }
+
+ void writeStylesheetRef( std::string const& url ) {
+ m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
+ }
+
+ XmlWriter& writeBlankLine() {
+ ensureTagClosed();
+ m_os << '\n';
+ return *this;
+ }
+
+ void ensureTagClosed() {
+ if( m_tagIsOpen ) {
+ m_os << ">" << std::endl;
+ m_tagIsOpen = false;
+ }
+ }
+
+ private:
+ XmlWriter( XmlWriter const& );
+ void operator=( XmlWriter const& );
+
+ void writeDeclaration() {
+ m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ }
+
+ void newlineIfNecessary() {
+ if( m_needsNewline ) {
+ m_os << std::endl;
+ m_needsNewline = false;
+ }
+ }
+
+ bool m_tagIsOpen;
+ bool m_needsNewline;
+ std::vector<std::string> m_tags;
+ std::string m_indent;
+ std::ostream& m_os;
+ };
+
+}
+// #included from: catch_reenable_warnings.h
+
+#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
+
+#ifdef __clang__
+# ifdef __ICC // icpc defines the __clang__ macro
+# pragma warning(pop)
+# else
+# pragma clang diagnostic pop
+# endif
+#elif defined __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
+
+namespace Catch {
+ class XmlReporter : public StreamingReporterBase {
+ public:
+ XmlReporter( ReporterConfig const& _config )
+ : StreamingReporterBase( _config ),
+ m_xml(_config.stream()),
+ m_sectionDepth( 0 )
+ {
+ m_reporterPrefs.shouldRedirectStdOut = true;
+ }
+
+ virtual ~XmlReporter() CATCH_OVERRIDE;
+
+ static std::string getDescription() {
+ return "Reports test results as an XML document";
+ }
+
+ virtual std::string getStylesheetRef() const {
+ return std::string();
+ }
+
+ void writeSourceInfo( SourceLineInfo const& sourceInfo ) {
+ m_xml
+ .writeAttribute( "filename", sourceInfo.file )
+ .writeAttribute( "line", sourceInfo.line );
+ }
+
+ public: // StreamingReporterBase
+
+ virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
+ StreamingReporterBase::noMatchingTestCases( s );
+ }
+
+ virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
+ StreamingReporterBase::testRunStarting( testInfo );
+ std::string stylesheetRef = getStylesheetRef();
+ if( !stylesheetRef.empty() )
+ m_xml.writeStylesheetRef( stylesheetRef );
+ m_xml.startElement( "Catch" );
+ if( !m_config->name().empty() )
+ m_xml.writeAttribute( "name", m_config->name() );
+ }
+
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
+ StreamingReporterBase::testGroupStarting( groupInfo );
+ m_xml.startElement( "Group" )
+ .writeAttribute( "name", groupInfo.name );
+ }
+
+ virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+ StreamingReporterBase::testCaseStarting(testInfo);
+ m_xml.startElement( "TestCase" )
+ .writeAttribute( "name", trim( testInfo.name ) )
+ .writeAttribute( "description", testInfo.description )
+ .writeAttribute( "tags", testInfo.tagsAsString );
+
+ writeSourceInfo( testInfo.lineInfo );
+
+ if ( m_config->showDurations() == ShowDurations::Always )
+ m_testCaseTimer.start();
+ m_xml.ensureTagClosed();
+ }
+
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
+ StreamingReporterBase::sectionStarting( sectionInfo );
+ if( m_sectionDepth++ > 0 ) {
+ m_xml.startElement( "Section" )
+ .writeAttribute( "name", trim( sectionInfo.name ) )
+ .writeAttribute( "description", sectionInfo.description );
+ writeSourceInfo( sectionInfo.lineInfo );
+ m_xml.ensureTagClosed();
+ }
+ }
+
+ virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
+
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+ const AssertionResult& assertionResult = assertionStats.assertionResult;
+
+ // Print any info messages in <Info> tags.
+ if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
+ for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
+ it != itEnd;
+ ++it ) {
+ if( it->type == ResultWas::Info ) {
+ m_xml.scopedElement( "Info" )
+ .writeText( it->message );
+ } else if ( it->type == ResultWas::Warning ) {
+ m_xml.scopedElement( "Warning" )
+ .writeText( it->message );
+ }
+ }
+ }
+
+ // Drop out if result was successful but we're not printing them.
+ if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
+ return true;
+
+ // Print the expression if there is one.
+ if( assertionResult.hasExpression() ) {
+ m_xml.startElement( "Expression" )
+ .writeAttribute( "success", assertionResult.succeeded() )
+ .writeAttribute( "type", assertionResult.getTestMacroName() );
+
+ writeSourceInfo( assertionResult.getSourceInfo() );
+
+ m_xml.scopedElement( "Original" )
+ .writeText( assertionResult.getExpression() );
+ m_xml.scopedElement( "Expanded" )
+ .writeText( assertionResult.getExpandedExpression() );
+ }
+
+ // And... Print a result applicable to each result type.
+ switch( assertionResult.getResultType() ) {
+ case ResultWas::ThrewException:
+ m_xml.startElement( "Exception" );
+ writeSourceInfo( assertionResult.getSourceInfo() );
+ m_xml.writeText( assertionResult.getMessage() );
+ m_xml.endElement();
+ break;
+ case ResultWas::FatalErrorCondition:
+ m_xml.startElement( "FatalErrorCondition" );
+ writeSourceInfo( assertionResult.getSourceInfo() );
+ m_xml.writeText( assertionResult.getMessage() );
+ m_xml.endElement();
+ break;
+ case ResultWas::Info:
+ m_xml.scopedElement( "Info" )
+ .writeText( assertionResult.getMessage() );
+ break;
+ case ResultWas::Warning:
+ // Warning will already have been written
+ break;
+ case ResultWas::ExplicitFailure:
+ m_xml.startElement( "Failure" );
+ writeSourceInfo( assertionResult.getSourceInfo() );
+ m_xml.writeText( assertionResult.getMessage() );
+ m_xml.endElement();
+ break;
+ default:
+ break;
+ }
+
+ if( assertionResult.hasExpression() )
+ m_xml.endElement();
+
+ return true;
+ }
+
+ virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
+ StreamingReporterBase::sectionEnded( sectionStats );
+ if( --m_sectionDepth > 0 ) {
+ XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
+ e.writeAttribute( "successes", sectionStats.assertions.passed );
+ e.writeAttribute( "failures", sectionStats.assertions.failed );
+ e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
+
+ if ( m_config->showDurations() == ShowDurations::Always )
+ e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
+
+ m_xml.endElement();
+ }
+ }
+
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+ StreamingReporterBase::testCaseEnded( testCaseStats );
+ XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
+ e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
+
+ if ( m_config->showDurations() == ShowDurations::Always )
+ e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
+
+ if( !testCaseStats.stdOut.empty() )
+ m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
+ if( !testCaseStats.stdErr.empty() )
+ m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
+
+ m_xml.endElement();
+ }
+
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+ StreamingReporterBase::testGroupEnded( testGroupStats );
+ // TODO: Check testGroupStats.aborting and act accordingly.
+ m_xml.scopedElement( "OverallResults" )
+ .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
+ .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
+ .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
+ m_xml.endElement();
+ }
+
+ virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
+ StreamingReporterBase::testRunEnded( testRunStats );
+ m_xml.scopedElement( "OverallResults" )
+ .writeAttribute( "successes", testRunStats.totals.assertions.passed )
+ .writeAttribute( "failures", testRunStats.totals.assertions.failed )
+ .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
+ m_xml.endElement();
+ }
+
+ private:
+ Timer m_testCaseTimer;
+ XmlWriter m_xml;
+ int m_sectionDepth;
+ };
+
+ INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_junit.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
+
+#include <assert.h>
+
+namespace Catch {
+
+ namespace {
+ std::string getCurrentTimestamp() {
+ // Beware, this is not reentrant because of backward compatibility issues
+ // Also, UTC only, again because of backward compatibility (%z is C++11)
+ time_t rawtime;
+ std::time(&rawtime);
+ const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
+
+#ifdef _MSC_VER
+ std::tm timeInfo = {};
+ gmtime_s(&timeInfo, &rawtime);
+#else
+ std::tm* timeInfo;
+ timeInfo = std::gmtime(&rawtime);
+#endif
+
+ char timeStamp[timeStampSize];
+ const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
+
+#ifdef _MSC_VER
+ std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
+#else
+ std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
+#endif
+ return std::string(timeStamp);
+ }
+
+ }
+
+ class JunitReporter : public CumulativeReporterBase {
+ public:
+ JunitReporter( ReporterConfig const& _config )
+ : CumulativeReporterBase( _config ),
+ xml( _config.stream() )
+ {
+ m_reporterPrefs.shouldRedirectStdOut = true;
+ }
+
+ virtual ~JunitReporter() CATCH_OVERRIDE;
+
+ static std::string getDescription() {
+ return "Reports test results in an XML format that looks like Ant's junitreport target";
+ }
+
+ virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
+
+ virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
+ CumulativeReporterBase::testRunStarting( runInfo );
+ xml.startElement( "testsuites" );
+ }
+
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
+ suiteTimer.start();
+ stdOutForSuite.str("");
+ stdErrForSuite.str("");
+ unexpectedExceptions = 0;
+ CumulativeReporterBase::testGroupStarting( groupInfo );
+ }
+
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+ if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
+ unexpectedExceptions++;
+ return CumulativeReporterBase::assertionEnded( assertionStats );
+ }
+
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+ stdOutForSuite << testCaseStats.stdOut;
+ stdErrForSuite << testCaseStats.stdErr;
+ CumulativeReporterBase::testCaseEnded( testCaseStats );
+ }
+
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+ double suiteTime = suiteTimer.getElapsedSeconds();
+ CumulativeReporterBase::testGroupEnded( testGroupStats );
+ writeGroup( *m_testGroups.back(), suiteTime );
+ }
+
+ virtual void testRunEndedCumulative() CATCH_OVERRIDE {
+ xml.endElement();
+ }
+
+ void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
+ XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
+ TestGroupStats const& stats = groupNode.value;
+ xml.writeAttribute( "name", stats.groupInfo.name );
+ xml.writeAttribute( "errors", unexpectedExceptions );
+ xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
+ xml.writeAttribute( "tests", stats.totals.assertions.total() );
+ xml.writeAttribute( "hostname", "tbd" ); // !TBD
+ if( m_config->showDurations() == ShowDurations::Never )
+ xml.writeAttribute( "time", "" );
+ else
+ xml.writeAttribute( "time", suiteTime );
+ xml.writeAttribute( "timestamp", getCurrentTimestamp() );
+
+ // Write test cases
+ for( TestGroupNode::ChildNodes::const_iterator
+ it = groupNode.children.begin(), itEnd = groupNode.children.end();
+ it != itEnd;
+ ++it )
+ writeTestCase( **it );
+
+ xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
+ xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
+ }
+
+ void writeTestCase( TestCaseNode const& testCaseNode ) {
+ TestCaseStats const& stats = testCaseNode.value;
+
+ // All test cases have exactly one section - which represents the
+ // test case itself. That section may have 0-n nested sections
+ assert( testCaseNode.children.size() == 1 );
+ SectionNode const& rootSection = *testCaseNode.children.front();
+
+ std::string className = stats.testInfo.className;
+
+ if( className.empty() ) {
+ if( rootSection.childSections.empty() )
+ className = "global";
+ }
+ writeSection( className, "", rootSection );
+ }
+
+ void writeSection( std::string const& className,
+ std::string const& rootName,
+ SectionNode const& sectionNode ) {
+ std::string name = trim( sectionNode.stats.sectionInfo.name );
+ if( !rootName.empty() )
+ name = rootName + '/' + name;
+
+ if( !sectionNode.assertions.empty() ||
+ !sectionNode.stdOut.empty() ||
+ !sectionNode.stdErr.empty() ) {
+ XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
+ if( className.empty() ) {
+ xml.writeAttribute( "classname", name );
+ xml.writeAttribute( "name", "root" );
+ }
+ else {
+ xml.writeAttribute( "classname", className );
+ xml.writeAttribute( "name", name );
+ }
+ xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
+
+ writeAssertions( sectionNode );
+
+ if( !sectionNode.stdOut.empty() )
+ xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
+ if( !sectionNode.stdErr.empty() )
+ xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
+ }
+ for( SectionNode::ChildSections::const_iterator
+ it = sectionNode.childSections.begin(),
+ itEnd = sectionNode.childSections.end();
+ it != itEnd;
+ ++it )
+ if( className.empty() )
+ writeSection( name, "", **it );
+ else
+ writeSection( className, name, **it );
+ }
+
+ void writeAssertions( SectionNode const& sectionNode ) {
+ for( SectionNode::Assertions::const_iterator
+ it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
+ it != itEnd;
+ ++it )
+ writeAssertion( *it );
+ }
+ void writeAssertion( AssertionStats const& stats ) {
+ AssertionResult const& result = stats.assertionResult;
+ if( !result.isOk() ) {
+ std::string elementName;
+ switch( result.getResultType() ) {
+ case ResultWas::ThrewException:
+ case ResultWas::FatalErrorCondition:
+ elementName = "error";
+ break;
+ case ResultWas::ExplicitFailure:
+ elementName = "failure";
+ break;
+ case ResultWas::ExpressionFailed:
+ elementName = "failure";
+ break;
+ case ResultWas::DidntThrowException:
+ elementName = "failure";
+ break;
+
+ // We should never see these here:
+ case ResultWas::Info:
+ case ResultWas::Warning:
+ case ResultWas::Ok:
+ case ResultWas::Unknown:
+ case ResultWas::FailureBit:
+ case ResultWas::Exception:
+ elementName = "internalError";
+ break;
+ }
+
+ XmlWriter::ScopedElement e = xml.scopedElement( elementName );
+
+ xml.writeAttribute( "message", result.getExpandedExpression() );
+ xml.writeAttribute( "type", result.getTestMacroName() );
+
+ std::ostringstream oss;
+ if( !result.getMessage().empty() )
+ oss << result.getMessage() << '\n';
+ for( std::vector<MessageInfo>::const_iterator
+ it = stats.infoMessages.begin(),
+ itEnd = stats.infoMessages.end();
+ it != itEnd;
+ ++it )
+ if( it->type == ResultWas::Info )
+ oss << it->message << '\n';
+
+ oss << "at " << result.getSourceInfo();
+ xml.writeText( oss.str(), false );
+ }
+ }
+
+ XmlWriter xml;
+ Timer suiteTimer;
+ std::ostringstream stdOutForSuite;
+ std::ostringstream stdErrForSuite;
+ unsigned int unexpectedExceptions;
+ };
+
+ INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_console.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
+
+#include <cfloat>
+#include <cstdio>
+
+namespace Catch {
+
+ namespace {
+ // Because formatting using c++ streams is stateful, drop down to C is required
+ // Alternatively we could use stringstream, but its performance is... not good.
+ std::string getFormattedDuration( double duration ) {
+ // Max exponent + 1 is required to represent the whole part
+ // + 1 for decimal point
+ // + 3 for the 3 decimal places
+ // + 1 for null terminator
+ const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
+ char buffer[maxDoubleSize];
+#ifdef _MSC_VER
+ sprintf_s(buffer, "%.3f", duration);
+#else
+ sprintf(buffer, "%.3f", duration);
+#endif
+ return std::string(buffer);
+ }
+ }
+
+ struct ConsoleReporter : StreamingReporterBase {
+ ConsoleReporter( ReporterConfig const& _config )
+ : StreamingReporterBase( _config ),
+ m_headerPrinted( false )
+ {}
+
+ virtual ~ConsoleReporter() CATCH_OVERRIDE;
+ static std::string getDescription() {
+ return "Reports test results as plain lines of text";
+ }
+
+ virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
+ stream << "No test cases matched '" << spec << '\'' << std::endl;
+ }
+
+ virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
+ }
+
+ virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
+ AssertionResult const& result = _assertionStats.assertionResult;
+
+ bool printInfoMessages = true;
+
+ // Drop out if result was successful and we're not printing those
+ if( !m_config->includeSuccessfulResults() && result.isOk() ) {
+ if( result.getResultType() != ResultWas::Warning )
+ return false;
+ printInfoMessages = false;
+ }
+
+ lazyPrint();
+
+ AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
+ printer.print();
+ stream << std::endl;
+ return true;
+ }
+
+ virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
+ m_headerPrinted = false;
+ StreamingReporterBase::sectionStarting( _sectionInfo );
+ }
+ virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
+ if( _sectionStats.missingAssertions ) {
+ lazyPrint();
+ Colour colour( Colour::ResultError );
+ if( m_sectionStack.size() > 1 )
+ stream << "\nNo assertions in section";
+ else
+ stream << "\nNo assertions in test case";
+ stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
+ }
+ if( m_config->showDurations() == ShowDurations::Always ) {
+ stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
+ }
+ if( m_headerPrinted ) {
+ m_headerPrinted = false;
+ }
+ StreamingReporterBase::sectionEnded( _sectionStats );
+ }
+
+ virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
+ StreamingReporterBase::testCaseEnded( _testCaseStats );
+ m_headerPrinted = false;
+ }
+ virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
+ if( currentGroupInfo.used ) {
+ printSummaryDivider();
+ stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
+ printTotals( _testGroupStats.totals );
+ stream << '\n' << std::endl;
+ }
+ StreamingReporterBase::testGroupEnded( _testGroupStats );
+ }
+ virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
+ printTotalsDivider( _testRunStats.totals );
+ printTotals( _testRunStats.totals );
+ stream << std::endl;
+ StreamingReporterBase::testRunEnded( _testRunStats );
+ }
+
+ private:
+
+ class AssertionPrinter {
+ void operator= ( AssertionPrinter const& );
+ public:
+ AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
+ : stream( _stream ),
+ stats( _stats ),
+ result( _stats.assertionResult ),
+ colour( Colour::None ),
+ message( result.getMessage() ),
+ messages( _stats.infoMessages ),
+ printInfoMessages( _printInfoMessages )
+ {
+ switch( result.getResultType() ) {
+ case ResultWas::Ok:
+ colour = Colour::Success;
+ passOrFail = "PASSED";
+ //if( result.hasMessage() )
+ if( _stats.infoMessages.size() == 1 )
+ messageLabel = "with message";
+ if( _stats.infoMessages.size() > 1 )
+ messageLabel = "with messages";
+ break;
+ case ResultWas::ExpressionFailed:
+ if( result.isOk() ) {
+ colour = Colour::Success;
+ passOrFail = "FAILED - but was ok";
+ }
+ else {
+ colour = Colour::Error;
+ passOrFail = "FAILED";
+ }
+ if( _stats.infoMessages.size() == 1 )
+ messageLabel = "with message";
+ if( _stats.infoMessages.size() > 1 )
+ messageLabel = "with messages";
+ break;
+ case ResultWas::ThrewException:
+ colour = Colour::Error;
+ passOrFail = "FAILED";
+ messageLabel = "due to unexpected exception with message";
+ break;
+ case ResultWas::FatalErrorCondition:
+ colour = Colour::Error;
+ passOrFail = "FAILED";
+ messageLabel = "due to a fatal error condition";
+ break;
+ case ResultWas::DidntThrowException:
+ colour = Colour::Error;
+ passOrFail = "FAILED";
+ messageLabel = "because no exception was thrown where one was expected";
+ break;
+ case ResultWas::Info:
+ messageLabel = "info";
+ break;
+ case ResultWas::Warning:
+ messageLabel = "warning";
+ break;
+ case ResultWas::ExplicitFailure:
+ passOrFail = "FAILED";
+ colour = Colour::Error;
+ if( _stats.infoMessages.size() == 1 )
+ messageLabel = "explicitly with message";
+ if( _stats.infoMessages.size() > 1 )
+ messageLabel = "explicitly with messages";
+ break;
+ // These cases are here to prevent compiler warnings
+ case ResultWas::Unknown:
+ case ResultWas::FailureBit:
+ case ResultWas::Exception:
+ passOrFail = "** internal error **";
+ colour = Colour::Error;
+ break;
+ }
+ }
+
+ void print() const {
+ printSourceInfo();
+ if( stats.totals.assertions.total() > 0 ) {
+ if( result.isOk() )
+ stream << '\n';
+ printResultType();
+ printOriginalExpression();
+ printReconstructedExpression();
+ }
+ else {
+ stream << '\n';
+ }
+ printMessage();
+ }
+
+ private:
+ void printResultType() const {
+ if( !passOrFail.empty() ) {
+ Colour colourGuard( colour );
+ stream << passOrFail << ":\n";
+ }
+ }
+ void printOriginalExpression() const {
+ if( result.hasExpression() ) {
+ Colour colourGuard( Colour::OriginalExpression );
+ stream << " ";
+ stream << result.getExpressionInMacro();
+ stream << '\n';
+ }
+ }
+ void printReconstructedExpression() const {
+ if( result.hasExpandedExpression() ) {
+ stream << "with expansion:\n";
+ Colour colourGuard( Colour::ReconstructedExpression );
+ stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
+ }
+ }
+ void printMessage() const {
+ if( !messageLabel.empty() )
+ stream << messageLabel << ':' << '\n';
+ for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
+ it != itEnd;
+ ++it ) {
+ // If this assertion is a warning ignore any INFO messages
+ if( printInfoMessages || it->type != ResultWas::Info )
+ stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
+ }
+ }
+ void printSourceInfo() const {
+ Colour colourGuard( Colour::FileName );
+ stream << result.getSourceInfo() << ": ";
+ }
+
+ std::ostream& stream;
+ AssertionStats const& stats;
+ AssertionResult const& result;
+ Colour::Code colour;
+ std::string passOrFail;
+ std::string messageLabel;
+ std::string message;
+ std::vector<MessageInfo> messages;
+ bool printInfoMessages;
+ };
+
+ void lazyPrint() {
+
+ if( !currentTestRunInfo.used )
+ lazyPrintRunInfo();
+ if( !currentGroupInfo.used )
+ lazyPrintGroupInfo();
+
+ if( !m_headerPrinted ) {
+ printTestCaseAndSectionHeader();
+ m_headerPrinted = true;
+ }
+ }
+ void lazyPrintRunInfo() {
+ stream << '\n' << getLineOfChars<'~'>() << '\n';
+ Colour colour( Colour::SecondaryText );
+ stream << currentTestRunInfo->name
+ << " is a Catch v" << libraryVersion << " host application.\n"
+ << "Run with -? for options\n\n";
+
+ if( m_config->rngSeed() != 0 )
+ stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
+
+ currentTestRunInfo.used = true;
+ }
+ void lazyPrintGroupInfo() {
+ if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
+ printClosedHeader( "Group: " + currentGroupInfo->name );
+ currentGroupInfo.used = true;
+ }
+ }
+ void printTestCaseAndSectionHeader() {
+ assert( !m_sectionStack.empty() );
+ printOpenHeader( currentTestCaseInfo->name );
+
+ if( m_sectionStack.size() > 1 ) {
+ Colour colourGuard( Colour::Headers );
+
+ std::vector<SectionInfo>::const_iterator
+ it = m_sectionStack.begin()+1, // Skip first section (test case)
+ itEnd = m_sectionStack.end();
+ for( ; it != itEnd; ++it )
+ printHeaderString( it->name, 2 );
+ }
+
+ SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
+
+ if( !lineInfo.empty() ){
+ stream << getLineOfChars<'-'>() << '\n';
+ Colour colourGuard( Colour::FileName );
+ stream << lineInfo << '\n';
+ }
+ stream << getLineOfChars<'.'>() << '\n' << std::endl;
+ }
+
+ void printClosedHeader( std::string const& _name ) {
+ printOpenHeader( _name );
+ stream << getLineOfChars<'.'>() << '\n';
+ }
+ void printOpenHeader( std::string const& _name ) {
+ stream << getLineOfChars<'-'>() << '\n';
+ {
+ Colour colourGuard( Colour::Headers );
+ printHeaderString( _name );
+ }
+ }
+
+ // if string has a : in first line will set indent to follow it on
+ // subsequent lines
+ void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
+ std::size_t i = _string.find( ": " );
+ if( i != std::string::npos )
+ i+=2;
+ else
+ i = 0;
+ stream << Text( _string, TextAttributes()
+ .setIndent( indent+i)
+ .setInitialIndent( indent ) ) << '\n';
+ }
+
+ struct SummaryColumn {
+
+ SummaryColumn( std::string const& _label, Colour::Code _colour )
+ : label( _label ),
+ colour( _colour )
+ {}
+ SummaryColumn addRow( std::size_t count ) {
+ std::ostringstream oss;
+ oss << count;
+ std::string row = oss.str();
+ for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
+ while( it->size() < row.size() )
+ *it = ' ' + *it;
+ while( it->size() > row.size() )
+ row = ' ' + row;
+ }
+ rows.push_back( row );
+ return *this;
+ }
+
+ std::string label;
+ Colour::Code colour;
+ std::vector<std::string> rows;
+
+ };
+
+ void printTotals( Totals const& totals ) {
+ if( totals.testCases.total() == 0 ) {
+ stream << Colour( Colour::Warning ) << "No tests ran\n";
+ }
+ else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
+ stream << Colour( Colour::ResultSuccess ) << "All tests passed";
+ stream << " ("
+ << pluralise( totals.assertions.passed, "assertion" ) << " in "
+ << pluralise( totals.testCases.passed, "test case" ) << ')'
+ << '\n';
+ }
+ else {
+
+ std::vector<SummaryColumn> columns;
+ columns.push_back( SummaryColumn( "", Colour::None )
+ .addRow( totals.testCases.total() )
+ .addRow( totals.assertions.total() ) );
+ columns.push_back( SummaryColumn( "passed", Colour::Success )
+ .addRow( totals.testCases.passed )
+ .addRow( totals.assertions.passed ) );
+ columns.push_back( SummaryColumn( "failed", Colour::ResultError )
+ .addRow( totals.testCases.failed )
+ .addRow( totals.assertions.failed ) );
+ columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
+ .addRow( totals.testCases.failedButOk )
+ .addRow( totals.assertions.failedButOk ) );
+
+ printSummaryRow( "test cases", columns, 0 );
+ printSummaryRow( "assertions", columns, 1 );
+ }
+ }
+ void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
+ for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
+ std::string value = it->rows[row];
+ if( it->label.empty() ) {
+ stream << label << ": ";
+ if( value != "0" )
+ stream << value;
+ else
+ stream << Colour( Colour::Warning ) << "- none -";
+ }
+ else if( value != "0" ) {
+ stream << Colour( Colour::LightGrey ) << " | ";
+ stream << Colour( it->colour )
+ << value << ' ' << it->label;
+ }
+ }
+ stream << '\n';
+ }
+
+ static std::size_t makeRatio( std::size_t number, std::size_t total ) {
+ std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
+ return ( ratio == 0 && number > 0 ) ? 1 : ratio;
+ }
+ static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
+ if( i > j && i > k )
+ return i;
+ else if( j > k )
+ return j;
+ else
+ return k;
+ }
+
+ void printTotalsDivider( Totals const& totals ) {
+ if( totals.testCases.total() > 0 ) {
+ std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
+ std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
+ std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
+ while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
+ findMax( failedRatio, failedButOkRatio, passedRatio )++;
+ while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
+ findMax( failedRatio, failedButOkRatio, passedRatio )--;
+
+ stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
+ stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
+ if( totals.testCases.allPassed() )
+ stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
+ else
+ stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
+ }
+ else {
+ stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
+ }
+ stream << '\n';
+ }
+ void printSummaryDivider() {
+ stream << getLineOfChars<'-'>() << '\n';
+ }
+
+ private:
+ bool m_headerPrinted;
+ };
+
+ INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
+
+} // end namespace Catch
+
+// #included from: ../reporters/catch_reporter_compact.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
+
+namespace Catch {
+
+ struct CompactReporter : StreamingReporterBase {
+
+ CompactReporter( ReporterConfig const& _config )
+ : StreamingReporterBase( _config )
+ {}
+
+ virtual ~CompactReporter();
+
+ static std::string getDescription() {
+ return "Reports test results on a single line, suitable for IDEs";
+ }
+
+ virtual ReporterPreferences getPreferences() const {
+ ReporterPreferences prefs;
+ prefs.shouldRedirectStdOut = false;
+ return prefs;
+ }
+
+ virtual void noMatchingTestCases( std::string const& spec ) {
+ stream << "No test cases matched '" << spec << '\'' << std::endl;
+ }
+
+ virtual void assertionStarting( AssertionInfo const& ) {
+ }
+
+ virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
+ AssertionResult const& result = _assertionStats.assertionResult;
+
+ bool printInfoMessages = true;
+
+ // Drop out if result was successful and we're not printing those
+ if( !m_config->includeSuccessfulResults() && result.isOk() ) {
+ if( result.getResultType() != ResultWas::Warning )
+ return false;
+ printInfoMessages = false;
+ }
+
+ AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
+ printer.print();
+
+ stream << std::endl;
+ return true;
+ }
+
+ virtual void testRunEnded( TestRunStats const& _testRunStats ) {
+ printTotals( _testRunStats.totals );
+ stream << '\n' << std::endl;
+ StreamingReporterBase::testRunEnded( _testRunStats );
+ }
+
+ private:
+ class AssertionPrinter {
+ void operator= ( AssertionPrinter const& );
+ public:
+ AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
+ : stream( _stream )
+ , stats( _stats )
+ , result( _stats.assertionResult )
+ , messages( _stats.infoMessages )
+ , itMessage( _stats.infoMessages.begin() )
+ , printInfoMessages( _printInfoMessages )
+ {}
+
+ void print() {
+ printSourceInfo();
+
+ itMessage = messages.begin();
+
+ switch( result.getResultType() ) {
+ case ResultWas::Ok:
+ printResultType( Colour::ResultSuccess, passedString() );
+ printOriginalExpression();
+ printReconstructedExpression();
+ if ( ! result.hasExpression() )
+ printRemainingMessages( Colour::None );
+ else
+ printRemainingMessages();
+ break;
+ case ResultWas::ExpressionFailed:
+ if( result.isOk() )
+ printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
+ else
+ printResultType( Colour::Error, failedString() );
+ printOriginalExpression();
+ printReconstructedExpression();
+ printRemainingMessages();
+ break;
+ case ResultWas::ThrewException:
+ printResultType( Colour::Error, failedString() );
+ printIssue( "unexpected exception with message:" );
+ printMessage();
+ printExpressionWas();
+ printRemainingMessages();
+ break;
+ case ResultWas::FatalErrorCondition:
+ printResultType( Colour::Error, failedString() );
+ printIssue( "fatal error condition with message:" );
+ printMessage();
+ printExpressionWas();
+ printRemainingMessages();
+ break;
+ case ResultWas::DidntThrowException:
+ printResultType( Colour::Error, failedString() );
+ printIssue( "expected exception, got none" );
+ printExpressionWas();
+ printRemainingMessages();
+ break;
+ case ResultWas::Info:
+ printResultType( Colour::None, "info" );
+ printMessage();
+ printRemainingMessages();
+ break;
+ case ResultWas::Warning:
+ printResultType( Colour::None, "warning" );
+ printMessage();
+ printRemainingMessages();
+ break;
+ case ResultWas::ExplicitFailure:
+ printResultType( Colour::Error, failedString() );
+ printIssue( "explicitly" );
+ printRemainingMessages( Colour::None );
+ break;
+ // These cases are here to prevent compiler warnings
+ case ResultWas::Unknown:
+ case ResultWas::FailureBit:
+ case ResultWas::Exception:
+ printResultType( Colour::Error, "** internal error **" );
+ break;
+ }
+ }
+
+ private:
+ // Colour::LightGrey
+
+ static Colour::Code dimColour() { return Colour::FileName; }
+
+#ifdef CATCH_PLATFORM_MAC
+ static const char* failedString() { return "FAILED"; }
+ static const char* passedString() { return "PASSED"; }
+#else
+ static const char* failedString() { return "failed"; }
+ static const char* passedString() { return "passed"; }
+#endif
+
+ void printSourceInfo() const {
+ Colour colourGuard( Colour::FileName );
+ stream << result.getSourceInfo() << ':';
+ }
+
+ void printResultType( Colour::Code colour, std::string passOrFail ) const {
+ if( !passOrFail.empty() ) {
+ {
+ Colour colourGuard( colour );
+ stream << ' ' << passOrFail;
+ }
+ stream << ':';
+ }
+ }
+
+ void printIssue( std::string issue ) const {
+ stream << ' ' << issue;
+ }
+
+ void printExpressionWas() {
+ if( result.hasExpression() ) {
+ stream << ';';
+ {
+ Colour colour( dimColour() );
+ stream << " expression was:";
+ }
+ printOriginalExpression();
+ }
+ }
+
+ void printOriginalExpression() const {
+ if( result.hasExpression() ) {
+ stream << ' ' << result.getExpression();
+ }
+ }
+
+ void printReconstructedExpression() const {
+ if( result.hasExpandedExpression() ) {
+ {
+ Colour colour( dimColour() );
+ stream << " for: ";
+ }
+ stream << result.getExpandedExpression();
+ }
+ }
+
+ void printMessage() {
+ if ( itMessage != messages.end() ) {
+ stream << " '" << itMessage->message << '\'';
+ ++itMessage;
+ }
+ }
+
+ void printRemainingMessages( Colour::Code colour = dimColour() ) {
+ if ( itMessage == messages.end() )
+ return;
+
+ // using messages.end() directly yields compilation error:
+ std::vector<MessageInfo>::const_iterator itEnd = messages.end();
+ const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
+
+ {
+ Colour colourGuard( colour );
+ stream << " with " << pluralise( N, "message" ) << ':';
+ }
+
+ for(; itMessage != itEnd; ) {
+ // If this assertion is a warning ignore any INFO messages
+ if( printInfoMessages || itMessage->type != ResultWas::Info ) {
+ stream << " '" << itMessage->message << '\'';
+ if ( ++itMessage != itEnd ) {
+ Colour colourGuard( dimColour() );
+ stream << " and";
+ }
+ }
+ }
+ }
+
+ private:
+ std::ostream& stream;
+ AssertionStats const& stats;
+ AssertionResult const& result;
+ std::vector<MessageInfo> messages;
+ std::vector<MessageInfo>::const_iterator itMessage;
+ bool printInfoMessages;
+ };
+
+ // Colour, message variants:
+ // - white: No tests ran.
+ // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
+ // - white: Passed [both/all] N test cases (no assertions).
+ // - red: Failed N tests cases, failed M assertions.
+ // - green: Passed [both/all] N tests cases with M assertions.
+
+ std::string bothOrAll( std::size_t count ) const {
+ return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
+ }
+
+ void printTotals( const Totals& totals ) const {
+ if( totals.testCases.total() == 0 ) {
+ stream << "No tests ran.";
+ }
+ else if( totals.testCases.failed == totals.testCases.total() ) {
+ Colour colour( Colour::ResultError );
+ const std::string qualify_assertions_failed =
+ totals.assertions.failed == totals.assertions.total() ?
+ bothOrAll( totals.assertions.failed ) : std::string();
+ stream <<
+ "Failed " << bothOrAll( totals.testCases.failed )
+ << pluralise( totals.testCases.failed, "test case" ) << ", "
+ "failed " << qualify_assertions_failed <<
+ pluralise( totals.assertions.failed, "assertion" ) << '.';
+ }
+ else if( totals.assertions.total() == 0 ) {
+ stream <<
+ "Passed " << bothOrAll( totals.testCases.total() )
+ << pluralise( totals.testCases.total(), "test case" )
+ << " (no assertions).";
+ }
+ else if( totals.assertions.failed ) {
+ Colour colour( Colour::ResultError );
+ stream <<
+ "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
+ "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
+ }
+ else {
+ Colour colour( Colour::ResultSuccess );
+ stream <<
+ "Passed " << bothOrAll( totals.testCases.passed )
+ << pluralise( totals.testCases.passed, "test case" ) <<
+ " with " << pluralise( totals.assertions.passed, "assertion" ) << '.';
+ }
+ }
+ };
+
+ INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
+
+} // end namespace Catch
+
+namespace Catch {
+ // These are all here to avoid warnings about not having any out of line
+ // virtual methods
+ NonCopyable::~NonCopyable() {}
+ IShared::~IShared() {}
+ IStream::~IStream() CATCH_NOEXCEPT {}
+ FileStream::~FileStream() CATCH_NOEXCEPT {}
+ CoutStream::~CoutStream() CATCH_NOEXCEPT {}
+ DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
+ StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
+ IContext::~IContext() {}
+ IResultCapture::~IResultCapture() {}
+ ITestCase::~ITestCase() {}
+ ITestCaseRegistry::~ITestCaseRegistry() {}
+ IRegistryHub::~IRegistryHub() {}
+ IMutableRegistryHub::~IMutableRegistryHub() {}
+ IExceptionTranslator::~IExceptionTranslator() {}
+ IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
+ IReporter::~IReporter() {}
+ IReporterFactory::~IReporterFactory() {}
+ IReporterRegistry::~IReporterRegistry() {}
+ IStreamingReporter::~IStreamingReporter() {}
+ AssertionStats::~AssertionStats() {}
+ SectionStats::~SectionStats() {}
+ TestCaseStats::~TestCaseStats() {}
+ TestGroupStats::~TestGroupStats() {}
+ TestRunStats::~TestRunStats() {}
+ CumulativeReporterBase::SectionNode::~SectionNode() {}
+ CumulativeReporterBase::~CumulativeReporterBase() {}
+
+ StreamingReporterBase::~StreamingReporterBase() {}
+ ConsoleReporter::~ConsoleReporter() {}
+ CompactReporter::~CompactReporter() {}
+ IRunner::~IRunner() {}
+ IMutableContext::~IMutableContext() {}
+ IConfig::~IConfig() {}
+ XmlReporter::~XmlReporter() {}
+ JunitReporter::~JunitReporter() {}
+ TestRegistry::~TestRegistry() {}
+ FreeFunctionTestCase::~FreeFunctionTestCase() {}
+ IGeneratorInfo::~IGeneratorInfo() {}
+ IGeneratorsForTest::~IGeneratorsForTest() {}
+ WildcardPattern::~WildcardPattern() {}
+ TestSpec::Pattern::~Pattern() {}
+ TestSpec::NamePattern::~NamePattern() {}
+ TestSpec::TagPattern::~TagPattern() {}
+ TestSpec::ExcludedPattern::~ExcludedPattern() {}
+
+ void Config::dummy() {}
+
+ namespace TestCaseTracking {
+ ITracker::~ITracker() {}
+ TrackerBase::~TrackerBase() {}
+ SectionTracker::~SectionTracker() {}
+ IndexTracker::~IndexTracker() {}
+ }
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+#endif
+
+#ifdef CATCH_CONFIG_MAIN
+// #included from: internal/catch_default_main.hpp
+#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
+
+#ifndef __OBJC__
+
+// Standard C/C++ main entry point
+int main (int argc, char * argv[]) {
+ int result = Catch::Session().run( argc, argv );
+ return ( result < 0xff ? result : 0xff );
+}
+
+#else // __OBJC__
+
+// Objective-C entry point
+int main (int argc, char * const argv[]) {
+#if !CATCH_ARC_ENABLED
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+#endif
+
+ Catch::registerTestMethods();
+ int result = Catch::Session().run( argc, (char* const*)argv );
+
+#if !CATCH_ARC_ENABLED
+ [pool drain];
+#endif
+
+ return ( result < 0xff ? result : 0xff );
+}
+
+#endif // __OBJC__
+
+#endif
+
+#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
+# undef CLARA_CONFIG_MAIN
+#endif
+
+//////
+
+// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
+#ifdef CATCH_CONFIG_PREFIX_ALL
+
+#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
+#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
+
+#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
+#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
+#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
+#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
+
+#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
+#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
+#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
+#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
+#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
+
+#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" )
+#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
+#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
+#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
+
+#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
+#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
+
+#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
+#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
+#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
+#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
+#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+ #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
+ #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
+ #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+ #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
+ #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+ #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
+ #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
+#else
+ #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
+ #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
+ #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
+ #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
+ #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
+ #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
+ #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
+#endif
+#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
+
+#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
+#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
+
+#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
+
+// "BDD-style" convenience wrappers
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
+#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
+#else
+#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
+#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
+#endif
+#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
+#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
+#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
+#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
+#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
+
+// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
+#else
+
+#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
+#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
+
+#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
+#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
+#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
+#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
+
+#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
+#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
+#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
+#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
+#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
+
+#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
+#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
+#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
+#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
+
+#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
+#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
+
+#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
+#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
+#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
+#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
+#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
+
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+ #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
+ #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
+ #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+ #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
+ #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
+ #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
+ #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
+#else
+ #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
+ #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
+ #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
+ #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
+ #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
+ #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
+ #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
+#endif
+#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
+
+#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
+#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
+
+#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
+
+#endif
+
+#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
+
+// "BDD-style" convenience wrappers
+#ifdef CATCH_CONFIG_VARIADIC_MACROS
+#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
+#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
+#else
+#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
+#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
+#endif
+#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
+#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
+#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
+#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
+#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
+
+using Catch::Detail::Approx;
+
+#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+
diff --git a/fuzzylite/test/hedge/HedgeFunctionTest.cpp b/fuzzylite/test/hedge/HedgeFunctionTest.cpp
new file mode 100644
index 0000000..dab70f5
--- /dev/null
+++ b/fuzzylite/test/hedge/HedgeFunctionTest.cpp
@@ -0,0 +1,141 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ /**
+ * Tests: hedge/HedgeFunction
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ static std::string hedgeEngine() {
+#ifdef FL_CPP98
+ return "";
+#else
+ return R""(
+Engine: Sugeno-Tip-Calculator
+InputVariable: FoodQuality
+ enabled: true
+ range: 1.000 10.000
+ lock-range: false
+ term: Bad Trapezoid 0.000 1.000 3.000 7.000
+ term: Good Trapezoid 3.000 7.000 10.000 11.000
+InputVariable: Service
+ enabled: true
+ range: 1.000 10.000
+ lock-range: false
+ term: Bad Trapezoid 0.000 1.000 3.000 7.000
+ term: Good Trapezoid 3.000 7.000 10.000 11.000
+OutputVariable: CheapTip
+ enabled: true
+ range: 5.000 25.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: Low Constant 10.000
+ term: Medium Constant 15.000
+ term: High Constant 20.000
+OutputVariable: AverageTip
+ enabled: true
+ range: 5.000 25.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: Low Constant 10.000
+ term: Medium Constant 15.000
+ term: High Constant 20.000
+OutputVariable: GenerousTip
+ enabled: true
+ range: 5.000 25.000
+ lock-range: false
+ aggregation: none
+ defuzzifier: WeightedAverage TakagiSugeno
+ default: nan
+ lock-previous: false
+ term: Low Constant 10.000
+ term: Medium Constant 15.000
+ term: High Constant 20.000
+RuleBlock:
+ enabled: true
+ conjunction: EinsteinProduct
+ disjunction: none
+ implication: none
+ activation: General
+ rule: if FoodQuality is extremely Bad and Service is extremely Bad then CheapTip is extremely Low and AverageTip is very Low and GenerousTip is Low
+ rule: if FoodQuality is Good and Service is extremely Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium
+ rule: if FoodQuality is very Good and Service is very Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High
+ rule: if FoodQuality is Bad and Service is Bad then CheapTip is Low and AverageTip is Low and GenerousTip is Medium
+ rule: if FoodQuality is Good and Service is Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is High
+ rule: if FoodQuality is extremely Good and Service is Bad then CheapTip is Low and AverageTip is Medium and GenerousTip is very High
+ rule: if FoodQuality is Bad and Service is Good then CheapTip is Low and AverageTip is Medium and GenerousTip is High
+ rule: if FoodQuality is Good and Service is Good then CheapTip is Medium and AverageTip is Medium and GenerousTip is very High
+ rule: if FoodQuality is very Bad and Service is very Good then CheapTip is Low and AverageTip is Medium and GenerousTip is High
+ rule: if FoodQuality is very very Good and Service is very very Good then CheapTip is High and AverageTip is very High and GenerousTip is extremely High
+)"";
+#endif
+ }
+
+ static Hedge* myVeryConstructor() {
+ return new HedgeFunction("x*x");
+ }
+
+ static Hedge* myExtraVeryConstructor() {
+ return new HedgeFunction("x*x*x");
+ }
+
+ TEST_CASE("HedgeFunction x*x is equivalent to hedge Very", "[hedge][function]") {
+#ifdef FL_CPP98
+ FL_IUNUSED(&(hedgeEngine));
+ FL_IUNUSED(&(myVeryConstructor));
+ FL_IUNUSED(&(myExtraVeryConstructor));
+ WARN("Test only runs with -DFL_CPP98=OFF");
+ return;
+#else
+ std::string fllEngine = hedgeEngine();
+ //Import using regular hedge very
+ FL_unique_ptr<Engine> engine(FllImporter().fromString(fllEngine));
+ std::string fldVery = FldExporter().toString(engine.get(), 1024);
+
+ //Replace hedge very with a HedgeFunction(x*x)
+ HedgeFactory* factory = FactoryManager::instance()->hedge();
+ factory->registerConstructor("very", &(myVeryConstructor));
+ //Import again with new HedgeFunction
+ engine.reset(FllImporter().fromString(fllEngine));
+ std::string anotherFld = FldExporter().toString(engine.get(), 1024);
+ //Both must be equal
+ CHECK(fldVery == anotherFld);
+
+ //Replace very with a HedgeFunction(x*x*x)
+ factory->registerConstructor("very", &(myExtraVeryConstructor));
+
+ engine.reset(FllImporter().fromString(fllEngine));
+ anotherFld = FldExporter().toString(engine.get(), 1024);
+
+ //Must be different
+ CHECK(fldVery != anotherFld);
+#endif
+ }
+
+}
diff --git a/fuzzylite/test/imex/FldExporterTest.cpp b/fuzzylite/test/imex/FldExporterTest.cpp
new file mode 100644
index 0000000..e312f1d
--- /dev/null
+++ b/fuzzylite/test/imex/FldExporterTest.cpp
@@ -0,0 +1,45 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ TEST_CASE("Exports same number of values in scopes", "[imex]") {
+ FL_unique_ptr<Engine> engine(Console::mamdani());
+ engine->addInputVariable(new InputVariable("Dummy2", 0, 1));
+ engine->addInputVariable(new InputVariable("Dummy3", 0, 1));
+ engine->addInputVariable(new InputVariable("Dummy4", 0, 1));
+
+ FldExporter exporter("\t");
+ exporter.setExportHeader(false);
+
+ int valuesEachVariable = 3;
+ int expectedValues = (int) std::pow(valuesEachVariable, 1.0 * engine->numberOfInputVariables());
+
+ std::string eachVariable = exporter.toString(engine.get(), valuesEachVariable, FldExporter::EachVariable);
+ // FL_LOG("eachVariable:\n" << eachVariable);
+ std::vector<std::string> linesByVariable = Op::split(eachVariable, "\n");
+ CHECK(int(linesByVariable.size()) == expectedValues);
+
+ std::string allVariables = exporter.toString(engine.get(), expectedValues, FldExporter::AllVariables);
+ std::vector<std::string> linesAllVariables = Op::split(allVariables, "\n");
+ // FL_LOG("allVariables:\n" << allVariables);
+ CHECK(int(linesAllVariables.size()) == expectedValues);
+ }
+
+}
diff --git a/fuzzylite/test/imex/FllImporterTest.cpp b/fuzzylite/test/imex/FllImporterTest.cpp
new file mode 100644
index 0000000..d31701a
--- /dev/null
+++ b/fuzzylite/test/imex/FllImporterTest.cpp
@@ -0,0 +1,56 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ TEST_CASE("Template of FuzzyLite Language works", "[imex]") {
+ std::string fllTemplate;
+#ifdef FL_CPP98
+ //ignore
+#else
+ fllTemplate = R""(
+#Template: FuzzyLite Language (FLL)
+#Engine: string
+#InputVariable: identifier
+# enabled: boolean
+# range: scalar scalar
+# term: identifier Term [parameters]
+#OutputVariable: identifier
+# enabled: boolean
+# range: scalar scalar
+# aggregation: SNorm|none
+# defuzzifier: [Defuzzifier [parameter]]|none
+# default: scalar
+# lock-previous: boolean
+# lock-range: boolean
+# term: identifier Term [parameters]
+#RuleBlock: string
+# enabled: boolean
+# conjunction: TNorm|none
+# disjunction: SNorm|none
+# implication: TNorm|none
+# rule: if antecedent then consequent with weight
+)"";
+#endif
+ FL_unique_ptr<Engine> engine(FllImporter().fromString(fllTemplate));
+ Engine empty;
+ CHECK(FllExporter().toString(engine.get()) == FllExporter().toString(&empty));
+ }
+
+}
diff --git a/fuzzylite/test/imex/RScriptExporterTest.cpp b/fuzzylite/test/imex/RScriptExporterTest.cpp
new file mode 100644
index 0000000..b6d87d8
--- /dev/null
+++ b/fuzzylite/test/imex/RScriptExporterTest.cpp
@@ -0,0 +1,103 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+#include <fstream>
+
+namespace fl {
+
+ TEST_CASE("RExporter creates plots with a single variable", "[imex]") {
+ FL_unique_ptr<Engine> engine(Console::mamdani());
+ engine->addInputVariable(new InputVariable("Dummy", 0, 1));
+
+ std::string filename("/tmp/simple-dimmer.fld");
+ {
+ std::ofstream os(filename.c_str());
+ FldExporter().write(engine.get(), os, 1024);
+ os.close();
+ }
+
+ std::ifstream is(filename.c_str());
+ std::string dummy;
+ std::getline(is, dummy); //remove header
+
+ std::ostringstream os;
+
+ RScriptExporter().writeScriptImportingDataFrame(engine.get(), os,
+ engine->getInputVariable(0), engine->getInputVariable(1),
+ "/dummy/path/to/x.fld",
+ engine->outputVariables());
+ FL_LOG(os.str());
+ }
+
+ TEST_CASE("RExporter ") {
+ std::string fll =
+ "Engine: mam21\n"
+ "InputVariable: angle\n"
+ " enabled: true\n"
+ " range: -5.000 5.000\n"
+ " lock-range: false\n"
+ " term: small Bell -5.000 5.000 8.000\n"
+ " term: big Bell 5.000 5.000 8.000\n"
+ "InputVariable: velocity\n"
+ " enabled: true\n"
+ " range: -5.000 5.000\n"
+ " lock-range: false\n"
+ " term: small Bell -5.000 5.000 2.000\n"
+ " term: big Bell 5.000 5.000 2.000\n"
+ "OutputVariable: force\n"
+ " enabled: true\n"
+ " range: -5.000 5.000\n"
+ " lock-range: false\n"
+ " aggregation: Maximum\n"
+ " defuzzifier: Centroid 200\n"
+ " default: nan\n"
+ " lock-previous: false\n"
+ " term: negBig Bell -5.000 1.670 8.000\n"
+ " term: negSmall Bell -1.670 1.670 8.000\n"
+ " term: posSmall Bell 1.670 1.670 8.000\n"
+ " term: posBig Bell 5.000 1.670 8.000\n"
+ "OutputVariable: force2\n"
+ " enabled: true\n"
+ " range: -5.000 5.000\n"
+ " lock-range: false\n"
+ " aggregation: Maximum\n"
+ " defuzzifier: Centroid 200\n"
+ " default: nan\n"
+ " lock-previous: false\n"
+ " term: negBig2 Bell -3.000 1.670 8.000\n"
+ " term: negSmall2 Bell -1.000 1.670 8.000\n"
+ " term: posSmall2 Bell 1.000 1.670 8.000\n"
+ " term: posBig2 Bell 3.000 1.670 8.000\n"
+ "RuleBlock: \n"
+ " enabled: true\n"
+ " conjunction: Minimum\n"
+ " disjunction: Maximum\n"
+ " implication: Minimum\n"
+ " activation: General\n"
+ " rule: if angle is small and velocity is small then force is negBig and force2 is posBig2\n"
+ " rule: if angle is small and velocity is big then force is negSmall and force2 is posSmall2\n"
+ " rule: if angle is big and velocity is small then force is posSmall and force2 is negSmall2\n"
+ " rule: if angle is big and velocity is big then force is posBig and force2 is negBig2\n";
+
+ Engine* engine = FllImporter().fromString(fll);
+ RScriptExporter().toFile("/tmp/mam22.R", engine,
+ engine->getInputVariable(0), engine->getInputVariable(1),
+ 1024, FldExporter::AllVariables, engine->outputVariables());
+ }
+
+}
diff --git a/fuzzylite/test/norm/NormFunctionTest.cpp b/fuzzylite/test/norm/NormFunctionTest.cpp
new file mode 100644
index 0000000..afce4c8
--- /dev/null
+++ b/fuzzylite/test/norm/NormFunctionTest.cpp
@@ -0,0 +1,202 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ /**
+ * Tests: norm/NormFunctions
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ static std::string snormEngine() {
+#ifdef FL_CPP98
+ return "";
+#else
+ return R""(
+Engine: tipper
+InputVariable: service
+ enabled: true
+ range: 0.000 10.000
+ lock-range: false
+ term: poor Gaussian 0.000 1.500
+ term: good Gaussian 5.000 1.500
+ term: excellent Gaussian 10.000 1.500
+InputVariable: food
+ enabled: true
+ range: 0.000 10.000
+ lock-range: false
+ term: rancid Trapezoid 0.000 0.000 1.000 3.000
+ term: delicious Trapezoid 7.000 9.000 10.000 10.000
+OutputVariable: tip
+ enabled: true
+ range: 0.000 30.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: cheap Triangle 0.000 5.000 10.000
+ term: average Triangle 10.000 15.000 20.000
+ term: generous Triangle 20.000 25.000 30.000
+RuleBlock:
+ enabled: true
+ conjunction: Minimum
+ disjunction: Maximum
+ implication: Minimum
+ activation: General
+ rule: if service is poor or food is rancid then tip is cheap
+ rule: if service is good then tip is average
+ rule: if service is excellent or food is delicious then tip is generous
+)"";
+#endif
+ }
+
+ static SNorm* myMaximumNorm() {
+ return new SNormFunction("max(a,b)");
+ }
+
+ static SNorm* myNotSoMaximumNorm() {
+ return new SNormFunction("max(a,b) * 0.5");
+ }
+
+ TEST_CASE("SNormFunction (max(a,b)) is equivalent to Maximum", "[snorm][maximum]") {
+#ifdef FL_CPP98
+ FL_IUNUSED(&(myMaximumNorm));
+ FL_IUNUSED(&(myNotSoMaximumNorm));
+ FL_IUNUSED(&(snormEngine));
+ WARN("Test only runs with -DFL_CPP98=OFF");
+ return;
+#else
+ std::string fllEngine = snormEngine();
+ FL_unique_ptr<Engine> engine(FllImporter().fromString(fllEngine));
+ std::string fld = FldExporter().toString(engine.get(), 1024);
+
+ SNormFactory* factory = FactoryManager::instance()->snorm();
+ factory->registerConstructor("Maximum", &(myMaximumNorm));
+
+ //Check our custom SNorm is registered
+ FL_unique_ptr<SNorm> x(factory->constructObject("Maximum"));
+ CHECK(Op::isEq(x->compute(0, 0.5), 0.5));
+
+ //Test creating an engine with the new SNorm
+ engine.reset(FllImporter().fromString(fllEngine));
+ std::string anotherFld = FldExporter().toString(engine.get(), 1024);
+
+ CHECK(fld == anotherFld);
+
+ //Make sure a different SNorm fails in results
+
+ factory->registerConstructor("Maximum", &(myNotSoMaximumNorm));
+ engine.reset(FllImporter().fromString(fllEngine));
+ anotherFld = FldExporter().toString(engine.get(), 1024);
+
+ CHECK(fld != anotherFld);
+#endif
+ }
+
+ static std::string tnormEngine() {
+#ifdef FL_CPP98
+ return "";
+#else
+ return R""(
+Engine: mam21
+InputVariable: angle
+ enabled: true
+ range: -5.000 5.000
+ lock-range: false
+ term: small Bell -5.000 5.000 8.000
+ term: big Bell 5.000 5.000 8.000
+InputVariable: velocity
+ enabled: true
+ range: -5.000 5.000
+ lock-range: false
+ term: small Bell -5.000 5.000 2.000
+ term: big Bell 5.000 5.000 2.000
+OutputVariable: force
+ enabled: true
+ range: -5.000 5.000
+ lock-range: false
+ aggregation: Maximum
+ defuzzifier: Centroid 200
+ default: nan
+ lock-previous: false
+ term: negBig Bell -5.000 1.670 8.000
+ term: negSmall Bell -1.670 1.670 8.000
+ term: posSmall Bell 1.670 1.670 8.000
+ term: posBig Bell 5.000 1.670 8.000
+RuleBlock:
+ enabled: true
+ conjunction: Minimum
+ disjunction: Maximum
+ implication: Minimum
+ activation: General
+ rule: if angle is small and velocity is small then force is negBig
+ rule: if angle is small and velocity is big then force is negSmall
+ rule: if angle is big and velocity is small then force is posSmall
+ rule: if angle is big and velocity is big then force is posBig
+)"";
+#endif
+ }
+
+ static TNorm* myMinimumNorm() {
+ return new TNormFunction("min(a,b)");
+ }
+
+ static TNorm* myNotSoMinimumNorm() {
+ return new TNormFunction("min(a,b) * 0.5");
+ }
+
+ TEST_CASE("TNormFunction (min(a,b)) is equivalent to Minimum", "[tnorm][minimum]") {
+#ifdef FL_CPP98
+ FL_IUNUSED(&(myMinimumNorm));
+ FL_IUNUSED(&(myNotSoMinimumNorm));
+ FL_IUNUSED(&(tnormEngine));
+ WARN("Test only runs with -DFL_CPP98=OFF");
+ return;
+#else
+ std::string fllEngine = tnormEngine();
+ FL_unique_ptr<Engine> engine(FllImporter().fromString(fllEngine));
+ std::string fld = FldExporter().toString(engine.get(), 1024);
+
+ TNormFactory* factory = FactoryManager::instance()->tnorm();
+ factory->registerConstructor("Minimum", &(myMinimumNorm));
+
+ //Check our custom SNorm is registered
+ FL_unique_ptr<TNorm> x(factory->constructObject("Minimum"));
+ CHECK(Op::isEq(x->compute(0.5, 1), 0.5));
+
+ //Test creating an engine with the new SNorm
+ engine.reset(FllImporter().fromString(fllEngine));
+ std::string anotherFld = FldExporter().toString(engine.get(), 1024);
+
+ CHECK(fld == anotherFld);
+
+ //Make sure a different SNorm fails in results
+
+ factory->registerConstructor("Minimum", &(myNotSoMinimumNorm));
+ engine.reset(FllImporter().fromString(fllEngine));
+ anotherFld = FldExporter().toString(engine.get(), 1024);
+
+ CHECK(fld != anotherFld);
+#endif
+ }
+
+}
diff --git a/fuzzylite/test/term/AggregatedTest.cpp b/fuzzylite/test/term/AggregatedTest.cpp
new file mode 100644
index 0000000..bb3f0e4
--- /dev/null
+++ b/fuzzylite/test/term/AggregatedTest.cpp
@@ -0,0 +1,52 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ /**
+ * Tests: term/Aggregated
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ TEST_CASE("highest term in aggregated", "[term][aggregated]") {
+
+ FL_unique_ptr<Term> dark(new Triangle("DARK", 0.000, 0.250, 0.500));
+ FL_unique_ptr<Term> medium(new Triangle("MEDIUM", 0.250, 0.500, 0.750));
+ FL_unique_ptr<Term> bright(new Triangle("BRIGHT", 0.500, 0.750, 1.000));
+
+ Aggregated aggregated;
+ aggregated.addTerm(dark.get(), 0.5, fl::null);
+ aggregated.addTerm(medium.get(), 0.1, fl::null);
+ aggregated.addTerm(bright.get(), 0.6, fl::null);
+
+ REQUIRE(aggregated.highestActivatedTerm()->getTerm() == bright.get());
+
+ aggregated.terms().at(1).setDegree(0.7);
+ REQUIRE(aggregated.highestActivatedTerm()->getTerm() == medium.get());
+
+ aggregated.terms().front().setDegree(0.9);
+ REQUIRE(aggregated.highestActivatedTerm()->getTerm() == dark.get());
+
+ aggregated.clear();
+ REQUIRE(aggregated.highestActivatedTerm() == fl::null);
+ }
+
+}
diff --git a/fuzzylite/test/term/DiscreteTest.cpp b/fuzzylite/test/term/DiscreteTest.cpp
new file mode 100644
index 0000000..2fb32aa
--- /dev/null
+++ b/fuzzylite/test/term/DiscreteTest.cpp
@@ -0,0 +1,125 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ /**
+ * Tests: term/Discrete
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ TEST_CASE("discrete finds elements using binary search", "[term][discrete]") {
+ fuzzylite::setLogging(true);
+ fuzzylite::setDebugging(false);
+ Rectangle rectangle("rectangle", 0, 1);
+ FL_unique_ptr<Discrete> discrete(Discrete::discretize(&rectangle, rectangle.getStart(), rectangle.getEnd(), 10));
+ FL_LOG(discrete->toString());
+
+ CHECK(discrete->membership(.25) == 1.0);
+ CHECK(discrete->membership(0.0) == 1.0);
+ CHECK(discrete->membership(-1.0) == 1.0);
+ CHECK(discrete->membership(1.0) == 1.0);
+ CHECK(discrete->membership(2.0) == 1.0);
+ CHECK(Op::isNaN(discrete->membership(fl::nan)));
+ CHECK(discrete->membership(fl::inf) == 1.0);
+ CHECK(discrete->membership(-fl::inf) == 1.0);
+ }
+
+ TEST_CASE("discrete still finds elements using binary search", "[term][discrete]") {
+ fuzzylite::setLogging(true);
+ fuzzylite::setDebugging(false);
+ Triangle triangle("triangle", 0, 1);
+ FL_unique_ptr<Discrete> discrete(Discrete::discretize(&triangle, triangle.getVertexA(), triangle.getVertexC(), 100));
+ FL_LOG(discrete->toString());
+ for (int i = 0; i < 200; ++i) {
+ scalar x = Op::scale(i, 0, 200, -1, 1);
+ if (not Op::isEq(triangle.membership(x), discrete->membership(x))) {
+ fuzzylite::setDebugging(true);
+ CHECK(Op::isEq(triangle.membership(x), discrete->membership(x)));
+ fuzzylite::setDebugging(false);
+ }
+ }
+ }
+
+ TEST_CASE("discrete finds all elements using binary search", "[term][discrete]") {
+ fuzzylite::setLogging(true);
+ fuzzylite::setDebugging(false);
+ scalar min = -1.0;
+ scalar max = 1.0;
+ scalar range = max - min;
+ scalar mean = 0.5 * (max + min);
+
+
+ std::vector<Term*> terms;
+ terms.push_back(new Triangle("triangle", min, mean, max));
+ terms.push_back(new Trapezoid("trapezoid", min, min + .25 * range, min + .75 * range, max));
+ terms.push_back(new Rectangle("rectangle", min, max));
+ terms.push_back(new Bell("bell", mean, range / 4, 3.0));
+ terms.push_back(new Cosine("cosine", mean, range));
+ terms.push_back(new Gaussian("gaussian", mean, range / 4));
+ terms.push_back(new GaussianProduct("gaussianProduct", mean, range / 4, mean, range / 4));
+ terms.push_back(new PiShape("piShape", min, mean, mean, max));
+ terms.push_back(new SigmoidDifference("sigmoidDifference", min + .25 * range, 20 / range, 20 / range, max - .25 * range));
+ terms.push_back(new SigmoidProduct("sigmoidProduct", min + .25 * range, 20 / range, 20 / range, max - .25 * range));
+ terms.push_back(new Spike("spike", mean, range));
+
+ terms.push_back(new Binary("binary", min, max));
+ terms.push_back(new Concave("concave", mean, max));
+ terms.push_back(new Ramp("ramp", min, max));
+ terms.push_back(new Sigmoid("sigmoid", mean, 20 / range));
+ terms.push_back(new SShape("sshape", min, max));
+ terms.push_back(new ZShape("zshape", min, max));
+
+ for (std::size_t t = 0; t < terms.size(); ++t) {
+ Term* term = terms.at(t);
+ std::vector<Discrete::Pair> pairs;
+ srand(0);
+ for (int i = 0; i < 1000; ++i) {
+ int randomX = std::rand();
+ scalar x = Op::scale(randomX % 100, 0, 100, -1, 1);
+ pairs.push_back(Discrete::Pair(x, term->membership(x)));
+ }
+ Discrete::sort(pairs);
+
+ Discrete discrete("discrete", pairs);
+ for (std::size_t i = 0; i < pairs.size(); ++i) {
+ Discrete::Pair pair = pairs.at(i);
+ scalar x = pair.first;
+ if (not Op::isEq(discrete.membership(x), term->membership(x))) {
+ fuzzylite::setDebugging(true);
+ CHECK(discrete.membership(x) == term->membership(x));
+ fuzzylite::setDebugging(false);
+ }
+ }
+ for (int i = 0 ; i < 100 ; i++) {
+ scalar x = Op::scale(i, 0, 100, -1, 1);
+ if (not Op::isEq(discrete.membership(x), term->membership(x))) {
+ fuzzylite::setDebugging(true);
+ CHECK(discrete.membership(x) == term->membership(x));
+ fuzzylite::setDebugging(false);
+ }
+ }
+ }
+ for (std::size_t i = 0 ; i < terms.size(); ++i){
+ delete terms.at(i);
+ }
+ }
+}
diff --git a/fuzzylite/test/term/FunctionTest.cpp b/fuzzylite/test/term/FunctionTest.cpp
new file mode 100644
index 0000000..a42e37b
--- /dev/null
+++ b/fuzzylite/test/term/FunctionTest.cpp
@@ -0,0 +1,115 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ /**
+ * Tests: term/Function
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ TEST_CASE("function parses basic arithmetic", "[term][function]") {
+ Function f;
+ std::string text = "3+4*2/(1-5)^2^3";
+ CHECK(f.toPostfix(text) == "3 4 2 * 1 5 - 2 3 ^ ^ / +");
+ CHECK(f.parse(text)->toInfix() == "3.000 ^ 2.000 ^ 5.000 - 1.000 / 2.000 * 4.000 + 3.000");
+ CHECK(f.parse(text)->toPrefix() == "+ / ^ ^ 3.000 2.000 - 5.000 1.000 * 2.000 4.000 3.000");
+ }
+
+ TEST_CASE("function parses basic trigonometry", "[term][function]") {
+ Function f;
+ std::string text = "sin(y*x)^2/x";
+
+ CHECK_THROWS(f.load(text));
+
+ f.variables["y"] = 1.0;
+ f.load(text);
+
+ CHECK(f.toPostfix(text) == "y x * sin 2 ^ x /");
+ CHECK(f.parse(text)->toInfix() == "x / 2.000 ^ x * y sin");
+ CHECK(f.parse(text)->toPrefix() == "/ x ^ 2.000 sin * x y");
+ }
+
+ TEST_CASE("function parses propositions", "[term][function]") {
+ Function f;
+
+ std::string text = "(Temperature is High and Oxygen is Low) or "
+ "(Temperature is Low and (Oxygen is Low or Oxygen is High))";
+
+ CHECK(f.toPostfix(text) == "Temperature is High Oxygen is Low "
+ "and Temperature is Low Oxygen is Low Oxygen is High or and or");
+ }
+
+ TEST_CASE("function cannot deal with negative numbers", "[term][function]") {
+ Function f;
+ std::string text = "-5 *4/sin(-pi/2)";
+
+ SECTION("function throws exception") {
+ CHECK_THROWS(f.parse(text)->evaluate());
+ }
+
+ f.variables["pi"] = 3.14;
+ CHECK_THROWS(f.parse(text)->evaluate(&f.variables));
+
+ text = "~5 *4/sin(~pi/2)";
+ CHECK(f.parse(text)->evaluate(&f.variables) == Approx(20));
+
+ f.load(text);
+
+ f.variables["pi"] = 3.14;
+
+ CHECK(f.toPostfix(text) == "5 ~ 4 * pi ~ 2 / sin /");
+ CHECK(f.parse(text)->toInfix() == "2.000 / pi ~ sin / 4.000 * 5.000 ~");
+ CHECK(f.parse(text)->toPrefix() == "/ sin / 2.000 ~ pi * 4.000 ~ 5.000");
+ }
+
+ TEST_CASE("Function is clonable", "[term][function]") {
+ Function* f = new Function;
+ std::string text = "2+2";
+ f->load(text);
+ CHECK(Op::isEq(f->membership(fl::nan), 4));
+ Function* clone = f->clone();
+ delete f;
+ CHECK(Op::isEq(clone->membership(fl::nan), 4));
+ delete clone;
+ }
+
+ TEST_CASE("Function is constructor copyable", "[term][function]") {
+ Function* f = new Function;
+ std::string text = "2+2";
+ f->load(text);
+ CHECK(Op::isEq(f->membership(fl::nan), 4));
+ Function* clone = new Function(*f);
+ delete f;
+ CHECK(Op::isEq(clone->membership(fl::nan), 4));
+ delete clone;
+ }
+
+ TEST_CASE("Function computes tree size correctly", "[term][function]"){
+ Function f("f", "x*x+(x-x)/x+log(x)");
+ f.load();
+ CHECK(f.root()->treeSize() == 6);
+ CHECK(f.root()->treeSize(Function::Element::Function) == 1);
+ CHECK(f.root()->treeSize(Function::Element::Operator) == 5);
+ FL_LOG(f.complexity().toString());
+ }
+
+}
diff --git a/fuzzylite/test/term/TrapezoidTest.cpp b/fuzzylite/test/term/TrapezoidTest.cpp
new file mode 100644
index 0000000..8581ac1
--- /dev/null
+++ b/fuzzylite/test/term/TrapezoidTest.cpp
@@ -0,0 +1,53 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ /**
+ * Tests: term/Trapezoid
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ TEST_CASE("trapezoid can be open ended with -infinity", "[term][trapezoid]") {
+ Trapezoid trapezoid("A", -fl::inf, 0, 1, 2);
+ Ramp ramp("a", 2, 1);
+ //(-inf, inf)
+ for (scalar i = -10.0; Op::isLE(i, 10.0); i += .2) {
+ FL_DBG("A(" << i << ")=" << trapezoid.membership(i));
+ FL_DBG("a(" << i << ")=" << ramp.membership(i));
+ REQUIRE(Op::isEq(trapezoid.membership(i), ramp.membership(i)));
+ }
+ REQUIRE(Op::isEq(trapezoid.membership(-fl::inf), 1.0));
+ REQUIRE(Op::isEq(trapezoid.membership(fl::inf), 0.0));
+ }
+
+ TEST_CASE("trapezoid can be open ended with +infinity", "[term][trapezoid]") {
+ Trapezoid trapezoid("A", 0, 1, 2, fl::inf);
+ Ramp ramp("a", 0, 1);
+ //(-inf, inf)
+ for (scalar i = -10.0; Op::isLE(i, 10.0); i += .2) {
+ REQUIRE(Op::isEq(trapezoid.membership(i), ramp.membership(i)));
+ }
+ REQUIRE(Op::isEq(trapezoid.membership(fl::inf), 1.0));
+ REQUIRE(Op::isEq(trapezoid.membership(-fl::inf), 0.0));
+ }
+
+}
diff --git a/fuzzylite/test/term/TriangleTest.cpp b/fuzzylite/test/term/TriangleTest.cpp
new file mode 100644
index 0000000..bd1459d
--- /dev/null
+++ b/fuzzylite/test/term/TriangleTest.cpp
@@ -0,0 +1,66 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+namespace fl {
+
+ /**
+ * Tests: term/Triangle
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ TEST_CASE("triangle can be open ended with -infinity", "[term][triangle]") {
+ Triangle triangle("A", -fl::inf, 0, 1);
+ Ramp ramp("a", 1, 0);
+ for (int i = -10; i < 2; ++i) {
+ FL_DBG("A(" << i << ")=" << triangle.membership(i));
+ FL_DBG("a(" << i << ")=" << ramp.membership(i));
+ REQUIRE(Op::isEq(triangle.membership(i), ramp.membership(i)));
+ }
+ REQUIRE(Op::isEq(triangle.membership(-fl::inf), 1.0));
+ REQUIRE(Op::isEq(triangle.membership(fl::inf), 0.0));
+ }
+
+ TEST_CASE("triangle can be open ended with +infinity", "[term][triangle]") {
+ Triangle triangle("A", 0, 1, fl::inf);
+ Ramp ramp("a", 0, 1);
+ for (int i = 10; i >= -2; --i) {
+ FL_DBG("A(" << i << ")=" << triangle.membership(i));
+ FL_DBG("a(" << i << ")=" << ramp.membership(i));
+ REQUIRE(Op::isEq(triangle.membership(i), ramp.membership(i)));
+ }
+ REQUIRE(Op::isEq(triangle.membership(fl::inf), 1.0));
+ REQUIRE(Op::isEq(triangle.membership(-fl::inf), 0.0));
+ }
+
+ TEST_CASE("triangle defuzzification is correct", "[term][triangle]") {
+ Triangle a("A", 0, 1, 2);
+ Triangle b("B", 1, 2, 3);
+ AlgebraicProduct times;
+ Aggregated x("X", 0, 3, new AlgebraicSum);
+ x.addTerm(&a, 1, &times);
+ x.addTerm(&b, 1, &times);
+ Centroid c(101);
+ FL_LOG(c.defuzzify(&x, 0, 3));
+
+ Triangle t("T", 0, 0, 1);
+ FL_LOG(c.defuzzify(&t, 0, 1));
+ }
+}
diff --git a/fuzzylite/test/variable/VariableTest.cpp b/fuzzylite/test/variable/VariableTest.cpp
new file mode 100644
index 0000000..6f77e94
--- /dev/null
+++ b/fuzzylite/test/variable/VariableTest.cpp
@@ -0,0 +1,74 @@
+/*
+ fuzzylite (R), a fuzzy logic control library in C++.
+ Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
+ Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>
+
+ This file is part of fuzzylite.
+
+ fuzzylite is free software: you can redistribute it and/or modify it under
+ the terms of the FuzzyLite License included with the software.
+
+ You should have received a copy of the FuzzyLite License along with
+ fuzzylite. If not, see <http://www.fuzzylite.com/license/>.
+
+ fuzzylite is a registered trademark of FuzzyLite Limited.
+ */
+
+#include "test/catch.hpp"
+#include "fl/Headers.h"
+
+#include <algorithm> // std::random_shuffle
+
+namespace fl {
+
+ /**
+ * Tests: variable/Variable
+ *
+ * @author Juan Rada-Vilela, Ph.D.
+ *
+ */
+
+ TEST_CASE("variable of Constant terms is sorted", "[variable][variable]") {
+ Variable variable("Variable", -10, 10);
+ for (int i = 0; i <= 20; ++i) {
+ variable.addTerm(new Constant(Op::str(i), i - 10));
+ }
+ std::random_shuffle(variable.terms().begin(), variable.terms().end());
+ FL_DBG(variable.toString());
+ REQUIRE(variable.numberOfTerms() == 21);
+ variable.sort();
+ REQUIRE(variable.numberOfTerms() == 21);
+ int value = -10;
+ for (std::size_t i = 0; i < variable.terms().size(); ++i) {
+ Constant* term = dynamic_cast<Constant*> (variable.terms().at(i));
+ REQUIRE(term);
+ REQUIRE(term->getValue() == float(value));
+ ++value;
+ }
+ FL_DBG(variable.toString());
+ }
+
+ TEST_CASE("variable of Triangle terms is sorted", "[variable][variable]") {
+ Variable variable("Variable", -30, 30);
+ for (int i = 0; i <= 20; ++i) {
+ variable.addTerm(new Triangle(Op::str(i), i - 1, i, i + 1));
+ }
+ std::random_shuffle(variable.terms().begin(), variable.terms().end());
+ FL_DBG(variable.toString());
+ REQUIRE(variable.numberOfTerms() == 21);
+ variable.sort();
+ FL_DBG("Shuffled:");
+ FL_DBG(variable.toString());
+ REQUIRE(variable.numberOfTerms() == 21);
+ int value = 0;
+ for (std::size_t i = 0; i < variable.terms().size(); ++i) {
+ Triangle* term = dynamic_cast<Triangle*> (variable.terms().at(i));
+ REQUIRE(term);
+ REQUIRE(term->getName() == Op::str(value < 0 ? -1 * value : value));
+ ++value;
+ }
+ FL_DBG(variable.toString());
+ }
+
+}
+