def _var_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
    if len(a.eps()) != len(b.eps()): return False
    if len(a.variables()) != len(b.variables()): return False
    #if len(a.hcons()) != len(b.hcons()): return False

    # pre-populate varmap; first top variables
    varmap = {}
    for pair in [(a.top, b.top), (a.index, b.index), (a.xarg, b.xarg)]:
        if pair != (None, None):
            v1, v2 = pair
            if None in pair:
                return False
            if check_varprops and a.properties(v1) != b.properties(v2):
                return False
            varmap[v1] = v2

    # find permutations of variables, grouped by those that share the
    # same signature.

    a_sigs = defaultdict(list)
    for var, vd in a._vars.items():
        if var not in varmap:
            var_sig = _isomorphic_var_signature(vd, a, check_varprops)
            a_sigs[var_sig].append(var)
    b_sigs = defaultdict(list)
    tgtmapped = set(varmap.values())
    for var, vd in b._vars.items():
        if var not in tgtmapped:
            var_sig = _isomorphic_var_signature(vd, b, check_varprops)
            b_sigs[var_sig].append(var)

    candidates = []
    for sig, a_vars in sorted(a_sigs.items(), key=lambda x: len(x[1])):
        b_vars = b_sigs.get(sig, [])
        if len(a_vars) != len(b_vars):
            return False
        print(sig, a_vars, b_vars)
        candidates.append((a_vars, b_vars))

    varmaps = _var_isomorphic(a, b, candidates, varmap)

    # double check HCONS (it's hard to do with var signatures)
    for vm in varmaps:
        if all(vm[lo] == b._hcons.get(vm[hi], (None, None, None))[2]
               for hi, _, lo in a.hcons()):
            return True
    return False