public HM5Model( ICalculationsAbstractFactory calculationsAbstractFactory, IConstraintElementsAbstractFactory constraintElementsAbstractFactory, IConstraintsAbstractFactory constraintsAbstractFactory, ICrossJoinElementsAbstractFactory crossJoinElementsAbstractFactory, ICrossJoinsAbstractFactory crossJoinsAbstractFactory, IDependenciesAbstractFactory dependenciesAbstractFactory, IIndexElementsAbstractFactory indexElementsAbstractFactory, IIndicesAbstractFactory indicesAbstractFactory, IObjectiveFunctionsAbstractFactory objectiveFunctionsAbstractFactory, IParameterElementsAbstractFactory parameterElementsAbstractFactory, IParametersAbstractFactory parametersAbstractFactory, IVariablesAbstractFactory variablesAbstractFactory, IHM5InputContext HM5InputContext) { this.Context = HM5InputContext; this.Model = dependenciesAbstractFactory.CreateModelFactory().Create(); // Indices // d1 this.d1 = indicesAbstractFactory.Created1Factory().Create( this.Context.Weekdays .Select(x => indexElementsAbstractFactory.Created1IndexElementFactory().Create((PositiveInt)x)) .ToImmutableList()); // d2 this.d2 = indicesAbstractFactory.Created2Factory().Create( this.Context.Weekdays .Select(x => indexElementsAbstractFactory.Created2IndexElementFactory().Create((PositiveInt)x)) .ToImmutableList()); // j this.j = indicesAbstractFactory.CreatejFactory().Create( this.Context.SurgicalSpecialties .Select(x => x.Item1) .Select(x => indexElementsAbstractFactory.CreatejIndexElementFactory().Create(x)) .ToImmutableList()); // l this.l = indicesAbstractFactory.CreatelFactory().Create( this.Context.LengthOfStayDays .Select(x => indexElementsAbstractFactory.CreatelIndexElementFactory().Create((PositiveInt)x)) .ToImmutableList()); // r this.r = indicesAbstractFactory.CreaterFactory().Create( this.Context.OperatingRooms .Entry .Where(x => x.Resource is Location) .Select(x => indexElementsAbstractFactory.CreaterIndexElementFactory().Create((Location)x.Resource)) .ToImmutableList()); // s this.s = indicesAbstractFactory.CreatesFactory().Create( this.Context.Surgeons .Entry .Where(x => x.Resource is Organization) .Select(x => indexElementsAbstractFactory.CreatesIndexElementFactory().Create((Organization)x.Resource)) .ToImmutableList()); // t this.t = indicesAbstractFactory.CreatetFactory().Create( this.Context.PlanningHorizon .Select(x => indexElementsAbstractFactory.CreatetIndexElementFactory().Create( x.Key.Value.Value, x.Value)) .ToImmutableList()); // Λ this.Λ = indicesAbstractFactory.CreateΛFactory().Create( this.Context.Scenarios .Select(x => indexElementsAbstractFactory.CreateΛIndexElementFactory().Create((PositiveInt)x)) .ToImmutableList()); // Cross joins // rd1 this.rd1 = crossJoinsAbstractFactory.Createrd1Factory().Create( this.r.Value .SelectMany(b => this.d1.Value, (a, b) => crossJoinElementsAbstractFactory.Createrd1CrossJoinElementFactory().Create(a, b)) .ToImmutableList()); // rd1d2 this.rd1d2 = crossJoinsAbstractFactory.Createrd1d2Factory().Create( this.r.Value .SelectMany(b => this.d1.Value, (a, b) => crossJoinElementsAbstractFactory.Createrd1CrossJoinElementFactory().Create(a, b)) .SelectMany(b => this.d2.Value, (a, b) => crossJoinElementsAbstractFactory.Createrd1d2CrossJoinElementFactory().Create(a.rIndexElement, a.d1IndexElement, b)) .ToImmutableList()); // rd2 this.rd2 = crossJoinsAbstractFactory.Createrd2Factory().Create( this.r.Value .SelectMany(b => this.d2.Value, (a, b) => crossJoinElementsAbstractFactory.Createrd2CrossJoinElementFactory().Create(a, b)) .ToImmutableList()); // rt this.rt = crossJoinsAbstractFactory.CreatertFactory().Create( this.r.Value .SelectMany(b => this.t.Value, (a, b) => crossJoinElementsAbstractFactory.CreatertCrossJoinElementFactory().Create(a, b)) .ToImmutableList()); // slΛ this.slΛ = crossJoinsAbstractFactory.CreateslΛFactory().Create( this.s.Value .SelectMany(b => this.l.Value, (a, b) => crossJoinElementsAbstractFactory.CreateslCrossJoinElementFactory().Create(a, b)) .SelectMany(b => this.Λ.Value, (a, b) => crossJoinElementsAbstractFactory.CreateslΛCrossJoinElementFactory().Create(a.sIndexElement, a.lIndexElement, b)) .ToImmutableList()); // srd2 this.srd2 = crossJoinsAbstractFactory.Createsrd2Factory().Create( this.s.Value .SelectMany(b => this.r.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrCrossJoinElementFactory().Create(a, b)) .SelectMany(b => this.d2.Value, (a, b) => crossJoinElementsAbstractFactory.Createsrd2CrossJoinElementFactory().Create(a.sIndexElement, a.rIndexElement, b)) .ToImmutableList()); // srd2t this.srd2t = crossJoinsAbstractFactory.Createsrd2tFactory().Create( this.s.Value .SelectMany(b => this.r.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrCrossJoinElementFactory().Create(a, b)) .SelectMany(b => this.d2.Value, (a, b) => crossJoinElementsAbstractFactory.Createsrd2CrossJoinElementFactory().Create(a.sIndexElement, a.rIndexElement, b)) .SelectMany(b => this.t.Value, (a, b) => crossJoinElementsAbstractFactory.Createsrd2tCrossJoinElementFactory().Create(a.sIndexElement, a.rIndexElement, a.d2IndexElement, b)) .ToImmutableList()); // srt this.srt = crossJoinsAbstractFactory.CreatesrtFactory().Create( this.s.Value .SelectMany(b => this.r.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrCrossJoinElementFactory().Create(a, b)) .SelectMany(b => this.t.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrtCrossJoinElementFactory().Create(a.sIndexElement, a.rIndexElement, b)) .ToImmutableList()); // st this.st = crossJoinsAbstractFactory.CreatestFactory().Create( this.s.Value .SelectMany(b => this.t.Value, (a, b) => crossJoinElementsAbstractFactory.CreatestCrossJoinElementFactory().Create(a, b)) .ToImmutableList()); // sΛ this.sΛ = crossJoinsAbstractFactory.CreatesΛFactory().Create( this.s.Value .SelectMany(b => this.Λ.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesΛCrossJoinElementFactory().Create(a, b)) .ToImmutableList()); // tΛ this.tΛ = crossJoinsAbstractFactory.CreatetΛFactory().Create( this.t.Value .SelectMany(b => this.Λ.Value, (a, b) => crossJoinElementsAbstractFactory.CreatetΛCrossJoinElementFactory().Create(a, b)) .ToImmutableList()); // Parameters // H this.H = parametersAbstractFactory.CreateHFactory().Create( this.Context.TimeBlockLength); // h(s, Λ) this.h = parametersAbstractFactory.CreatehFactory().Create( this.Context.SurgeonScenarioWeightedAverageSurgicalDurations .Select(x => parameterElementsAbstractFactory.CreatehParameterElementFactory().Create( this.s.GetElementAt(x.Item1), this.Λ.GetElementAt((PositiveInt)x.Item2), x.Item3)) .ToImmutableList()); // L(s) this.L = parametersAbstractFactory.CreateLFactory().Create( this.Context.SurgeonLengthOfStayMaximums .Select(x => parameterElementsAbstractFactory.CreateLParameterElementFactory().Create( this.s.GetElementAt(x.Key), (PositiveInt)x.Value)) .ToImmutableList()); // n(s, Λ) this.n = parametersAbstractFactory.CreatenFactory().Create( this.Context.SurgeonScenarioMaximumNumberPatients .Select(x => parameterElementsAbstractFactory.CreatenParameterElementFactory().Create( this.s.GetElementAt(x.Item1), this.Λ.GetElementAt((PositiveInt)x.Item2), (PositiveInt)x.Item3)) .ToImmutableList()); // p(s, l, Λ) this.p = parametersAbstractFactory.CreatepFactory().Create( this.Context.SurgeonDayScenarioLengthOfStayProbabilities .Select(x => parameterElementsAbstractFactory.CreatepParameterElementFactory().Create( this.s.GetElementAt(x.Item1), this.l.GetElementAt((PositiveInt)x.Item2), this.Λ.GetElementAt((PositiveInt)x.Item3), (FhirDecimal)x.Item4)) .ToImmutableList()); // Δ(j) // Must be populated before S1 this.Δ = parametersAbstractFactory.CreateΔFactory().Create( this.Context.SurgicalSpecialties .Select(x => parameterElementsAbstractFactory.CreateΔParameterElementFactory().Create( this.j.GetElementAt(x.Item1), x.Item2.Select(i => this.s.GetElementAt(i)).ToImmutableList())) .ToImmutableList()); // x(s, r, t) // Must be populated before S1 this.x = parametersAbstractFactory.CreatexFactory().Create( this.Context.SurgeonOperatingRoomDayAssignments .Select(x => parameterElementsAbstractFactory.CreatexParameterElementFactory().Create( this.s.GetElementAt(x.Item1), this.r.GetElementAt(x.Item2), this.t.GetElementAt(x.Item3), (FhirBoolean)x.Item4)) .ToImmutableList()); // S1 this.S1 = calculationsAbstractFactory.CreateS1CalculationFactory().Create().Calculate( parameterElementsAbstractFactory.CreateS1ParameterElementFactory(), parametersAbstractFactory.CreateS1Factory(), this.r, this.x, this.Δ); // W // Must be populated before S2 this.W = parametersAbstractFactory.CreateWFactory().Create( (PositiveInt)this.Context.NumberDaysPerWeek); // S2 this.S2 = calculationsAbstractFactory.CreateS2CalculationFactory().Create().Calculate( parameterElementsAbstractFactory.CreateS2ParameterElementFactory(), parametersAbstractFactory.CreateS2Factory(), this.d1, this.d2, this.r, this.t, this.rd1d2, this.W, this.x, this.Δ); // y(s, r) this.y = parametersAbstractFactory.CreateyFactory().Create( this.Context.SurgeonOperatingRoomAssignments .Select(x => parameterElementsAbstractFactory.CreateyParameterElementFactory().Create( this.s.GetElementAt(x.Item1), this.r.GetElementAt(x.Item2), (FhirBoolean)x.Item3)) .ToImmutableList()); // γ(r, t) this.γ = parametersAbstractFactory.CreateγFactory().Create( this.Context.OperatingRoomDayAssignedAvailabilities .Select(x => parameterElementsAbstractFactory.CreateγParameterElementFactory().Create( this.r.GetElementAt(x.Item1), this.t.GetElementAt(x.Item2), (FhirBoolean)x.Item3)) .ToImmutableList()); // μ(s, Λ) this.μ = parametersAbstractFactory.CreateμFactory().Create( this.Context.SurgeonScenarioMaximumNumberPatientMeans .Select(x => parameterElementsAbstractFactory.CreateμParameterElementFactory().Create( this.s.GetElementAt(x.Item1), this.Λ.GetElementAt((PositiveInt)x.Item2), (FhirDecimal)x.Item3)) .ToImmutableList()); // Ρ(Λ) this.Ρ = parametersAbstractFactory.CreateΡFactory().Create( this.Context.ScenarioProbabilities .Select(x => parameterElementsAbstractFactory.CreateΡParameterElementFactory().Create( this.Λ.GetElementAt((PositiveInt)x.Key), (FhirDecimal)x.Value)) .ToImmutableList()); // σ(s, Λ) this.σ = parametersAbstractFactory.CreateσFactory().Create( this.Context.SurgeonScenarioMaximumNumberPatientStandardDeviations .Select(x => parameterElementsAbstractFactory.CreateσParameterElementFactory().Create( this.s.GetElementAt(x.Item1), this.Λ.GetElementAt((PositiveInt)x.Item2), (FhirDecimal)x.Item3)) .ToImmutableList()); // ΦHat(s, l, Λ) this.ΦHat = parametersAbstractFactory.CreateΦHatFactory().Create( this.Context.SurgeonDayScenarioCumulativeNumberPatients .Select(x => parameterElementsAbstractFactory.CreateΦHatParameterElementFactory().Create( this.s.GetElementAt(x.Item1), this.l.GetElementAt((PositiveInt)x.Item2), this.Λ.GetElementAt((PositiveInt)x.Item3), (FhirDecimal)x.Item4)) .ToImmutableList()); // Ω this.Ω = parametersAbstractFactory.CreateΩFactory().Create( (PositiveInt)this.Context.MaximumNumberRecoveryWardBeds); // Variables // IHat(t, Λ) this.IHat = variablesAbstractFactory.CreateIHatFactory().Create( dependenciesAbstractFactory.CreateVariableCollectionFactory().Create( model: this.Model, indexSet1: this.t.Value, indexSet2: this.Λ.Value, lowerBoundGenerator: (a, b) => 0, upperBoundGenerator: (a, b) => double.MaxValue, variableTypeGenerator: (a, b) => VariableType.Continuous)); // xHat(s, r, t) this.xHat = variablesAbstractFactory.CreatexHatFactory().Create( dependenciesAbstractFactory.CreateVariableCollectionFactory().Create( model: this.Model, indexSet1: this.s.Value, indexSet2: this.r.Value, indexSet3: this.t.Value, lowerBoundGenerator: (a, b, c) => 0, upperBoundGenerator: (a, b, c) => 1, variableTypeGenerator: (a, b, c) => VariableType.Binary)); // z(s, t) this.z = variablesAbstractFactory.CreatezFactory().Create( dependenciesAbstractFactory.CreateVariableCollectionFactory().Create( model: this.Model, indexSet1: this.s.Value, indexSet2: this.t.Value, lowerBoundGenerator: (a, b) => 0, upperBoundGenerator: (a, b) => 1, variableTypeGenerator: (a, b) => VariableType.Binary)); // α(r, d1, d2) this.α = variablesAbstractFactory.CreateαFactory().Create( dependenciesAbstractFactory.CreateVariableCollectionFactory().Create( model: this.Model, indexSet1: this.r.Value, indexSet2: this.d1.Value, indexSet3: this.d2.Value, lowerBoundGenerator: (a, b, c) => 0, upperBoundGenerator: (a, b, c) => 1, variableTypeGenerator: (a, b, c) => VariableType.Binary)); // Constraints // Constraints 1 this.Model.AddConstraints( this.st.Value .Select( x => constraintElementsAbstractFactory.CreateConstraints1ConstraintElementFactory().Create( x.sIndexElement, x.tIndexElement, this.r, this.xHat, this.z) .Value)); // Constraints 2 this.Model.AddConstraints( this.rt.Value .Select( x => constraintElementsAbstractFactory.CreateConstraints2ConstraintElementFactory().Create( x.rIndexElement, x.tIndexElement, this.s, this.γ, this.xHat) .Value)); // Constraints 3 this.Model.AddConstraints( this.srt.Value .Select( x => constraintElementsAbstractFactory.CreateConstraints3ConstraintElementFactory().Create( x.rIndexElement, x.sIndexElement, x.tIndexElement, this.y, this.xHat) .Value)); // Constraints 4 this.Model.AddConstraints( this.tΛ.Value .Select( x => constraintElementsAbstractFactory.CreateConstraints4ConstraintElementFactory().Create( x.tIndexElement, x.ΛIndexElement, this.l, this.t, this.st, this.ΦHat, this.IHat, this.z) .Value)); // Constraints 5 this.Model.AddConstraints( this.rd1.Value .Where(x => this.S1.IsThereElementAt(x.rIndexElement)) .Select( x => constraintElementsAbstractFactory.CreateConstraints5ConstraintElementFactory().Create( x.d1IndexElement, x.rIndexElement, this.d2, this.α) .Value)); // Constraints 6 this.Model.AddConstraints( this.rd2.Value .Where(x => this.S1.IsThereElementAt(x.rIndexElement)) .Select( x => constraintElementsAbstractFactory.CreateConstraints6ConstraintElementFactory().Create( x.d2IndexElement, x.rIndexElement, this.d1, this.α) .Value)); // Constraints 7 this.Model.AddConstraints( this.rd1d2.Value .Where(x => this.S1.IsThereElementAt(x.rIndexElement)) .Where(x => this.S2.IsThereElementAt( x.rIndexElement, x.d1IndexElement, x.d2IndexElement)) .Select( x => constraintElementsAbstractFactory.CreateConstraints7ConstraintElementFactory().Create( x.rIndexElement, x.d1IndexElement, x.d2IndexElement, this.α) .Value)); // Constraints 8 this.Model.AddConstraints( this.srd2.Value .Where(x => this.S1.IsThereElementAt(x.rIndexElement)) .SelectMany(b => this.t.GetNthElementsAt( 0, this.W.Value.Value.Value * ((this.t.GetT() / this.W.Value.Value.Value) - 1), this.W.Value.Value.Value), (a, b) => Tuple.Create(a.sIndexElement, a.rIndexElement, a.d2IndexElement, b)) .Select( x => constraintElementsAbstractFactory.CreateConstraints8ConstraintElementFactory().Create( x.Item3, x.Item2, x.Item1, x.Item4, this.d1, this.t, this.x, this.xHat, this.α) .Value)); // Constraints 9 this.Model.AddConstraints( this.srt.Value .Where(x => !this.S1.IsThereElementAt(x.rIndexElement)) .Select( x => constraintElementsAbstractFactory.CreateConstraints9ConstraintElementFactory().Create( x.rIndexElement, x.sIndexElement, x.tIndexElement, this.x, this.xHat) .Value)); // Objective function this.Model.AddObjective( objectiveFunctionsAbstractFactory.CreateObjectiveFunctionFactory().Create( dependenciesAbstractFactory.CreateObjectiveFactory(), this.t, this.Λ, this.Ρ, this.IHat) .Value); }