En guide til OptaPlanner

1. Introduksjon til OptaPlanner

I denne veiledningen ser vi på en Java constraint tilfredshetsløser som heter OptaPlanner.

OptaPlanner løser planleggingsproblemer ved hjelp av en rekke algoritmer med minimalt oppsett.

Selv om en forståelse av algoritmene kan gi nyttige detaljer, med rammen som utfører det harde arbeidet for oss.

2. Maven avhengighet

Først legger vi til en Maven-avhengighet for OptaPlanner:

 org.optaplanner optaplanner-core 7.9.0.Final 

Vi finner den nyeste versjonen av OptaPlanner fra Maven Central repository.

3. Problem / løsningsklasse

For å løse et problem trenger vi absolutt en spesifikk som et eksempel.

Forelesningsplanlegging er et passende eksempel på grunn av vanskeligheter med å balansere ressurser som rom, tid og lærere.

3.1. Kursplan

Kursplan inneholder en kombinasjon av våre problemvariabler og planleggingsenheter, derfor er det løsningsklassen. Som et resultat bruker vi flere kommentarer for å konfigurere den.

La oss se nærmere på hver for seg:

@PlanningSolution offentlig klasse CourseSchedule {private List roomList; private Liste periodeListe; privat List lectureList; privat HardSoftScore-poengsum;

De PlanningLøsning kommentar forteller OptaPlanner at denne klassen inneholder dataene for å omfatte en løsning.

OptaPlanner forventer disse minimumskomponentene: planleggingsenheten, problemfakta og en poengsum.

3.2. Foredrag

Foredrag, en POJO, ser ut som:

@PlanningEntity offentlig klasse Forelesning {public Integer roomNumber; offentlig helhetsperiode; offentlig String lærer; @PlanningVariable (valueRangeProviderRefs = {"availablePeriods"}) offentlig Heltall getPeriod () {returperiode; } @PlanningVariable (valueRangeProviderRefs = {"availableRooms"}) offentlig Heltall getRoomNumber () {return roomNumber; }}

Vi bruker Foredrag klasse som planleggingsenheten, så vi legger til en ny kommentar på getter i Kursplan:

@PlanningEntityCollectionProperty public List getLectureList () {return lectureList; }

Planleggingsenheten vår inneholder begrensningene som blir satt.

De PlanleggingVariabel kommentar og valueRangeProviderRef merknader knytter begrensningene til faktafakta.

Disse begrensningsverdiene blir scoret senere på tvers av alle planleggingsenheter.

3.3. Problem fakta

De romnummer og periode variabler fungerer som begrensninger på samme måte som hverandre.

OptaPlanner skårer løsningene som et resultat av logikk ved hjelp av disse variablene. Vi legger til kommentarer til begge getter metoder:

@ValueRangeProvider (id = "availableRooms") @ProblemFactCollectionProperty public List getRoomList () {return roomList; } @ValueRangeProvider (id = "availablePeriods") @ProblemFactCollectionProperty public List getPeriodList () {return periodList; } 

Disse listene er alle mulige verdier som brukes i Foredrag Enger.

OptaPlanner fyller dem i alle løsninger på tvers av søkeområdet.

Til slutt setter den en poengsum for hver av løsningene, så vi trenger et felt for å lagre poengsummen:

@PlanningScore offentlig HardSoftScore getScore () {retur score; }

Uten poengsum kan OptaPlanner ikke finne den optimale løsningen derav den viktige viktigheten tidligere.

4. Scoring

I motsetning til det vi har sett på så langt, krever poengklassen mer tilpasset kode.

Dette er fordi poengkalkulatoren er spesifikk for problemet og domenemodellen.

4.1. Egendefinert Java

Vi bruker en enkel poengsumberegning for å løse dette problemet (selv om det kanskje ikke virker som det):

offentlig klasse ScoreCalculator implementerer EasyScoreCalculator {@ Override offentlig score beregneScore (CourseSchedule courseSchedule) {int hardScore = 0; int softScore = 0; Sett okkuperte rom = nye HashSet (); for (Lecture lecture: courseSchedule.getLectureList ()) {String roomInUse = lecture.getPeriod () .toString () + ":" + lecture.getRoomNumber (). toString (); hvis (okkupertRom.contains (roomInUse)) {hardScore + = -1; } annet {okkupertRom.add (roomInUse); }} returner HardSoftScore.valueOf (hardScore, softScore); }}

Hvis vi ser nærmere på ovennevnte kode, blir de viktige delene tydeligere. Vi beregner en poengsum i løkken fordi Liste inneholder spesifikke ikke-unike kombinasjoner av rom og perioder.

De HashSet brukes til å lagre en unik nøkkel (streng) slik at vi kan straffe dupliserte forelesninger i samme rom og periode.

Som et resultat mottar vi unike sett med rom og perioder.

4.2. Drools

Drools-filer gir oss en rask måte å endre regler for bruk på filer. Mens syntaksen noen ganger kan være forvirrende, kan Drools-filen være en måte å håndtere logikk utenfor de kompilerte klassene.

Vår regel for å forhindre nulloppføringer ser slik ut:

global HardSoftScoreHolder scoreHolder; regel "noNullRoomPeriod" når forelesning (roomNumber == null); Forelesning (periode == null); deretter scoreHolder.addHardConstraintMatch (kcontext, -1); slutt

5. Løserkonfigurasjon

En annen nødvendig konfigurasjonsfil, vi trenger en XML-fil for å konfigurere løseren.

5.1. XML-konfigurasjonsfil

    org.baeldung.optaplanner.ScoreCalculator 10 

På grunn av kommentarene våre i Kursplan klasse bruker vi scanAnnotatedClasses elementet her for å skanne filer på klassestien.

De scoreDirectorFactory elementinnhold setter vår ScoreCalculator klasse for å inneholde poenglogikken vår.

Når vi vil bruke en Drools-fil, erstatter vi elementets innhold med:

kursScheduleScoreRules.drl

Vår endelige innstilling er avslutningselementet. I stedet for å søke uendelig etter en optimalisert løsning som kanskje aldri eksisterer, vil denne innstillingen stoppe søket etter en tidsbegrensning.

Ti sekunder er mer enn nok for de fleste problemer.

6. Testing

Vi konfigurerte løsnings-, løsnings- og problemklasser. La oss teste det!

6.1. Sette opp testen vår

Først gjør vi litt oppsett:

SolverFactory solverFactory = SolverFactory .createFromXmlResource ("courseScheduleSolverConfiguration.xml"); solver = solverFactory.buildSolver (); unsolvedCourseSchedule = ny CourseSchedule ();

For det andre fyller vi ut data i planleggingsenhetssamlingen og problemfakta Liste gjenstander.

6.2. Testutførelse og verifisering

Til slutt tester vi det ved å ringe løse.

CourseSchedule solvedCourseSchedule = solver.solve (unsolvedCourseSchedule); assertNotNull (solvedCourseSchedule.getScore ()); assertEquals (-4, solvedCourseSchedule.getScore (). getHardScore ());

Vi sjekker at solvedCourseSchedule har en poengsum som forteller oss at vi har den “optimale” løsningen.

For en bonus lager vi en utskriftsmetode som viser vår optimaliserte løsning:

public void printCourseSchedule () {lectureList.stream () .map (c -> "Lecture in Room" + c.getRoomNumber (). toString () + "under Period" + c.getPeriod (). toString ()) .forEach (k -> logger.info (k)); }

Denne metoden viser:

Forelesning i rom 1 i periode 1 Foredrag i rom 2 i periode 1 Forelesning i rom 1 i periode 2 Forelesning i rom 2 i periode 2 Forelesning i rom 1 i periode 3 Forelesning i rom 2 i periode 3 Foredrag i rom 1 i periode 1 Forelesning i rom 1 i periode 1 Forelesning i rom 1 i periode 1 Foredrag i rom 1 i periode 1

Legg merke til hvordan de tre siste oppføringene gjentas. Dette skjer fordi det ikke er noen optimal løsning på problemet vårt. Vi valgte tre perioder, to klasserom og ti forelesninger.

Det er bare seks mulige forelesninger på grunn av disse faste ressursene. I det minste viser dette svaret brukeren at det ikke er nok rom eller perioder til å inneholde alle forelesningene.

7. Ekstra funksjoner

Eksemplet vårt for OptaPlanner vi opprettet var enkelt, men rammeverket har lagt til funksjoner for mer varierte brukssaker. Det kan være lurt å implementere eller endre algoritmen vår for optimalisering og deretter spesifisere rammeverket for å bruke den.

På grunn av nylige forbedringer i Java's multi-threading-muligheter, gir OptaPlanner også utviklere muligheten til å bruke flere implementeringer av multi-threading som gaffel og join, inkrementell løsning og multitenancy.

Se dokumentasjonen for mer informasjon.

8. Konklusjon

OptaPlanner-rammeverket gir utviklere et kraftig verktøy for å løse problemer med tilfredshet med begrensninger som planlegging og ressurstildeling.

OptaPlanner tilbyr minimal bruk av JVM-ressurser samt integrering med Jakarta EE. Forfatteren fortsetter å støtte rammeverket, og Red Hat har lagt det til som en del av sin Business Rules Management Suite.

Som alltid kan koden finnes på Github.


$config[zx-auto] not found$config[zx-overlay] not found