def test_solver_minmax_custom_demands_paper_with_0_demand():
    aggregate_score_matrix_A = np.transpose(
        np.array([[0.2, 0.1, 0.4], [0.5, 0.2, 0.3], [0.2, 0.0, 0.6],
                  [0.7, 0.9, 0.3]]))
    constraint_matrix = np.zeros(np.shape(aggregate_score_matrix_A))
    solver_A = MinMaxSolver([0, 0, 0, 0], [2, 2, 2, 2], [2, 1, 0],
                            encoder(aggregate_score_matrix_A,
                                    constraint_matrix))
    res_A = solver_A.solve()
    assert res_A.shape == (3, 4)
    assert np.sum(res_A, axis=1)[2] == 0
def test_solver_minmax_custom_demand_and_supply():
    aggregate_score_matrix_A = np.transpose(
        np.array([[0.2, 0.1, 0.4], [0.5, 0.2, 0.3], [0.2, 0.0, 0.6],
                  [0.7, 0.9, 0.3]]))
    constraint_matrix = np.zeros(np.shape(aggregate_score_matrix_A))
    solver_A = MinMaxSolver([0, 0, 0, 0], [2, 1, 3, 1], [2, 1, 3],
                            encoder(aggregate_score_matrix_A,
                                    constraint_matrix))
    res_A = solver_A.solve()
    print(res_A)
    assert res_A.shape == (3, 4)
def test_solver_minmax_random():
    '''When costs are all zero, compute random assignments'''
    cost_matrix_A = np.transpose(
        np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]))
    constraint_matrix = np.zeros(np.shape(cost_matrix_A))
    solver_A = MinMaxSolver([1, 1, 1, 1], [2, 2, 2, 2], [1, 1, 2],
                            encoder(cost_matrix_A, constraint_matrix))
    res_A = solver_A.solve()
    assert res_A.shape == (3, 4)

    cost_matrix_B = np.transpose(
        np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]))
    constraint_matrix = np.zeros(np.shape(cost_matrix_B))
    solver_B = MinMaxSolver([1, 1, 1, 1], [2, 2, 2, 2], [1, 1, 2],
                            encoder(cost_matrix_B, constraint_matrix))
    res_B = solver_B.solve()
    assert res_B.shape == (3, 4)

    # ensure that the cost matrices are random
    # (i.e. overwhelmingly likely to be different)
    assert not np.array_equal(solver_A.cost_matrix, solver_B.cost_matrix)
def test_solver_minmax_impossible_constraints():
    '''
    Test to ensure that the MinMaxSolver's 'solved' attribute is correctly set
    when no solution is possible due to constraints.
    '''

    # 20 papers, 5 reviewers
    num_papers = 20
    num_reviewers = 5
    cost_matrix = np.zeros((num_papers, num_reviewers))
    constraint_matrix = -1 * np.ones(
        (num_papers,
         num_reviewers))  # all pairs are constrained! should be impossible

    minimums = [5] * 5
    maximums = [20] * 5
    demands = [3] * 20

    solver = MinMaxSolver(minimums, maximums, demands,
                          encoder(cost_matrix, constraint_matrix))

    solver.solve()
    assert not solver.solved
Esempio n. 5
0
def test_solver5():
    '''
    Tests 3 papers, 4 reviewers.   Reviewers review min: 1, max: 3 papers.   Each paper needs 3 reviews.
    Reviewer 4 has very high cost.  Other reviewers have 0 cost.
    Purpose:  Make sure all reviewers get at least their minimum
    '''
    num_papers = 3
    num_reviewers = 4
    min_papers_per_reviewer = 1
    max_papers_per_reviewer = 3
    paper_revs_reqd = 3
    cost_matrix = np.transpose(np.array([
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [2000, 2000, 2000]]))
    constraint_matrix = np.transpose(np.array([
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]]))


    rev_mins = [min_papers_per_reviewer] * num_reviewers
    rev_maxs = [max_papers_per_reviewer] * num_reviewers
    papers_reqd = [paper_revs_reqd] * num_papers
    solver = MinMaxSolver(
        rev_mins,
        rev_maxs,
        papers_reqd,
        encoder(cost_matrix, constraint_matrix)
    )
    res = solver.solve()
    assert res.shape == (3, 4)
    # make sure every reviewer has at least 1 paper
    nrows, ncols = res.shape
    for rix in range(nrows):
        reviewer_count_reviews = 0
        for pix in range(ncols):
            if res[rix,pix] != 0:
                reviewer_count_reviews += 1
        assert reviewer_count_reviews >= 1
    # TestSolver.silent = False
    check_solution(solver,solver.optimal_cost)
