Time table Generation using Genetic Algorithms in java - java

I am trying to seek a solution for timetable generation using Genetic Algorithms(GA).
In my scenario i view a timetable of 6 days. Monday to Saturday.
Each day is divided into number of lectures/Time slots.(maximum no. of lectures are 6 in a day/Each time slot if 1 hr so that means 6 hours for a day)
I have tried to represent a Class consisting of Teacher,Student Group(set), and a lecture.
I maintain a pool of possible teachers,possible subjects and possible student groups.
And i randomly assign them to these Class.
so a Class is collection of all these references.
so for each time slot we have the Class object representation in it.
similarly a day is made up of number of lectures Class object representation.
and so on with the week making up of 6 days.
A set of possible constraints that i have is:
1.A teacher can take only one lecture in one time slot
2.A teacher can take a set of subjects(finite)
3.A teacher can be unavailable on a certain day
4.A teacher can be unavailable on a certain timeslot
And other constraints as it may be included lately.
Can anyone give me a idea about how to represent these constraints or handle these constraints? and how to calculate the fitness scores depending on constraints?
EDIT : The implementation is here https://github.com/shridattz/dynamicTimeTable

UPDATE:
The code can be found here
github.com/shridattz/dynamicTimeTable
In my TimeTable Generation I have used A timetable object. This object consists of ClassRoom objects and the timetable schedule for each them also a fittness score for the timetable.
Fittness score corresponds to the number of clashes the timetable has with respect to the other schedules for various classes.
ClassRoom object consists of week objects.Week objects consist of Days. and Days consists of Timeslots. TimeSlot has a lecture in which a subject,student group attending the lecture and professor teaching the subject is associated
This way I have represented the timetable as a chromosome.
And further on talking about the constraints, I have used composite design pattern, which make it well extendable to add or remove as many constraints.
in each constraint class the condition as specified in my question is checked between two timetable objects.
If condition is satisfied i.e there is a clash is present then the score is incremented by one.
This way the timetable with the least Score is the Best we can get.

For this problem ther is no efficint solution. I think you got that too because you use genetic algorithms. I wrote some month ago a framework for genetic algorithm myself.
I think you missed: every class has a list of lessons per week and only one lesson can happen at a time. Now you can combine randomly teachers and classes for the timeslots.
In the fitnes function I'd give a huge plus if a class has all lessons to do a week. A big minus would be if teachers haven't simmilar load (teacher a has two lessons a week and teacher b 12 for example). This you might relativate if a teacher has to work just 20 hours a week (use %).
All in all it is not that trivial and you might look for an experienced co-worker or mentor to help you with this topic.
If you want more specific advises, please specify your question.

Related

Structuring java Class UMLs Correctly

can someone explain to me how would I correctly structure these classes I have made an attempt but am not sure if they are correct.
https://imgur.com/a/7inqMQ5 - UML
https://imgur.com/a/slb80uR - Dataset
A. List all crime types (by name) for which you have data.
B. For a given crime type and LSOA, display details of all crimes, for which you have data.
C. For a given LSOA, determine how many crimes are presently
“Under investigation”
“Investigation complete; no suspect identified” for a given month
D. Find the LSOA with the highest average total crime frequency
E. Find the LSOA with the highest average frequency of crimes under investigation.
F. For a given crime, find which LSOA has the most occurrences.
Your UML for the first class is great, although if all the strings for a property are repeated or from a certain list, I'd recommend looking into Enums
The second class is also along the right lines but I've made an example one: see this which you can add to/rename slightly to better fit your requirements.

Hungarian Algorithm- what to do when some 'jobs' are unavailable to certain workers?

