Make clear that interface does not adhere to Liskov substitution principle
I think we should drop current implicit requirement that our class inheritance of base classes adheres to Liskov substitution principle. I think we should define that methods have to be there based on inheritance, but that each consumer of the object has to inspect arguments and determine which arguments are needed.
An example why is this problematic is in set_training_data, where different primitives can get a different combination of inputs and outputs. Some take inputs, some take outputs and some take both. But Liskov substitution principle would mean that anyone who can operate on a base class itself could call set_training_data, but which arguments to pass? Some primitives might not expect outputs, some not inputs.
This is why is set_training_data currently not defined on the base class, but this is confusing.
This relaxation would be only between base classes (those defined in this package) and not for primitives extending these base classes. They should still adhere to Liskov substitution principle.