def test_solver_minmax_finds_lowest_cost_soln():
    '''
    4 reviewers 3 papers.   Papers 0,1 need 1 review; Paper 2 needs 2 reviews.  Reviewers can do max of 2 reviews
    Setup so that lowest cost solution should be
    Reviewer 0 reviews paper 0
             1 reviews paper 1
             2 reviews paper 2
             3 reviews paper 2
    Purpose:  Finds the lowest cost solution
    '''
    cost_matrix = np.transpose(
        np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0], [2, 2, 0]]))
    constraint_matrix = np.zeros(np.shape(cost_matrix))
    solver = MinMaxSolver([1, 1, 1, 1], [2, 2, 2, 2], [1, 1, 2],
                          encoder(cost_matrix, constraint_matrix),
                          allow_zero_score_assignments=True)
    res = solver.solve()
    assert res.shape == (3, 4)

    expected_cost = 0
    check_solution(solver, expected_cost)
Esempio n. 7
0
def test_solver_respects_constraints():
    '''
    Tests 5 papers, 4 reviewers.   Reviewers review min: 1, max: 3 papers.   Each paper needs 2 reviews.
    Constrained such that:
    Reviewer 0: available for all papers
             1: cannot review papers 2,3
             2: cannot review papers 2,3
             3: cannot review papers 0, 1
    All scores set to 1 so that any match that does not violate constraints is optimal
    Purpose:  Honors constraints in its solution
    '''
    cost_matrix = np.transpose(np.array([
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]]))
    constraint_matrix = np.transpose(np.array([
        [0, 0, 0, 0, 0],
        [0, 0, -1, -1, 0],
        [0, 0, -1, -1, 0],
        [-1, -1, 0, 0, 0]]))

    solver = MinMaxSolver(
        [1,1,1,1],
        [3,3,3,3],
        [2,2,2,2,2],
        encoder(cost_matrix, constraint_matrix)
    )

    res = solver.solve()
    assert res.shape == (5, 4)
    # make sure result does not violate constraints (i.e. no flow at i,j if there is a -1 constraint at i,j
    nrows, ncols = res.shape
    for i in range(nrows):
        for j in range(ncols):
            assert not (constraint_matrix[i,j] == -1 and res[i,j] > 0), "Solution violates constraint at [{},{}]".format(i,j)

    check_solution(solver, solver.optimal_cost)
Esempio n. 8
0
def test_solver4():
    '''
    Tests 6 papers, 6 reviewers.   Reviewers review min: 2, max: 3 papers.   Each paper needs 2 reviews.
    All scores set to 1 so that any match that does not violate constraints is optimal
    Purpose:  Honors minimums == 2 for all reviewers
    '''
    cost_matrix = np.array([
        [1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1, 1]])
    constraint_matrix = np.array([
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0]])

    solver = MinMaxSolver(
        [2,2,2,2,2,2],
        [3,3,3,3,3,3],
        [2,2,2,2,2,2],
        encoder(cost_matrix, constraint_matrix)
    )
    res = solver.solve()
    assert res.shape == (6,6)
    # make sure every reviewer is reviewing 2 papers
    nrows, ncols = res.shape
    for rix in range(nrows):
        reviewer_count_reviews = 0
        for pix in range(ncols):
            if res[rix,pix] != 0:
                reviewer_count_reviews += 1
        assert reviewer_count_reviews == 2
    check_solution(solver,solver.optimal_cost)
Esempio n. 9
0
def test_solver_find_lowest_cost_and_respect_constraints():
    '''
    Tests 5 papers, 4 reviewers.   Reviewers review min: 1, max: 3 papers.   Each paper needs 2 reviews.
    Constrained such that:
    Reviewer 0: available for all papers
             1: cannot review papers 0,3
             2: cannot review papers 3,4
             3: cannot review papers 1,2
    Scores set such that a lowest-cost solution can be found along all reviewer-paper arcs with cost = -10 and no others.
    Purpose:  Finds the lowest cost solution in combination with honoring constraints (i.e. ignores lower-cost paths that are constrained to be ommitted)
    '''
    cost_matrix = np.transpose(np.array([
        [-10, 1, 1, -10, -10],
        [-100, -10, -10, -100, 1],
        [1, -10, -10, -100, -100],
        [-10, -100, -100, -10, -10]]))
    constraint_matrix = np.transpose(np.array([
        [0, 0, 0, 0, 0],
        [-1, 0, 0, -1, 0],
        [0, 0 , 0, -1, -1],
        [0, -1,-1, 0, 0]]))

    solver = MinMaxSolver(
        [1,1,1,1],
        [3,3,3,3],
        [2,2,2,2,2],
        encoder(cost_matrix, constraint_matrix)
    )
    res = solver.solve()
    assert res.shape == (5, 4)
    # make sure result does not violate constraints (i.e. no flow at i,j if there is a -1 constraint at i,j
    # make sure the score at i,j = -10 if there is flow there.
    nrows, ncols = res.shape
    for i in range(nrows):
        for j in range(ncols):
            assert not (constraint_matrix[i,j] == -1 and res[i,j] > 0), "Solution violates constraint at [{},{}]".format(i,j)
            assert not (res[i,j] > 0 and cost_matrix[i,j] > -10), "Solution contains an arc that is not part of an lowest-cost solution"
    check_solution(solver,solver.optimal_cost)