@@ -210,6 +210,17 @@ def __init__(self, inputs=None, outputs=None, states=None, params={},
210210 def __repr__ (self ):
211211 return self .name if self .name is not None else str (type (self ))
212212
213+ def __str__ (self ):
214+ """String representation of an input/output system"""
215+ str = "System: " + (self .name if self .name else "(none)" ) + "\n "
216+ str += "Inputs (%d): " % self .ninputs
217+ for key in self .input_index : str += key + ", "
218+ str += "\n Outputs (%d): " % self .noutputs
219+ for key in self .output_index : str += key + ", "
220+ str += "\n States (%d): " % self .nstates
221+ for key in self .state_index : str += key + ", "
222+ return str
223+
213224 def __mul__ (sys2 , sys1 ):
214225 """Multiply two input/output systems (series interconnection)"""
215226
@@ -363,7 +374,11 @@ def _process_signal_list(self, signals, prefix='s'):
363374
364375 elif isinstance (signals , int ):
365376 # Number of signals given; make up the names
366- return signals , {'x[%d]' % i : i for i in range (signals )}
377+ return signals , {'%s[%d]' % (prefix , i ): i for i in range (signals )}
378+
379+ elif isinstance (signals , str ):
380+ # Single string given => single signal with given name
381+ return 1 , {signals : 0 }
367382
368383 elif all (isinstance (s , str ) for s in signals ):
369384 # Use the list of strings as the signal names
@@ -433,7 +448,7 @@ def set_outputs(self, outputs, prefix='y'):
433448 optional prefix parameter).
434449 prefix : string, optional
435450 If `outputs` is an integer, create the names of the states using
436- the given prefix (default = 'u '). The names of the input will be
451+ the given prefix (default = 'y '). The names of the input will be
437452 of the form `prefix[i]`.
438453
439454 """
@@ -453,7 +468,7 @@ def set_states(self, states, prefix='x'):
453468 optional prefix parameter).
454469 prefix : string, optional
455470 If `states` is an integer, create the names of the states using
456- the given prefix (default = 'u '). The names of the input will be
471+ the given prefix (default = 'x '). The names of the input will be
457472 of the form `prefix[i]`.
458473
459474 """
@@ -667,13 +682,16 @@ def __init__(self, linsys, inputs=None, outputs=None, states=None,
667682
668683 # Process input, output, state lists, if given
669684 # Make sure they match the size of the linear system
670- ninputs , self .input_index = self ._process_signal_list (inputs )
685+ ninputs , self .input_index = self ._process_signal_list (
686+ inputs if inputs is not None else linsys .inputs , prefix = 'u' )
671687 if ninputs is not None and linsys .inputs != ninputs :
672688 raise ValueError ("Wrong number/type of inputs given." )
673- noutputs , self .output_index = self ._process_signal_list (outputs )
689+ noutputs , self .output_index = self ._process_signal_list (
690+ outputs if outputs is not None else linsys .outputs , prefix = 'y' )
674691 if noutputs is not None and linsys .outputs != noutputs :
675692 raise ValueError ("Wrong number/type of outputs given." )
676- nstates , self .state_index = self ._process_signal_list (states )
693+ nstates , self .state_index = self ._process_signal_list (
694+ states if states is not None else linsys .states , prefix = 'x' )
677695 if nstates is not None and linsys .states != nstates :
678696 raise ValueError ("Wrong number/type of states given." )
679697
@@ -868,20 +886,20 @@ def __init__(self, syslist, connections=[], inplist=[], outlist=[],
868886
869887 inplist : tuple of input specifications, optional
870888 List of specifications for how the inputs for the overall system
871- are mapped to the subsystems . The input specification is the same
872- as the form defined in the connection specification. Each system
873- input is added to the input for the listed subsystem.
889+ are mapped to the subsystem inputs . The input specification is
890+ the same as the form defined in the connection specification.
891+ Each system input is added to the input for the listed subsystem.
874892
875893 If omitted, the input map can be specified using the
876894 `set_input_map` method.
877895
878896 outlist : tuple of output specifications, optional
879897 List of specifications for how the outputs for the subsystems are
880- mapped to overall system. The output specification is the same as
881- the form defined in the connection specification (including the
882- optional gain term). Numbered outputs must be chosen from the
883- list of subsystem outputs, but named outputs can also be contained
884- in the list of subsystem inputs.
898+ mapped to overall system outputs . The output specification is the
899+ same as the form defined in the connection specification
900+ (including the optional gain term). Numbered outputs must be
901+ chosen from the list of subsystem outputs, but named outputs can
902+ also be contained in the list of subsystem inputs.
885903
886904 If omitted, the output map can be specified using the
887905 `set_output_map` method.
@@ -964,10 +982,12 @@ def __init__(self, syslist, connections=[], inplist=[], outlist=[],
964982 states = nstates , params = params , dt = dt )
965983
966984 # If input or output list was specified, update it
967- nsignals , self .input_index = self ._process_signal_list (inputs )
985+ nsignals , self .input_index = \
986+ self ._process_signal_list (inputs , prefix = 'u' )
968987 if nsignals is not None and len (inplist ) != nsignals :
969988 raise ValueError ("Wrong number/type of inputs given." )
970- nsignals , self .output_index = self ._process_signal_list (outputs )
989+ nsignals , self .output_index = \
990+ self ._process_signal_list (outputs , prefix = 'y' )
971991 if nsignals is not None and len (outlist ) != nsignals :
972992 raise ValueError ("Wrong number/type of outputs given." )
973993
@@ -981,8 +1001,10 @@ def __init__(self, syslist, connections=[], inplist=[], outlist=[],
9811001
9821002 # Convert the input list to a matrix: maps system to subsystems
9831003 self .input_map = np .zeros ((ninputs , self .ninputs ))
984- for index in range (len (inplist )):
985- self .input_map [self ._parse_input_spec (inplist [index ]), index ] = 1
1004+ for index , inpspec in enumerate (inplist ):
1005+ if isinstance (inpspec , (int , str , tuple )): inpspec = [inpspec ]
1006+ for spec in inpspec :
1007+ self .input_map [self ._parse_input_spec (spec ), index ] = 1
9861008
9871009 # Convert the output list to a matrix: maps subsystems to system
9881010 self .output_map = np .zeros ((self .noutputs , noutputs + ninputs ))
@@ -1116,10 +1138,9 @@ def _compute_static_io(self, t, x, u):
11161138 def _parse_input_spec (self , spec ):
11171139 """Parse an input specification and returns the index
11181140
1119- This function parses a specification of an input of an
1120- interconnected system component and returns the index of that
1121- input in the internal input vector. Input specifications
1122- are of one of the following forms:
1141+ This function parses a specification of an input of an interconnected
1142+ system component and returns the index of that input in the internal
1143+ input vector. Input specifications are of one of the following forms:
11231144
11241145 i first input for the ith system
11251146 (i,) first input for the ith system
@@ -1228,8 +1249,8 @@ def _parse_signal(self, spec, signame='input', dictname=None):
12281249 # For now, only allow signal level of system name
12291250 # TODO: expand to allow nested signal names
12301251 if len (namelist ) != 2 :
1231- raise ValueError ("Couldn't parse signal reference '%s'."
1232- % spec )
1252+ raise ValueError ("Couldn't parse %s signal reference '%s'."
1253+ % ( signame , spec ) )
12331254
12341255 system_index = self ._find_system (namelist [0 ])
12351256 if system_index is None :
0 commit comments