I'm optimizing fantasy golf teams using a for loop and want to add a constraint for unique teams only.

2 views (last 30 days)
I'm optimizing for a minimal Team Odds. I want NumTeams number of different teams and right now I get that by constraining objective to objectiveValue+1 on each loop. The problem with this is I could pontentially miss out on teams that have the same odds as the first time through the loop. To avoid this and get different teams with same odds, I want to add in a constraint that requires each team to be unique without incrementing the objectiveValue, i.e. they can have the same total salary and same total odds but have different combinations of players. Code I have thus far...
clc
clear all
basename = "MexicoOpenSalOdds";
baseoutname = "MexicoOpen";
T = readtable(sprintf("%s.csv",basename));
% Minimum Salary to use
minsalary = 6500;
T = T(T.Salary>=minsalary,:);
% How many teams to create
NumTeams = 20;
% pre-allocate arrays
Team = strings(NumTeams,10);
TeamSal = strings(NumTeams);
TeamAvgSal = strings(NumTeams);
TeamStdSal = strings(NumTeams);
TeamUL = ["G","G","G","G","G","G"];
% group the salaries so this runs faster
Tgroups = groupcounts(T,{'Salary'});
groupnames = "Group"++(1:length(Tgroups.Salary));
GrMinOdds = 0;
objectiveValue = 0;
groupPlayer1 = "";
for ii = 1:length(Tgroups.Salary)
% when theres more than one player in a Salary group take the one with best odds
GrMinOdds(ii) = min(T.Odds1(T.Salary==Tgroups.Salary(ii)));
% when theres more than one player in the best-odds-group take one at random
idxName = T.Name((T.Salary==Tgroups.Salary(ii) & T.Odds1 == GrMinOdds(ii)));
idxNameID = T.ID((T.Salary==Tgroups.Salary(ii) & T.Odds1 == GrMinOdds(ii)));
idxRandPlayer = randi([1 size(idxName,1)]);
if size(idxName,1)>1
idxName = idxName(idxRandPlayer);
end
if size(idxNameID,1)>1
idxNameID = idxNameID(idxRandPlayer);
end
groupPlayer1(ii) = idxName;
groupNameID(ii) = idxNameID;
end
Tgroups.Group = groupnames';
Tgroups.GrOdds = GrMinOdds';
Tgroups.Name = groupPlayer1';
Tgroups.NameID = groupNameID';
Tgroups.Use = zeros(length(Tgroups.Name));
TeamID =0;
% Build the optimization problem and select NumTeams number of teams
for i=1:NumTeams
fprintf("working on Team %d",i)
% C = size(unique(Team(:,1:6),'rows'),1);
UsePlayer = optimvar("UsePlayer",length(Tgroups.Salary),"Type","integer","LowerBound",0,...
"UpperBound",1);
% Set initial starting point for the solver
initialPoint2.UsePlayer = ones(size(UsePlayer));
% Create problem
problem = optimproblem;
% Define problem objective
problem.Objective = sum(UsePlayer .* Tgroups.GrOdds);
% Define problem constraints
problem.Constraints.constraint1 = sum(UsePlayer .* Tgroups.Salary) <= 50000;
problem.Constraints.constraint2 = sum(UsePlayer) == 6;
problem.Constraints.constraint3 = problem.Objective >= objectiveValue+1;
% problem.Constraints.constraint3 = C -6 + sum(UsePlayer) == i;
problem.Constraints.constraint4 = sum(UsePlayer .* Tgroups.Salary) >= 48300;
% problem.Constraints.constraint5 = UsePlayer .* Tgroups.Salary >= 7500;
% Set nondefault solver options
options2 = optimoptions("intlinprog","Display","final");
% Solve problem
[solution,objectiveValue,reasonSolverStopped] = solve(problem,initialPoint2,...
"Solver","intlinprog","Options",options2);
% Build output arrays by collecting results of optimizer for each loop
Tgroups.Use = round(solution.UsePlayer,1);
TeamSal(i) = sum(Tgroups.Salary(Tgroups.Use==1));
TeamAvgSal(i) = round(mean(Tgroups.Salary(Tgroups.Use==1)),0);
TeamStdSal(i) = round(std(Tgroups.Salary(Tgroups.Use==1)),0);
Team(i,1:10) = [(Tgroups.Name(Tgroups.Use==1))',TeamSal(i),TeamAvgSal(i),TeamStdSal(i),objectiveValue];
TeamUL = [TeamUL;(Tgroups.NameID(Tgroups.Use==1))'];
end
fprintf("Complete. %d Teams created.",i)
% Build output fioles for import to dfs website
writematrix(TeamUL,sprintf("%sUL.csv",baseoutname),'Delimiter',',');
writematrix(Team,sprintf("%sTeams.csv",baseoutname),'Delimiter',',');
% some logic to analyze the distribution of players
TeamTable = [Team(:,1);Team(:,2);Team(:,3);Team(:,4);Team(:,5);Team(:,6)];
[mostNum, mostPlayer] = groupcounts(TeamTable);
exposure = sortrows([mostPlayer, mostNum],2,'descend');

Answers (1)

Udit06
Udit06 on 21 Nov 2023
Hi Karli,
I understand that you are working on an optimization problem where you are trying to create multiple unique teams with the same total odds without exceeding a certain total salary. One approach could be to add a constraint that requires at least one player to be different from the players in previously selected teams.
% New constraint to ensure at least one player is different from previous teams
if i > 1
for j = 1:i-1
problem.Constraints.("constraintUnique" + j) = sum(UsePlayer .* previousTeams(j, :)) <= 5;
end
end
% matrix previousTeams keeps track of the players selected in each team
% For each previous team, a new constraint is added with a unique name,
% like constraintUnique1, constraintUnique2, and so on.
The new constraint ensures that the sum of the "UsePlayer" variables for the current team and any previous team is less than or equal to 5, which means at least one player must be different
I hope this helps.

Products


Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!