To ensure that modular learning was working correctly, I ran an onAB Blocks World task overnight, which creates and utilises the clear module.
The results? Well, the final module consists of:
(declare (variables ?_MOD_a))
(on ?X ?_MOD_a) (above ?X ?) (clear ?X) (block ?_MOD_a) => (moveFloor ?X)
(clear ?X) (clear ?Y) (above ?X ?_MOD_a) (block ?_MOD_a) => (move ?X ?Y)
This isn’t the most ideal looking module, but in fact it does work optimally. While the first rule only fires in the very last step, the second rule performs the first few steps. In the case of a singular stacked state, neither will fire, but the policy the module will apply to guarantees that a block will be moved from the stack.
The module breaks down in application to multiple parameters ((clear a) (clear b)). Because the movement for the ‘a’ module may cover the ‘b’ module and vice-versa.
The reason (on ?X ?_MOD_a) developed opposed to (above ?X ?_MOD_a) is probably because it happened to converge.