@@ -297,3 +297,150 @@ def test_linear_interconnect():
297
297
inplist = ['sum.r' ], inputs = 'r' ,
298
298
outlist = ['plant.y' ], outputs = 'y' )
299
299
assert clsys .syslist [0 ].name == 'ctrl'
300
+
301
+ @pytest .mark .parametrize (
302
+ "connections, inplist, outlist, inputs, outputs" , [
303
+ pytest .param (
304
+ [['sys2' , 'sys1' ]], 'sys1' , 'sys2' , None , None ,
305
+ id = "sysname only, no i/o args" ),
306
+ pytest .param (
307
+ [['sys2' , 'sys1' ]], 'sys1' , 'sys2' , 3 , 3 ,
308
+ id = "i/o signal counts" ),
309
+ pytest .param (
310
+ [[('sys2' , [0 , 1 , 2 ]), ('sys1' , [0 , 1 , 2 ])]],
311
+ [('sys1' , [0 , 1 , 2 ])], [('sys2' , [0 , 1 , 2 ])],
312
+ 3 , 3 ,
313
+ id = "signal lists, i/o counts" ),
314
+ pytest .param (
315
+ [['sys2.u[0:3]' , 'sys1.y[:]' ]],
316
+ 'sys1.u[:]' , ['sys2.y[0:3]' ], None , None ,
317
+ id = "signal slices" ),
318
+ pytest .param (
319
+ ['sys2.u' , 'sys1.y' ], 'sys1.u' , 'sys2.y' , None , None ,
320
+ id = "signal basenames" ),
321
+ pytest .param (
322
+ [[('sys2' , [0 , 1 , 2 ]), ('sys1' , [0 , 1 , 2 ])]],
323
+ [('sys1' , [0 , 1 , 2 ])], [('sys2' , [0 , 1 , 2 ])],
324
+ None , None ,
325
+ id = "signal lists, no i/o counts" ),
326
+ pytest .param (
327
+ [[(1 , ['u[0]' , 'u[1]' , 'u[2]' ]), (0 , ['y[0]' , 'y[1]' , 'y[2]' ])]],
328
+ [('sys1' , [0 , 1 , 2 ])], [('sys2' , [0 , 1 , 2 ])],
329
+ 3 , ['y1' , 'y2' , 'y3' ],
330
+ id = "mixed specs" ),
331
+ pytest .param (
332
+ [[f'sys2.u[{ i } ]' , f'sys1.y[{ i } ]' ] for i in range (3 )],
333
+ [f'sys1.u[{ i } ]' for i in range (3 )],
334
+ [f'sys2.y[{ i } ]' for i in range (3 )],
335
+ [f'u[{ i } ]' for i in range (3 )], [f'y[{ i } ]' for i in range (3 )],
336
+ id = "full enumeration" ),
337
+ ])
338
+ def test_interconnect_series (connections , inplist , outlist , inputs , outputs ):
339
+ # Create an interconnected system for testing
340
+ sys1 = ct .rss (4 , 3 , 3 , name = 'sys1' )
341
+ sys2 = ct .rss (4 , 3 , 3 , name = 'sys2' )
342
+ series = sys2 * sys1
343
+
344
+ # Simple series interconnection
345
+ icsys = ct .interconnect (
346
+ [sys1 , sys2 ], connections = connections ,
347
+ inplist = inplist , outlist = outlist , inputs = inputs , outputs = outputs
348
+ )
349
+ np .testing .assert_allclose (icsys .A , series .A )
350
+ np .testing .assert_allclose (icsys .B , series .B )
351
+ np .testing .assert_allclose (icsys .C , series .C )
352
+ np .testing .assert_allclose (icsys .D , series .D )
353
+
354
+
355
+ @pytest .mark .parametrize (
356
+ "connections, inplist, outlist" , [
357
+ pytest .param (
358
+ [['P' , 'C' ], ['C' , '-P' ]], 'C' , 'P' ,
359
+ id = "sysname only, no i/o args" ),
360
+ pytest .param (
361
+ [['P.u' , 'C.y' ], ['C.u' , '-P.y' ]], 'C.u' , 'P.y' ,
362
+ id = "sysname only, no i/o args" ),
363
+ pytest .param (
364
+ [['P.u[:]' , 'C.y[0:2]' ],
365
+ [('C' , 'u' ), ('P' , ['y[0]' , 'y[1]' ], - 1 )]],
366
+ ['C.u[0]' , 'C.u[1]' ], ('P' , [0 , 1 ]),
367
+ id = "mixed cases" ),
368
+ ])
369
+ def test_interconnect_feedback (connections , inplist , outlist ):
370
+ # Create an interconnected system for testing
371
+ P = ct .rss (4 , 2 , 2 , name = 'P' , strictly_proper = True )
372
+ C = ct .rss (4 , 2 , 2 , name = 'C' )
373
+ feedback = ct .feedback (P * C , np .eye (2 ))
374
+
375
+ # Simple feedback interconnection
376
+ icsys = ct .interconnect (
377
+ [C , P ], connections = connections ,
378
+ inplist = inplist , outlist = outlist
379
+ )
380
+ np .testing .assert_allclose (icsys .A , feedback .A )
381
+ np .testing .assert_allclose (icsys .B , feedback .B )
382
+ np .testing .assert_allclose (icsys .C , feedback .C )
383
+ np .testing .assert_allclose (icsys .D , feedback .D )
384
+
385
+
386
+ @pytest .mark .parametrize (
387
+ "pinputs, poutputs, connections, inplist, outlist" , [
388
+ pytest .param (
389
+ ['w[0]' , 'w[1]' , 'u[0]' , 'u[1]' ], # pinputs
390
+ ['z[0]' , 'z[1]' , 'y[0]' , 'y[1]' ], # poutputs
391
+ [[('P' , [2 , 3 ]), ('C' , [0 , 1 ])], [('C' , [0 , 1 ]), ('P' , [2 , 3 ], - 1 )]],
392
+ [('C' , [0 , 1 ]), ('P' , [0 , 1 ])], # inplist
393
+ [('P' , [0 , 1 , 2 , 3 ]), ('C' , [0 , 1 ])], # outlist
394
+ id = "signal indices" ),
395
+ pytest .param (
396
+ ['w[0]' , 'w[1]' , 'u[0]' , 'u[1]' ], # pinputs
397
+ ['z[0]' , 'z[1]' , 'y[0]' , 'y[1]' ], # poutputs
398
+ [[('P' , [2 , 3 ]), ('C' , [0 , 1 ])], [('C' , [0 , 1 ]), ('P' , [2 , 3 ], - 1 )]],
399
+ ['C' , ('P' , [0 , 1 ])], ['P' , 'C' ], # inplist, outlist
400
+ id = "signal indices, when needed" ),
401
+ pytest .param (
402
+ 4 , 4 , # default I/O names
403
+ [['P.u[2:4]' , 'C.y[:]' ], ['C.u' , '-P.y[2:]' ]],
404
+ ['C' , 'P.u[:2]' ], ['P.y[:]' , 'P.u[2:]' ], # inplist, outlist
405
+ id = "signal slices" ),
406
+ pytest .param (
407
+ ['w[0]' , 'w[1]' , 'u[0]' , 'u[1]' ], # pinputs
408
+ ['z[0]' , 'z[1]' , 'y[0]' , 'y[1]' ], # poutputs
409
+ [['P.u' , 'C.y' ], ['C.u' , '-P.y' ]], # connections
410
+ ['C.u' , 'P.w' ], ['P.z' , 'P.y' , 'C.y' ], # inplist, outlist
411
+ id = "basename, control output" ),
412
+ pytest .param (
413
+ ['w[0]' , 'w[1]' , 'u[0]' , 'u[1]' ], # pinputs
414
+ ['z[0]' , 'z[1]' , 'y[0]' , 'y[1]' ], # poutputs
415
+ [['P.u' , 'C.y' ], ['C.u' , '-P.y' ]], # connections
416
+ ['C.u' , 'P.w' ], ['P.z' , 'P.y' , 'P.u' ], # inplist, outlist
417
+ id = "basename, process input" ),
418
+ ])
419
+ def test_interconnect_partial_feedback (
420
+ pinputs , poutputs , connections , inplist , outlist ):
421
+ P = ct .rss (
422
+ states = 6 , name = 'P' , strictly_proper = True ,
423
+ inputs = pinputs , outputs = poutputs )
424
+ C = ct .rss (4 , 2 , 2 , name = 'C' )
425
+
426
+ # Low level feedback connection (feedback around "lower" process I/O)
427
+ partial = ct .interconnect (
428
+ [C , P ],
429
+ connections = [
430
+ [(1 , 2 ), (0 , 0 )], [(1 , 3 ), (0 , 1 )],
431
+ [(0 , 0 ), (1 , 2 , - 1 )], [(0 , 1 ), (1 , 3 , - 1 )]],
432
+ inplist = [(0 , 0 ), (0 , 1 ), (1 , 0 ), (1 , 1 )], # C.u, P.w
433
+ outlist = [(1 , 0 ), (1 , 1 ), (1 , 2 ), (1 , 3 ),
434
+ (0 , 0 ), (0 , 1 )], # P.z, P.y, C.y
435
+ )
436
+
437
+ # High level feedback conections
438
+ icsys = ct .interconnect (
439
+ [C , P ], connections = connections ,
440
+ inplist = inplist , outlist = outlist
441
+ )
442
+ np .testing .assert_allclose (icsys .A , partial .A )
443
+ np .testing .assert_allclose (icsys .B , partial .B )
444
+ np .testing .assert_allclose (icsys .C , partial .C )
445
+ np .testing .assert_allclose (icsys .D , partial .D )
446
+ > >> >> >> 7 c86239 (add / move interconnect unit tests (); clean up list / tuple ; small fixes )
0 commit comments