{-# LANGUAGE CPP, FlexibleContexts #-}
module WeekDaze.Input.Options(
ShowLocationViewOfTimetable,
ShowTeacherViewOfTimetable,
Options(..),
tag,
appendOutputStudentViewTimetableFilePath,
setDisplayRuntimeInformation,
setFecundityDecayRatio,
setInputStudentViewTimetableFilePath,
setMaybeNInitialScouts,
setMaybeOutputConfigFilePath,
setMaybeRandomSeed,
setMinimumPopulationDiversityRatio,
setNDecimalDigits,
setOptimiseLessonCriteriaWeights,
setPermitTemporaryStudentBodyMerger,
setReduceStudentBodyRegister,
setRemoveRedundantCourses,
setTimeslotIdBounds,
setVerbosity,
zeroInappropriateExecutionOptions
) where
import Control.Arrow((&&&))
import qualified Control.Arrow
import qualified Control.Monad.Writer
import qualified Data.Default
import qualified Data.Foldable
import qualified Data.Map
import qualified Data.Maybe
import qualified Data.Set
import qualified Distribution.Verbosity
import qualified Factory.Data.Interval
import qualified System.FilePath
import qualified Text.XML.HXT.Arrow.Pickle as HXT
import qualified Text.XML.HXT.DOM.Util
import qualified ToolShed.SelfValidate
import qualified WeekDaze.Aggregate.LocationCatalogue as Aggregate.LocationCatalogue
import qualified WeekDaze.Aggregate.StudentBodyRegister as Aggregate.StudentBodyRegister
import qualified WeekDaze.Aggregate.StudentClass as Aggregate.StudentClass
import qualified WeekDaze.Aggregate.TeacherRegister as Aggregate.TeacherRegister
import qualified WeekDaze.Configuration as Configuration
import qualified WeekDaze.Data.Course as Data.Course
import qualified WeekDaze.Data.Student as Data.Student
import qualified WeekDaze.Data.Teacher as Data.Teacher
import qualified WeekDaze.ExecutionConfiguration.CriterionWeight as ExecutionConfiguration.CriterionWeight
import qualified WeekDaze.ExecutionConfiguration.EvolutionStrategies as ExecutionConfiguration.EvolutionStrategies
import qualified WeekDaze.ExecutionConfiguration.ExecutionOptions as ExecutionConfiguration.ExecutionOptions
import qualified WeekDaze.ExecutionConfiguration.LessonCriteriaWeights as ExecutionConfiguration.LessonCriteriaWeights
import qualified WeekDaze.ExecutionConfiguration.OptimiseLessonCriteriaWeights as ExecutionConfiguration.OptimiseLessonCriteriaWeights
import qualified WeekDaze.ExecutionConfiguration.TimetableBreederFecundity as ExecutionConfiguration.TimetableBreederFecundity
import qualified WeekDaze.ExecutionConfiguration.TimetableCriteriaWeights as ExecutionConfiguration.TimetableCriteriaWeights
import qualified WeekDaze.Input.ConfigVersion as Input.ConfigVersion
import qualified WeekDaze.OutputConfiguration.FileFormat as OutputConfiguration.FileFormat
import qualified WeekDaze.OutputConfiguration.Format as OutputConfiguration.Format
import qualified WeekDaze.OutputConfiguration.Options as OutputConfiguration.Options
import qualified WeekDaze.OutputConfiguration.Style as OutputConfiguration.Style
import qualified WeekDaze.OutputConfiguration.View as OutputConfiguration.View
import qualified WeekDaze.ProblemConfiguration.ProblemParameters as ProblemConfiguration.ProblemParameters
import qualified WeekDaze.ProblemConfiguration.ProblemValidationSwitches as ProblemConfiguration.ProblemValidationSwitches
import qualified WeekDaze.Size as Size
import qualified WeekDaze.Temporal.Day as Temporal.Day
#ifdef USE_HDBC
import qualified Control.DeepSeq
import qualified Database.HDBC
import qualified Data.Convertible
import qualified Data.Typeable
import qualified WeekDaze.Database.Selector as Database.Selector
instance (
Control.DeepSeq.NFData campus,
Control.DeepSeq.NFData criterionWeight,
Control.DeepSeq.NFData level,
Control.DeepSeq.NFData fecundityDecayRatio,
Control.DeepSeq.NFData locationId,
Control.DeepSeq.NFData minimumContrastRatio,
Control.DeepSeq.NFData populationDiversityRatio,
Control.DeepSeq.NFData stream,
Control.DeepSeq.NFData synchronisationId,
Control.DeepSeq.NFData teacherId,
Control.DeepSeq.NFData teachingRatio,
Control.DeepSeq.NFData timeslotId,
Data.Convertible.Convertible Database.HDBC.SqlValue campus,
Data.Convertible.Convertible Database.HDBC.SqlValue criterionWeight,
Data.Convertible.Convertible Database.HDBC.SqlValue fecundityDecayRatio,
Data.Convertible.Convertible Database.HDBC.SqlValue level,
Data.Convertible.Convertible Database.HDBC.SqlValue locationId,
Data.Convertible.Convertible Database.HDBC.SqlValue populationDiversityRatio,
Data.Convertible.Convertible Database.HDBC.SqlValue stream,
Data.Convertible.Convertible Database.HDBC.SqlValue synchronisationId,
Data.Convertible.Convertible Database.HDBC.SqlValue teacherId,
Data.Convertible.Convertible Database.HDBC.SqlValue teachingRatio,
Data.Convertible.Convertible Database.HDBC.SqlValue timeslotId,
Data.Default.Default campus,
Data.Default.Default stream,
Data.Typeable.Typeable criterionWeight,
Data.Typeable.Typeable fecundityDecayRatio,
Data.Typeable.Typeable populationDiversityRatio,
Data.Typeable.Typeable teachingRatio,
Fractional minimumContrastRatio,
Ord level,
Ord locationId,
Ord synchronisationId,
Ord teacherId,
Ord timeslotId,
RealFrac criterionWeight,
RealFrac fecundityDecayRatio,
RealFrac populationDiversityRatio,
RealFrac teachingRatio,
Show campus,
Show criterionWeight,
Show level,
Show locationId,
Show minimumContrastRatio,
Show synchronisationId,
Show timeslotId
) => Database.Selector.Selector (Options campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId) where
fromDatabase connection projectIdSql = let
tableName :: Database.Selector.TableName
tableName = Database.Selector.tablePrefix ++ tag
in do
configVersionStrings <- map head `fmap` Database.Selector.select connection [Input.ConfigVersion.tag] [tableName] [(Database.Selector.projectIdColumnName, projectIdSql)]
(problemParameters, executionOptions, outputOptions)
#ifdef QUERY_DB_CONCURRENTLY
<- Database.Selector.fromDatabaseConcurrently connection projectIdSql
#else
<- Database.Selector.fromDatabase connection projectIdSql
#endif
return MkOptions {
getConfigVersion = if null configVersionStrings
then Input.ConfigVersion.defaultConfigVersion
else Data.Maybe.maybe (
error $ "WeekDaze.Input.Options.fromDatabase:\tnull " ++ show Input.ConfigVersion.tag ++ "."
) Input.ConfigVersion.fromString . Database.HDBC.fromSql $ head configVersionStrings,
getProblemParameters = problemParameters,
getExecutionOptions = executionOptions,
getOutputOptions = outputOptions
}
#endif /* USE_HDBC */
type Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId = Options campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId -> Options campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
appendOutputStudentViewTimetableFilePath
:: Show minimumContrastRatio
=> System.FilePath.FilePath
-> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
appendOutputStudentViewTimetableFilePath filePath options = options {
getOutputOptions = outputOptions {
OutputConfiguration.Options.getFileFormats = OutputConfiguration.FileFormat.mkFileFormat filePath (OutputConfiguration.Format.XML OutputConfiguration.View.StudentView) : OutputConfiguration.Options.getFileFormats outputOptions
}
} where
outputOptions = getOutputOptions options
tag :: String
tag = "options"
type ShowLocationViewOfTimetable = Bool
type ShowTeacherViewOfTimetable = Bool
data Options campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId = MkOptions {
getConfigVersion :: Input.ConfigVersion.ConfigVersion,
getExecutionOptions :: ExecutionConfiguration.ExecutionOptions.ExecutionOptions criterionWeight fecundityDecayRatio populationDiversityRatio,
getOutputOptions :: OutputConfiguration.Options.Options minimumContrastRatio,
getProblemParameters :: ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
} deriving (Eq, Show)
instance (
Enum timeslotId,
Num fecundityDecayRatio,
Num populationDiversityRatio,
Ord fecundityDecayRatio,
Ord level,
Ord locationId,
Ord populationDiversityRatio,
Ord stream,
Ord synchronisationId,
Ord teacherId,
Ord timeslotId,
Real criterionWeight,
RealFrac teachingRatio,
Show criterionWeight,
Show fecundityDecayRatio,
Show level,
Show locationId,
Show minimumContrastRatio,
Show populationDiversityRatio,
Show stream,
Show synchronisationId,
Show teacherId,
Show teachingRatio,
Show timeslotId
) => ToolShed.SelfValidate.SelfValidator (Options campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId) where
getErrors MkOptions {
getExecutionOptions = executionOptions,
getOutputOptions = outputOptions,
getProblemParameters = problemParameters
}
| not $ ToolShed.SelfValidate.isValid executionOptions = ToolShed.SelfValidate.getErrors executionOptions
| not $ ToolShed.SelfValidate.isValid outputOptions = ToolShed.SelfValidate.getErrors outputOptions
| not $ ToolShed.SelfValidate.isValid problemParameters = ToolShed.SelfValidate.getErrors problemParameters
| otherwise = ToolShed.SelfValidate.extractErrors [
(
ExecutionConfiguration.ExecutionOptions.getPermitTemporaryStudentBodyMerger executionOptions && uncurry (||) (
ProblemConfiguration.ProblemValidationSwitches.getCheckIfStudentBodiesExceedTeachers &&& ProblemConfiguration.ProblemValidationSwitches.getCheckIfStudentBodySizeExceedsLocationCapacity $ ProblemConfiguration.ProblemParameters.getProblemValidationSwitches problemParameters
),
show ExecutionConfiguration.ExecutionOptions.permitTemporaryStudentBodyMergerTag ++ " & any of " ++ show [ProblemConfiguration.ProblemValidationSwitches.checkIfStudentBodiesExceedTeachersTag, ProblemConfiguration.ProblemValidationSwitches.checkIfStudentBodySizeExceedsLocationCapacityTag] ++ ", are incompatible"
),
let
nMutations, nTimeslotsPerWeek :: Size.NTimeslots
nMutations = ExecutionConfiguration.EvolutionStrategies.getStudentViewTimetableForWeekMutationNTimeslots $ ExecutionConfiguration.ExecutionOptions.getEvolutionStrategies executionOptions
nTimeslotsPerWeek = ProblemConfiguration.ProblemParameters.calculateNTimeslotsPerDay (ProblemConfiguration.ProblemParameters.getTimeslotIdBounds problemParameters) * Temporal.Day.nDaysPerWeek
in (
nMutations > nTimeslotsPerWeek,
"the specified number of time-slots " ++ show nMutations ++ ", to mutate during " ++ show ExecutionConfiguration.EvolutionStrategies.studentViewTimetableForWeekMutationTag ++ ", mustn't exceed the " ++ show nTimeslotsPerWeek ++ " available time-slots per week"
)
]
instance (
Data.Default.Default campus,
Data.Default.Default stream,
Eq campus,
Eq stream,
Fractional criterionWeight,
Fractional fecundityDecayRatio,
Fractional minimumContrastRatio,
Fractional populationDiversityRatio,
HXT.XmlPickler campus,
HXT.XmlPickler criterionWeight,
HXT.XmlPickler fecundityDecayRatio,
HXT.XmlPickler level,
HXT.XmlPickler locationId,
HXT.XmlPickler minimumContrastRatio,
HXT.XmlPickler populationDiversityRatio,
HXT.XmlPickler stream,
HXT.XmlPickler synchronisationId,
HXT.XmlPickler teacherId,
HXT.XmlPickler teachingRatio,
HXT.XmlPickler timeslotId,
Ord fecundityDecayRatio,
Ord level,
Ord locationId,
Ord minimumContrastRatio,
Ord populationDiversityRatio,
Ord synchronisationId,
Ord teacherId,
Ord timeslotId,
Real criterionWeight,
Real teachingRatio,
Show campus,
Show criterionWeight,
Show fecundityDecayRatio,
Show level,
Show minimumContrastRatio,
Show populationDiversityRatio,
Show synchronisationId,
Show timeslotId
) => HXT.XmlPickler (Options campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId) where
xpickle = HXT.xpElem tag . HXT.xpWrap (
Text.XML.HXT.DOM.Util.uncurry4 MkOptions,
\MkOptions {
getConfigVersion = configVersion,
getExecutionOptions = executionOptions,
getOutputOptions = outputOptions,
getProblemParameters = problemParameters
} -> (
configVersion,
executionOptions,
outputOptions,
problemParameters
)
) $ HXT.xp4Tuple (
HXT.xpDefault Input.ConfigVersion.defaultConfigVersion . HXT.xpElem Input.ConfigVersion.tag . HXT.xpList1 . HXT.xpElem Input.ConfigVersion.elementTag $ HXT.xpAttr "integer" HXT.xpInt
) (
HXT.xpDefault Data.Default.def HXT.xpickle
) HXT.xpickle HXT.xpickle
setDisplayRuntimeInformation :: OutputConfiguration.Style.DisplayRuntimeInformation -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setDisplayRuntimeInformation b options = options {
getOutputOptions = outputOptions {
OutputConfiguration.Options.getFileFormats = map (
\fileFormat -> fileFormat {
OutputConfiguration.FileFormat.getFormat = case OutputConfiguration.FileFormat.getFormat fileFormat of
OutputConfiguration.Format.XHTML style -> OutputConfiguration.Format.XHTML style { OutputConfiguration.Style.getDisplayRuntimeInformation = b }
xml -> xml
}
) $ OutputConfiguration.Options.getFileFormats outputOptions
}
} where
outputOptions = getOutputOptions options
setFecundityDecayRatio :: fecundityDecayRatio -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setFecundityDecayRatio fecundityDecayRatio options = options {
getExecutionOptions = ExecutionConfiguration.ExecutionOptions.setFecundityDecayRatio fecundityDecayRatio $ getExecutionOptions options
}
setInputStudentViewTimetableFilePath :: System.FilePath.FilePath -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setInputStudentViewTimetableFilePath filePath options = options {
getExecutionOptions = (getExecutionOptions options) {
ExecutionConfiguration.ExecutionOptions.getMaybeHint = Just $ Right filePath
}
}
setMaybeNInitialScouts :: Maybe Size.NTimetables -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setMaybeNInitialScouts maybeNInitialScouts options = options {
getExecutionOptions = ExecutionConfiguration.ExecutionOptions.setMaybeNInitialScouts maybeNInitialScouts $ getExecutionOptions options
}
setMaybeOutputConfigFilePath :: Maybe System.FilePath.FilePath -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setMaybeOutputConfigFilePath maybeOutputConfigFilePath options = options {
getOutputOptions = (getOutputOptions options) {
OutputConfiguration.Options.getMaybeOutputConfigFilePath = maybeOutputConfigFilePath
}
}
setMaybeRandomSeed :: Maybe ExecutionConfiguration.ExecutionOptions.RandomSeed -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setMaybeRandomSeed maybeSeed options = options {
getExecutionOptions = (getExecutionOptions options) {
ExecutionConfiguration.ExecutionOptions.getMaybeRandomSeed = maybeSeed
}
}
setMinimumPopulationDiversityRatio :: populationDiversityRatio -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setMinimumPopulationDiversityRatio populationDiversityRatio options = options {
getExecutionOptions = ExecutionConfiguration.ExecutionOptions.setMinimumPopulationDiversityRatio populationDiversityRatio $ getExecutionOptions options
}
setNDecimalDigits :: OutputConfiguration.Options.NDecimalDigits -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setNDecimalDigits nDecimalDigits options = options {
getOutputOptions = (getOutputOptions options) {
OutputConfiguration.Options.getNDecimalDigits = nDecimalDigits
}
}
setOptimiseLessonCriteriaWeights :: ExecutionConfiguration.OptimiseLessonCriteriaWeights.OptimiseLessonCriteriaWeights criterionWeight -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setOptimiseLessonCriteriaWeights optimiseLessonCriteriaWeights options = options {
getExecutionOptions = (getExecutionOptions options) {
ExecutionConfiguration.ExecutionOptions.getOptimiseLessonCriteriaWeights = optimiseLessonCriteriaWeights
}
}
setPermitTemporaryStudentBodyMerger :: Num criterionWeight => ExecutionConfiguration.ExecutionOptions.PermitTemporaryStudentBodyMerger -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setPermitTemporaryStudentBodyMerger permitTemporaryStudentBodyMerger options = options {
getProblemParameters = problemParameters {
ProblemConfiguration.ProblemParameters.getProblemValidationSwitches = (ProblemConfiguration.ProblemParameters.getProblemValidationSwitches problemParameters) {
ProblemConfiguration.ProblemValidationSwitches.getCheckIfStudentBodiesExceedTeachers = not permitTemporaryStudentBodyMerger,
ProblemConfiguration.ProblemValidationSwitches.getCheckIfStudentBodySizeExceedsLocationCapacity = not permitTemporaryStudentBodyMerger
}
},
getExecutionOptions = ExecutionConfiguration.ExecutionOptions.setPermitTemporaryStudentBodyMerger permitTemporaryStudentBodyMerger $ getExecutionOptions options
} where
problemParameters = getProblemParameters options
setReduceStudentBodyRegister :: ExecutionConfiguration.ExecutionOptions.ReduceStudentBodyRegister -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setReduceStudentBodyRegister b options = options {
getExecutionOptions = (getExecutionOptions options) {
ExecutionConfiguration.ExecutionOptions.getReduceStudentBodyRegister = b
}
}
setRemoveRedundantCourses :: ExecutionConfiguration.ExecutionOptions.RemoveRedundantCourses -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setRemoveRedundantCourses b options = options {
getExecutionOptions = (getExecutionOptions options) {
ExecutionConfiguration.ExecutionOptions.getRemoveRedundantCourses = b
}
}
setTimetableCriteriaWeights :: ExecutionConfiguration.TimetableCriteriaWeights.TimetableCriteriaWeights criterionWeight -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setTimetableCriteriaWeights timetableCriteriaWeights options = options {
getExecutionOptions = (getExecutionOptions options) {
ExecutionConfiguration.ExecutionOptions.getTimetableCriteriaWeights = timetableCriteriaWeights
}
}
setTimeslotIdBounds :: (Enum timeslotId, Num criterionWeight) => Factory.Data.Interval.Interval timeslotId -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setTimeslotIdBounds timeslotIdBounds options
| timeslotsPerDay < 2 = setTimetableCriteriaWeights (
timetableCriteriaWeights {
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseAverageAbsoluteDeviationFromIdealTimeslotRequest = minBound,
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseRatioOfConsecutiveEqualLessons = minBound,
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseRatioOfSeparatedEqualLessonsWithinAnyDay = minBound
}
) options'
| timeslotsPerDay < 3 = setTimetableCriteriaWeights (
timetableCriteriaWeights {
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseRatioOfSeparatedEqualLessonsWithinAnyDay = minBound
}
) options'
| otherwise = options'
where
timeslotsPerDay = ProblemConfiguration.ProblemParameters.calculateNTimeslotsPerDay timeslotIdBounds
options' = options {
getProblemParameters = (getProblemParameters options) {
ProblemConfiguration.ProblemParameters.getTimeslotIdBounds = timeslotIdBounds
}
}
timetableCriteriaWeights = ExecutionConfiguration.ExecutionOptions.getTimetableCriteriaWeights $ getExecutionOptions options'
setVerbosity :: Distribution.Verbosity.Verbosity -> Mutator campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId
setVerbosity verbosity options = options {
getOutputOptions = (getOutputOptions options) {
OutputConfiguration.Options.getVerbosity = verbosity
}
}
criteriaWeightsMutator :: (
Eq criterionWeight,
Num criterionWeight
)
=> criteriaWeights
-> [
(
(
criteriaWeights -> ExecutionConfiguration.CriterionWeight.CriterionWeight criterionWeight,
Bool
), (
criteriaWeights -> criteriaWeights,
String
)
)
]
-> Control.Monad.Writer.Writer [String] criteriaWeights
criteriaWeightsMutator criteriaWeights = foldr (
(
\(mutator, message) -> (
Control.Monad.Writer.tell [message] >>
) . fmap mutator
) . snd
) (
return criteriaWeights
) . filter (
uncurry (&&) . Control.Arrow.first (
(/= minBound) . ($ criteriaWeights)
) . fst
)
zeroInappropriateExecutionOptions :: (
Enum timeslotId,
Eq criterionWeight,
Num criterionWeight,
Ord campus,
Ord level,
Ord synchronisationId,
Ord timeslotId,
RealFrac teachingRatio
)
=> Bool
-> ProblemConfiguration.ProblemParameters.ProblemParameters campus level locationId stream synchronisationId teacherId teachingRatio timeslotId
-> ExecutionConfiguration.ExecutionOptions.ExecutionOptions criterionWeight fecundityDecayRatio populationDiversityRatio
-> (
ExecutionConfiguration.ExecutionOptions.ExecutionOptions criterionWeight fecundityDecayRatio populationDiversityRatio,
(
(
[String],
[String]
),
[String]
)
)
zeroInappropriateExecutionOptions zeroNonCritical problemParameters executionOptions = (
executionOptions {
ExecutionConfiguration.ExecutionOptions.getLessonCriteriaWeights = lessonCriteriaWeights,
ExecutionConfiguration.ExecutionOptions.getTimetableCriteriaWeights = timetableCriteriaWeights,
ExecutionConfiguration.ExecutionOptions.getEvolutionStrategies = evolutionStrategies
}, (
(
zeroedLessonCriterionWeightTags,
zeroedTimetableCriterionWeightTags
),
zeroedEvolutionStrategyFecundityTags
)
) where
nTimeslotsPerDay :: Size.NTimeslots
nTimeslotsPerDay = ProblemConfiguration.ProblemParameters.calculateNTimeslotsPerDay $ ProblemConfiguration.ProblemParameters.getTimeslotIdBounds problemParameters
permitTemporaryStudentBodyMerger :: Bool
permitTemporaryStudentBodyMerger = ExecutionConfiguration.ExecutionOptions.getPermitTemporaryStudentBodyMerger executionOptions
locationCatalogue = ProblemConfiguration.ProblemParameters.getLocationCatalogue problemParameters
studentBodyRegister = ProblemConfiguration.ProblemParameters.getStudentBodyRegister problemParameters
teacherRegister = ProblemConfiguration.ProblemParameters.getTeacherRegister problemParameters
nLocations :: Size.NLocations
nLocations = Data.Map.size locationCatalogue
nStudents :: Size.NStudents
nStudents = Aggregate.StudentClass.getSize $ Aggregate.StudentBodyRegister.getStudentBodies studentBodyRegister
nTeachers :: Size.NTeachers
nTeachers = Data.Map.size teacherRegister
(distinctCourses, noTeacherHasMoreThanOneLesson) = Aggregate.TeacherRegister.extractDistinctCourses &&& Data.Foldable.all (
(<= 1) . Data.Foldable.foldr (
(+) . Data.Course.getRequiredLessonsPerWeek
) 0 . Data.Teacher.getService
) $ teacherRegister
hasAnyFacilities, isSingleCampus, hasAnyOptionalKnowledgeRequirements, hasAnyCourseMaximumClassSizes, hasAnySynchronisedCourses, requireAnyFacilities :: Bool
(hasAnyFacilities, isSingleCampus) = Aggregate.LocationCatalogue.hasAnyFacilities &&& Aggregate.LocationCatalogue.isSingleCampus $ locationCatalogue
hasAnyOptionalKnowledgeRequirements = Aggregate.StudentBodyRegister.hasAnyOptionalKnowledgeRequirements studentBodyRegister
(hasAnyCourseMaximumClassSizes, hasAnySynchronisedCourses) = Aggregate.TeacherRegister.hasAnyCourseMaximumClassSizes &&& Aggregate.TeacherRegister.hasAnySynchronisedCourses $ teacherRegister
requireAnyFacilities = Data.Foldable.any (not . Data.Set.null . Data.Course.getRequiredFacilityNames) distinctCourses
smallestMinimumConsecutivePeriods :: Size.NTimeslots
smallestMinimumConsecutivePeriods = Data.Foldable.minimum $ Data.Set.map Data.Course.getMinimumConsecutiveLessons distinctCourses
(lessonCriteriaWeights, zeroedLessonCriterionWeightTags) = Control.Monad.Writer.runWriter $ criteriaWeightsMutator (
ExecutionConfiguration.ExecutionOptions.getLessonCriteriaWeights executionOptions
) [
(
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfGreatestMinimumConsecutiveLessons,
zeroNonCritical && not (
ProblemConfiguration.ProblemParameters.hasVariousMinimumConsecutiveLessons problemParameters
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfGreatestMinimumConsecutiveLessons,
ExecutionConfiguration.LessonCriteriaWeights.weightOfGreatestMinimumConsecutiveLessonsTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfGreatestSynchronisedCourseSetSize,
zeroNonCritical && not hasAnySynchronisedCourses
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfGreatestSynchronisedCourseSetSize,
ExecutionConfiguration.LessonCriteriaWeights.weightOfGreatestSynchronisedCourseSetSizeTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfIsCoreKnowledgeRequirement,
zeroNonCritical && not (
Aggregate.StudentBodyRegister.hasAnyCoreKnowledgeRequirements studentBodyRegister && hasAnyOptionalKnowledgeRequirements
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfIsCoreKnowledgeRequirement,
ExecutionConfiguration.LessonCriteriaWeights.weightOfIsCoreKnowledgeRequirementTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfIsSpecialistInTopic,
zeroNonCritical && (
nTeachers == 1 || not (Aggregate.TeacherRegister.hasAnySpecialists teacherRegister)
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfIsSpecialistInTopic,
ExecutionConfiguration.LessonCriteriaWeights.weightOfIsSpecialistInTopicTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMatchCourseClassSizeToLocationCapacity,
zeroNonCritical && (
nLocations == 1 || not hasAnyCourseMaximumClassSizes
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMatchCourseClassSizeToLocationCapacity,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMatchCourseClassSizeToLocationCapacityTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMaximiseRelativeFacilityUtilisation,
zeroNonCritical && not (
hasAnyFacilities && requireAnyFacilities
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMaximiseRelativeFacilityUtilisation,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMaximiseRelativeFacilityUtilisationTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMaximiseStudentClassSizeOverCourseClassSize,
zeroNonCritical && or [
Data.Map.size studentBodyRegister == 1,
not hasAnyCourseMaximumClassSizes,
Data.Foldable.all (
Data.Maybe.maybe True (
>= nStudents
) . Data.Course.getMaybeMaximumClassSize
) distinctCourses
]
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMaximiseStudentClassSizeOverCourseClassSize,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMaximiseStudentClassSizeOverCourseClassSizeTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMaximiseStudentClassSizeOverLocationCapacity,
zeroNonCritical && nLocations == 1
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMaximiseStudentClassSizeOverLocationCapacity,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMaximiseStudentClassSizeOverLocationCapacityTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseBookingAtAnotherCoursesSpecifiedTime,
zeroNonCritical && not (Aggregate.TeacherRegister.hasAnySpecificTimeRequests teacherRegister)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMinimiseBookingAtAnotherCoursesSpecifiedTime,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseBookingAtAnotherCoursesSpecifiedTimeTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseBookingOfLocationByOtherTeachers,
zeroNonCritical && (
nLocations == 1 || nTeachers == 1
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMinimiseBookingOfLocationByOtherTeachers,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseBookingOfLocationByOtherTeachersTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseDeviationFromTimeslotRequest,
zeroNonCritical && not (Aggregate.TeacherRegister.hasAnyTimeslotRequests teacherRegister)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMinimiseDeviationFromTimeslotRequest,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseDeviationFromTimeslotRequestTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseInterCampusMigrationsOfStudents,
zeroNonCritical && (
nTimeslotsPerDay <= smallestMinimumConsecutivePeriods || isSingleCampus
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMinimiseInterCampusMigrationsOfStudents,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseInterCampusMigrationsOfStudentsTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseInterCampusMigrationsOfTeachers,
zeroNonCritical && (
nTimeslotsPerDay <= smallestMinimumConsecutivePeriods || isSingleCampus
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMinimiseInterCampusMigrationsOfTeachers,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseInterCampusMigrationsOfTeachersTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseTeachersLocusOperandi,
zeroNonCritical && (
nLocations == 1 || noTeacherHasMoreThanOneLesson
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMinimiseTeachersLocusOperandi,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseTeachersLocusOperandiTag
)
), (
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseWasteOfScarceFacilities,
zeroNonCritical && not (
hasAnyFacilities && requireAnyFacilities
)
), (
ExecutionConfiguration.LessonCriteriaWeights.zeroWeightOfMinimiseWasteOfScarceFacilities,
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseWasteOfScarceFacilitiesTag
)
)
]
(timetableCriteriaWeights, zeroedTimetableCriterionWeightTags) = Control.Monad.Writer.runWriter $ criteriaWeightsMutator (
ExecutionConfiguration.ExecutionOptions.getTimetableCriteriaWeights executionOptions
) [
(
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMaximiseComplianceWithFreePeriodPreferences,
zeroNonCritical && (
nTimeslotsPerDay <= smallestMinimumConsecutivePeriods || not (
ProblemConfiguration.ProblemParameters.hasAnyFreePeriodPreference problemParameters
)
)
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMaximiseComplianceWithFreePeriodPreferences,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMaximiseComplianceWithFreePeriodPreferencesTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMaximiseSynchronisationOfSynchronisedCourses,
zeroNonCritical && not hasAnySynchronisedCourses
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMaximiseSynchronisationOfSynchronisedCourses,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMaximiseSynchronisationOfSynchronisedCoursesTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseAverageAbsoluteDeviationFromIdealTimeslotRequest,
zeroNonCritical && (
nTimeslotsPerDay <= smallestMinimumConsecutivePeriods || not (
Aggregate.TeacherRegister.hasAnyIdealTimeslotRequests teacherRegister
)
)
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseAverageAbsoluteDeviationFromIdealTimeslotRequest,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseAverageAbsoluteDeviationFromIdealTimeslotRequestTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseDispersionOfStudentFreePeriodsPerDay,
zeroNonCritical && Data.Foldable.all (
(== 1) . Data.Student.getTeachingRatio
) studentBodyRegister
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseDispersionOfStudentFreePeriodsPerDay,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseDispersionOfStudentFreePeriodsPerDayTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseMeanInterCampusMigrationsOfStudents,
zeroNonCritical && (
nTimeslotsPerDay <= smallestMinimumConsecutivePeriods || isSingleCampus
)
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseMeanInterCampusMigrationsOfStudents,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseMeanInterCampusMigrationsOfStudentsTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseMeanInterCampusMigrationsOfTeachers,
zeroNonCritical && (
nTimeslotsPerDay <= smallestMinimumConsecutivePeriods || isSingleCampus
)
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseMeanInterCampusMigrationsOfTeachers,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseMeanInterCampusMigrationsOfTeachersTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseMeanLocationChangesOfTeachers,
zeroNonCritical && (
nLocations == 1 || noTeacherHasMoreThanOneLesson
)
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseMeanLocationChangesOfTeachers,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseMeanLocationChangesOfTeachersTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseMeanLocusOperandiOfTeachers,
zeroNonCritical && (
nLocations == 1 || noTeacherHasMoreThanOneLesson
)
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseMeanLocusOperandiOfTeachers,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseMeanLocusOperandiOfTeachersTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseMeanRatioOfIncompletelyBookedOptionalKnowledge,
zeroNonCritical && not hasAnyOptionalKnowledgeRequirements
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseMeanRatioOfIncompletelyBookedOptionalKnowledge,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseMeanRatioOfIncompletelyBookedOptionalKnowledgeTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseRatioOfConsecutiveEqualLessons,
nTimeslotsPerDay <= smallestMinimumConsecutivePeriods
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseRatioOfConsecutiveEqualLessons,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseRatioOfConsecutiveEqualLessonsTag
)
), (
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseRatioOfSeparatedEqualLessonsWithinAnyDay,
nTimeslotsPerDay <= 2 * smallestMinimumConsecutivePeriods
), (
ExecutionConfiguration.TimetableCriteriaWeights.zeroWeightOfMinimiseRatioOfSeparatedEqualLessonsWithinAnyDay,
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseRatioOfSeparatedEqualLessonsWithinAnyDayTag
)
)
]
(evolutionStrategies, zeroedEvolutionStrategyFecundityTags) = Control.Monad.Writer.runWriter . foldr (
(
\(mutator, message) -> (
Control.Monad.Writer.tell [message] >>
) . fmap mutator
) . snd
) (
return $ ExecutionConfiguration.ExecutionOptions.getEvolutionStrategies executionOptions
) $ filter (
uncurry (&&) . Control.Arrow.first (
(/= ExecutionConfiguration.TimetableBreederFecundity.zero) . ($ ExecutionConfiguration.ExecutionOptions.getEvolutionStrategies executionOptions)
) . fst
) [
(
(
ExecutionConfiguration.EvolutionStrategies.getSynchronisedCourseMutationFecundity,
zeroNonCritical && not hasAnySynchronisedCourses
), (
ExecutionConfiguration.EvolutionStrategies.zeroSynchronisedCourseMutationFecundity,
ExecutionConfiguration.EvolutionStrategies.synchronisedCourseMutationTag
)
), (
(
ExecutionConfiguration.EvolutionStrategies.getSynchronisedCourseByDayMutationFecundity,
zeroNonCritical && not hasAnySynchronisedCourses
), (
ExecutionConfiguration.EvolutionStrategies.zeroSynchronisedCourseByDayMutationFecundity,
ExecutionConfiguration.EvolutionStrategies.synchronisedCourseByDayMutationTag
)
), (
(
ExecutionConfiguration.EvolutionStrategies.getExcessRunlengthMutationFecundity,
zeroNonCritical && nTimeslotsPerDay <= smallestMinimumConsecutivePeriods
), (
ExecutionConfiguration.EvolutionStrategies.zeroExcessRunlengthMutationFecundity,
ExecutionConfiguration.EvolutionStrategies.excessRunlengthMutationTag
)
), (
(
ExecutionConfiguration.EvolutionStrategies.getSingletonStudentClassMutationFecundity,
zeroNonCritical && not permitTemporaryStudentBodyMerger
), (
ExecutionConfiguration.EvolutionStrategies.zeroSingletonStudentClassMutationFecundity,
ExecutionConfiguration.EvolutionStrategies.singletonStudentClassMutationTag
)
), (
(
ExecutionConfiguration.EvolutionStrategies.getSplitSessionMutationFecundity,
zeroNonCritical && nTimeslotsPerDay <= 2 * smallestMinimumConsecutivePeriods
), (
ExecutionConfiguration.EvolutionStrategies.zeroSplitSessionMutationFecundity,
ExecutionConfiguration.EvolutionStrategies.splitSessionMutationTag
)
), (
(
ExecutionConfiguration.EvolutionStrategies.getStudentBodyCombinationMutationFecundity,
zeroNonCritical && not permitTemporaryStudentBodyMerger
), (
ExecutionConfiguration.EvolutionStrategies.zeroStudentBodyCombinationMutationFecundity,
ExecutionConfiguration.EvolutionStrategies.studentBodyCombinationMutationTag
)
)
]
instance (
Enum timeslotId,
Eq criterionWeight,
Num criterionWeight,
Ord campus,
Ord level,
Ord synchronisationId,
Ord teacherId,
Ord timeslotId,
RealFrac teachingRatio,
Show level,
Show synchronisationId,
Show teacherId,
Show timeslotId
) => Configuration.Configuration (Options campus criterionWeight fecundityDecayRatio level locationId minimumContrastRatio populationDiversityRatio stream synchronisationId teacherId teachingRatio timeslotId) where
issueWarnings inputOptions = Configuration.issueWarnings executionOptions ++ Configuration.issueWarnings problemParameters ++ [
message ++ ", but the weight assigned to the lesson-criterion " ++ show criterionTag ++ " is zero" | (criterionWeightAccessor, condition, message, criterionTag) <- [
(
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfGreatestSynchronisedCourseSetSize,
hasAnySynchronisedCourses,
"synchronised courses have been defined",
ExecutionConfiguration.LessonCriteriaWeights.weightOfGreatestSynchronisedCourseSetSizeTag
), (
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfIsSpecialistInTopic,
Aggregate.TeacherRegister.hasAnySpecialists teacherRegister,
"topic-specialists have been defined",
ExecutionConfiguration.LessonCriteriaWeights.weightOfIsSpecialistInTopicTag
), (
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMaximiseRelativeFacilityUtilisation,
hasAnyFacilities,
"facilities have been defined in various locations",
ExecutionConfiguration.LessonCriteriaWeights.weightOfMaximiseRelativeFacilityUtilisationTag
), (
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseWasteOfScarceFacilities,
hasAnyFacilities,
"facilities have been defined in various locations",
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseWasteOfScarceFacilitiesTag
), (
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseBookingAtAnotherCoursesSpecifiedTime,
hasAnyTimeslotRequests,
"time-slots have been requested by teachers",
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseBookingAtAnotherCoursesSpecifiedTimeTag
), (
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseDeviationFromTimeslotRequest,
hasAnyTimeslotRequests,
"time-slots have been requested by teachers",
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseDeviationFromTimeslotRequestTag
), (
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseInterCampusMigrationsOfStudents,
not isSingleCampus,
"locations have been partitioned into different campuses",
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseInterCampusMigrationsOfStudentsTag
), (
ExecutionConfiguration.LessonCriteriaWeights.getWeightOfMinimiseInterCampusMigrationsOfTeachers,
not isSingleCampus,
"locations have been partitioned into different campuses",
ExecutionConfiguration.LessonCriteriaWeights.weightOfMinimiseInterCampusMigrationsOfTeachersTag
)
],
criterionWeightAccessor lessonCriteriaWeights == minBound,
condition
] ++ [
message ++ ", but the weight assigned to the timetable-criterion " ++ show criterionTag ++ " is zero" | (criterionWeightAccessor, condition, message, criterionTag) <- [
(
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMaximiseSynchronisationOfSynchronisedCourses,
hasAnySynchronisedCourses,
"synchronised courses have been defined",
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMaximiseSynchronisationOfSynchronisedCoursesTag
), (
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseAverageAbsoluteDeviationFromIdealTimeslotRequest,
Aggregate.TeacherRegister.hasAnyIdealTimeslotRequests teacherRegister,
"ideal time-slots have been specified for courses",
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseAverageAbsoluteDeviationFromIdealTimeslotRequestTag
), (
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMaximiseComplianceWithFreePeriodPreferences,
ProblemConfiguration.ProblemParameters.hasAnyFreePeriodPreference problemParameters,
"free-period preferences have been expressed",
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMaximiseComplianceWithFreePeriodPreferencesTag
), (
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseMeanInterCampusMigrationsOfStudents,
not isSingleCampus,
"locations have been partitioned into different campuses",
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseMeanInterCampusMigrationsOfStudentsTag
), (
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseMeanInterCampusMigrationsOfTeachers,
not isSingleCampus,
"locations have been partitioned into different campuses",
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseMeanInterCampusMigrationsOfTeachersTag
), (
ExecutionConfiguration.TimetableCriteriaWeights.getWeightOfMinimiseMeanRatioOfIncompletelyBookedOptionalKnowledge,
Aggregate.StudentBodyRegister.hasAnyOptionalKnowledgeRequirements studentBodyRegister,
"student-bodies have specified optional knowledge-requirements",
ExecutionConfiguration.TimetableCriteriaWeights.weightOfMinimiseMeanRatioOfIncompletelyBookedOptionalKnowledgeTag
)
],
criterionWeightAccessor timetableCriteriaWeights == minBound,
condition
] where
(executionOptions, problemParameters) = getExecutionOptions &&& getProblemParameters $ inputOptions
(lessonCriteriaWeights, timetableCriteriaWeights) = ExecutionConfiguration.ExecutionOptions.getLessonCriteriaWeights &&& ExecutionConfiguration.ExecutionOptions.getTimetableCriteriaWeights $ executionOptions
(studentBodyRegister, teacherRegister) = ProblemConfiguration.ProblemParameters.getStudentBodyRegister &&& ProblemConfiguration.ProblemParameters.getTeacherRegister $ problemParameters
locationCatalogue = ProblemConfiguration.ProblemParameters.getLocationCatalogue problemParameters
(hasAnyFacilities, isSingleCampus) = Aggregate.LocationCatalogue.hasAnyFacilities &&& Aggregate.LocationCatalogue.isSingleCampus $ locationCatalogue
(hasAnySynchronisedCourses, hasAnyTimeslotRequests) = Aggregate.TeacherRegister.hasAnySynchronisedCourses &&& Aggregate.TeacherRegister.hasAnyTimeslotRequests $ teacherRegister