485 lines
22 KiB
Python
485 lines
22 KiB
Python
# -*- coding: utf-8 -*-
|
|
'''
|
|
This started as a copy of skfuzzy/control/tests/test_controlsystem.py
|
|
I've hacked it a bit to partially use the FCL parser.
|
|
@hacker: james.power@mu.ie Created on Tue Aug 21 10:11:04 2018
|
|
'''
|
|
|
|
from __future__ import division
|
|
import os
|
|
|
|
import numpy as np
|
|
import numpy.testing as tst
|
|
import nose
|
|
|
|
import skfuzzy.control as ctrl
|
|
|
|
from fcl_parser import FCLParser
|
|
|
|
|
|
def test_tipping_problem():
|
|
'''
|
|
Define the variables as usual,
|
|
but use FCL for some membership functions and for all the rules.
|
|
'''
|
|
|
|
# First we set up the variables in the usual way:
|
|
food = ctrl.Antecedent(np.linspace(0, 10, 11), 'quality')
|
|
service = ctrl.Antecedent(np.linspace(0, 10, 11), 'service')
|
|
tip = ctrl.Consequent(np.linspace(0, 25, 26), 'tip')
|
|
|
|
# Auto-generate the membership functions for the inputs:
|
|
food.automf(3)
|
|
service.automf(3)
|
|
|
|
# Define a FCL parser-object:
|
|
p = FCLParser()
|
|
# Use FCL to define membership functions for the output:
|
|
tip['bad'] = p.mf('Triangle 0 0 13', tip.universe)
|
|
tip['middling'] = p.mf('Triangle 0 13 25', tip.universe)
|
|
tip['lots'] = p.mf('Triangle 13 25 25', tip.universe)
|
|
|
|
# We need to tell the parser about the variables before we parse the rules:
|
|
p.add_vars([food, service, tip])
|
|
|
|
# Now use FCL to define three rules:
|
|
rule1 = p.rule('IF quality IS poor OR service IS poor THEN tip IS bad')
|
|
rule2 = p.rule('IF service is average THEN tip is middling')
|
|
rule3 = p.rule('if service is good or quality is good then tip is lots')
|
|
|
|
# To get the control system, just add the rules (from the parser):
|
|
tipping = ctrl.ControlSystem(p.rules)
|
|
|
|
# From here on it's just the same as the original:
|
|
tipping2 = ctrl.ControlSystem(rule1)
|
|
tipping2.addrule(rule2)
|
|
tipping2.addrule(rule3)
|
|
|
|
tip_sim = ctrl.ControlSystemSimulation(tipping)
|
|
tip_sim2 = ctrl.ControlSystemSimulation(tipping2)
|
|
|
|
# Inputs added both possible ways
|
|
inputs = {'quality': 6.5, 'service': 9.8}
|
|
for key, value in inputs.items():
|
|
tip_sim.input[key] = value
|
|
|
|
tip_sim2.inputs(inputs)
|
|
|
|
# Compute the system
|
|
tip_sim.compute()
|
|
tip_sim2.compute()
|
|
|
|
# Ensure both methods of defining rules yield the same results
|
|
for val0, val1 in zip(tip_sim.output.values(),
|
|
tip_sim2.output.values()):
|
|
tst.assert_allclose(val0, val1)
|
|
|
|
# Verify against manual computation
|
|
tst.assert_allclose(tip_sim.output['tip'], 19.8578, atol=1e-2, rtol=1e-2)
|
|
|
|
|
|
def setup_rule_order():
|
|
''' We can define variables in FCL and add terms afterwards: '''
|
|
global _parser # Make this global so we can access vars elsewhere
|
|
_parser = FCLParser()
|
|
# Use the parser to define the variables and their universes
|
|
_parser.function_block('''
|
|
FUNCTION_BLOCK
|
|
// Define variables, but not terms for the moment:
|
|
FUZZIFY a RANGE := (0 .. 11) WITH 1 END_FUZZIFY
|
|
FUZZIFY b RANGE := (0 .. 11) WITH 1 END_FUZZIFY
|
|
FUZZIFY c RANGE := (0 .. 11) WITH 1 END_FUZZIFY
|
|
FUZZIFY d RANGE := (0 .. 11) WITH 1 END_FUZZIFY
|
|
// No rules at all; that's OK.
|
|
END_FUNCTION_BLOCK
|
|
''')
|
|
|
|
# The use skfuzzy to define the membership functions:
|
|
for v in _parser.fuzzy_variables:
|
|
v.automf(3)
|
|
|
|
|
|
@nose.with_setup(setup_rule_order)
|
|
def test_bad_rules():
|
|
'''Can access variables by using parser as a dict'''
|
|
not_rules = ['me', 192238, 42, dict()]
|
|
tst.assert_raises(ValueError, ctrl.ControlSystem, not_rules)
|
|
|
|
testsystem = ctrl.ControlSystem()
|
|
tst.assert_raises(ValueError, testsystem.addrule, _parser['a'])
|
|
|
|
|
|
def test_multiple_rules_same_consequent_term():
|
|
'''
|
|
Here we define the variables fully in FCL,
|
|
and use a rule-block for the set of rules.
|
|
'''
|
|
x1_inputs = [0.6, 0.2, 0.4, 0.7, 1, 1.2, 1.8]
|
|
x2_inputs = [0.9, 1, 0.8, 0, 1.2, 0.6, 1.8]
|
|
|
|
p = FCLParser()
|
|
|
|
p.fuzzify_block('''
|
|
FUZZIFY x1
|
|
RANGE := (0 .. 2.1) WITH 0.01 // Hacked the FCL syntax here
|
|
TERM label0 := Triangle 0.2 0.2 0.6
|
|
TERM label1 := Triangle 0.2 0.6 1.0
|
|
TERM label2 := Triangle 0.6 1.0 1.4
|
|
TERM label3 := Triangle 1.0 1.4 1.8
|
|
TERM label4 := Triangle 1.4 1.8 1.8
|
|
END_FUZZIFY
|
|
''')
|
|
|
|
p.fuzzify_block('''
|
|
FUZZIFY x2
|
|
RANGE := (0 .. 2.1) WITH 0.01
|
|
TERM label0 := Triangle 0.0 0.0 0.45
|
|
TERM label1 := Triangle 0.0 0.45 0.9
|
|
TERM label2 := Triangle 0.45 0.9 1.35
|
|
TERM label3 := Triangle 0.9 1.35 1.8
|
|
TERM label4 := Triangle 1.35 1.8 1.8
|
|
END_FUZZIFY
|
|
''')
|
|
|
|
p.defuzzify_block('''
|
|
DEFUZZIFY y
|
|
RANGE := (0 .. 2.1) WITH 0.01
|
|
TERM label0 := Triangle 0.3 0.3 0.725
|
|
TERM label1 := Triangle 0.3 0.725 1.15
|
|
TERM label2 := Triangle 0.725 1.15 1.575
|
|
TERM label3 := Triangle 1.15 1.575 2.0
|
|
TERM label4 := Triangle 1.575 2.0 2.0
|
|
END_DEFUZZIFY
|
|
''')
|
|
|
|
first_three = p.rule_block('''
|
|
RULEBLOCK // Name of rule-block is optional
|
|
RULE 1: IF x1 is label0 AND x2 is label2 THEN y is label0
|
|
RULE 2: IF x1 is label1 AND x2 is label0 THEN y is label0
|
|
RULE 3: IF x1 is label1 AND x2 is label2 THEN y is label0
|
|
END_RULEBLOCK
|
|
''')
|
|
|
|
# Equivalent to above 3 rules
|
|
r123 = p.rule('''
|
|
IF x1 is label0 AND x2 is label2
|
|
OR x1 is label1 AND x2 is label0
|
|
OR x1 is label1 AND x2 is label2
|
|
THEN y is label0
|
|
''')
|
|
|
|
last_three = p.rule_block('''
|
|
RULEBLOCK // Name of rule-block is optional
|
|
RULE 4: IF x1 is label2 AND x2 is label1 THEN y is label2
|
|
RULE 5: IF x1 is label2 AND x2 is label3 THEN y is label3
|
|
RULE 6: IF x1 is label4 AND x2 is label4 THEN y is label4
|
|
END_RULEBLOCK
|
|
''')
|
|
|
|
# Build a system with three rules targeting the same Consequent Term,
|
|
# and then an equivalent system with those three rules combined into one.
|
|
cs0 = ctrl.ControlSystem(first_three + last_three)
|
|
cs1 = ctrl.ControlSystem([r123] + last_three)
|
|
|
|
expected_results = [0.438372093023,
|
|
0.443962536855,
|
|
0.461436409933,
|
|
0.445290345769,
|
|
1.575,
|
|
1.15,
|
|
1.86162790698]
|
|
|
|
# Ensure the results are equivalent within error
|
|
for inst, expected in zip(range(7), expected_results):
|
|
sim0 = ctrl.ControlSystemSimulation(cs0)
|
|
sim1 = ctrl.ControlSystemSimulation(cs1)
|
|
|
|
sim0.input["x1"] = x1_inputs[inst]
|
|
sim0.input["x2"] = x2_inputs[inst]
|
|
sim1.input["x1"] = x1_inputs[inst]
|
|
sim1.input["x2"] = x2_inputs[inst]
|
|
|
|
sim0.compute()
|
|
sim1.compute()
|
|
|
|
tst.assert_allclose(sim0.output['y'], sim1.output['y'])
|
|
tst.assert_allclose(expected, sim0.output['y'], atol=1e-4, rtol=1e-4)
|
|
|
|
|
|
def test_multiple_rules_same_consequent_term_file():
|
|
'''
|
|
Here we define the whole system in an FCL file, and read it in...
|
|
'''
|
|
x1_inputs = [0.6, 0.2, 0.4, 0.7, 1, 1.2, 1.8]
|
|
x2_inputs = [0.9, 1, 0.8, 0, 1.2, 0.6, 1.8]
|
|
|
|
p = FCLParser()
|
|
# FCL input file is in the same directory as this script:
|
|
infile = os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
|
'multiple.fcl')
|
|
p.read_fcl_file(infile)
|
|
|
|
# Build a system with three rules targeting the same Consequent Term,
|
|
# and then an equivalent system with those three rules combined into one.
|
|
separate = [r for r in p.rules if not r.label.startswith('extra')]
|
|
cs0 = ctrl.ControlSystem(separate) # 6 rules, as before
|
|
cs1 = ctrl.ControlSystem(p.rules) # Throw in all 7 rules
|
|
|
|
expected_results = [0.438372093023,
|
|
0.443962536855,
|
|
0.461436409933,
|
|
0.445290345769,
|
|
1.575,
|
|
1.15,
|
|
1.86162790698]
|
|
|
|
# Ensure the results are equivalent within error
|
|
for inst, expected in zip(range(7), expected_results):
|
|
sim0 = ctrl.ControlSystemSimulation(cs0)
|
|
sim1 = ctrl.ControlSystemSimulation(cs1)
|
|
|
|
sim0.input["x1"] = x1_inputs[inst]
|
|
sim0.input["x2"] = x2_inputs[inst]
|
|
sim1.input["x1"] = x1_inputs[inst]
|
|
sim1.input["x2"] = x2_inputs[inst]
|
|
|
|
sim0.compute()
|
|
sim1.compute()
|
|
|
|
tst.assert_allclose(sim0.output['y'], sim1.output['y'])
|
|
tst.assert_allclose(expected, sim0.output['y'], atol=1e-4, rtol=1e-4)
|
|
|
|
|
|
def test_complex_system():
|
|
'''In this example we parse a whole rule-back in one go'''
|
|
|
|
universe = np.linspace(-2, 2, 5)
|
|
vars = [ctrl.Antecedent(universe, 'error'),
|
|
ctrl.Antecedent(universe, 'delta'),
|
|
ctrl.Consequent(universe, 'output')]
|
|
|
|
for var in vars:
|
|
var.automf(names=['nb', 'ns', 'ze', 'ps', 'pb'])
|
|
|
|
# Define a FCL parser-object, tell it about the variables:
|
|
p = FCLParser(vars)
|
|
|
|
# Now supply all the rules as a ruleblock
|
|
rulebase = p.rule_block('''
|
|
RULEBLOCK ComplexSystem // Name of rule-block is optional
|
|
RULE rule_nb:
|
|
IF error is nb and delta is nb
|
|
or error is ns and delta is nb
|
|
or error is nb and delta is ns
|
|
THEN output is nb
|
|
RULE rule_ns:
|
|
IF error is nb and delta is ze or error is nb and delta is ps
|
|
or error is ns and delta is ns or error is ns and delta is ze
|
|
or error is ze and delta is ns or error is ze and delta is nb
|
|
or error is ps and delta is nb
|
|
THEN output is ns
|
|
RULE rule_ze:
|
|
IF error is nb and delta is pb
|
|
or error is ns and delta is ps
|
|
or error is ze and delta is ze
|
|
or error is ps and delta is ns
|
|
or error is pb and delta is nb
|
|
THEN output is ze
|
|
RULE rule_ps:
|
|
IF error is ns and delta is pb
|
|
or error is ze and delta is pb or error is ze and delta is ps
|
|
or error is ps and delta is ps or error is ps and delta is ze
|
|
or error is pb and delta is ze or error is pb and delta is ns
|
|
THEN output is ps
|
|
RULE rule_pb:
|
|
IF error is ps and delta is pb
|
|
or error is pb and delta is pb or error is pb and delta is ps
|
|
THEN output is pb
|
|
END_RULEBLOCK
|
|
''')
|
|
|
|
# Same as before from here on...
|
|
system = ctrl.ControlSystem(rules=rulebase)
|
|
|
|
sim = ctrl.ControlSystemSimulation(system, cache=False)
|
|
|
|
x, y = np.meshgrid(np.linspace(-2, 2, 21), np.linspace(-2, 2, 21))
|
|
z0 = np.zeros_like(x)
|
|
z1 = np.zeros_like(x)
|
|
|
|
# The original, slow way - one set of values at a time
|
|
for i in range(21):
|
|
for j in range(21):
|
|
sim.input['error'] = x[i, j]
|
|
sim.input['delta'] = y[i, j]
|
|
sim.compute()
|
|
z0[i, j] = sim.output['output']
|
|
|
|
sim.reset()
|
|
|
|
# The new way - array inputs
|
|
sim.input['error'] = x
|
|
sim.input['delta'] = y
|
|
sim.compute()
|
|
z1 = sim.output['output']
|
|
|
|
# Ensure results align
|
|
np.testing.assert_allclose(z0, z1)
|
|
|
|
# Big expected array
|
|
expected = \
|
|
np.array([[-1.66666667e+00, -1.65555556e+00, -1.62857143e+00,
|
|
-1.62857143e+00, -1.65555556e+00, -1.66666667e+00,
|
|
-1.34414414e+00, -1.18294574e+00, -1.10000000e+00,
|
|
-1.05641026e+00, -1.00000000e+00, -1.00000000e+00,
|
|
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
|
-1.00000000e+00, -7.37704918e-01, -5.72916667e-01,
|
|
-4.27083333e-01, -2.62295082e-01, -2.77555756e-17],
|
|
[-1.65555556e+00, -1.34414414e+00, -1.29494949e+00,
|
|
-1.29494949e+00, -1.34414414e+00, -1.34414414e+00,
|
|
-1.34414414e+00, -1.18294574e+00, -1.10000000e+00,
|
|
-1.05641026e+00, -1.00000000e+00, -7.37704918e-01,
|
|
-7.13580247e-01, -7.13580247e-01, -7.37704918e-01,
|
|
-7.37704918e-01, -4.36619718e-01, -2.91555556e-01,
|
|
-1.56140351e-01, 1.96914557e-16, 2.62295082e-01],
|
|
[-1.62857143e+00, -1.29494949e+00, -1.18294574e+00,
|
|
-1.18294574e+00, -1.18294574e+00, -1.18294574e+00,
|
|
-1.18294574e+00, -1.18294574e+00, -1.10000000e+00,
|
|
-1.05333333e+00, -1.00000000e+00, -7.13580247e-01,
|
|
-5.72916667e-01, -5.72916667e-01, -5.72916667e-01,
|
|
-5.72916667e-01, -2.91555556e-01, -1.26984127e-01,
|
|
6.45478503e-17, 1.56140351e-01, 4.27083333e-01],
|
|
[-1.62857143e+00, -1.29494949e+00, -1.18294574e+00,
|
|
-1.10000000e+00, -1.10000000e+00, -1.10000000e+00,
|
|
-1.10000000e+00, -1.10000000e+00, -1.10000000e+00,
|
|
-1.05333333e+00, -1.00000000e+00, -7.13580247e-01,
|
|
-5.72916667e-01, -4.27083333e-01, -4.27083333e-01,
|
|
-4.27083333e-01, -1.56140351e-01, 2.42054439e-16,
|
|
1.26984127e-01, 2.91555556e-01, 5.72916667e-01],
|
|
[-1.65555556e+00, -1.34414414e+00, -1.18294574e+00,
|
|
-1.10000000e+00, -1.05641026e+00, -1.05641026e+00,
|
|
-1.05641026e+00, -1.05333333e+00, -1.05333333e+00,
|
|
-1.05641026e+00, -1.00000000e+00, -7.37704918e-01,
|
|
-5.72916667e-01, -4.27083333e-01, -2.62295082e-01,
|
|
-2.62295082e-01, 2.29733650e-16, 1.56140351e-01,
|
|
2.91555556e-01, 4.36619718e-01, 7.37704918e-01],
|
|
[-1.66666667e+00, -1.34414414e+00, -1.18294574e+00,
|
|
-1.10000000e+00, -1.05641026e+00, -1.00000000e+00,
|
|
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
|
-1.00000000e+00, -1.00000000e+00, -7.37704918e-01,
|
|
-5.72916667e-01, -4.27083333e-01, -2.62295082e-01,
|
|
-2.77555756e-17, 2.62295082e-01, 4.27083333e-01,
|
|
5.72916667e-01, 7.37704918e-01, 1.00000000e+00],
|
|
[-1.34414414e+00, -1.34414414e+00, -1.18294574e+00,
|
|
-1.10000000e+00, -1.05641026e+00, -1.00000000e+00,
|
|
-7.37704918e-01, -7.13580247e-01, -7.13580247e-01,
|
|
-7.37704918e-01, -7.37704918e-01, -4.36619718e-01,
|
|
-2.91555556e-01, -1.56140351e-01, 4.17271323e-16,
|
|
2.62295082e-01, 2.62295082e-01, 4.27083333e-01,
|
|
5.72916667e-01, 7.37704918e-01, 1.00000000e+00],
|
|
[-1.18294574e+00, -1.18294574e+00, -1.18294574e+00,
|
|
-1.10000000e+00, -1.05333333e+00, -1.00000000e+00,
|
|
-7.13580247e-01, -5.72916667e-01, -5.72916667e-01,
|
|
-5.72916667e-01, -5.72916667e-01, -2.91555556e-01,
|
|
-1.26984127e-01, 2.09780513e-16, 1.56140351e-01,
|
|
4.27083333e-01, 4.27083333e-01, 4.27083333e-01,
|
|
5.72916667e-01, 7.13580247e-01, 1.00000000e+00],
|
|
[-1.10000000e+00, -1.10000000e+00, -1.10000000e+00,
|
|
-1.10000000e+00, -1.05333333e+00, -1.00000000e+00,
|
|
-7.13580247e-01, -5.72916667e-01, -4.27083333e-01,
|
|
-4.27083333e-01, -4.27083333e-01, -1.56140351e-01,
|
|
2.42054439e-16, 1.26984127e-01, 2.91555556e-01,
|
|
5.72916667e-01, 5.72916667e-01, 5.72916667e-01,
|
|
5.72916667e-01, 7.13580247e-01, 1.00000000e+00],
|
|
[-1.05641026e+00, -1.05641026e+00, -1.05333333e+00,
|
|
-1.05333333e+00, -1.05641026e+00, -1.00000000e+00,
|
|
-7.37704918e-01, -5.72916667e-01, -4.27083333e-01,
|
|
-2.62295082e-01, -2.62295082e-01, 2.29733650e-16,
|
|
1.56140351e-01, 2.91555556e-01, 4.36619718e-01,
|
|
7.37704918e-01, 7.37704918e-01, 7.13580247e-01,
|
|
7.13580247e-01, 7.37704918e-01, 1.00000000e+00],
|
|
[-1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
|
-1.00000000e+00, -1.00000000e+00, -1.00000000e+00,
|
|
-7.37704918e-01, -5.72916667e-01, -4.27083333e-01,
|
|
-2.62295082e-01, -2.77555756e-17, 2.62295082e-01,
|
|
4.27083333e-01, 5.72916667e-01, 7.37704918e-01,
|
|
1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
|
1.00000000e+00, 1.00000000e+00, 1.00000000e+00],
|
|
[-1.00000000e+00, -7.37704918e-01, -7.13580247e-01,
|
|
-7.13580247e-01, -7.37704918e-01, -7.37704918e-01,
|
|
-4.36619718e-01, -2.91555556e-01, -1.56140351e-01,
|
|
2.29733650e-16, 2.62295082e-01, 2.62295082e-01,
|
|
4.27083333e-01, 5.72916667e-01, 7.37704918e-01,
|
|
1.00000000e+00, 1.05641026e+00, 1.05333333e+00,
|
|
1.05333333e+00, 1.05641026e+00, 1.05641026e+00],
|
|
[-1.00000000e+00, -7.13580247e-01, -5.72916667e-01,
|
|
-5.72916667e-01, -5.72916667e-01, -5.72916667e-01,
|
|
-2.91555556e-01, -1.26984127e-01, 2.42054439e-16,
|
|
1.56140351e-01, 4.27083333e-01, 4.27083333e-01,
|
|
4.27083333e-01, 5.72916667e-01, 7.13580247e-01,
|
|
1.00000000e+00, 1.05333333e+00, 1.10000000e+00,
|
|
1.10000000e+00, 1.10000000e+00, 1.10000000e+00],
|
|
[-1.00000000e+00, -7.13580247e-01, -5.72916667e-01,
|
|
-4.27083333e-01, -4.27083333e-01, -4.27083333e-01,
|
|
-1.56140351e-01, 2.09780513e-16, 1.26984127e-01,
|
|
2.91555556e-01, 5.72916667e-01, 5.72916667e-01,
|
|
5.72916667e-01, 5.72916667e-01, 7.13580247e-01,
|
|
1.00000000e+00, 1.05333333e+00, 1.10000000e+00,
|
|
1.18294574e+00, 1.18294574e+00, 1.18294574e+00],
|
|
[-1.00000000e+00, -7.37704918e-01, -5.72916667e-01,
|
|
-4.27083333e-01, -2.62295082e-01, -2.62295082e-01,
|
|
4.17271323e-16, 1.56140351e-01, 2.91555556e-01,
|
|
4.36619718e-01, 7.37704918e-01, 7.37704918e-01,
|
|
7.13580247e-01, 7.13580247e-01, 7.37704918e-01,
|
|
1.00000000e+00, 1.05641026e+00, 1.10000000e+00,
|
|
1.18294574e+00, 1.34414414e+00, 1.34414414e+00],
|
|
[-1.00000000e+00, -7.37704918e-01, -5.72916667e-01,
|
|
-4.27083333e-01, -2.62295082e-01, -2.77555756e-17,
|
|
2.62295082e-01, 4.27083333e-01, 5.72916667e-01,
|
|
7.37704918e-01, 1.00000000e+00, 1.00000000e+00,
|
|
1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
|
1.00000000e+00, 1.05641026e+00, 1.10000000e+00,
|
|
1.18294574e+00, 1.34414414e+00, 1.66666667e+00],
|
|
[-7.37704918e-01, -4.36619718e-01, -2.91555556e-01,
|
|
-1.56140351e-01, 2.29733650e-16, 2.62295082e-01,
|
|
2.62295082e-01, 4.27083333e-01, 5.72916667e-01,
|
|
7.37704918e-01, 1.00000000e+00, 1.05641026e+00,
|
|
1.05333333e+00, 1.05333333e+00, 1.05641026e+00,
|
|
1.05641026e+00, 1.05641026e+00, 1.10000000e+00,
|
|
1.18294574e+00, 1.34414414e+00, 1.65555556e+00],
|
|
[-5.72916667e-01, -2.91555556e-01, -1.26984127e-01,
|
|
2.42054439e-16, 1.56140351e-01, 4.27083333e-01,
|
|
4.27083333e-01, 4.27083333e-01, 5.72916667e-01,
|
|
7.13580247e-01, 1.00000000e+00, 1.05333333e+00,
|
|
1.10000000e+00, 1.10000000e+00, 1.10000000e+00,
|
|
1.10000000e+00, 1.10000000e+00, 1.10000000e+00,
|
|
1.18294574e+00, 1.29494949e+00, 1.62857143e+00],
|
|
[-4.27083333e-01, -1.56140351e-01, 6.45478503e-17,
|
|
1.26984127e-01, 2.91555556e-01, 5.72916667e-01,
|
|
5.72916667e-01, 5.72916667e-01, 5.72916667e-01,
|
|
7.13580247e-01, 1.00000000e+00, 1.05333333e+00,
|
|
1.10000000e+00, 1.18294574e+00, 1.18294574e+00,
|
|
1.18294574e+00, 1.18294574e+00, 1.18294574e+00,
|
|
1.18294574e+00, 1.29494949e+00, 1.62857143e+00],
|
|
[-2.62295082e-01, 1.96914557e-16, 1.56140351e-01,
|
|
2.91555556e-01, 4.36619718e-01, 7.37704918e-01,
|
|
7.37704918e-01, 7.13580247e-01, 7.13580247e-01,
|
|
7.37704918e-01, 1.00000000e+00, 1.05641026e+00,
|
|
1.10000000e+00, 1.18294574e+00, 1.34414414e+00,
|
|
1.34414414e+00, 1.34414414e+00, 1.29494949e+00,
|
|
1.29494949e+00, 1.34414414e+00, 1.65555556e+00],
|
|
[-2.77555756e-17, 2.62295082e-01, 4.27083333e-01,
|
|
5.72916667e-01, 7.37704918e-01, 1.00000000e+00,
|
|
1.00000000e+00, 1.00000000e+00, 1.00000000e+00,
|
|
1.00000000e+00, 1.00000000e+00, 1.05641026e+00,
|
|
1.10000000e+00, 1.18294574e+00, 1.34414414e+00,
|
|
1.66666667e+00, 1.65555556e+00, 1.62857143e+00,
|
|
1.62857143e+00, 1.65555556e+00, 1.66666667e+00]]) # nopep8
|
|
|
|
# Ensure results are within expected limits
|
|
np.testing.assert_allclose(z1, expected)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
tst.run_module_suite()
|