def embed_ising(source_linear, source_quadratic, embedding, target_adjacency, chain_strength=1.0):
    unused = {v for v in target_adjacency} - set().union(*embedding.values())
    target_linear = {v: 0. for v in target_adjacency}
    for v, bias in iteritems(source_linear):
        try:
            chain_variables = embedding[v]
        except KeyError:
            try:
                embedding[v] = {unused.pop()}
            except KeyError:
                raise ValueError('no embedding provided for source variable {}'.format(v))
            chain_variables = embedding[v]
        b = bias / len(chain_variables)
        for s in chain_variables:
            try:
                target_linear[s] += b
            except KeyError:
                raise ValueError('chain variable {} not in target_adjacency'.format(s))
    target_quadratic = {}
    for (u, v), bias in iteritems(source_quadratic):
        edges = set()
        if u not in embedding:
            raise ValueError('no embedding provided for source variable {}'.format(u))
        if v not in embedding:
            raise ValueError('no embedding provided for source variable {}'.format(v))
        for s in embedding[u]:
            for t in embedding[v]:
                try:
                    if s in target_adjacency[t] and (t, s) not in edges:
                        edges.add((s, t))
                except KeyError:
                    raise ValueError('chain variable {} not in target_adjacency'.format(s))
        if not edges:
            raise ValueError("no edges in target graph between source variables {}, {}".format(u, v))
        b = bias / len(edges)
        for s, t in edges:
            if (s, t) in target_quadratic:
                target_quadratic[(s, t)] += b
            elif (t, s) in target_quadratic:
                target_quadratic[(t, s)] += b
            else:
                target_quadratic[(s, t)] = b
    chain_quadratic = {}
    for chain in itervalues(embedding):
        chain_quadratic.update(chain_to_quadratic(chain, target_adjacency, chain_strength))
    return target_linear, target_quadratic, chain_quadratic