def METHOD_NAME(self, end_node_name):
    """Calculate values of end node of constant node sequence.
    there may be layers whose inputs are all constant in the graph, like:
      const
            > add
      const
    the value of add can be calculated in advance.
    Args:
      end_node_name: name of the end node of the sequence. e.g. add in the above examples.
    Returns:
      values of end node.
    Raises:
      ValueError: If the graph contains tensors which can't be broadcast.
    """
    end_node = self.graph_info[end_node_name].node
    def can_broadcast(s1, s2):
        if s1.shape and s2.shape:
            s1a = np.asarray(s1.shape)
            s2a = np.asarray(s2.shape)
            return ((s1a == 1) | (s2a == 1) | (s2a == s1a)).all()
        return True
    if self.graph_info[end_node_name].node.input:
        if end_node.op == "Mul":
            first_value = self.METHOD_NAME(list(end_node.input)[0])
            first_type = first_value.dtype
            fold_value = np.array(1.0).astype(first_type)
            for index, input in enumerate(end_node.input):
                # broadcast if needed
                input_value = self.METHOD_NAME(input)
                input_type = input_value.dtype
                if can_broadcast(fold_value, input_value):
                    fold_value = fold_value * input_value
                else:
                    raise ValueError("input {} of node {} can't be broadcast".format(input.name, end_node.name))
            return fold_value.astype(first_type)
        elif end_node.op == "Add" or end_node.op == "AddV2":
            first_value = self.METHOD_NAME(list(end_node.input)[0])
            first_type = first_value.dtype
            fold_value = np.array(0.0).astype(first_type).reshape(())
            for index, input in enumerate(end_node.input):
                # broadcast if needed
                input_value = self.METHOD_NAME(input)
                if can_broadcast(fold_value, input_value):
                    fold_value = fold_value + input_value
                else:
                    raise ValueError("input {} of node {} can't be broadcast".format(input.name, end_node.name))
            return fold_value.astype(first_type)
        elif end_node.op == "Rsqrt":
            return 1 / np.sqrt(self.METHOD_NAME(end_node.input[0]))
        elif end_node.op == "Sub":
            first_value = self.METHOD_NAME(list(end_node.input)[0])
            first_type = first_value.dtype
            fold_value = np.array(0.0, dtype=first_type)
            for index, input in enumerate(end_node.input):
                # broadcast if needed
                input_value = self.METHOD_NAME(input)
                if first_type != input_value.dtype:
                    raise ValueError(
                        "input of node {} must be in same dtype but get {}and {}".format(
                            input.name, first_type, input_value.dtype
                        )
                    )
                if can_broadcast(fold_value, input_value):
                    fold_value = fold_value + (-1) ** index * input_value
                else:
                    raise ValueError("input {} of node {} can't be broadcast".format(input.name, end_node.name))
            return fold_value.astype(first_type)
        else:
            tf_logging.info(
                "Currently fold-constant only support limited ops {} but face {}".format(
                    self.supported_op_type, end_node.op
                )
            )
    else:
        return GraphRewriterHelper.values_from_const(end_node)