private static void rationalityConstrPlayer2(State s, Func <State, Action, Action, double> getQ, Dictionary <Tuple <Action, Action>, Decision> actDecisions, Model model, string constPrefix) { var rotList = new Queue <Action>(); foreach (Action action in Enum.GetValues(typeof(Action))) { rotList.Enqueue(action); } var cons_cnt = 0; for (var i = 0; i < Enum.GetValues(typeof(Action)).Length; ++i) { var constRowSum = new SumTermBuilder(5); var isConstrow = true; Action contextAction = Action.N; foreach (Action player2Action in rotList) { var otherRowSum = new SumTermBuilder(5); if (isConstrow) { contextAction = player2Action; } foreach (Action currentAction in Enum.GetValues(typeof(Action))) { var policy = getActDecision(currentAction, contextAction, actDecisions); if (isConstrow) { var qValue = getQ(s, currentAction, player2Action); constRowSum.Add(policy * qValue); } else { var qValue = getQ(s, currentAction, player2Action); otherRowSum.Add(policy * qValue); } } if (!isConstrow) { model.AddConstraint(constPrefix + "const" + cons_cnt, constRowSum.ToTerm() >= otherRowSum.ToTerm()); cons_cnt++; } isConstrow = false; } //Rotate list var elementToRotate = rotList.Dequeue(); rotList.Enqueue(elementToRotate); } }
public static Tuple <double, List <double> > PlayerBStrategy(List <List <int> > matrix) { SolverContext context = SolverContext.GetContext(); context.ClearModel(); Model model = context.CreateModel(); List <Decision> decicionList = new List <Decision>(); for (int j = 0; j < matrix[0].Count; j++) { decicionList.Add(new Decision(Domain.RealNonnegative, "B" + j)); } foreach (var decision in decicionList) { model.AddDecision(decision); } for (int i = 0; i < matrix.Count; i++) { SumTermBuilder rowSum = new SumTermBuilder(decicionList.Count); for (int j = 0; j < decicionList.Count; j++) { rowSum.Add(decicionList[j] * matrix[i][j]); } model.AddConstraint("con" + i, rowSum.ToTerm() <= 1); } SumTermBuilder decisionSum = new SumTermBuilder(decicionList.Count); for (int j = 0; j < decicionList.Count; j++) { model.AddConstraint("nonneg" + j, decicionList[j] >= 0); decisionSum.Add(decicionList[j]); } model.AddGoal("max", GoalKind.Maximize, decisionSum.ToTerm()); Solution solution = context.Solve(new SimplexDirective()); double gameValue = 1 / solution.Goals.First().ToDouble(); List <double> parsedDecicionList = new List <double>(); foreach (var decision in decicionList) { parsedDecicionList.Add(decision.ToDouble() * gameValue); } return(new Tuple <double, List <double> >(gameValue, parsedDecicionList)); }
private static void AddObjectiveFunctionTerms(State s, CorrelatedQTable q, Dictionary <Tuple <Action, Action>, Decision> actionDecisions, SumTermBuilder objectiveSum) { foreach (Action currentAction in Enum.GetValues(typeof(Action))) { foreach (Action opponentAction in Enum.GetValues(typeof(Action))) { var pi = GetActionDecision(currentAction, opponentAction, actionDecisions); var qValue = q.GetCurrentPlayerQValue(s, currentAction, opponentAction); objectiveSum.Add(pi * qValue); } } foreach (Action currentAction in Enum.GetValues(typeof(Action))) { foreach (Action opponentAction in Enum.GetValues(typeof(Action))) { var pi = GetActionDecision(currentAction, opponentAction, actionDecisions); var opponentQValue = q.GetOpponentQValue(s, currentAction, opponentAction); objectiveSum.Add(pi * opponentQValue); } } }
private static void ObjFunctermAdd(State s, CorrelatedQTable q, Dictionary <Tuple <Action, Action>, Decision> actDecisions, SumTermBuilder objectSum) { foreach (Action currentAction in Enum.GetValues(typeof(Action))) { foreach (Action player2Action in Enum.GetValues(typeof(Action))) { var policy = getActDecision(currentAction, player2Action, actDecisions); var qValue = q.getCurrPQvalue(s, currentAction, player2Action); objectSum.Add(policy * qValue); } } foreach (Action currentAction in Enum.GetValues(typeof(Action))) { foreach (Action player2Action in Enum.GetValues(typeof(Action))) { var policy = getActDecision(currentAction, player2Action, actDecisions); var player2Qv = q.getPlayer2Qval(s, currentAction, player2Action); objectSum.Add(policy * player2Qv); } } }
public static Tuple <double, double> GetValue(State s, CorrelatedQTable q) { var contxt = SolverContext.GetContext(); contxt.ClearModel(); var model = contxt.CreateModel(); var actDecisions = new Dictionary <Tuple <Action, Action>, Decision>(); foreach (Action currentAction in Enum.GetValues(typeof(Action))) { foreach (Action player2Action in Enum.GetValues(typeof(Action))) { var decision = new Decision(Domain.RealNonnegative, currentAction.ToString() + player2Action.ToString()); model.AddDecisions(decision); actDecisions.Add(new Tuple <Action, Action>(currentAction, player2Action), decision); } } var actDecisionSum = new SumTermBuilder(25); foreach (var decision in actDecisions.Values) { actDecisionSum.Add(decision); } model.AddConstraint("probSumConst", actDecisionSum.ToTerm() == 1.0); rationalconsts(s, q.getCurrPQvalue, actDecisions, model, "A"); rationalityConstrPlayer2(s, q.getPlayer2Qval, actDecisions, model, "B"); var objectSum = new SumTermBuilder(10); //Add my terms from my Q table to objective function ObjFunctermAdd(s, q, actDecisions, objectSum); model.AddGoal("MaximizeV", GoalKind.Maximize, objectSum.ToTerm()); var sol = contxt.Solve(new SimplexDirective()); if (sol.Quality != SolverQuality.Optimal) { contxt.ClearModel(); return(new Tuple <double, double>(1.0, 1.0)); } double Player1nextVal = 0.0; double Player2nextVal = 0.0; foreach (Action currentAction in Enum.GetValues(typeof(Action))) { foreach (Action player2Action in Enum.GetValues(typeof(Action))) { var policy = getActDecision(currentAction, player2Action, actDecisions); var qValue = q.getCurrPQvalue(s, currentAction, player2Action); Player1nextVal += policy.ToDouble() * qValue; var player2Qv = q.getPlayer2Qval(s, currentAction, player2Action); Player2nextVal += policy.ToDouble() * player2Qv; } } return(new Tuple <double, double>(Player1nextVal, Player2nextVal)); }
public SimplexMethod(double[,] table) : this() { M = table.GetLength(0); N = table.GetLength(1); var decisionsA = new Decision[M]; ResultsA = new double[M]; for (int i = 0; i < M; i++) { decisionsA[i] = new Decision(Domain.RealNonnegative, $"A{i}"); } _model.AddDecisions(decisionsA); var decisionsB = new Decision[N]; ResultsB = new double[N]; for (int j = 0; j < N; j++) { decisionsB[j] = new Decision(Domain.RealNonnegative, $"B{j}"); } _model.AddDecisions(decisionsB); for (int j = 0; j < N; j++) { var sum = new SumTermBuilder(M); for (int i = 0; i < M; i++) { sum.Add(decisionsA[i] * table[i, j]); } _model.AddConstraint($"C_A{j}", sum.ToTerm() >= 1); } for (int i = 0; i < M; i++) { var sum = new SumTermBuilder(N); for (int j = 0; j < N; j++) { sum.Add(decisionsB[j] * table[i, j]); } _model.AddConstraint($"C_B{i}", sum.ToTerm() <= 1); } var summinA = new SumTermBuilder(N); for (int i = 0; i < M; i++) { summinA.Add(decisionsA[i]); } _model.AddGoal("resA", GoalKind.Minimize, summinA.ToTerm()); var summinB = new SumTermBuilder(N); for (int j = 0; j < N; j++) { summinB.Add(decisionsB[j]); } _model.AddGoal("resB", GoalKind.Maximize, summinB.ToTerm()); _solver.Solve(); var gpsumA = 0.0; for (int i = 0; i < M; i++) { ResultsA[i] = decisionsA[i].GetDouble(); gpsumA += ResultsA[i]; } GamePriceA = 1 / gpsumA; var gpsumB = 0.0; for (int j = 0; j < N; j++) { ResultsB[j] = decisionsB[j].GetDouble(); gpsumB += ResultsB[j]; } GamePriceB = 1 / gpsumB; _solver.ClearModel(); }
public static Tuple <double, double> GetValue(State s, CorrelatedQTable q) { var context = SolverContext.GetContext(); context.ClearModel(); var model = context.CreateModel(); var actionDecisions = new Dictionary <Tuple <Action, Action>, Decision>(); foreach (Action currentAction in Enum.GetValues(typeof(Action))) { foreach (Action opponentAction in Enum.GetValues(typeof(Action))) { var decision = new Decision(Domain.RealNonnegative, currentAction.ToString() + opponentAction.ToString()); model.AddDecisions(decision); actionDecisions.Add(new Tuple <Action, Action>(currentAction, opponentAction), decision); } } var actionDecisionSum = new SumTermBuilder(25); foreach (var decision in actionDecisions.Values) { actionDecisionSum.Add(decision); } model.AddConstraint("probSumConst", actionDecisionSum.ToTerm() == 1.0); SetupRationalityConstraints(s, q.GetCurrentPlayerQValue, actionDecisions, model, "A"); SetupRationalityConstraintsOpponent(s, q.GetOpponentQValue, actionDecisions, model, "B"); var objectiveSum = new SumTermBuilder(10); //Add my terms from my Q table to objective function AddObjectiveFunctionTerms(s, q, actionDecisions, objectiveSum); model.AddGoal("MaximizeV", GoalKind.Maximize, objectiveSum.ToTerm()); var solution = context.Solve(new SimplexDirective()); //Console.WriteLine(solution.GetReport()); if (solution.Quality != SolverQuality.Optimal) { context.ClearModel(); return(new Tuple <double, double>(1.0, 1.0)); } double currentPlayerNextValue = 0.0; double opponentNextValue = 0.0; foreach (Action currentAction in Enum.GetValues(typeof(Action))) { foreach (Action opponentAction in Enum.GetValues(typeof(Action))) { var pi = GetActionDecision(currentAction, opponentAction, actionDecisions); var qValue = q.GetCurrentPlayerQValue(s, currentAction, opponentAction); currentPlayerNextValue += pi.ToDouble() * qValue; var opponentQValue = q.GetOpponentQValue(s, currentAction, opponentAction); opponentNextValue += pi.ToDouble() * opponentQValue; } } return(new Tuple <double, double>(currentPlayerNextValue, opponentNextValue)); }
private void InitializeConstraints(Project project, int eventCount) { // Establish the makespan: the maximum finish time over all activities. model.AddConstraint("c35", Model.ForEach(events1ToN, e => Model.ForEach(tasks, i => makespan >= start[e] + (isActive[i, e] - isActive[i, e - 1]) * duration[i]) )); // model.AddConstraint("ValidDeliveryDate", // Model.ForEach(tasks, e => start[e] + duration[e] <= entrega[e])); // model.AddConstraint("ModelSwitchPause", Model.ForEach(events1ToN, (t) => // start[t] >= start[t - 1] + duration[t - 1] + Model.If(molde[t] != molde[t - 1], 1, 0) //)); // The first event starts at time 0. model.AddConstraint("c_36", start[0] == 0); // Link the isActive decision to the starts of each event and task durations. model.AddConstraint("c_37", Model.ForEach(events1ToN, e => Model.ForEachWhere(events, f => Model.ForEach(tasks, i => start[f] >= start[e] + ((isActive[i, e] - isActive[i, e - 1]) - (isActive[i, f] - isActive[i, f - 1]) - 1) * duration[i] ), f => f > e))); // Link the isActive decision with the first event. This constraint is missing in the original // paper. model.AddConstraint("c_37_e0", Model.ForEach(events1ToN, f => Model.ForEach(tasks, i => start[f] >= start[0] + (isActive[i, 0] - (isActive[i, f] - isActive[i, f - 1]) - 1) * duration[i] ))); // Order the events. model.AddConstraint("c_38", Model.ForEach(events1ToN, e => start[e] >= start[e - 1])); // Ensure adjacency of events for an in-progress task. SumTermBuilder sum = new SumTermBuilder(eventCount); for (int i = 0; i < project.Tasks.Count; i++) { for (int e = 1; e < eventCount; e++) { sum.Add(isActive[i, e - 1]); model.AddConstraint("c_39_" + i + "_" + e, sum.ToTerm() <= e * (1 - (isActive[i, e] - isActive[i, e - 1]))); } sum.Clear(); } sum = new SumTermBuilder(eventCount); for (int i = 0; i < project.Tasks.Count; i++) { for (int e = 1; e < eventCount; e++) { for (int e1 = e; e1 < eventCount; e1++) { sum.Add(isActive[i, e1]); // (it's inefficient to reconstruct this for each value of e.) } model.AddConstraint("c_40_" + i + "_" + e, sum.ToTerm() <= e * (1 + (isActive[i, e] - isActive[i, e - 1]))); sum.Clear(); } } // All activities must be active during the project. model.AddConstraint("c_41", Model.ForEach(tasks, i => Model.Sum(Model.ForEach(events, e => isActive[i, e])) >= 1)); // A link (i, j) means that the start of task j must be after the finish of task i. int c42 = 0; foreach (TaskDependency link in project.Dependencies) { int i = link.Source.ID; int j = link.Destination.ID; sum = new SumTermBuilder(eventCount); for (int e = 0; e < eventCount; e++) { sum.Add(isActive[j, e]); // sum now has isActive[j, 0] .. isActive[j, e]. model.AddConstraint("c_42_" + c42++, isActive[i, e] + sum.ToTerm() <= 1 + e * (1 - isActive[i, e])); } } // Resource usage during each event must not exceed resource capacity. Dictionary <Resource, int> resToId = new Dictionary <Resource, int>(project.Resources.Count); for (int k = 0; k < project.Resources.Count; k++) { resToId[project.Resources[k]] = k; } SumTermBuilder[] totalResWork = new SumTermBuilder[project.Resources.Count]; int c43 = 0; for (int e = 0; e < eventCount; e++) { for (int taskID = 0; taskID < project.Tasks.Count; taskID++) { foreach (var assn in project.Tasks[taskID].Assignments) { int resID = resToId[assn.Resource]; if (totalResWork[resID] == null) { totalResWork[resID] = new SumTermBuilder(5); // most tasks will have <= 4 assignments. } totalResWork[resID].Add(assn.Units * isActive[taskID, e]); } } for (int resID = 0; resID < totalResWork.Length; resID++) { if (totalResWork[resID] != null) { model.AddConstraint("c43_" + c43++, totalResWork[resID].ToTerm() <= project.Resources[resID].MaxUnits); totalResWork[resID] = null; // note: memory churn... } } } }
public Solution alternative_solve(out Dictionary <Models.Shift, Decision> shiftsN, out Dictionary <Models.Shift, Decision> shiftsO) { SolverContext SC = SolverContext.GetContext(); Model model = SC.CreateModel(); var maxRq = HalfHourRequirements.Max(x => x.RequiredForce); shiftsN = shiftsO = null; //split shifts into two Dictionaries (each dict holds each Shift as key and the Decision variable as Value) var normal_shifts = new Dictionary <Models.Shift, Decision>(); //for normal shifts int i = 0; Shifts.ForEach(x => { Decision des = new Decision(Domain.IntegerRange(0, maxRq), string.Format("{0}_{1}", x.Name, i)); normal_shifts.Add(x, des); model.AddDecision(des); i++; }); var overtime_shifts = new Dictionary <Models.Shift, Decision>(); //for overtime shifts i = 0; OvertimeShifts.ForEach(x => { Decision des = new Decision(Domain.IntegerRange(0, maxRq), string.Format("{0}_{1}", x.Name, i)); overtime_shifts.Add(x, des); model.AddDecision(des); i++; }); List <Decision> excess = new List <Decision>(); //used to calculate sum of excess values HalfHourRequirements.ForEach(hh => { var ShiftsActive = new List <Decision>(); foreach (var entry in normal_shifts) { if (entry.Key.IncludesHalfHour(hh.Start)) { ShiftsActive.Add(entry.Value); excess.Add(entry.Value); } } foreach (var entry in overtime_shifts) { if (entry.Key.IncludesHalfHour(hh.Start)) { ShiftsActive.Add(entry.Value); excess.Add(entry.Value); } } //add constraint for sum of force of active shifts on that halfhour //if we need agents but no shifts exists for a halfhour, do not add a constraint if (ShiftsActive.Count > 0) { var sum_constr = new SumTermBuilder(ShiftsActive.Count); ShiftsActive.ForEach(s => sum_constr.Add(s)); var constr = sum_constr.ToTerm() >= hh.RequiredForce; model.AddConstraint(string.Format("_{0:hh}{0:mm}", hh.Start), constr); //constr = sum_constr.ToTerm() <= hh.RequiredForce * 2.0; //model.AddConstraint(string.Format("limitconst_for_{0:hh}{0:mm}", hh.Start), constr); } }); //Constrain maximum number of agents working 8hour shifts var max_agents_constraint = new SumTermBuilder(Shifts.Count); foreach (var entry in normal_shifts) { max_agents_constraint.Add(entry.Value); } var ma_constr = max_agents_constraint.ToTerm() <= MaxAgents; model.AddConstraint("Max_agents_constraint", ma_constr); //1st goal: Minimize overtime shifts (if work manageable by normal shifts, no overtime shifts will be used) var overtime_obj = new SumTermBuilder(OvertimeShifts.Count); foreach (var entry in overtime_shifts) { overtime_obj.Add(entry.Value); } model.AddGoal("Minimize_overtime", GoalKind.Minimize, overtime_obj.ToTerm()); //2st goal: Minimize normal shifts var normal_obj = new SumTermBuilder(Shifts.Count); foreach (var entry in normal_shifts) { normal_obj.Add(entry.Value); } model.AddGoal("Minimize_normal", GoalKind.Minimize, normal_obj.ToTerm()); //3rd goal: Try to minimize excess var sumReqs = HalfHourRequirements.Sum(x => x.RequiredForce); model.AddGoal("Minimize_excess", GoalKind.Minimize, Model.Sum(excess.ToArray()) - sumReqs); SimplexDirective simplex = new SimplexDirective(); Solution solution = SC.Solve(simplex); shiftsN = normal_shifts; shiftsO = overtime_shifts; return(solution); }