• Gurobi Staff

Hi Huib,

The question you have posed doesn't need to be posed as an optimization problem.  If you have the expression

K * m + R == a + b

and all values are non-negative integers with R < m then K, R can be calculated as

K = floor( (a+b)/m)  # or (a+b)//m in PythonR = a+b - K*m

The sequence that you're wanting to print can be achieved with

arr = ["B"]*(a+b+1)arr[::2*m] = ["A"]*len(arr[::2*m])arr[1::2*m] = ["A"]*len(arr[1::2*m])print(arr)

You mentioned that a player wins when they reach n points, but you neither use the value of n inside your function, or explain how it relates to the outputs you want to see.

- Riley

Ah yes, thank you for taking a look at it. So, I was making it way too difficult.

You're right, I excluded that from my question to simplify the project. But a player wins when he reaches points or when there is a tie (both players score n - 1) and the player wins two consecutive points hereafter. In the case of a tie, the serve changes per point. How would you include these rules into your array?

• Gurobi Staff

Hi Huib,

I think we're still missing a part of the question here.

Let's say n = 5, a = 0, b = 0.  So a game of "first to 5" is about to start.

What do you want to do with this information?  If there was a question such as "how many different ways can player A win, given the current scores" then this would make more sense, but at the moment it is not clear what you are wanting to produce and how the value of n affects this.

Maybe we can use n = 5, a = 0, b = 0 as an example.  What are the exact outputs you would like to see in this case?

- Riley

Hi Riley,

In the end that's exactly what I want to do; get all the different ways a score can be achieved. To be precise, I want all the ways A (B) can score a (b) points on his own serve. Below is my script where the output is all the different paths:

def get_score_on_serve_sequences(a: int, b: int, m: int, n: int, server: str, receiver: str) -> list:    sequences = []    model = create_model()    served = get_serve_sequence(a=a, b=b, m=m, n=n, server=server, receiver=receiver)    scored = [model.addVar(vtype=GRB.BINARY, name=f'serve_{idx+1}') for idx, _ in enumerate(served)]    if server == 'A':        model.addConstr(gurobi.quicksum([serve * score for serve, score in zip(served, scored)]) == a)    else:        model.addConstr(gurobi.quicksum([serve * score for serve, score in zip(served, scored)]) == b)    model.addConstrs((scored[_] == 0 for _, serve in enumerate(served) if serve == 0))    model.optimize()    if model.Status == GRB.OPTIMAL:        solutions = model.SolCount        for solution in range(0, solutions):            model.setParam(GRB.Param.SolutionNumber, solution)            sequences.append([int(score.Xn) for score in scored])    return sequences

However, I want to rewrite my function get_serve_sequence(). I used your earlier suggestion to write the following:

def get_serve_sequence(a: int, b: int, m: int, n: int, server: str, receiver: str) -> list:    sequence = [receiver] * (a + b + 1)    sequence[::2 * m] = [server] * len(sequence[::2 * m])    sequence[1::2 * m] = [server] * len(sequence[1::2 * m])    return sequence

However, now I want to also include a tie. When a tie is reached at score n - 1, n - 1, the server changes per turn.

So the output of get_serve_sequence(a=14, b=12, m=2, n=11, server='A', receiver='B') should be

['A', 'A', 'B', 'B', 'A', 'A', 'B', 'B', 'A', 'A', 'B', 'B', 'A', 'A', 'B', 'B', 'A', 'A', 'B', 'B', 'A', 'B', 'A', 'B', 'A', 'B']

• Gurobi Staff

Hi Huib,

I think something like this would work.  Some of the numbers may need tweaking as I haven't tested it, but this is the general idea.

def get_serve_sequence(a: int, b: int, m: int, n: int, server: str, receiver: str) -> list:    sequence = [receiver] * (a + b + 1)    sequence[::2 * m] = [server] * len(sequence[::2 * m])    sequence[1::2 * m] = [server] * len(sequence[1::2 * m])    if a + b > 2*(n-1):        sequence[:2*(n-1)-a-b] = [receiver] * (a+b - 2*(n-1))        sequence[2*(n-1)::2] = [server] * sequence[2*(n-1)::2]    return sequence

Unfortunately, mixed integer linear programming is really not the appropriate solution to "get all the different ways a score can be achieved".  This is either solved directly with binomial coefficients, or with dynamic programming.

Your model doesn't have an objective so the solver will stop at the first feasible solution, and model.SolCount will always be 1.  You could force it to find multiple solutions using SolutionPools, but then you need to tell it how many solutions to find - which is the problem you're trying to solve.

- Riley