def validate(
        self,
        force_validate: Optional[bool] = False,
        check_essential_scope: Optional[bool] = False,
    ) -> None:
        """
        Basic validation to protect against some invalid state.
        If force_validate is False, the validation is done only if the global variable DEBUG=True.
        """
        if not DEBUG and not force_validate:
            return

        # Check vars visibility
        if isinstance(self, Function):
            self._check_vars_visibility_in_block()

        # Other validations
        for op in self.operations:
            for b in op.blocks:
                b.validate(force_validate=force_validate)
            if op.outputs is None:
                raise InvalidBlockStateError()

            # Check the input output relationships
            # from outputs -> inputs
            for ov in op.outputs:
                child_op_count = Counter(ov.child_ops)
                for next_op, c in child_op_count.items():
                    c_actual = next_op.get_flattened_inputs().count(ov)
                    if c_actual != c:
                        msg = (
                            "Var {} should be consumed by op {} {}"
                            + " times, but op {} uses it {} times.\n{}"
                        )
                        raise InvalidBlockStateError(
                            msg.format(
                                ov.name,
                                next_op.name,
                                c,
                                next_op.name,
                                c_actual,
                                next_op,
                            )
                        )

            # from inputs -> outputs
            input_var_count = Counter(op.get_flattened_inputs())
            for iv, c in input_var_count.items():
                c_actual = iv.child_ops.count(op)
                if c_actual != c:
                    msg = (
                        "Var {} should be consumed by op {} {}"
                        + " times, but op {} uses it {} times.\n{}"
                    )
                    raise InvalidBlockStateError(
                        msg.format(iv.name, op.name, c_actual, op.name, c, op)
                    )

        # 1 to 1 mapping between Block outputs and Var.consuming_blocks
        for op in self.operations:
            for ov in op.outputs:
                for b in ov.consuming_blocks:
                    if ov not in b.outputs:
                        msg = "Var {} should be output of block {}: {}"
                        raise ValueError(msg.format(ov.name, b.name, b))

        for v in self.outputs:
            if self not in v.consuming_blocks:
                msg = "Var {} should be output of block {}: {}"
                raise ValueError(msg.format(ov.name, b.name, b))

        # checking internal vars are consistent with self._internal_vars
        internal_var_in_block = set()
        for op in self.operations:
            for v in op.internal_inputs.values():
                internal_var_in_block.add(v)
        if not internal_var_in_block == self._internal_vars:
            raise ValueError(
                "internal vars in the block are not consistent with self._internal_vars."
            )

        # check essential scope info are not missing
        if check_essential_scope:
            self._check_has_scope_info()

        Basic validation to protect against some invalid state.
        If force_validate is False, the validation is done only if the global variable DEBUG=True.
        
coremltools/converters/mil/mil/block.py