In my program, there will be students (from multiple year groups/grades) submitting choices for activities running from Monday to Friday.
Each activity may be applicable to one, or multiple year groups. Each student has say 4 choices (1st, 2nd, 3rd and 4th) per day. This is being stored in each student object as int[][] studentCosts which will be studentCosts=new int[5][4].
I have finished my hungarian algorithm but I need to decide how to add all the students' choices to an int[][].
I will be executing the algorithm separately for each day, so I will need to collate all the students' choices for that particular day into an int[][] costsForThatDay.
My problem is with how some year groups may be offered certain activities which are not offered to others, for example, on Monday, Year 7 are offered Windsurfing on Monday, whereas Years 8 and 9 are offered Golf on Monday.
If I were to execute the algorithm by day would it be best to set the 'costs' for unavailable activities to something like Integer.MAX_VALUE to make sure there is absolutely no way it will ever be chosen? E.g. Make Golf 'cost' for year 7 students and Windsurfing 'cost' for year 8 and 9 students Integer.MAX_VALUE

PlanningEntities split across multiple collections

I am writing a staff scheduler for my office. There are at least two shifts per day (7 days a week) and I want the optimizer to make sure no one staff member works drastically more weekend shifts than another.
I have a simple working program that assigns one Staff to each Shift.
The program structure is as follows:
SchedulingSolution is the #PlanningSolution
SchedulingSolution contains a List<Shift> which is the #PlanningEntityCollectionProperty
Shift is the #PlanningEntity
Shift contains a Staff which is the #PlanningVariable
SchedulingSolution contains a #ValueRangeProvider which returns our staff roster as a List<Staff>.
This working solution schedules all staff equally but does not consider weekends and weekdays. To delineate weekdays from weekends, I have replaced the List<Shift> in SchedulingSolution with a List<Day>. Every Day contains its own List<Shift> representing the shifts that occur on that day. Now when I want to compute the number of weekends a staff member has worked, I can find all Day objects that represent weekends and count only the Shifts contained in those days.
Unfortunately, this places the List<Shift> which is the #PlanningEntityCollectionProperty in a class that is not a #PlanningSolution. The #PlanningEntityCollectionProperty annotation is now ignored and the program fails.
Have I missed an obvious way to restructure my program, or is my only option to keep my original program structure and modify my shift objects to record which day they occur on?
Thanks in advance. I'll try to pass the help forward if I can.
I would restructure your Planning Solution.
Why don't you do:
Keep the List<Shift> in the Planning Solution
Discard the List<Day> in every shift
Add a field day in Shift, possibly even an indicator whether that day is a weekend using an enum.
You can then easily calculate the number of weekend days worked by each staff with Drools as so:
(Absolutely untested!!!)
rule "balancedStaffWeekend"
when
$staff: Staff()
accumulate(
Shift(
staff == $staff
day == Day.WEEKEND);
$count: count()
);
)
then
scoreHolder.addSoftConstraintMatch(kcontext, -Math.pow(count, 2));
end
Penalising the solution by counts raised to the power of two balances the number of weekends.

UUID generated using two programming languages?

Will the UUID generated using two programming languages say 'Ruby' and 'Java' be unique?
Yep. UUID is a standard format - the formatting will be the same in any language that accurately implements a UUID function. As for the IDs themselves being unique? You have a much better chance of being struck by lightning while being attacked by a shark, after your second plane crash of the day, after winning the lottery a few times in a row, than generating two identical UUIDs. :)
Yes a UUID (universally unique identifier) will be unique.
From wikipedia:
only after generating 1 billion UUIDs every second for the next 100
years, the probability of creating just one duplicate would be about
50%. Or, to put it another way, the probability of one duplicate would
be about 50% if every person on earth owns 600 million UUIDs.

Querying for today, within a week, and within a month

