def test_rotation_asymmetry():
    """
    create a bunch of chairs. The chairs are rotationally symmetric and then perturbed.
    """
    scores = []
    butil.clear_scene()
    obj_states = {}

    chairs = []
    for i in range(6):
        chair = bbox_mesh_from_hipoly(ChairFactory(0), i, use_pholder=False)
        obj_states[chair.name] = ObjectState(chair, tags={t.Semantics.Chair})
        chairs.append(chair)

    circle_locations_rotations = [
        ((2 * np.cos(i * np.pi / 3), 2 * np.sin(i * np.pi / 3), 0), i * np.pi / 3)
        for i in range(6)
    ]
    np.random.shuffle(circle_locations_rotations)
    # put the chairs in a circle
    for i in range(6):
        chairs[i].location = circle_locations_rotations[i][0]
        chairs[i].rotation_euler = (0, 0, circle_locations_rotations[i][1])

    bpy.context.view_layer.update()

    state = State(objs=obj_states)

    constraints = []
    score_terms = []
    scene = cl.scene()
    chairs_tagged = cl.tagged(scene, {t.Semantics.Chair})

    score_terms += [cl.rotational_asymmetry(chairs_tagged)]
    problem = cl.Problem(constraints, score_terms)
    res = evaluate.evaluate_problem(problem, state).loss()
    scores.append(res)
    assert np.isclose(res, 0, atol=1e-2)

    # assert the asymmetry increases as we gradually move one chair from the circle
    chairs[0].location += Vector(np.random.rand(3))
    bpy.context.view_layer.update()
    score_terms = []
    score_terms += [cl.rotational_asymmetry(chairs_tagged)]
    problem = cl.Problem(constraints, score_terms)
    res = evaluate.evaluate_problem(problem, state).loss()
    scores.append(res)

    # assert the asymmetry increases if we rotate chair 0
    chairs[0].rotation_euler = (0, 0, np.random.rand(1))
    bpy.context.view_layer.update()
    score_terms = []
    score_terms += [cl.rotational_asymmetry(chairs_tagged)]
    problem = cl.Problem(constraints, score_terms)
    res = evaluate.evaluate_problem(problem, state).loss()
    scores.append(res)

    # do the same for another chair
    chairs[1].location += Vector(np.random.rand(3))
    bpy.context.view_layer.update()
    score_terms = []
    score_terms += [cl.rotational_asymmetry(chairs_tagged)]
    problem = cl.Problem(constraints, score_terms)
    res = evaluate.evaluate_problem(problem, state).loss()
    scores.append(res)

    # assert monotonic
    # assert scores == sorted(scores) # warning: heisenbug. disabled by araistrick

    # assert it is strict
    assert (scores[0] < scores[1]) and scores[1] < scores[2] and scores[2] < scores[3]
    print("asymmetry scores", scores)

    create a bunch of chairs. The chairs are rotationally symmetric and then perturbed.
    
tests/solver/test_constraint_evaluator.py