<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def diagnose_embedding(emb, source, target):
 """A detailed diagnostic for minor embeddings. This diagnostic produces a generator, which lists all issues with `emb`. The errors are yielded in the form where the arguments following the class are used to construct the exception object. User-friendly variants of this function are :func:`is_valid_embedding`, which returns a bool, and :func:`verify_embedding` which raises the first observed error. All exceptions are subclasses of :exc:`.EmbeddingError`. Args: emb (dict):
 Dictionary mapping source nodes to arrays of target nodes. source (list/:obj:`networkx.Graph`):
 Graph to be embedded as a NetworkX graph or a list of edges. target (list/:obj:`networkx.Graph`):
 Graph being embedded into as a NetworkX graph or a list of edges. Yields: One of: :exc:`.MissingChainError`, snode: a source node label that does not occur as a key of `emb`, or for which emb[snode] is empty :exc:`.ChainOverlapError`, tnode, snode0, snode0: a target node which occurs in both `emb[snode0]` and `emb[snode1]` :exc:`.DisconnectedChainError`, snode: a source node label whose chain is not a connected subgraph of `target` :exc:`.InvalidNodeError`, tnode, snode: a source node label and putative target node label which is not a node of `target` :exc:`.MissingEdgeError`, snode0, snode1: a pair of source node labels defining an edge which is not present between their chains """


    if not hasattr(source, 'edges'):
        source = nx.Graph(source)
    if not hasattr(target, 'edges'):
        target = nx.Graph(target)

    label = {}
    embedded = set()
    for x in source:
        try:
            embx = emb[x]
            missing_chain = len(embx) == 0
        except KeyError:
            missing_chain = True
        if missing_chain:
            yield MissingChainError, x
            continue
        all_present = True
        for q in embx:
            if label.get(q, x) != x:
                yield ChainOverlapError, q, x, label[q]
            elif q not in target:
                all_present = False
                yield InvalidNodeError, x, q
            else:
                label[q] = x
        if all_present:
            embedded.add(x)
            if not nx.is_connected(target.subgraph(embx)):
                yield DisconnectedChainError, x

    yielded = nx.Graph()
    for p, q in target.subgraph(label).edges():
        yielded.add_edge(label[p], label[q])
    for x, y in source.edges():
        if x == y:
            continue
        if x in embedded and y in embedded and not yielded.has_edge(x, y):
            yield MissingEdgeError, x, y