def embed_bqm(source_bqm, embedding, target_adjacency, chain_strength=1.0,
              smear_vartype=None):
    if smear_vartype is dimod.SPIN and source_bqm.vartype is dimod.BINARY:
        return embed_bqm(source_bqm.spin, embedding, target_adjacency,
                         chain_strength=chain_strength, smear_vartype=None).binary
    elif smear_vartype is dimod.BINARY and source_bqm.vartype is dimod.SPIN:
        return embed_bqm(source_bqm.binary, embedding, target_adjacency,
                         chain_strength=chain_strength, smear_vartype=None).spin
    target_bqm = source_bqm.empty(source_bqm.vartype)
    target_bqm.add_offset(source_bqm.offset)
    for v, bias in iteritems(source_bqm.linear):
        if v in embedding:
            chain = embedding[v]
        else:
            raise MissingChainError(v)
        if any(u not in target_adjacency for u in chain):
            raise InvalidNodeError(v, next(u not in target_adjacency for u in chain))
        b = bias / len(chain)
        target_bqm.add_variables_from({u: b for u in chain})
    for (u, v), bias in iteritems(source_bqm.quadratic):
        available_interactions = {(s, t) for s in embedding[u] for t in embedding[v] if s in target_adjacency[t]}
        if not available_interactions:
            raise MissingEdgeError(u, v)
        b = bias / len(available_interactions)
        target_bqm.add_interactions_from((u, v, b) for u, v in available_interactions)
    for chain in itervalues(embedding):
        if len(chain) == 1:
            v, = chain
            target_bqm.add_variable(v, 0.0)
            continue
        quadratic_chain_biases = chain_to_quadratic(chain, target_adjacency, chain_strength)
        target_bqm.add_interactions_from(quadratic_chain_biases, vartype=dimod.SPIN)
        energy_diff = -sum(itervalues(quadratic_chain_biases))
        target_bqm.add_offset(energy_diff)
    return target_bqm