def test_priority_union_is_associative():
    for xWrapped, yWrapped, zWrapped in all3VecTriplesSet:
        x, y, z = xWrapped.unwrap(), yWrapped.unwrap(), zWrapped.unwrap()
        assert np.array_equal(
            fv.priority_union(fv.priority_union(x, y), z),
            fv.priority_union(x, fv.priority_union(y, z))
        )  #, f"({x}+{y})+{z} = {fv.priority_union(x,y)} + {z} = fv.priority_union()"
def test_priority_union_stack_right_as_expected():
    counterexamples = set()
    for xWrapped in all3VecsSet:
        x = xWrapped.unwrap()
        stackRightResult = fv.priority_union(x, all3Vecs)
        nonVectorResult = np.array([fv.priority_union(x, v) for v in all3Vecs],
                                   dtype=INT8)
        stackRightResultSet = fv.stack_to_set(stackRightResult)
        nonVectorResultSet = fv.stack_to_set(nonVectorResult)
        if stackRightResultSet != nonVectorResultSet:
            counterexamples.add((xWrapped))
    assert len(counterexamples) == 0, f"Counterexamples:\n{counterexamples}"
def test_priority_union_left_does_NOT_preserve_partial_order():
    prunion_pres_po_cxs_lefts = []
    for xWrapped in all3VecsSet:
        x = xWrapped.unwrap()
        rightArg = lambda right: fv.priority_union(x, right)
        current_prunion_pres_po_cxs_left = fv.preserves_partial_order(
            all3Vecs, rightArg, returnCounterexamples=True)
        prunion_pres_po_cxs_lefts.append(current_prunion_pres_po_cxs_left)
    prunion_pres_po_cxs_left = grand_union(prunion_pres_po_cxs_lefts)
    assert len(prunion_pres_po_cxs_left) > 0
def test_priority_union_right_preserves_partial_order():
    prunion_pres_po_cxs_rights = []
    for xWrapped in all3VecsSet:
        x = xWrapped.unwrap()
        leftArg = lambda left: fv.priority_union(left, x)
        current_prunion_pres_po_cxs_right = fv.preserves_partial_order(
            all3Vecs, leftArg, returnCounterexamples=True)
        prunion_pres_po_cxs_rights.append(current_prunion_pres_po_cxs_right)
    prunion_pres_po_cxs_right = grand_union(prunion_pres_po_cxs_rights)
    assert len(prunion_pres_po_cxs_right) == 0, f"{prunion_pres_po_cxs_right}"
def test_priority_union_right_inverse_all_expected_to_be_possible_are():
    Ms = fv.stack_to_set(all3Vecs)
    allPairs = {(c, b) for c in Ms for b in Ms}
    for (cWrapped, bWrapped) in allPairs:
        c, b = cWrapped.unwrap(), bWrapped.unwrap()
        ri = fv.right_inv_priority_union(c, b)
        if ri is not None:
            for a in ri:
                assert np.array_equal(fv.priority_union(a, b),
                                      c), f"{a}+{b}≠{c}"
def test_priority_union_left_inverse_all_expected_to_be_possible_are():
    Ms = fv.stack_to_set(all3Vecs)
    allPairs = {(a, c) for a in Ms for c in Ms}
    for (aWrapped, cWrapped) in allPairs:
        a, c = aWrapped.unwrap(), cWrapped.unwrap()
        li = fv.left_inv_priority_union(a, c)
        if li is not None:
            for b in li:
                assert np.array_equal(fv.priority_union(a, b),
                                      c), f"{a}+{b}≠{c}"
def test_priority_union_left_is_a_lattice_HM_over_LCs():
    prunion_lhm_LCs_cxs_lefts = []
    for xWrapped in all3VecsSet:
        x = xWrapped.unwrap()
        xLC = fv.lower_closure(x)
        rightArg = lambda right: fv.priority_union(x, right)
        current_prunion_lhm_LCs_cxs_left = fv.is_lattice_homomorphism(
            xLC, rightArg, returnCounterexamples=True)
        prunion_lhm_LCs_cxs_lefts.append(current_prunion_lhm_LCs_cxs_left)
    prunion_lhm_LCs_cxs_left = grand_union(prunion_lhm_LCs_cxs_lefts)
    assert len(prunion_lhm_LCs_cxs_left) == 0, f"{prunion_lhm_LCs_cxs_left}"
def test_priority_union_right_does_NOT_preserve_joins():
    prunion_pres_join_cxs_rights = []
    for xWrapped in all3VecsSet:
        x = xWrapped.unwrap()
        leftArg = lambda left: fv.priority_union(left, x)
        current_prunion_pres_join_cxs_right = fv.preserves_join(
            all3Vecs, leftArg, returnCounterexamples=True)
        prunion_pres_join_cxs_rights.append(
            current_prunion_pres_join_cxs_right)
    prunion_pres_join_cxs_right = grand_union(prunion_pres_join_cxs_rights)
    assert len(
        prunion_pres_join_cxs_right) > 0  #, f"{prunion_pres_join_cxs_right}"
def test_priority_union_right_is_a_meet_SL_HM_over_UCs():
    prunion_mslhm_UCs_cxs_rights = []
    for xWrapped in all3VecsSet:
        x = xWrapped.unwrap()
        xUC = fv.upper_closure(x)
        leftArg = lambda left: fv.priority_union(left, x)
        current_prunion_mslhm_UCs_cxs_right = fv.is_meet_semilattice_homomorphism(
            xUC, leftArg, returnCounterexamples=True)
        prunion_mslhm_UCs_cxs_rights.append(
            current_prunion_mslhm_UCs_cxs_right)
    prunion_mslhm_UCs_cxs_right = grand_union(prunion_mslhm_UCs_cxs_rights)
    assert len(
        prunion_mslhm_UCs_cxs_right) == 0, f"{prunion_mslhm_UCs_cxs_right}"
    joinsA = {
        fv.HashableArray(fv.join_specification(a.unwrap(), b.unwrap()))
        for a, b in allJoinablePairs
    }
    joinsB = {
        fv.HashableArray(
            fv.join_specification_stack(
                np.array([a.unwrap(), b.unwrap()], dtype=INT8)))
        for a, b in allJoinablePairs
    }
    missingFromB = joinsA - joinsB
    missingFromA = joinsB - joinsA
    assert joinsA == joinsB, f"Missing from stack-based result:\n{missingFromB}\nMissing from pairwise result:\n{missingFromA}"


all3VecIO = [(a, b, fv.priority_union(a, b)) for a in all3Vecs
             for b in all3Vecs]

#########################################
# priority union implementation testing #
#########################################


def test_priority_union_stack_left_as_expected():
    counterexamples = set()
    for xWrapped in all3VecsSet:
        x = xWrapped.unwrap()
        stackLeftResult = fv.priority_union(all3Vecs, x)
        nonVectorResult = np.array([fv.priority_union(v, x) for v in all3Vecs],
                                   dtype=INT8)
        stackLeftResultSet = fv.stack_to_set(stackLeftResult)