def _node_isomorphic(a, b, check_varprops=True):
    """
    Two Xmrs objects are isomorphic if they have the same structure as
    determined by variable linkages between preds.
    """
    # first some quick checks
    a_var_refs = sorted(len(vd['refs']) for vd in a._vars.values())
    b_var_refs = sorted(len(vd['refs']) for vd in b._vars.values())
    if a_var_refs != b_var_refs:
        return False
    print()

    # these signature: [node] indices are meant to avoid unnecessary
    # comparisons; they also take care of "semantic feasibility"
    # constraints (comparing node values and properties). All that's
    # left is the "syntactic feasibility", or node-edge shapes.
    # nodedicts are {sig: [(id, edges), ...], ...}
    a_nd = _node_isomorphic_build_nodedict(a, check_varprops)
    #print('a', a_nd)
    b_nd = _node_isomorphic_build_nodedict(b, check_varprops)
    #print('b', b_nd)
    #return

    a_sigs = {}  # for node -> sig mapping
    # don't recurse when things are unique
    agenda = []
    isomap = {}
    for sig, a_pairs in sorted(a_nd.items(), key=lambda x: len(x[1])):
        b_pairs = b_nd.get(sig, [])
        if len(a_pairs) != len(b_pairs):
            return False
        if len(a_pairs) == 1:
            a_, a_edges = a_pairs[0]
            b_, b_edges = b_pairs[0]
            if len(a_edges) != len(b_edges):
                return False
            a_sigs[a_] = sig
            isomap[a_] = b_
            for edge, a_tgt in a_edges.items():
                if edge not in b_edges:
                    return False
                isomap[a_tgt] = b_edges[edge]
        else:
            for a_, ed in a_pairs:
                a_sigs[a_] = sig
                agenda.append((a_, sig, ed))
    #print(agenda)
    #return
    isomaps = _node_isomorphic(agenda, a_sigs, b_nd, isomap, {})
    # for sig, a_candidates in sorted(a_nodes.items(), key=lambda x: len(x[1])):
    #     b_candidates = b_nodes.get(sig, [])
    #     if len(a_candidates) != len(b_candidates): return False
    #     candidates.append((a_candidates, b_candidates))
    #
    # nodemaps = _isomorphic(a, b, candidates, {})
    try:
        next(isomaps)
        return True
    except StopIteration:
        return False