Esempio n. 1
0
 public Task <IHM3BOutputContext> Solve(
     IAbstractFactory abstractFactory,
     IHM3BConfiguration HM3BConfiguration,
     IHM3BInputContext HM3BInputContext,
     ISolverConfiguration solverConfiguration,
     HM3BEncodingEnum HM3BEncodingEnum)
 {
     return(abstractFactory.CreateSolutionsAbstractFactory().CreateHM3BSolutionFactory().Create().Solve(
                abstractFactory.CreateCalculationsAbstractFactory(),
                abstractFactory.CreateConstraintElementsAbstractFactory(),
                abstractFactory.CreateConstraintsAbstractFactory(),
                abstractFactory.CreateContextsAbstractFactory(),
                abstractFactory.CreateCrossJoinElementsAbstractFactory(),
                abstractFactory.CreateCrossJoinsAbstractFactory(),
                abstractFactory.CreateDependenciesAbstractFactory(),
                abstractFactory.CreateIndexElementsAbstractFactory(),
                abstractFactory.CreateIndicesAbstractFactory(),
                abstractFactory.CreateModelsAbstractFactory(),
                abstractFactory.CreateObjectiveFunctionsAbstractFactory(),
                abstractFactory.CreateParameterElementsAbstractFactory(),
                abstractFactory.CreateParametersAbstractFactory(),
                abstractFactory.CreateResultElementsAbstractFactory(),
                abstractFactory.CreateResultsAbstractFactory(),
                abstractFactory.CreateVariablesAbstractFactory(),
                HM3BConfiguration,
                HM3BInputContext,
                solverConfiguration,
                HM3BEncodingEnum));
 }
Esempio n. 2
0
        public HM3B001Model(
            IConstraintElementsAbstractFactory constraintElementsAbstractFactory,
            IConstraintsAbstractFactory constraintsAbstractFactory,
            ICrossJoinElementsAbstractFactory crossJoinElementsAbstractFactory,
            ICrossJoinsAbstractFactory crossJoinsAbstractFactory,
            IDependenciesAbstractFactory dependenciesAbstractFactory,
            IIndexElementsAbstractFactory indexElementsAbstractFactory,
            IIndicesAbstractFactory indicesAbstractFactory,
            IObjectiveFunctionsAbstractFactory objectiveFunctionsAbstractFactory,
            IParameterElementsAbstractFactory parameterElementsAbstractFactory,
            IParametersAbstractFactory parametersAbstractFactory,
            IVariablesAbstractFactory variablesAbstractFactory,
            IHM3BInputContext HM3BInputContext) :
            base(
                constraintElementsAbstractFactory,
                constraintsAbstractFactory,
                crossJoinElementsAbstractFactory,
                crossJoinsAbstractFactory,
                dependenciesAbstractFactory,
                indexElementsAbstractFactory,
                indicesAbstractFactory,
                objectiveFunctionsAbstractFactory,
                parameterElementsAbstractFactory,
                parametersAbstractFactory,
                variablesAbstractFactory,
                HM3BInputContext)
        {
            // v(m, r)
            this.v = parametersAbstractFactory.CreatevFactory().Create(
                this.Context.MachineOperatingRoomAssignments
                .Select(x => parameterElementsAbstractFactory.CreatevParameterElementFactory().Create(
                            this.m.GetElementAt(x.Item1),
                            this.r.GetElementAt(x.Item2),
                            (FhirBoolean)x.Item3))
                .ToImmutableList());

            // w(j, r)
            this.w = parametersAbstractFactory.CreatewFactory().Create(
                this.Context.SurgicalSpecialtyOperatingRoomAssignments
                .Select(x => parameterElementsAbstractFactory.CreatewParameterElementFactory().Create(
                            this.j.GetElementAt(x.Item1),
                            this.r.GetElementAt(x.Item2),
                            (FhirBoolean)x.Item3))
                .ToImmutableList());

            // y(s, r)
            this.y = variablesAbstractFactory.CreateyFactory().Create(
                dependenciesAbstractFactory.CreateVariableCollectionFactory().CreateBinary(
                    model: this.Model,
                    indexSet1: this.s.Value,
                    indexSet2: this.r.Value));

            // Constraints 1
            this.Model.AddConstraints(
                this.mr.Value
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints1ConstraintElementFactory().Create(
                        x.mIndexElement,
                        x.rIndexElement,
                        this.m,
                        this.s,
                        this.v,
                        this.ζ,
                        this.y)
                    .Value));

            // Constraints 5L
            this.Model.AddConstraints(
                this.srj.Value
                .Where(
                    x => this.Δ.IsSurgeonMemberOfSurgicalSpecialty(
                        x.jIndexElement,
                        x.sIndexElement))
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints5LConstraintElementFactory().Create(
                        x.rIndexElement,
                        x.sIndexElement,
                        this.b,
                        this.y)
                    .Value));

            // Constraints 5M
            this.Model.AddConstraints(
                this.srj.Value
                .Where(
                    x => this.Δ.IsSurgeonMemberOfSurgicalSpecialty(
                        x.jIndexElement,
                        x.sIndexElement))
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints5MConstraintElementFactory().Create(
                        x.rIndexElement,
                        x.sIndexElement,
                        this.Bs,
                        this.b,
                        this.y)
                    .Value));

            // Constraints 5U
            this.Model.AddConstraints(
                this.srj.Value
                .Where(
                    x => this.Δ.IsSurgeonMemberOfSurgicalSpecialty(
                        x.jIndexElement,
                        x.sIndexElement))
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints5UConstraintElementFactory().Create(
                        x.jIndexElement,
                        x.rIndexElement,
                        x.sIndexElement,
                        this.BBar,
                        this.Bs,
                        this.w,
                        this.y)
                    .Value));

            // Constraints 10
            this.Model.AddConstraints(
                this.srt.Value
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints10ConstraintElementFactory().Create(
                        x.rIndexElement,
                        x.sIndexElement,
                        x.tIndexElement,
                        this.x,
                        this.y)
                    .Value));
        }