I'm new. I'm writing an app for a laser tag place where we've got kids of many ages coming to shoot beams at each other. We're making a highscore screen that'll display the best scores of the day, of the week, and of the month. The idea is that people will feel proud being on the list, and there'll also be prizes once a month.
I'm getting stuck at the whole filtering by date thing.
I basically modified the classic guestbook example to the point where I can add scores and customer info, and sort them by score.
Key guestbookKey = KeyFactory.createKey("Guestbook", guestbookName);
String fornavn = req.getParameter("fornavn");
Integer score = Integer.parseInt(req.getParameter("score"));
String email = req.getParameter("email");
String tlf = req.getParameter("tlf");
Date date = new Date();
Entity highscore = new Entity("Greeting", guestbookKey);
highscore.setProperty("date", date);
highscore.setProperty("fornavn", fornavn);
highscore.setProperty("score", score);
highscore.setProperty("email", email);
highscore.setProperty("tlf", tlf);
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(highscore);
And in the jsp there's a query that grabs the overall top 5.
Query query = new Query("Highscore", highscoreKey).addSort("score", Query.SortDirection.DESCENDING);
List<Entity> greetings = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(5));
And there's a form that sends the user input to the .java. Any tips as far as how I should set up the dates? Saving week # and month # and querying based on that? Seems cumbersome.
From what I can tell, your "HighScore" kind is actually a "Score" kind that keeps track of all scores.
Instead of querying for the high score for the week/month, you're probably better off having a single HighScore entity (that's separate from normal "Score" entities) that you update whenever you enter a score. Every time a new score is entered, check if the high score should be updated.
You never need a fancy query, you just need to fetch the high score entity.
Or you might want a separate high score entity for each month/week etc so you can keep track of the history. In this case you may want to encode week or month into the entity key, so you can get the current week/month's HighScore easily.
There are 2 possible approaches for a requirement like yours where you want to show highscores for a day, week, month, etc:
1, First option is to use your current model where you are storing date and score. Since app engine allows inequality filter only on 1 property, you need to apply an inequality filter on date and then find the n highest number of scores. But since the result will be sorted first for the property with inequality filter and then for any additional property, you cannot do a fetch for only the first n entries to find the top n because the top scores need not be in continuous order. See this post to understand this better. So you will have to fetch all the scores for the date range and then do further sorting of the query result at your client to find the top n. This approach is ok if the total number of scores for a week or a month will not be too high compared to the value of n. If not, this is not a scalable option.
2, Second approach is to redesign your model such that sorting happens on scores so that for getting top n scores for a particular period, you need to fetch only the first n entries. This means the approach is suitable even if number of scores are very large. This then requires converting your date to be suitable for equality filtering like for each entry storing a month number, a week number and calendar year. Then for example if you want to find the top n scores in the 3rd month, then you can query for month=3, sort by scores descending and fetch the first n matching entries. Similarly you can query for a particular week using a week number.
This is very similar to another high-score SO question. I have copied/pasted my answer to it below. Approaching this solution using a database query may cause you to join the ranks of folks who complain about GAE. You will be using a custom index. Your query will likely average 10x miliseconds slower than needed per request. You will need to index thousands, perhaps millions of records. This costs you money -- perhaps lots of it both re: data storage (indices) and instances due to your high latency for what will likely be a highly-called handler function. Think different please. My copy/paste is not as specific to your setup, but it can be easily extended easily. I hope that it might prompt you to think about lower resource, lower cost alternative. As always...HTH. -stevep
Previous high score answer:
You may want to consider an alternate approach. This is a lot of index overhead which will cause your costs to be higher, the response time for the handler executing this function to operate an order of magnitude slower and you will have moments where the eventual consistency of index updates will affect maintenance of this data. If you have a busy site, you will surely not be happy with the latency and costs associated with this approach.
There are a number of alternate approaches. Your expected site transactions per second would affect which you choose. Here is a very simple alternative. Create an ndb entity with a TextProperty. Serialize the top scores entries using a string such as score_userid. Store them in the text field by joining them with a unique character. When a new score comes in, use get_by_id to retrieve this record (ndb automatically handles memcaching for you). Split it into an array. Split the last element of the array, and check against the new score. If it is less than the score, drop it, and append the new score_userid string to the array. Sort the array, join it, and put() the new TextProperty. If you want you could set up an end of the day cron to scan your scores for the day to check to see if your process was affected by the very small chance that two scores arrived at nearly the same time causing one to overwrite the other. HTH. -stevep
Previous SO high score answer link:
GAE datastore query with filter and sort using objectify

Categories

Resources