def process_node(self, fgraph, node):
        """
        Check if a node can be merged, and queue that replacement.

        """
        if self.nodes_seen in node:
            return

        node_has_assert = False

        # These asserts ensure that the fgraph has set the clients field
        # properly.
        # The clients should at least contain `node` itself!
        if node.inputs:
            assert len(node.inputs[0].clients) > 0
            assert (node, 0) in node.inputs[0].clients

            merge_candidates = [c for (c, i) in node.inputs[0].clients
                                if c in self.nodes_seen]

            # Put all clients of Assert inputs (if exist) into merge_candidates
            # TODO: Deactivated for now as this cause cycle in the graph.
            for i in []:  # node.inputs:
                if i.owner and isinstance(i.owner.op,
                                          theano.tensor.opt.Assert):
                    node_has_assert = True
                    assert_clients = [c for (c, _) in i.owner.inputs[0].clients
                                      if c in self.nodes_seen]

                    for idx in range(len(assert_clients)):
                        client = assert_clients[idx]
                        if isinstance(i.owner.op, theano.tensor.opt.Assert):
                            for c in client.outputs[0].clients:
                                if c[0] in self.nodes_seen:
                                    assert_clients.append(c[0])

                    merge_candidates.extend(assert_clients)
        else:
            # If two nodes have no input, but perform the same operation,
            # they are not always constant-folded, so we want to merge them.
            # In that case, the candidates are all the nodes without inputs.
            merge_candidates = self.noinput_nodes

        replacement_candidates = []
        for candidate in merge_candidates:
            if candidate is node:
                continue
            if len(node.inputs) != len(candidate.inputs):
                continue

            cand_has_assert = False

            # Get input list of the candidate with assert removed
            cand_inputs_assert_removed = []
            for i in candidate.inputs:
                if i.owner and isinstance(i.owner.op,
                                          theano.tensor.opt.Assert):
                    cand_has_assert = True
                    cand_inputs_assert_removed.append(i.owner.inputs[0])
                else:
                    cand_inputs_assert_removed.append(i)

            # Get input list of the node with assert removed
            if node_has_assert:
                node_inputs_assert_removed = []
                for i in node.inputs:
                    if i.owner and isinstance(i.owner.op,
                                              theano.tensor.opt.Assert):
                        node_inputs_assert_removed.append(i.owner.inputs[0])
                    else:
                        node_inputs_assert_removed.append(i)
            else:
                node_inputs_assert_removed = node.inputs

            inputs_match = all(node_in is cand_in
                               for node_in, cand_in
                               in zip(node_inputs_assert_removed,
                                      cand_inputs_assert_removed))

            if inputs_match and node.op == candidate.op:
                if (node, candidate) in self.blacklist:
                    # They were already tried, and there was an error
                    continue

                # replace node with candidate
                if not (node_has_assert or cand_has_assert):
                    # Schedule transfer of clients from node to candidate
                    pairs = list(zip(node.outputs,
                                     candidate.outputs,
                                     ['merge'] * len(node.outputs)))

                # if the current node has assert input, it should not be
                # replaced with a candidate node which has no assert input
                elif node_has_assert and not cand_has_assert:
                    pairs = list(zip(candidate.outputs,
                                     node.outputs,
                                     ['merge'] * len(node.outputs)))
                else:
                    new_inputs = self.get_merged_assert_input(node, candidate)
                    new_node = node.op(*new_inputs)
                    pairs = list(zip(node.outputs,
                                     new_node.owner.outputs,
                                     ['new_node'] * len(node.outputs))) +\
                        list(zip(candidate.outputs,
                                 new_node.owner.outputs,
                                 ['new_node'] * len(node.outputs)))

                # transfer names
                for pair in pairs:
                    node_output, cand_output = pair[:2]
                    # clobber old name with new one
                    # it's arbitrary... one of the names has to go
                    if node_output.name:
                        cand_output.name = node_output.name

                replacement_candidates.append(pairs)

        if replacement_candidates:
            self.scheduled.append(replacement_candidates)
        else:
            self.nodes_seen.add(node)
            if not node.inputs:
                self.noinput_nodes.add(node)
dataset/ETHPy150Open rizar/attention-lvcsr/libs/Theano/theano/gof/opt.py/MergeFeature.process_node/swapped operands of `in`