Esempio n. 3
0
        public Task <IHM3BOutputContext> Solve(
            ICalculationsAbstractFactory calculationsAbstractFactory,
            IConstraintElementsAbstractFactory constraintElementsAbstractFactory,
            IConstraintsAbstractFactory constraintsAbstractFactory,
            IContextsAbstractFactory contextsAbstractFactory,
            ICrossJoinElementsAbstractFactory crossJoinElementsAbstractFactory,
            ICrossJoinsAbstractFactory crossJoinsAbstractFactory,
            IDependenciesAbstractFactory dependenciesAbstractFactory,
            IIndexElementsAbstractFactory indexElementsAbstractFactory,
            IIndicesAbstractFactory indicesAbstractFactory,
            IModelsAbstractFactory modelsAbstractFactory,
            IObjectiveFunctionsAbstractFactory objectiveFunctionsAbstractFactory,
            IParameterElementsAbstractFactory parameterElementsAbstractFactory,
            IParametersAbstractFactory parametersAbstractFactory,
            IResultElementsAbstractFactory resultElementsAbstractFactory,
            IResultsAbstractFactory resultsAbstractFactory,
            IVariablesAbstractFactory variablesAbstractFactory,
            IHM3BConfiguration HM3BConfiguration,
            IHM3BInputContext HM3BInputContext,
            ISolverConfiguration solverConfiguration,
            HM3BEncodingEnum HM3BEncodingEnum)
        {
            IHM3BOutputContext HM3BOutputContext = null;

            return(Task.Run(() =>
            {
                using (ModelScope modelScope = dependenciesAbstractFactory.CreateModelScopeFactory().Create(HM3BConfiguration.Value))
                {
                    IHM3BModel model = modelsAbstractFactory.CreateHM3BModelFactory().Create(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext,
                        HM3BEncodingEnum);

                    using (ISolver solver = dependenciesAbstractFactory.CreateSolverFactory().Create(solverConfiguration))
                    {
                        Solution solution = solver?.Solve(model?.Model);

                        if (solution.ModelStatus == OPTANO.Modeling.Optimization.Solver.ModelStatus.Feasible)
                        {
                            model.Model.VariableCollections.ForEach(vc => vc.SetVariableValues(solution.VariableValues));

                            HM3BOutputContext = contextsAbstractFactory.CreateHM3BOutputContextFactory().Create(
                                calculationsAbstractFactory,
                                dependenciesAbstractFactory,
                                resultElementsAbstractFactory,
                                resultsAbstractFactory,
                                model,
                                solution,
                                HM3BEncodingEnum);
                        }
                    }
                }

                return HM3BOutputContext;
            }));
        }
        public IHM3BModel Create(
            IConstraintElementsAbstractFactory constraintElementsAbstractFactory,
            IConstraintsAbstractFactory constraintsAbstractFactory,
            ICrossJoinElementsAbstractFactory crossJoinElementsAbstractFactory,
            ICrossJoinsAbstractFactory crossJoinsAbstractFactory,
            IDependenciesAbstractFactory dependenciesAbstractFactory,
            IIndexElementsAbstractFactory indexElementsAbstractFactory,
            IIndicesAbstractFactory indicesAbstractFactory,
            IObjectiveFunctionsAbstractFactory objectiveFunctionsAbstractFactory,
            IParameterElementsAbstractFactory parameterElementsAbstractFactory,
            IParametersAbstractFactory parametersAbstractFactory,
            IVariablesAbstractFactory variablesAbstractFactory,
            IHM3BInputContext HM3BInputContext,
            HM3BEncodingEnum HM3BEncodingEnum)
        {
            IHM3BModel model = null;

            try
            {
                model = HM3BEncodingEnum switch
                {
                    HM3BEncodingEnum.E000 => new HM3B000Model(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext),

                    HM3BEncodingEnum.E001 => new HM3B001Model(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext),

                    HM3BEncodingEnum.E010 => new HM3B010Model(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext),

                    HM3BEncodingEnum.E011 => new HM3B011Model(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext),

                    HM3BEncodingEnum.E100 => new HM3B100Model(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext),

                    HM3BEncodingEnum.E101 => new HM3B101Model(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext),

                    HM3BEncodingEnum.E110 => new HM3B110Model(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext),

                    HM3BEncodingEnum.E111 => new HM3B111Model(
                        constraintElementsAbstractFactory,
                        constraintsAbstractFactory,
                        crossJoinElementsAbstractFactory,
                        crossJoinsAbstractFactory,
                        dependenciesAbstractFactory,
                        indexElementsAbstractFactory,
                        indicesAbstractFactory,
                        objectiveFunctionsAbstractFactory,
                        parameterElementsAbstractFactory,
                        parametersAbstractFactory,
                        variablesAbstractFactory,
                        HM3BInputContext),

                    { } => throw new ArgumentException(nameof(HM3BEncodingEnum)),
                };
Esempio n. 5
0
        public IHM3BInputContext Create(
            ImmutableList <INullableValue <int> > weekdays,
            ImmutableList <Tuple <Organization, ImmutableList <Organization> > > surgicalSpecialties,
            ImmutableList <INullableValue <int> > lengthOfStayDays,
            Bundle machines,
            Bundle operatingRooms,
            Bundle surgeons,
            ImmutableList <KeyValuePair <INullableValue <int>, FhirDateTime> > planningHorizon,
            ImmutableList <INullableValue <int> > scenarios,
            ImmutableList <KeyValuePair <Organization, INullableValue <int> > > surgicalSpecialtyNumberAssignedTimeBlocks,
            ImmutableList <KeyValuePair <Organization, INullableValue <int> > > surgeonNumberAssignedTimeBlocks,
            Duration timeBlockLength,
            ImmutableList <Tuple <Organization, INullableValue <int>, Duration> > surgeonScenarioWeightedAverageSurgicalDurations,
            ImmutableList <KeyValuePair <Organization, INullableValue <int> > > surgeonLengthOfStayMaximums,
            ImmutableList <Tuple <Organization, INullableValue <int>, INullableValue <int> > > surgeonScenarioMaximumNumberPatients,
            ImmutableList <Tuple <Organization, INullableValue <int>, INullableValue <int>, INullableValue <decimal> > > surgeonDayScenarioLengthOfStayProbabilities,
            ImmutableList <Tuple <Device, Location, INullableValue <bool> > > machineOperatingRoomAssignments,
            INullableValue <int> numberDaysPerWeek,
            ImmutableList <Tuple <Organization, Location, INullableValue <bool> > > surgicalSpecialtyOperatingRoomAssignments,
            ImmutableList <Tuple <Organization, Location, INullableValue <bool> > > surgeonOperatingRoomAssignments,
            ImmutableList <Tuple <Organization, Device, INullableValue <bool> > > surgeonMachineRequirements,
            ImmutableList <Tuple <Organization, INullableValue <int>, INullableValue <decimal> > > surgeonScenarioMaximumNumberPatientMeans,
            ImmutableList <KeyValuePair <INullableValue <int>, INullableValue <decimal> > > scenarioProbabilities,
            ImmutableList <Tuple <Organization, INullableValue <int>, INullableValue <decimal> > > surgeonScenarioMaximumNumberPatientStandardDeviations,
            ImmutableList <KeyValuePair <FhirDateTime, INullableValue <bool> > > dayAvailabilities,
            INullableValue <int> maximumNumberRecoveryWardBeds)
        {
            IHM3BInputContext context = null;

            try
            {
                context = new HM3BInputContext(
                    weekdays,
                    surgicalSpecialties,
                    lengthOfStayDays,
                    machines,
                    operatingRooms,
                    surgeons,
                    planningHorizon,
                    scenarios,
                    surgicalSpecialtyNumberAssignedTimeBlocks,
                    surgeonNumberAssignedTimeBlocks,
                    timeBlockLength,
                    surgeonScenarioWeightedAverageSurgicalDurations,
                    surgeonLengthOfStayMaximums,
                    surgeonScenarioMaximumNumberPatients,
                    surgeonDayScenarioLengthOfStayProbabilities,
                    machineOperatingRoomAssignments,
                    numberDaysPerWeek,
                    surgicalSpecialtyOperatingRoomAssignments,
                    surgeonOperatingRoomAssignments,
                    surgeonMachineRequirements,
                    surgeonScenarioMaximumNumberPatientMeans,
                    scenarioProbabilities,
                    surgeonScenarioMaximumNumberPatientStandardDeviations,
                    dayAvailabilities,
                    maximumNumberRecoveryWardBeds);
            }
            catch (Exception exception)
            {
                this.Log.Error(
                    exception.Message,
                    exception);
            }

            return(context);
        }
Esempio n. 6
0
        public HM3BModel(
            IConstraintElementsAbstractFactory constraintElementsAbstractFactory,
            IConstraintsAbstractFactory constraintsAbstractFactory,
            ICrossJoinElementsAbstractFactory crossJoinElementsAbstractFactory,
            ICrossJoinsAbstractFactory crossJoinsAbstractFactory,
            IDependenciesAbstractFactory dependenciesAbstractFactory,
            IIndexElementsAbstractFactory indexElementsAbstractFactory,
            IIndicesAbstractFactory indicesAbstractFactory,
            IObjectiveFunctionsAbstractFactory objectiveFunctionsAbstractFactory,
            IParameterElementsAbstractFactory parameterElementsAbstractFactory,
            IParametersAbstractFactory parametersAbstractFactory,
            IVariablesAbstractFactory variablesAbstractFactory,
            IHM3BInputContext HM3BInputContext)
        {
            this.Context = HM3BInputContext;

            this.Model = dependenciesAbstractFactory.CreateModelFactory().Create();

            // Indices

            // d
            this.d = indicesAbstractFactory.CreatedFactory().Create(
                this.Context.Weekdays
                .Select(x => indexElementsAbstractFactory.CreatedIndexElementFactory().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());

            // m
            this.m = indicesAbstractFactory.CreatemFactory().Create(
                this.Context.Machines
                .Entry
                .Where(x => x.Resource is Device)
                .Select(x => indexElementsAbstractFactory.CreatemIndexElementFactory().Create((Device)x.Resource))
                .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

            // dt
            this.dt = crossJoinsAbstractFactory.CreatedtFactory().Create(
                this.d.Value
                .SelectMany(b => this.t.Value, (a, b) => crossJoinElementsAbstractFactory.CreatedtCrossJoinElementFactory().Create(a, b))
                .ToImmutableList());

            // mr
            this.mr = crossJoinsAbstractFactory.CreatemrFactory().Create(
                this.m.Value
                .SelectMany(b => this.r.Value, (a, b) => crossJoinElementsAbstractFactory.CreatemrCrossJoinElementFactory().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());

            // sd
            this.sd = crossJoinsAbstractFactory.CreatesdFactory().Create(
                this.s.Value
                .SelectMany(b => this.d.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesdCrossJoinElementFactory().Create(a, b))
                .ToImmutableList());

            // sdt
            this.sdt = crossJoinsAbstractFactory.CreatesdtFactory().Create(
                this.s.Value
                .SelectMany(b => this.d.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesdCrossJoinElementFactory().Create(a, b))
                .SelectMany(b => this.t.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesdtCrossJoinElementFactory().Create(a.sIndexElement, a.dIndexElement, 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());

            // sr
            this.sr = crossJoinsAbstractFactory.CreatesrFactory().Create(
                this.s.Value
                .SelectMany(b => this.r.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrCrossJoinElementFactory().Create(a, b))
                .ToImmutableList());

            // srd
            this.srd = crossJoinsAbstractFactory.CreatesrdFactory().Create(
                this.s.Value
                .SelectMany(b => this.r.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrCrossJoinElementFactory().Create(a, b))
                .SelectMany(b => this.d.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrdCrossJoinElementFactory().Create(a.sIndexElement, a.rIndexElement, b))
                .ToImmutableList());

            // srj
            this.srj = crossJoinsAbstractFactory.CreatesrjFactory().Create(
                this.s.Value
                .SelectMany(b => this.r.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrCrossJoinElementFactory().Create(a, b))
                .SelectMany(b => this.j.Value, (a, b) => crossJoinElementsAbstractFactory.CreatesrjCrossJoinElementFactory().Create(a.sIndexElement, a.rIndexElement, 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

            // BBar(j)
            this.BBar = parametersAbstractFactory.CreateBBarFactory().Create(
                this.Context.SurgicalSpecialtyNumberAssignedTimeBlocks
                .Select(x => parameterElementsAbstractFactory.CreateBBarParameterElementFactory().Create(
                            this.j.GetElementAt(x.Key),
                            (PositiveInt)x.Value))
                .ToImmutableList());

            // B(s)
            this.Bs = parametersAbstractFactory.CreateBsFactory().Create(
                this.Context.SurgeonNumberAssignedTimeBlocks
                .Select(x => parameterElementsAbstractFactory.CreateBsParameterElementFactory().Create(
                            this.s.GetElementAt(x.Key),
                            (PositiveInt)x.Value))
                .ToImmutableList());

            // 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());

            // W
            this.W = parametersAbstractFactory.CreateWFactory().Create(
                (PositiveInt)this.Context.NumberDaysPerWeek);

            // Δ(j)
            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());

            // ζ(s, m)
            this.ζ = parametersAbstractFactory.CreateζFactory().Create(
                this.Context.SurgeonMachineRequirements
                .Select(x => parameterElementsAbstractFactory.CreateζParameterElementFactory().Create(
                            this.s.GetElementAt(x.Item1),
                            this.m.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());

            // ψ(t)
            this.ψ = parametersAbstractFactory.CreateψFactory().Create(
                this.Context.DayAvailabilities
                .Select(x => parameterElementsAbstractFactory.CreateψParameterElementFactory().Create(
                            this.t.GetElementAt(x.Key),
                            (FhirBoolean)x.Value))
                .ToImmutableList());

            // Ω
            this.Ω = parametersAbstractFactory.CreateΩFactory().Create(
                (PositiveInt)this.Context.MaximumNumberRecoveryWardBeds);

            // Variables

            // b(s, r)
            this.b = variablesAbstractFactory.CreatebFactory().Create(
                dependenciesAbstractFactory.CreateVariableCollectionFactory().Create(
                    model: this.Model,
                    indexSet1: this.s.Value,
                    indexSet2: this.r.Value,
                    lowerBoundGenerator: (a, b) => 0,
                    upperBoundGenerator: (a, b) => int.MaxValue,
                    variableTypeGenerator: (a, b) => VariableType.Integer));

            // u(s, d)
            this.u = variablesAbstractFactory.CreateuFactory().Create(
                dependenciesAbstractFactory.CreateVariableCollectionFactory().CreateBinary(
                    model: this.Model,
                    indexSet1: this.s.Value,
                    indexSet2: this.d.Value));

            // x(s, r, t)
            this.x = variablesAbstractFactory.CreatexFactory().Create(
                dependenciesAbstractFactory.CreateVariableCollectionFactory().CreateBinary(
                    model: this.Model,
                    indexSet1: this.s.Value,
                    indexSet2: this.r.Value,
                    indexSet3: this.t.Value));

            // z(s, t)
            this.z = variablesAbstractFactory.CreatezFactory().Create(
                dependenciesAbstractFactory.CreateVariableCollectionFactory().CreateBinary(
                    model: this.Model,
                    indexSet1: this.s.Value,
                    indexSet2: this.t.Value));

            // β(s, r, d)
            this.β = variablesAbstractFactory.CreateβFactory().Create(
                dependenciesAbstractFactory.CreateVariableCollectionFactory().Create(
                    model: this.Model,
                    indexSet1: this.s.Value,
                    indexSet2: this.r.Value,
                    indexSet3: this.d.Value,
                    lowerBoundGenerator: (a, b, c) => 0,
                    upperBoundGenerator: (a, b, c) => int.MaxValue,
                    variableTypeGenerator: (a, b, c) => VariableType.Integer));

            // γ(r, t)
            this.γ = variablesAbstractFactory.CreateγFactory().Create(
                dependenciesAbstractFactory.CreateVariableCollectionFactory().CreateBinary(
                    model: this.Model,
                    indexSet1: this.r.Value,
                    indexSet2: this.t.Value));

            // Constraints
            // 1 (v, y), 5 L/M/U (v, w, y), 10 (y)
            // 2, 3, 4, 6, 7, 8, 9

            // Constraints 2
            this.Model.AddConstraints(
                this.s.Value
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints2ConstraintElementFactory().Create(
                        x,
                        this.r,
                        this.Bs,
                        this.b)
                    .Value));

            // Constraints 3
            this.Model.AddConstraints(
                this.r.Value
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints3ConstraintElementFactory().Create(
                        x,
                        this.s,
                        this.t,
                        this.b,
                        this.γ)
                    .Value));

            // Constraints 4
            this.Model.AddConstraints(
                this.rt.Value
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints4ConstraintElementFactory().Create(
                        x.rIndexElement,
                        x.tIndexElement,
                        this.ψ,
                        this.γ)
                    .Value));

            // Constraints 6
            this.Model.AddConstraints(
                this.sr.Value
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints6ConstraintElementFactory().Create(
                        x.rIndexElement,
                        x.sIndexElement,
                        this.d,
                        this.b,
                        this.β)
                    .Value));

            // Constraints 7
            this.Model.AddConstraints(
                this.srd.Value
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints7ConstraintElementFactory().Create(
                        x.dIndexElement,
                        x.rIndexElement,
                        x.sIndexElement,
                        this.t,
                        this.W,
                        this.x,
                        this.β)
                    .Value));

            // Constraints 8L
            this.Model.AddConstraints(
                this.sd.Value
                .SelectMany(b =>
                            this.t.GetNthElementsAt(
                                b.dIndexElement.Value.Value.Value,
                                this.t.GetT() - this.W.Value.Value.Value + b.dIndexElement.Value.Value.Value,
                                this.W.Value.Value.Value),
                            (a, b) => Tuple.Create(a.sIndexElement, a.dIndexElement, b))
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints8LConstraintElementFactory().Create(
                        x.Item2,
                        x.Item1,
                        x.Item3,
                        this.r,
                        this.x,
                        this.z)
                    .Value));

            // Constraints 8U
            this.Model.AddConstraints(
                this.sd.Value
                .SelectMany(b =>
                            this.t.GetNthElementsAt(
                                b.dIndexElement.Value.Value.Value,
                                this.t.GetT() - this.W.Value.Value.Value + b.dIndexElement.Value.Value.Value,
                                this.W.Value.Value.Value),
                            (a, b) => Tuple.Create(a.sIndexElement, a.dIndexElement, b))
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints8UConstraintElementFactory().Create(
                        x.Item2,
                        x.Item1,
                        x.Item3,
                        this.u,
                        this.z)
                    .Value));

            // Constraints 9
            this.Model.AddConstraints(
                this.rt.Value
                .Select(
                    x => constraintElementsAbstractFactory.CreateConstraints9ConstraintElementFactory().Create(
                        x.rIndexElement,
                        x.tIndexElement,
                        this.s,
                        this.x,
                        this.γ)
                    .Value));

            // Objective function
            this.Model.AddObjective(
                objectiveFunctionsAbstractFactory.CreateObjectiveFunctionFactory().Create(
                    dependenciesAbstractFactory.CreateObjectiveFactory(),
                    this.sd,
                    this.u)
                .Value);
        }