pathsim 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. pathsim/__init__.py +3 -0
  2. pathsim/blocks/__init__.py +14 -0
  3. pathsim/blocks/_block.py +209 -0
  4. pathsim/blocks/adder.py +30 -0
  5. pathsim/blocks/amplifier.py +34 -0
  6. pathsim/blocks/delay.py +70 -0
  7. pathsim/blocks/differentiator.py +70 -0
  8. pathsim/blocks/function.py +82 -0
  9. pathsim/blocks/integrator.py +66 -0
  10. pathsim/blocks/lti.py +155 -0
  11. pathsim/blocks/multiplier.py +30 -0
  12. pathsim/blocks/ode.py +86 -0
  13. pathsim/blocks/rf/__init__.py +4 -0
  14. pathsim/blocks/rf/filters.py +169 -0
  15. pathsim/blocks/rf/noise.py +218 -0
  16. pathsim/blocks/rf/sources.py +163 -0
  17. pathsim/blocks/rf/wienerhammerstein.py +338 -0
  18. pathsim/blocks/rng.py +57 -0
  19. pathsim/blocks/scope.py +224 -0
  20. pathsim/blocks/sources.py +71 -0
  21. pathsim/blocks/spectrum.py +316 -0
  22. pathsim/connection.py +112 -0
  23. pathsim/simulation.py +652 -0
  24. pathsim/solvers/__init__.py +25 -0
  25. pathsim/solvers/_solver.py +403 -0
  26. pathsim/solvers/bdf.py +240 -0
  27. pathsim/solvers/dirk2.py +101 -0
  28. pathsim/solvers/dirk3.py +86 -0
  29. pathsim/solvers/esdirk32.py +131 -0
  30. pathsim/solvers/esdirk4.py +99 -0
  31. pathsim/solvers/esdirk43.py +139 -0
  32. pathsim/solvers/esdirk54.py +141 -0
  33. pathsim/solvers/esdirk85.py +200 -0
  34. pathsim/solvers/euler.py +81 -0
  35. pathsim/solvers/rk4.py +61 -0
  36. pathsim/solvers/rkbs32.py +101 -0
  37. pathsim/solvers/rkck54.py +108 -0
  38. pathsim/solvers/rkdp54.py +111 -0
  39. pathsim/solvers/rkdp87.py +116 -0
  40. pathsim/solvers/rkf45.py +102 -0
  41. pathsim/solvers/rkf78.py +111 -0
  42. pathsim/solvers/rkv65.py +103 -0
  43. pathsim/solvers/ssprk22.py +62 -0
  44. pathsim/solvers/ssprk33.py +65 -0
  45. pathsim/solvers/ssprk34.py +74 -0
  46. pathsim/subsystem.py +267 -0
  47. pathsim/utils/__init__.py +0 -0
  48. pathsim/utils/adaptivebuffer.py +87 -0
  49. pathsim/utils/anderson.py +180 -0
  50. pathsim/utils/funcs.py +205 -0
  51. pathsim/utils/gilbert.py +110 -0
  52. pathsim/utils/progresstracker.py +90 -0
  53. pathsim/utils/realtimeplotter.py +230 -0
  54. pathsim/utils/statespacerealizations.py +116 -0
  55. pathsim/utils/waveforms.py +36 -0
  56. pathsim-0.2.0.dist-info/LICENSE.txt +21 -0
  57. pathsim-0.2.0.dist-info/METADATA +149 -0
  58. pathsim-0.2.0.dist-info/RECORD +109 -0
  59. pathsim-0.2.0.dist-info/WHEEL +5 -0
  60. pathsim-0.2.0.dist-info/top_level.txt +2 -0
  61. tests/__init__.py +0 -0
  62. tests/blocks/__init__.py +0 -0
  63. tests/blocks/test_adder.py +85 -0
  64. tests/blocks/test_amplifier.py +66 -0
  65. tests/blocks/test_block.py +138 -0
  66. tests/blocks/test_delay.py +122 -0
  67. tests/blocks/test_differentiator.py +102 -0
  68. tests/blocks/test_function.py +165 -0
  69. tests/blocks/test_integrator.py +92 -0
  70. tests/blocks/test_lti.py +162 -0
  71. tests/blocks/test_multiplier.py +87 -0
  72. tests/blocks/test_ode.py +125 -0
  73. tests/blocks/test_rng.py +109 -0
  74. tests/blocks/test_scope.py +196 -0
  75. tests/blocks/test_sources.py +119 -0
  76. tests/blocks/test_spectrum.py +119 -0
  77. tests/solvers/__init__.py +0 -0
  78. tests/solvers/test_bdf.py +364 -0
  79. tests/solvers/test_dirk2.py +138 -0
  80. tests/solvers/test_dirk3.py +137 -0
  81. tests/solvers/test_esdirk32.py +158 -0
  82. tests/solvers/test_esdirk4.py +138 -0
  83. tests/solvers/test_esdirk43.py +158 -0
  84. tests/solvers/test_esdirk54.py +160 -0
  85. tests/solvers/test_esdirk85.py +157 -0
  86. tests/solvers/test_euler.py +223 -0
  87. tests/solvers/test_rk4.py +138 -0
  88. tests/solvers/test_rkbs32.py +159 -0
  89. tests/solvers/test_rkck54.py +157 -0
  90. tests/solvers/test_rkdp54.py +159 -0
  91. tests/solvers/test_rkdp87.py +157 -0
  92. tests/solvers/test_rkf45.py +159 -0
  93. tests/solvers/test_rkf78.py +160 -0
  94. tests/solvers/test_rkv65.py +160 -0
  95. tests/solvers/test_solver.py +119 -0
  96. tests/solvers/test_ssprk22.py +136 -0
  97. tests/solvers/test_ssprk33.py +136 -0
  98. tests/solvers/test_ssprk34.py +136 -0
  99. tests/test_connection.py +176 -0
  100. tests/test_simulation.py +271 -0
  101. tests/test_subsystem.py +182 -0
  102. tests/utils/__init__.py +0 -0
  103. tests/utils/test_adaptivebuffer.py +111 -0
  104. tests/utils/test_anderson.py +142 -0
  105. tests/utils/test_funcs.py +143 -0
  106. tests/utils/test_gilbert.py +108 -0
  107. tests/utils/test_progresstracker.py +144 -0
  108. tests/utils/test_realtimeplotter.py +122 -0
  109. tests/utils/test_statespacerealizations.py +107 -0
