This improves checking the constraint that an HRGRule's lhs and rhs types have to match (closes #79).
It also adds more flexibility in creating an HRGRule. This partially helps with #140.
Analogous to #156, an HRGRule can be created with no lhs at first, and the the lhs can be set later.
Every time the lhs is set, it is checked for compatibility with rhs.ext.
If HRGRule is called with no rhs, an empty rhs is constructed.
New method HRGRule.set_lhs_ext for setting the lhs and rhs.ext simultaneously.
If rhs.ext is changed, it is not checked for compatibility with lhs.
The alternative to the last point would be if we moved ext from Graph to HRGRule. In other words, Graph would be just a hypergraph (not a "hypergraph fragment") and an HRGRule would have an lhs, a rhs, and external nodes. Then HRGRule would be able to check the consistency of lhs and ext perfectly. However, there would be no way to stop someone from deleting an external node. I prefer this alternative (since I envision node deletion being much less common then setting the external nodes).
(This PR is part of a larger plan to fix #140 and generally try to simplify things.)
This improves checking the constraint that an HRGRule's lhs and rhs types have to match (closes #79).
It also adds more flexibility in creating an HRGRule. This partially helps with #140.
The alternative to the last point would be if we moved ext from Graph to HRGRule. In other words, Graph would be just a hypergraph (not a "hypergraph fragment") and an HRGRule would have an lhs, a rhs, and external nodes. Then HRGRule would be able to check the consistency of lhs and ext perfectly. However, there would be no way to stop someone from deleting an external node. I prefer this alternative (since I envision node deletion being much less common then setting the external nodes).
(This PR is part of a larger plan to fix #140 and generally try to simplify things.)