How to find second last value in Answer Set Programming (ASP Clingo) - answer-set-programming

I'm modelling a university curriculum timetable with Answer Set Programming (Clingo). The requirements are that each lesson must be asssigned to a specific week , day and start /end hours until the total hours are reached.
In a day there are max 8 hours and each lesson is 2 hours minimum. Also the scheduled lessons are until the 10th week.
week(1..10). time(9,11;11,13;14,16;16,18).
So first I generated each assigned lesson slot
TotalHours { assigned(Week,Day,Start,End,Course,Teacher) : day(Day), time(Start,End), week(Week) } TotalHours :-
lesson(Course,Teacher,TotalHours).
After that for other requirements and rules I needed to find the last course assigned in the timetable. I don't know if this is a good way but I was able to find a solution
MaxWeek = #max {Week : assigned(Week,_,_,_,Course,_)},
MaxDay = #max {Day : assigned(MaxWeek,Day,_,_,Course,_)},
MaxStart= #max {Start : assigned(MaxWeek,MaxDay,Start,_,Course,_)},
assigned(_,_,_,_,Course,_).
I'm new to ASP and so far I couldn't find a good way to find the second last lesson of the course assigned in the timetable(Week,Day,Start,End) needed for other schedule requirements.
So given for example
assigned(1,Monday,9,11,History,John) , assigned(1,Tuesday,11,13,Math,Smith), assigned(4,Tuesday,16,18,History,John),assigned(5,Monday,11,13,History,John)
I want to find the second last lesson of History which is
assigned(4,Tuesday,16,18)
Any tips or solutions is really appreciated

Consider having a second assigned predicate (with a different arity) to be something more absolute, like:
assigned((Week-1)*7*24+Day+Start,End,Course,Teacher) :- assigned(Week,Day,Start,End,Course,Teacher).
Now you just have one field that is completely ordered over all assignments, which is total hours since start of the year.
To find the last courses, the last aggregate performs very badly, and can be optimized using chaining constraints:
auxLastCourse(C,T) :- assigned(T,_,C,_).
auxLastCourse(C,T-1) :- auxLastCourse(C,T), T > 0.
lastCourse(C,T) :- auxLastCourse(C,T), not auxLastCourse(C,T+1).
Also note that in your example aren't any courses during the night, so this could be optimized further by not beeing so finegranular and explicitly representing every hour, but maybe only hours that actually occur in a possible schedule. THis would mean replacing the T-1 in the aux code with an explicit next relation over weeks and days and hours. Currently I'm just too lazy to add something like this.
For the second last course you can do exactly the same thing:
auxSecondLastCourse(C,T) :- assigned(T,_,C,_), not lastCourse(C,T).
auxSecondLastCourse(C,T-1) :- auxSecondLastCourse(C,T), T > 0.
secondLastCourse(C,T) :- auxSecondLastCourse(C,T), not auxSecondLastCourse(C,T+1).
PS: Note that I assume that your days are given as numbers 0..6, and not as words as in your example, I'm sure you will figure out how to translate them using another predicate.
PPS: I haven't tested the code, as you did'nt provide an MWE.

Related

Acumatica, creating a generic inquiry with a condition on a field equal to the previous day

I have created a simple generic inquiry that shows some data after joining two tables. I am now struggling to implement a condition that should make the result only contain rows where a date field is equal to yesterday date.
I am a bit annoyed as Acumatica has created the method `today()` neatly, but not a `yesterday()` or `tomorrow()`.
Does anyone have a good solution that they care to share?
Help is much appreciated,
Cheers.
P.s
I have made this very hackish solution that somewhat works, but breaks between change in month or year.
=CStr(Year(Today()))+CStr(Month( Today() ))+CStr( Day(Today())-1)
Okay, so I found the solution to my problem!
I read that Acumatica is coded C# and.NET which made me think of how adding dates is done there. You utilise the DateAdd(date, interval, number) under the time tab to create relative changes to date.
In this case, the date is the time source from where you want to change, interval is in which interval/dimension you wanna move, for example, 'd' is for days. You can find more prefixes here: crosspost. Lastly, number is how much you want to change in the interval, in my case -1.
TLDR; Use DateAdd(Today(), 'd', -1) to get the previous date in relation to the current date.
You can simply write Equals to #Today-1 for Yesterday like below:

How to get only the first 6 months action of all my records

