Week 1 - GSoC '21

Week-1 of the program is officially over, and the learning experience had been quite fruitful. Progress of this week-

  1. Changed the API of TransferFunction and TransferFunctionMatrix to make it more beginner-friendly as well as efficient at the same time.
    • TransferFunction objects can now be directly created by directly passing the rational expression instead of passing the num and den parameters separately. It’s backward compatible, so if users want, they can also use the old way.
    • Suppose there is only a single variable present in the expression. In that case, users will not be required to pass the var parameter.
    • Expansion of numerator and denominator expressions passed is done by default now. This is done to preserve the general polynomial convention mentioned in the definition of the transfer function.
    • Removed the num_inputs, num_outputs and shape properties for TransferFunction. It was introduced, in the first place, by Naman to make things compatible with the TransferFunctionMatrix in his implementation. Since I have updated the internal structuring of the TransferFunctionMatrix, it is no longer required. Also, in my implementation, (1, 1) shaped TransferFunctionMatrix object and a TransferFunction object will be treated differently. I will soon be removing the _is_Matrix() property, which used extensively in Series and Parallel classes.
    • Users can now raise TransferFunction objects to any integer power (even symbolic expressions unless they are Integers).
    • Added a new method in TransferFunction class (_to_expr()) to ease the conversion of TransferFunction instances to Expr instances. This will ease the computation of Series(*args).doit() and Parallel(*args).doit() in later phases even if they are convoluted.
    • TransferFunctionMatrix now inherits ImmutableMatrix (sympy.matrices.immutable.ImmutableDenseMatrix) as its parent class. This has drastically improved the computation time for typical matrix operations. Attributes like shape and functionalities like determinant, submatrix extraction, accessing individual elements by indices, and lambda expression compatibility are all compatible with TransferFunctionMatrix without writing the redundant code again for each of them.
    • Creating new TransferFunctionMatrix objects is also eased, just like TransferFunction. The optional parameter shape is removed now. Users can create TransferFunctionMatrix by passing a list (or list of list) of Expr or TransferFunction or even a combination of two. I also didn’t override the args attribute. Therefore, ImmutableMatrix(*args).args and TransferFunctionMatrix(*args).args have a similar structure making it compatible for easy interconversion. Also, var is now a keyword argument and not a positional one.
    • Updated the magic method __mul__(self, other) of TransferFunctionMatrix as the previous implementation was wrong. A*B (A and B both being TransferFunctionMatrix objects) should return Series(B, A) and not Series(A, B).
    • Added a method in TransferFunctionMatrix class (_to_Immutable_Matrix()) to ease the conversion to ImmutableDenseMatrix. It will act as a bridge in efficient Matrix operations.
  2. Changed the documentation of TransferFunction and TransferFunctionMatrix. Added a bit more explanation and links to resources in the docs to make it beginner-friendly. After completing this PR, I also plan to add illustrations like in sympy.physics.continuum_mechanics. Here is a glimpse of the same-

  3. Modified the Series and Parallel class’ methods and attributes corresponding to changes in the structure of TransferFunction and TransferFunctionMatrix mentioned above. Although, it is not complete yet.

  4. I have modified the unit tests corresponding to the changes mentioned above.

Most of the difficult parts of Phase-1 over now (at least in my opinion). The fundamental structure is now more robust, and building functionalities on it would be easier now. For Week-2, I have the following tasks-

  • Completing the class-level docstrings and unit tests for all the classes.
  • Finishing the Series and Parallel class’ implementation. I will also be benchmark testing the Series().doit(), Parallel().doit() and TransferFunctionMatrix().doit(). I will be comparing the code execution time taken by these operations with their equivalent Matrix expression counterpart to ensure that performance is not affected.
  • Adding the comprehensive textbook example mentioned in the previous blogpost, in the docs of control.
  • Modifying the Feedback class.
  • And finally, after all the tests pass, removing the commented-out code (tidying up the codebase, basically).

I’m working strenuously to make sure that this PR gets merged successfully until the end of Week-2 so that I can start the work on the StateSpace class from Week-3.