def ios18_quant_params_to_ios16(quant_params: QuantParams) -> QuantParamsIos16:
    """
    Transform iOS18 quant params to iOS16 version.

    The iOS16 constexpr_affine_dequantize op requires axis, and it requires scale and zero_point to
    have rank 0 or 1.
    """
    # Infer the axis based on scale's shape.
    non_single_dim = [dim for dim, dim_size in enumerate(quant_params.scale.shape) if dim_size > 1]
    if len(non_single_dim) > 2:
        raise AssertionError(
            "The constexpr_affine_dequantize op doesn't support scale which "
            "have more than one non-single dimensions. Got scale with shape "
            f"{quant_params.scale.shape}"
        )
    # If non_single_dim is empty, it means it's per-tensor quantization, just use a dummy axis.
    axis = 0 if len(non_single_dim) == 0 else non_single_dim[0]

    scale = quant_params.scale
    zero_point = quant_params.offset
    if zero_point is None:
        # The constexpr_affine_dequantize op requires zero_point.
        zero_point = np.zeros_like(scale).astype(quant_params.data.dtype)

    # The constexpr_affine_dequantize op requires scale and zero_point to have rank 0 or 1.
    if isinstance(scale, (np.ndarray, np.generic)):
        scale = np.squeeze(scale)
    if isinstance(zero_point, (np.ndarray, np.generic)):
        zero_point = np.squeeze(zero_point)

    return QuantParamsIos16(
        quantized_data=quant_params.data, zero_point=zero_point, scale=scale, axis=np.int32(axis)
    )

    Transform iOS18 quant params to iOS16 version.

    The iOS16 constexpr_affine_dequantize op requires axis, and it requires scale and zero_point to
    have rank 0 or 1.
    
coremltools/optimize/_utils.py