I'm pretty new in Tableau. I have looked at the forum already and the answered suggested. But I'm not quite sure it match my question.
I have a bunch of records. This is about registration for a sport lesson depending on time. All of them have a start date and and some of them a finish date. The other never finish (They continue until date T with T = now).
My goal is to compare only the first 6 months of all my records, I think there are 50 of them, like the evolution during this period of time. So, for some the start date would be in January 2009, for some other, it would be in May 2016, etc.
As field provided, I have the start date and the number of person that have subscribed those lesson through time.
So, do you if there is any to achieve this goal? Is there enough detail for you to understand what I am saying ?
Thx to you guys !!
EDIT
You can find enclosed a screenshot of the result that I already have.
number of registration for all lesson through time
I'm not sure to be clear, what I try to do is to compare the first 6 months only of each courses. So the evolution of the first 6 months of this course compare to the evolution of the first 6 months of this other course and so on :)
If I understand your question correctly you are wanting to show only the first six months of your data but you want this by each category.
I am assumuming that by definition this means 6 months from the first record in your data for each category.
In order to achieve this I would create a true/false flag using a level of detail expression. As you are new to tableau I would suggest you do some reading on this but basically you can force a calculation to be at a certain level of the data rather than at the row level. You use this to find the minimum date in the table and then use a date diff to return true if the actual date field is within 6 months of this.
Create a calculated field as follows:
[date] <= DATEADD('month', 6, { FIXED [category] :min([date])})
Then drag this onto your filters pane and select "TRUE". This should give you only the first six months of records for each category.
Let me know if you need anything else.

800xA, assigning and manipulating dates

I have a quick question regarding handling of dates and times in 800xA.
What I´m trying to do is to take the current date, add/subtract days and save the result to a new variable.
I´m currently using "Date_and_timetocalendarstruct", to split the current date down to "current year", "current month", "current week" and so on.
I want to work it like this :
for example : take the current date and subtract it by one (or any other number) and thus, generating a new date to store away for future use.
This particular scenario is in ABB,s 800xA systems and its configured against a AC 800M controller.
I have tried a couple of things so for, regarding applying arithmetic operations to dates, but without success.
I hope someone here could point me in the right direction.
Thanks in advance
I think what you missed is the time data type.
date_and_time is used for a Calendar type of Data while time is a time span, e.g. a number of days.
What I understand you want to calculate is (in ST, but works in FBD as well):
OutDate := sub( InDate, Days);
Where OutDate and InDate are of Type date_and_time and Days is time.
If you specify Days with Value 5d, you will get OutDate as 5 days before InDate.
In a similar way, you will get a time span (type time) as output when subtracting two date_and_time values!

Grouping Expert, Current date against start date

I am having trouble grouping certain results in a work in progress report that arranges by start date, I have grouped using fixed values before but because the dates keep moving I am unsure what to do.
The start date is WIP_Schedule.Start_Date
the groups I am trying to create are:
[Group1] Overdue = the current date has passed the start date.
[Group2] (Yet to be named) = the current date 2 week period prior to the start date
[Group3] To Do = the current date after the two week period prior to the start date.
I am after a works instruction on how to achieve this.
I know this isn't a lot of information, if you require any more please ask.
Thanks,
Daniel
This is a pretty straightforward requirement, so you should be able to figure it out by searching the web. However, I'll give you part of the answer and hopefully you can figure it out.
Start by creating a formula to figure out the status of the date.
If {WIP_Schedule.Start_Date} > current date then "Overdue"
Else......
Then you can group based on that formula. All you have to do is figure out the rest of the formula.

Set one date from another date

I am using Objective-C within X-code.
I am iterating through a dictionary which contains a date value as one of it's keys. All I want to do is get an array of all the distinct dates so I can use them in a table, as headers. I just plan on
iterating the dictionary and adding dates to a mutable array each time I encounter a new date.
I must set previous date to new date for comparisons to work and I am having a very difficult time figuring out how to set one date equal to another date.
This seems like it should be such a simple thing to do and I am trying to avoid converting the dates to strings first - but if that's what I have to do, then so be it.
Any help would be appreciated.
Thanks,
Gerry O.
If you know the time offset is same as GMT, you could do it by dividing the date's timestamp by 86400 seconds (or three more 0s in milliseconds) and comparing those. If a time offset is there, add or subtract by 3600 seconds per hour before you divide them. But then again, leap years and seconds would break that...
Most languages have libraries support extracting the year, date, month, etc. They take everything into account, usually.
In Objc, you can get a NSDateComponents from NSCalendar's components:fromDate: method. After this, you can call the components to see exactly what each component (I suggest year, month, day) is.
I think you want code to compare dates and You need two loops nested.... where in outer loops iterates with conditional inner loop... In inner loop you just check that previously you had the same date or not...
please go through the below post on same site...
How to compare two dates in Objective-C
hope you will get solution... else clarify your question....