Einsum.getDefaultShapes requires every input to resolve to a single known shape; a ⊤ or multi-shape input yields a ⊤ output. The label bindings introduced for the operand refinement (ponder-lab#612) support a partial composition instead: every output label bound by a resolved operand contributes its dimension, and the rest carry Unresolved (or the operand refinement's rank evidence), so the output keeps its rank and the known axes.
Witness, from the #704 fixture family: tf.einsum("BFND,NDH->BFH", input_tensor, w) with w = (3, 5, 6) statically known and input_tensor unresolved currently types the result float32 with an unknown shape, although H = 6 and rank 3 are proven. Expected: (?, ?, 6) with the unknown axes Unresolved.
The multi-shape (cross-product) case deferred in getDefaultShapes is the same clause and could ride along.
Einsum.getDefaultShapesrequires every input to resolve to a single known shape; a ⊤ or multi-shape input yields a ⊤ output. The label bindings introduced for the operand refinement (ponder-lab#612) support a partial composition instead: every output label bound by a resolved operand contributes its dimension, and the rest carryUnresolved(or the operand refinement's rank evidence), so the output keeps its rank and the known axes.Witness, from the #704 fixture family:
tf.einsum("BFND,NDH->BFH", input_tensor, w)withw = (3, 5, 6)statically known andinput_tensorunresolved currently types the resultfloat32with an unknown shape, althoughH = 6and rank 3 are proven. Expected:(?, ?, 6)with the unknown axesUnresolved.The multi-shape (cross-product) case deferred in
getDefaultShapesis the same clause and could ride along.