static public TensorType rename(TensorType inputType, List<String> from, List<String> to) {
        if (from.isEmpty()) {
            throw new IllegalArgumentException("Renaming no dimensions");
        }
        if (from.size() != to.size()) {
            throw new IllegalArgumentException("Bad rename, from size "+from.size()+" != to.size "+to.size());
        }
        Map<String,Dimension> oldDims = new HashMap<>();
        for (Dimension dim : inputType.dimensions()) {
            oldDims.put(dim.name(), dim);
        }
        Map<String,Dimension> newDims = new HashMap<>();
        for (int i = 0; i < from.size(); ++i) {
            String oldName = from.get(i);
            String newName = to.get(i);
            if (oldDims.containsKey(oldName)) {
                var dim = oldDims.remove(oldName);
                newDims.put(newName, dim.withName(newName));
            } else {
                logger.log(Level.WARNING, "Renaming non-existing dimension "+oldName+" in type "+inputType);
                // throw new IllegalArgumentException("bad rename, dimension  "+oldName+" not found");
            }
        }
        for (var keep : oldDims.values()) {
            newDims.put(keep.name(), keep);
        }
        if (inputType.dimensions().size() == newDims.size()) {
            return new TensorType(inputType.valueType(), newDims.values());
        } else {
            throw new IllegalArgumentException("Bad rename, lost some dimensions");
        }
    }
Common type resolving for basic tensor operations.

@author arnej
vespajlib/src/main/java/com/yahoo/tensor/TypeResolver.java