@@ -0,0 +1,119 @@
1
+ ########################################################################################
2
+ ##
3
+ ## TESTS FOR 'solvers/_solver.py'
4
+ ##
5
+ ## Milan Rother 2024
6
+ ##
7
+ ########################################################################################
8
+
9
+ # IMPORTS ==============================================================================
10
+
11
+ import unittest
12
+ import numpy as np
13
+
14
+
15
+ from pathsim.solvers._solver import (
16
+ Solver,
17
+ ExplicitSolver,
18
+ ImplicitSolver)
19
+
20
+
21
+ # HELPER FUNCTIONS =====================================================================
22
+
23
+ def simple_func(x, u, t):
24
+ return u - x
25
+
26
+ def simple_jac(x, u, t):
27
+ return -1
28
+
29
+
30
+ # TESTS ================================================================================
31
+
32
+ class TestBaseSolver(unittest.TestCase):
33
+ """
34
+ Test the implementation of the base 'Solver' class
35
+ """
36
+
37
+ def setUp(self):
38
+ self.solver = Solver(initial_value=1.0, func=simple_func, jac=simple_jac)
39
+
40
+ def test_init(self):
41
+ self.assertEqual(self.solver.x, 1.0)
42
+ self.assertEqual(self.solver.x_0, 1.0)
43
+ self.assertEqual(self.solver.initial_value, 1.0)
44
+ self.assertEqual(self.solver.func, simple_func)
45
+ self.assertEqual(self.solver.jac, simple_jac)
46
+ self.assertFalse(self.solver.is_adaptive)
47
+
48
+ def test_str(self):
49
+ self.assertEqual(str(self.solver), "Solver")
50
+
51
+ def test_stages(self):
52
+ stages = list(self.solver.stages(0, 1))
53
+ self.assertEqual(stages, [0])
54
+
55
+ def test_get_set(self):
56
+ self.solver.set(2.0)
57
+ self.assertEqual(self.solver.get(), 2.0)
58
+
59
+ def test_reset(self):
60
+ self.solver.set(2.0)
61
+ self.solver.reset()
62
+ self.assertEqual(self.solver.get(), 1.0)
63
+
64
+ def test_buffer(self):
65
+ self.solver.x = 2.0
66
+ self.solver.buffer()
67
+ self.assertEqual(self.solver.x_0, 2.0)
68
+
69
+ def test_change(self):
70
+ new_solver = self.solver.change(ExplicitSolver)
71
+ self.assertIsInstance(new_solver, ExplicitSolver)
72
+ self.assertEqual(new_solver.get(), self.solver.get())
73
+
74
+
75
+ class ExplicitSolverTest(unittest.TestCase):
76
+ """
77
+ Test the implementation of the 'ExplicitSolver' base class
78
+ """
79
+ def setUp(self):
80
+ self.solver = ExplicitSolver(initial_value=1.0, func=simple_func, jac=simple_jac)
81
+
82
+ def test_init(self):
83
+ self.assertTrue(self.solver.is_explicit)
84
+ self.assertFalse(self.solver.is_implicit)
85
+
86
+ def test_integrate_singlestep(self):
87
+ success, error, scale = self.solver.integrate_singlestep(time=0, dt=0.1)
88
+ self.assertTrue(success)
89
+ self.assertEqual(error, 0.0)
90
+ self.assertEqual(scale, 1.0)
91
+
92
+ def test_integrate(self):
93
+ times, states = self.solver.integrate(time_start=0, time_end=1, dt=0.1)
94
+ self.assertEqual(len(times), len(states))
95
+ self.assertGreater(len(times), 1)
96
+ self.assertEqual(times[0], 0)
97
+
98
+
99
+ class ImplicitSolverTest(unittest.TestCase):
100
+ """
101
+ Test the implementation of the 'ImplicitSolver' base class
102
+ """
103
+
104
+ def setUp(self):
105
+ self.solver = ImplicitSolver(initial_value=1.0, func=simple_func, jac=simple_jac)
106
+
107
+ def test_init(self):
108
+ self.assertFalse(self.solver.is_explicit)
109
+ self.assertTrue(self.solver.is_implicit)
110
+
111
+ def test_solve(self):
112
+ error = self.solver.solve(0, 0, 0.1)
113
+ self.assertEqual(error, 0.0)
114
+
115
+
116
+ # RUN TESTS LOCALLY ====================================================================
117
+
118
+ if __name__ == '__main__':
119
+ unittest.main(verbosity=2)
@@ -0,0 +1,136 @@
1
+ ########################################################################################
2
+ ##
3
+ ## TESTS FOR
4
+ ## 'solvers/ssprk22.py'
5
+ ##
6
+ ## Milan Rother 2024
7
+ ##
8
+ ########################################################################################
9
+
10
+ # IMPORTS ==============================================================================
11
+
12
+ import unittest
13
+ import numpy as np
14
+
15
+ from pathsim.solvers.ssprk22 import SSPRK22
16
+
17
+
18
+ # TEST PROBLEMS ========================================================================
19
+
20
+ class Problem:
21
+ def __init__(self, name, func, jac, x0, solution):
22
+ self.name = name
23
+ self.func = func
24
+ self.jac = jac
25
+ self.x0 = x0
26
+ self.solution = solution
27
+
28
+
29
+ #create some reference problems for testing
30
+ reference_problems = [
31
+ Problem(name="linear_feedback",
32
+ func=lambda x, u, t: -x,
33
+ jac=lambda x, u, t: -1,
34
+ x0=1.0,
35
+ solution=lambda t: np.exp(-t)
36
+ ),
37
+ Problem(name="logistic",
38
+ func=lambda x, u, t: x*(1-x),
39
+ jac=lambda x, u, t: 1-2*x,
40
+ x0=0.5,
41
+ solution=lambda t: 1/(1 + np.exp(-t))
42
+ )
43
+ ]
44
+
45
+
46
+ # TESTS ================================================================================
47
+
48
+ class TestSSPRK22(unittest.TestCase):
49
+ """
50
+ Test the implementation of the 'SSPRK22' solver class
51
+ """
52
+
53
+ def test_init(self):
54
+
55
+ #test default initializtion
56
+ solver = SSPRK22()
57
+
58
+ self.assertTrue(callable(solver.func))
59
+ self.assertEqual(solver.jac, None)
60
+ self.assertEqual(solver.initial_value, 0)
61
+
62
+ self.assertEqual(solver.stage, 0)
63
+ self.assertFalse(solver.is_adaptive)
64
+ self.assertTrue(solver.is_explicit)
65
+ self.assertFalse(solver.is_implicit)
66
+
67
+ #test specific initialization
68
+ solver = SSPRK22(initial_value=1,
69
+ func=lambda x, u, t: -x,
70
+ jac=lambda x, u, t: -1,
71
+ tolerance_lte=1e-6)
72
+
73
+ self.assertEqual(solver.func(2, 0, 0), -2)
74
+ self.assertEqual(solver.jac(2, 0, 0), -1)
75
+ self.assertEqual(solver.initial_value, 1)
76
+ self.assertEqual(solver.tolerance_lte, 1e-6)
77
+
78
+
79
+ def test_stages(self):
80
+
81
+ solver = SSPRK22()
82
+
83
+ for i, t in enumerate(solver.stages(0, 1)):
84
+
85
+ #test the stage iterator
86
+ self.assertEqual(t, solver.eval_stages[i])
87
+
88
+
89
+ def test_step(self):
90
+
91
+ solver = SSPRK22()
92
+
93
+ for i, t in enumerate(solver.stages(0, 1)):
94
+
95
+ #test if stage incrementation works
96
+ self.assertEqual(solver.stage, i)
97
+
98
+ success, err, scale = solver.step(0.0, t, 1)
99
+
100
+ #test if expected return at intermediate stages
101
+ self.assertTrue(success)
102
+ self.assertEqual(err, 0.0)
103
+ self.assertEqual(scale, 1.0)
104
+
105
+
106
+ def test_integrate_fixed(self):
107
+
108
+ #integrate test problem and assess convergence order
109
+
110
+ timesteps = np.logspace(-0.4, 0, 20)
111
+
112
+ for problem in reference_problems:
113
+
114
+ solver = SSPRK22(problem.x0, problem.func, problem.jac)
115
+
116
+ errors = []
117
+
118
+ for dt in timesteps:
119
+
120
+ solver.reset()
121
+ time, numerical_solution = solver.integrate(time_start=0.0, time_end=3.0, dt=dt, adaptive=False)
122
+
123
+ errors.append(np.linalg.norm(numerical_solution - problem.solution(time)))
124
+
125
+ #test if errors are monotonically decreasing
126
+ self.assertTrue(np.all(np.diff(errors)>0))
127
+
128
+ #test convergence order, expected 2
129
+ p, _ = np.polyfit(np.log10(timesteps), np.log10(errors), deg=1)
130
+ self.assertEqual(round(p), 2)
131
+
132
+
133
+ # RUN TESTS LOCALLY ====================================================================
134
+
135
+ if __name__ == '__main__':
136
+ unittest.main(verbosity=2)
@@ -0,0 +1,136 @@
1
+ ########################################################################################
2
+ ##
3
+ ## TESTS FOR
4
+ ## 'solvers/ssprk33.py'
5
+ ##
6
+ ## Milan Rother 2024
7
+ ##
8
+ ########################################################################################
9
+
10
+ # IMPORTS ==============================================================================
11
+
12
+ import unittest
13
+ import numpy as np
14
+
15
+ from pathsim.solvers.ssprk33 import SSPRK33
16
+
17
+
18
+ # TEST PROBLEMS ========================================================================
19
+
20
+ class Problem:
21
+ def __init__(self, name, func, jac, x0, solution):
22
+ self.name = name
23
+ self.func = func
24
+ self.jac = jac
25
+ self.x0 = x0
26
+ self.solution = solution
27
+
28
+
29
+ #create some reference problems for testing
30
+ reference_problems = [
31
+ Problem(name="linear_feedback",
32
+ func=lambda x, u, t: -x,
33
+ jac=lambda x, u, t: -1,
34
+ x0=1.0,
35
+ solution=lambda t: np.exp(-t)
36
+ ),
37
+ Problem(name="logistic",
38
+ func=lambda x, u, t: x*(1-x),
39
+ jac=lambda x, u, t: 1-2*x,
40
+ x0=0.5,
41
+ solution=lambda t: 1/(1 + np.exp(-t))
42
+ )
43
+ ]
44
+
45
+
46
+ # TESTS ================================================================================
47
+
48
+ class TestSSPRK33(unittest.TestCase):
49
+ """
50
+ Test the implementation of the 'SSPRK33' solver class
51
+ """
52
+
53
+ def test_init(self):
54
+
55
+ #test default initializtion
56
+ solver = SSPRK33()
57
+
58
+ self.assertTrue(callable(solver.func))
59
+ self.assertEqual(solver.jac, None)
60
+ self.assertEqual(solver.initial_value, 0)
61
+
62
+ self.assertEqual(solver.stage, 0)
63
+ self.assertFalse(solver.is_adaptive)
64
+ self.assertTrue(solver.is_explicit)
65
+ self.assertFalse(solver.is_implicit)
66
+
67
+ #test specific initialization
68
+ solver = SSPRK33(initial_value=1,
69
+ func=lambda x, u, t: -x,
70
+ jac=lambda x, u, t: -1,
71
+ tolerance_lte=1e-6)
72
+
73
+ self.assertEqual(solver.func(2, 0, 0), -2)
74
+ self.assertEqual(solver.jac(2, 0, 0), -1)
75
+ self.assertEqual(solver.initial_value, 1)
76
+ self.assertEqual(solver.tolerance_lte, 1e-6)
77
+
78
+
79
+ def test_stages(self):
80
+
81
+ solver = SSPRK33()
82
+
83
+ for i, t in enumerate(solver.stages(0, 1)):
84
+
85
+ #test the stage iterator
86
+ self.assertEqual(t, solver.eval_stages[i])
87
+
88
+
89
+ def test_step(self):
90
+
91
+ solver = SSPRK33()
92
+
93
+ for i, t in enumerate(solver.stages(0, 1)):
94
+
95
+ #test if stage incrementation works
96
+ self.assertEqual(solver.stage, i)
97
+
98
+ success, err, scale = solver.step(0.0, t, 1)
99
+
100
+ #test if expected return at intermediate stages
101
+ self.assertTrue(success)
102
+ self.assertEqual(err, 0.0)
103
+ self.assertEqual(scale, 1.0)
104
+
105
+
106
+ def test_integrate_fixed(self):
107
+
108
+ #integrate test problem and assess convergence order
109
+
110
+ timesteps = np.logspace(-0.4, 0, 20)
111
+
112
+ for problem in reference_problems:
113
+
114
+ solver = SSPRK33(problem.x0, problem.func, problem.jac)
115
+
116
+ errors = []
117
+
118
+ for dt in timesteps:
119
+
120
+ solver.reset()
121
+ time, numerical_solution = solver.integrate(time_start=0.0, time_end=3.0, dt=dt, adaptive=False)
122
+
123
+ errors.append(np.linalg.norm(numerical_solution - problem.solution(time)))
124
+
125
+ #test if errors are monotonically decreasing
126
+ self.assertTrue(np.all(np.diff(errors)>0))
127
+
128
+ #test convergence order, expected 3
129
+ p, _ = np.polyfit(np.log10(timesteps), np.log10(errors), deg=1)
130
+ self.assertEqual(round(p), 3)
131
+
132
+
133
+ # RUN TESTS LOCALLY ====================================================================
134
+
135
+ if __name__ == '__main__':
136
+ unittest.main(verbosity=2)
@@ -0,0 +1,136 @@
1
+ ########################################################################################
2
+ ##
3
+ ## TESTS FOR
4
+ ## 'solvers/ssprk34.py'
5
+ ##
6
+ ## Milan Rother 2024
7
+ ##
8
+ ########################################################################################
9
+
10
+ # IMPORTS ==============================================================================
11
+
12
+ import unittest
13
+ import numpy as np
14
+
15
+ from pathsim.solvers.ssprk34 import SSPRK34
16
+
17
+
18
+ # TEST PROBLEMS ========================================================================
19
+
20
+ class Problem:
21
+ def __init__(self, name, func, jac, x0, solution):
22
+ self.name = name
23
+ self.func = func
24
+ self.jac = jac
25
+ self.x0 = x0
26
+ self.solution = solution
27
+
28
+
29
+ #create some reference problems for testing
30
+ reference_problems = [
31
+ Problem(name="linear_feedback",
32
+ func=lambda x, u, t: -x,
33
+ jac=lambda x, u, t: -1,
34
+ x0=1.0,
35
+ solution=lambda t: np.exp(-t)
36
+ ),
37
+ Problem(name="logistic",
38
+ func=lambda x, u, t: x*(1-x),
39
+ jac=lambda x, u, t: 1-2*x,
40
+ x0=0.5,
41
+ solution=lambda t: 1/(1 + np.exp(-t))
42
+ )
43
+ ]
44
+
45
+
46
+ # TESTS ================================================================================
47
+
48
+ class TestSSPRK34(unittest.TestCase):
49
+ """
50
+ Test the implementation of the 'SSPRK34' solver class
51
+ """
52
+
53
+ def test_init(self):
54
+
55
+ #test default initializtion
56
+ solver = SSPRK34()
57
+
58
+ self.assertTrue(callable(solver.func))
59
+ self.assertEqual(solver.jac, None)
60
+ self.assertEqual(solver.initial_value, 0)
61
+
62
+ self.assertEqual(solver.stage, 0)
63
+ self.assertFalse(solver.is_adaptive)
64
+ self.assertTrue(solver.is_explicit)
65
+ self.assertFalse(solver.is_implicit)
66
+
67
+ #test specific initialization
68
+ solver = SSPRK34(initial_value=1,
69
+ func=lambda x, u, t: -x,
70
+ jac=lambda x, u, t: -1,
71
+ tolerance_lte=1e-6)
72
+
73
+ self.assertEqual(solver.func(2, 0, 0), -2)
74
+ self.assertEqual(solver.jac(2, 0, 0), -1)
75
+ self.assertEqual(solver.initial_value, 1)
76
+ self.assertEqual(solver.tolerance_lte, 1e-6)
77
+
78
+
79
+ def test_stages(self):
80
+
81
+ solver = SSPRK34()
82
+
83
+ for i, t in enumerate(solver.stages(0, 1)):
84
+
85
+ #test the stage iterator
86
+ self.assertEqual(t, solver.eval_stages[i])
87
+
88
+
89
+ def test_step(self):
90
+
91
+ solver = SSPRK34()
92
+
93
+ for i, t in enumerate(solver.stages(0, 1)):
94
+
95
+ #test if stage incrementation works
96
+ self.assertEqual(solver.stage, i)
97
+
98
+ success, err, scale = solver.step(0.0, t, 1)
99
+
100
+ #test if expected return at intermediate stages
101
+ self.assertTrue(success)
102
+ self.assertEqual(err, 0.0)
103
+ self.assertEqual(scale, 1.0)
104
+
105
+
106
+ def test_integrate_fixed(self):
107
+
108
+ #integrate test problem and assess convergence order
109
+
110
+ timesteps = np.logspace(-0.4, 0, 20)
111
+
112
+ for problem in reference_problems:
113
+
114
+ solver = SSPRK34(problem.x0, problem.func, problem.jac)
115
+
116
+ errors = []
117
+
118
+ for dt in timesteps:
119
+
120
+ solver.reset()
121
+ time, numerical_solution = solver.integrate(time_start=0.0, time_end=3.0, dt=dt, adaptive=False)
122
+
123
+ errors.append(np.linalg.norm(numerical_solution - problem.solution(time)))
124
+
125
+ #test if errors are monotonically decreasing
126
+ self.assertTrue(np.all(np.diff(errors)>0))
127
+
128
+ #test convergence order, expected 3
129
+ p, _ = np.polyfit(np.log10(timesteps), np.log10(errors), deg=1)
130
+ self.assertEqual(round(p), 3)
131
+
132
+
133
+ # RUN TESTS LOCALLY ====================================================================
134
+
135
+ if __name__ == '__main__':
136
+ unittest.main(verbosity=2)
@@ -0,0 +1,176 @@
1
+ ########################################################################################
2
+ ##
3
+ ## TESTS FOR
4
+ ## 'connection.py'
5
+ ##
6
+ ## Milan Rother 2024
7
+ ##
8
+ ########################################################################################
9
+
10
+ # IMPORTS ==============================================================================
11
+
12
+ import unittest
13
+ import numpy as np
14
+
15
+ from pathsim.connection import Connection
16
+ from pathsim.blocks._block import Block
17
+
18
+
19
+ # TESTS ================================================================================
20
+
21
+ class TestConnection(unittest.TestCase):
22
+ """
23
+ Test the implementation of the 'Connection' class
24
+ """
25
+
26
+ def test_init_single(self):
27
+
28
+ B1, B2 = Block(), Block()
29
+
30
+ #default
31
+ C = Connection(B1, B2)
32
+
33
+ #test if ports assigned correctly
34
+ self.assertEqual(C.source, (B1, 0))
35
+ self.assertEqual(C.targets, [(B2, 0)])
36
+
37
+ #mixed
38
+ C1 = Connection(B1, (B2, 2))
39
+ C2 = Connection((B1, 3), B2)
40
+
41
+ #test if ports assigned correctly
42
+ self.assertEqual(C1.source, (B1, 0))
43
+ self.assertEqual(C1.targets, [(B2, 2)])
44
+
45
+ #test if ports assigned correctly
46
+ self.assertEqual(C2.source, (B1, 3))
47
+ self.assertEqual(C2.targets, [(B2, 0)])
48
+
49
+ #all
50
+ C = Connection((B1, 4), (B2, 1))
51
+
52
+ #test if ports assigned correctly
53
+ self.assertEqual(C.source, (B1, 4))
54
+ self.assertEqual(C.targets, [(B2, 1)])
55
+
56
+
57
+ def test_init_multi(self):
58
+
59
+ B1, B2, B3 = Block(), Block(), Block()
60
+
61
+ #default
62
+ C = Connection(B1, B2, B3)
63
+
64
+ #test if ports assigned correctly
65
+ self.assertEqual(C.source, (B1, 0))
66
+ self.assertEqual(C.targets, [(B2, 0), (B3, 0)])
67
+
68
+ #mixed
69
+ C1 = Connection(B1, (B2, 2), B3)
70
+ C2 = Connection((B1, 3), B2, (B3, 1))
71
+
72
+ #test if ports assigned correctly
73
+ self.assertEqual(C1.source, (B1, 0))
74
+ self.assertEqual(C1.targets, [(B2, 2), (B3, 0)])
75
+
76
+ #test if ports assigned correctly
77
+ self.assertEqual(C2.source, (B1, 3))
78
+ self.assertEqual(C2.targets, [(B2, 0), (B3, 1)])
79
+
80
+ #all
81
+ C = Connection((B1, 4), (B2, 1), (B3, 2))
82
+
83
+ #test if ports assigned correctly
84
+ self.assertEqual(C.source, (B1, 4))
85
+ self.assertEqual(C.targets, [(B2, 1), (B3, 2)])
86
+
87
+
88
+ def test_overwrites(self):
89
+
90
+ B1, B2, B3 = Block(), Block(), Block()
91
+
92
+ C1 = Connection(B1, B2)
93
+ C2 = Connection(B1, B3)
94
+ C3 = Connection(B2, B3)
95
+
96
+ self.assertFalse(C1.overwrites(C2))
97
+ self.assertFalse(C2.overwrites(C1))
98
+ self.assertTrue(C3.overwrites(C2))
99
+ self.assertTrue(C2.overwrites(C3))
100
+
101
+ C1 = Connection(B1, B2, B3)
102
+ C2 = Connection(B1, B3)
103
+
104
+ self.assertTrue(C1.overwrites(C2))
105
+ self.assertTrue(C2.overwrites(C1))
106
+
107
+ C1 = Connection(B1, (B2, 1))
108
+ C2 = Connection(B1, (B2, 2))
109
+
110
+ self.assertFalse(C1.overwrites(C2))
111
+ self.assertFalse(C2.overwrites(C1))
112
+
113
+ C1 = Connection((B1, 1), B3)
114
+ C2 = Connection((B1, 2), B3)
115
+
116
+ self.assertTrue(C1.overwrites(C2))
117
+ self.assertTrue(C2.overwrites(C1))
118
+
119
+ C1 = Connection((B1, 1), B3)
120
+ C2 = Connection((B1, 2), (B3, 0))
121
+
122
+ self.assertTrue(C1.overwrites(C2))
123
+ self.assertTrue(C2.overwrites(C1))
124
+
125
+
126
+ def test_update_single(self):
127
+
128
+ B1, B2 = Block(), Block()
129
+
130
+ #test data transfer with default ports
131
+ C = Connection(B1, B2)
132
+ B1.outputs[0] = 3
133
+ C.update()
134
+ self.assertEqual(B2.inputs[0], 3)
135
+
136
+ #test data transfer with specific ports
137
+ C = Connection((B1, 2), (B2, 2))
138
+ B1.outputs[2] = 3
139
+ C.update()
140
+ self.assertEqual(B2.inputs[2], 3)
141
+
142
+ #test data transfer with mixed ports
143
+ C = Connection(B1, (B2, 2))
144
+ B1.outputs[0] = 3
145
+ C.update()
146
+ self.assertEqual(B2.inputs[2], 3)
147
+
148
+ C = Connection((B1, 2), B2)
149
+ B1.outputs[2] = 3
150
+ C.update()
151
+ self.assertEqual(B2.inputs[0], 3)
152
+
153
+
154
+ def test_update_multi(self):
155
+
156
+ B1, B2, B3 = Block(), Block(), Block()
157
+
158
+ #test data transfer with default ports
159
+ C = Connection(B1, B2, B3)
160
+ B1.outputs[0] = 3
161
+ C.update()
162
+ self.assertEqual(B2.inputs[0], 3)
163
+ self.assertEqual(B3.inputs[0], 3)
164
+
165
+ #test data transfer with specific ports
166
+ C = Connection((B1, 2), (B2, 2), (B3, 1))
167
+ B1.outputs[2] = 3
168
+ C.update()
169
+ self.assertEqual(B2.inputs[2], 3)
170
+ self.assertEqual(B3.inputs[1], 3)
171
+
172
+
173
+ # RUN TESTS LOCALLY ====================================================================
174
+
175
+ if __name__ == '__main__':
176
+ unittest.main(verbosity=2)