How do I design a search operation in Z notation whereby the search function requires at least one details? - formal-methods

This is my Z schema for Appointment DB.
|--AppointmentDB----------------
|attendees : P Person /** those involved in the appointment **/
|
|/** a new TYPE object to store attendees, schedule and purpose **/
|appointments : P APPOINTMENT
|hasAppointment : Person <-> APPOINTMENT
|schedule : APPOINTMENT -> DateTime
|purpose : APPOINTMENT -> Report
|
|/** a forward relation compositions to relate attendees with purpose and schedule **/
|attendeePurpose : hasAppointment;purpose
|attendeeSchedule : hasAppointment;schedule
|-----------------------------
|attendees ⊆ dom(hasAppointment)
|attendees ⊆ dom(attendeePurpose)
|appointments ⊆ ran(hasAppointment)
|-----------------------------
I would like to create a search function that finds an appointment based on the name of the attendees.
I want the search function to return all the details of the appointment object.
How do I design it?
Here is my take :
|--FindAppointment---------------------------------------------------
|ΞAppointmentDB
|attendees? : Person
|appointmentAttendees! : P Person
|appointmentPurpose! : Report
|appointmentSchedule! : DateTime
|-----------------------------
|/** if name of any attendees is given, then it must exist in appointments' domain
|respectively before this function can run**/
|attendees? ∈ dom(attendees)
|
|/** return the set of attendees of the same APPOINTMENT using attendees? as input **/
|appointmentAttendees! = hasAppointment~(|{attendees?}|)
|
|/** Get the image of both forward relational compositions according to set of
|attendees?**/
|appointmentPurpose! = attendeePurpose(|{attendees?}|)
|appointmentSchedule! = attendeeSchedule(|{attendees?}|)
|----------------------------------------------------------------------

Have you type checked your specification?
Your declaration subject? : P Person states that subject? is a set of persons, but subject? : dom(attendees) implies that subject? is a single person.
If you want to have either none or one person given you could introduce a datatype analogous to the Maybe monad in functional programming languages (or null values in other programming languages):
MaybePerson ::= NoPerson | JustPerson <<Person>>
Then you can declare an input like
subject? : MaybePerson
Then I would to suggest to restrain the possible solutions for one input
subject? : ran(JustPerson) => schedule! : schedule(|{ JustPerson~ subject? }|)
If subject? is a set of persons you can achieve the same with:
subject? /= {} => schedule! : schedule(|subject?|)
And then just do the same for the other possible input. You can add also a condition that not both entries should be NoPerson resp. not both input sets should be empty.

Related

Optaplanner. School timetabling. Force first lession

I'm trying to add constraints to School timetabling example. For example: "all groups should have the first lesson".
I tried EasyScore and Streaming - no success. EasyScore cant finds a proper solution, shuffles lessons a lot. Streaming gave me an error: Undo for (Lesson(subj...)) does not exist
Code for Streaming:
from(Lesson::class.java)
.filter { it.timeslot != null }
.groupBy({ it.studentGroup }, { it.timeslot!!.day }, ConstraintCollectors.toList())
.filter { group, day, list ->
list.any { it.timeslot!!.number != 1 }
}
.penalize(
"Student must have first lesson",
HardSoftScore.ONE_HARD
) { group, day, list -> list.count { it.timeslot!!.number != 1 } },
Looks like I'm thinking the wrong direction.
https://github.com/Lewik/timetable
Any help will be greatly appreciated.
update: fixed == -> =!
As far as I understand it, I don't think you're enforcing what you intend to enforce. From what I make from your source code, you penalize every studentgroup's first lesson of the day.
What you should do to enforce the intended goal, is to penalize every studentgroup that does NOT have a timeslot with number == 1 but DOES have one (of the same day) where timeslot number != 1.
So something like :
join all Lesson.class instances with all Lesson.class instances where the first lesson's studentGroup equals the second lesson's studentGroup AND the first lesson's timeSlot's day equals the second lesson's timeSlot's day. You obtain a BiConstraintStream<Lesson, Lesson> this way...
from this, filter all Lesson.class instances where the first lesson's timeSlot's number is less than the second lesson's timeSlot number
then penalise the remaining where the first lesson's timeSlot number differs from 1. That equals penalising all of a studentGroup's days where they have some lesson that day without having any lesson that day during the first timeslot.
If I understood you correctly, that's what you wanted ?
I don't know the real source of the problem, but it's about hashCode. The exception was thrown because HashMap with Object key can't find by that Object.
Lesson class:
#Serializable
#NoArg
#PlanningEntity
data class Lesson(
val subject: String,
val teacher: String,
val studentGroup: String,
#PlanningVariable(valueRangeProviderRefs = ["timeslotRange"])
var timeslot: TimeSlot? = null,
#PlanningId
val id: String = UUID.randomUUID().toString(),
)
The implementation above will not work. It could be fixed if I remove data or add override fun hashCode() = Objects.hash(id). #PlanningId does not help here. Kotlin generates hashCode for data classes and seems it not working with optaplanner (or vise versa)
How about using .ifNotExists()?
First, convert student group from a String into a class and add #ProblemFactCollectionProperty List<StudentGroup> on your solution, then do
from(StudentGroup.class)
.ifNotExists(from(Lesson.class).filter(Lesson::isFirstTimeslot),
equals(this -> this, Lesson::getStudentGroup)
.penalize(...);

SPARQL Multi-Valued properties - Rendering Results

I am new to SPARQL, and graph database querying as a whole so please excuse any ignorance but I am trying to write a basic output using some data stored within Fueski and am struggling to understand the best practice for handling duplication of rows due to the cardinality that exist between the various concepts.
I will use a simple example to hopefully demonstrate my point.
Data Set
This is a representative sample of the types of data and relationships I am currently working with;
Data Set
Based on this structure I have produced the following triples (N-Triple format);
<http://www.test.com/ontologies/Author/JohnGrisham> <http://www.test.com/ontologies/property#firstName> "John" .
<http://www.test.com/ontologies/Author/JohnGrisham> <http://www.test.com/ontologies/property#lastName> "Grisham" .
<http://www.test.com/ontologies/Author/JohnGrisham> <http://www.test.com/ontologies/property#hasWritten> <http://www.test.com/ontologies/Book/TheClient> .
<http://www.test.com/ontologies/Author/JohnGrisham> <http://www.test.com/ontologies/property#hasWritten> <http://www.test.com/ontologies/Book/TheFirm> .
<http://www.test.com/ontologies/Book/TheFirm> <http://www.test.com/ontologies/property#name> "The Firm" .
<http://www.test.com/ontologies/Book/TheFirm> <http://www.test.com/ontologies/property#soldBy> <http://www.test.com/ontologies/Retailer/Foyles> .
<http://www.test.com/ontologies/Book/TheFirm> <http://www.test.com/ontologies/property#soldBy> <http://www.test.com/ontologies/Retailer/Waterstones> .
<http://www.test.com/ontologies/Book/TheClient> <http://www.test.com/ontologies/property#name> "The Client" .
<http://www.test.com/ontologies/Book/TheClient> <http://www.test.com/ontologies/property#soldBy> <http://www.test.com/ontologies/Retailer/Amazon> .
<http://www.test.com/ontologies/Book/TheClient> <http://www.test.com/ontologies/property#soldBy> <http://www.test.com/ontologies/Retailer/Waterstones> .
<http://www.test.com/ontologies/Retailer/Amazon> <http://www.test.com/ontologies/property#name> "Amazon" .
<http://www.test.com/ontologies/Retailer/Waterstones> <http://www.test.com/ontologies/property#name> "Waterstones" .
<http://www.test.com/ontologies/Retailer/Foyles> <http://www.test.com/ontologies/property#name> "Foyles" .
Render Output Format
Now what I am trying to do is render a page where all authors are displayed showing details of all the books and the retailers in which those individual books are sold. so something like this (suedo code);
for-each:Author
<h1>Author.firstName + Author.lastName</h1>
for-each:Author.Book
<h2>Book.Name</h2>
Sold By:
for-each:Book.Retailer
<h2>Retailer.name</h2>
SPARQL
For the rendering to work my thinking was I would need the author's First name and last name, then all book names they have and the various retailer names those books are sold through and therefore I came up with the following SPARQL;
PREFIX p: <http://www.test.com/ontologies/property#>
SELECT ?authorfirstname
?authorlastname
?bookname
?retailername
WHERE {
?author p:firstName ?authorfirstname;
p:lastName ?authorlastname;
p:hasWritten ?book .
OPTIONAL {
?book p:name ?bookname;
p:soldBy ?retailer .
?retailer p:name ?retailername .
}
}
This provides the following results;
Results Triple Table
Unfortunately due to the duplication of rows my basic rendering attempt cannot produce output as expected, in fact it's rendering a new "Author" section for every row returned from the query.
I guess what I'm trying to understand is how should this type of rendering should be done.
Is it the renderer that is supposed to regroup data back into the graph form it wants to travese (I honestly cannot see how this can be the case)
Is the SPARQL invalid - is there a way to do what I want in the SPARQL language itself?
Am I just doing something completely wrong?
AMENDMENT - More Detailed Analysis on GROUP_CONCAT
When reviewing the options available to me I came across GROUP_CONCAT but after a bit of playing with it decided it probably wasn't the option that was going to give me what I wanted and probably wasn't the best route. The reasons for this are;
Data Size
Whilst the data set I am running my examples over in this post is small only spanning 3 concepts and a very restricted data set the actual concepts and data I am running against in the real world is far far larger where concatenating results will produce extremely long delimitered strings, especially for free format columns such as descriptions.
Loss of context
Whilst trying out group_concat I quickly realised that I couldn't understand the context of how the various data elements across the group_concat columns related.. I can show that by using the book example above.
SPARQL
PREFIX p: <http://www.test.com/ontologies/property#>
select ?authorfirstname
?authorLastName
(group_concat(distinct ?bookname; separator = ";") as ?booknames)
(group_concat(distinct ?retailername; separator = ";") as ?retailernames)
where {
?author p:firstName ?authorfirstname;
p:lastName ?authorLastName;
p:hasWritten ?book .
OPTIONAL {
?book p:name ?bookname;
p:soldBy ?retailer .
?retailer p:name ?retailername .
}
}
group by ?authorfirstname ?authorLastName
This produced the following output;
firstname = "John"
lastname = "Grisham"
booknames = "The Client;The Firm"
retailernames = "Amazon;Waterstones;Foyles"
As you can see this has produced one result row but you can no longer work out how the various data elements relate. Which Retailers are for which Book?
Any help/guidance would be greatly appreciated.
Current Solution
Based on the recommended solution below I have used the concept of keys to bring the various data sets togehter however I have tweeked it slightly so that I am using a query per concept (E.g. author, book and retailer) and then used the keys to bring together the results in my renderer.
Author Results
firstname lastname books
--------------------------------------------------------------------------------
1 John Grisham ontologies/Book/TheClient|ontologies/Book/TheFirm
Book Results
id name retailers
-------------------------------------------------------------------------------------------------------
1 ontologies/Book/TheClient The Client ontologies/Retailer/WaterStones|ontologies/Retailer/Amazon
2 ontologies/Book/TheFirm The Firm ontologies/Retailer/WaterStones|ontologies/Retailer/Foyles
Retailer Results
id name
--------------------------------------------------
1 ontologies/Retailer/Amazon Amazon
2 ontologies/Retailer/Waterstones Waterstones
3 ontologies/Retailer/Foyles Foyles
What I then do in my renderer is use the ID's to pull results from the various result sets...
for-each author a : authors
output(a.firstname)
for-each book b : a.books.split("|")
book = books.get(b) // get the result for book b (e.g. Id to Foreign key)
output(book.name)
for-each retailer r : book.retailers.split("|")
retailer = retailers.get(r)
output(retailer.name)
So effectively you are stitching together what you want from the various different result sets and presenting it.
This seems to be working OK for the moment.
I find it easier to construct objects out of the SPARQL results in code rather than trying to form a query that returns only a single row per the relevant resource.
I would use the URI of the resources to identify which rows belong to which resource (author in this case), and then merge the result rows based on said URI.
For JS applications I use the code here to construct objects out of SPARQL results.
For complex values I use __ in the variable name to denote that an object should be constructed from the value. For example all values with variables prefixed with ?book__ would be turned into an object with the remainder of the variable's name as the name of the object's attribute, each object identified by ?book__id. So having values for ?book__id and ?book__name would result in an attribute book for the author, such that author.book = { id: '<book-uri>', name: 'book name'} (or a list of such objects if there are multiple books).
For example in this case I would use the following query:
PREFIX p: <http://www.test.com/ontologies/property#>
SELECT ?id ?firstName ?lastName ?book__id ?book__name
?book__retailer
WHERE {
?id p:firstName ?firstName;
p:lastName ?lastName;
p:hasWritten ?book__id .
OPTIONAL {
?book__id p:name ?book__name;
p:soldBy/p:name ?book__retailer .
}
}
And in the application code I would construct Author objects that look like this (JavaScript notation):
[{
id: '<http://www.test.com/ontologies/Author/JohnGrisham>',
firstName: 'John',
lastName: 'Grisham',
book: [
{
id: '<http://www.test.com/ontologies/Book/TheFirm>',
name: 'The Firm',
retailer: ['Amazon', 'Waterstones', 'Foyles']
},
{
id: '<http://www.test.com/ontologies/Book/TheClient>',
name: 'The Client',
retailer: ['Amazon', 'Waterstones', 'Foyles']
}
]
}]
This is a common problem that can strike any relational database, I suppose. As you say GROUP_CONCAT is useful in many situations, but does lose fidelity.
I worked out a solution you might find interesting. Let's assume you want to construct a view or result tree looping though authors, then for each author their books, then for each author the retailer.
SELECT DISTINCT ?authorname ?bookname ?retailername {
...
} ORDER BY ?authorname ?bookname ?retailername
That gives you results like this:
author book retailer
-----------------------------
1 author1 book1 retailer1
2 author1 book1 retailer2
3 author1 book2 retailer2
4 author2 book3 retailer2
5 author2 book3 retailer3
...
Because of the ordering it's possible to step through
get next result
currentauthor = author in result
print currentauthor
while author in next result = currentauthor:
get next result
currentbook = book in result
print currentauthor
while book in next result = currentbook:
get next result
print retailer in result

Model relationship with eloquent

I have the following table structure :
Artists
id
name
picture
Entry
id
dj_id
producer_id
dj_id and producer_id field in most cases won't be the same, but it might happen. So I've set both field to be foreign keys on the artists_id field.
So in my Entry model, I have this function :
public function dj()
{
return $this->hasOne('Artist', 'id', 'dj_id');
}
This doesn't really work. It keeps returning the artist with id "1" even if the dj_id equals "5". Code sample :
$test = Entry::find(1);
var_dump($test->dj_id); // shows 5
var_dump($test->dj->id); // shows 1
What am I doing wrong ?
Ok so I figured it out, I had to change my dj relation to
return $this->belongsTo('Artist', 'dj_id', 'id');

YII: Dropdownlist with relation

DB table:
Mcourse(Master course )-> contains Course Names
Lcourse(Linked
Course- courses belongs to a college) -> contains foreign key
Mcourse_Id. & college Id.
Nw the problem is
I want to display list of courses available in a college using dropdownlist.
So sql query is:
select Lcourse_Id, Mcourse_Name* from Lcourse inner join Mcourse on Lcourse_Mcourse_Id=Mcourse Id..
*Id & value pair for dropdownlist
I could do this usin createCommand..Its working pretty fine. But i cant do this usin Relations ..Help me.
Let's imagine for a minute that your Mcourse table is called courses and model for that table is called Courses, your Lcourse table is called courses_colleges and your colleges table is colleges and model for that table is Colleges
Now, You should have Courses model with relations:
public function relations() {
return array(
'colleges' => array(self::MANY_MANY, 'Colleges', 'courses_colleges(course_id, college_id)')
);
}
Your Colleges model should have similar relations:
public function relations() {
return array(
'courses' => array(self::MANY_MANY, 'Courses', 'courses_colleges(college_id, course_id)')
);
}
Now if you want to print out a dropdown with all courses available for a certain college. In your controller action method get the model of that college including its courses:
public function actionShow() {
$id = 1; // We set just some sample id. You could get it from request ofc.
$college = Colleges::model()->with('courses')->findByPk($id);
$this->render('show', array('college'=>$college));
}
Now in your view print out this:
echo CHtml::dropDownList('courses', '', CHtml::listData($college->courses, 'id', 'name'));
Where 'id' and 'name' are columns of your Courses model.
Something like that.
The error is in the listData() function in your view, specifically that you don't have a mc_Id in your Lcourse model.
As you haven't clarified the model that each of those relationships are assigned with, it's impossible to guess what you should substitute for 'mc_Id' in your view - check your Lcourse model to determine the proper column name.

Table based declarative reactive programming

Is there a programming language or package that supports table based reactive declarative programming in memory very similar to the SQL language and trigger facility?
For example, I could define PERSON and JOB tables as functions
name: PERSON -> STRING
female: PERSON -> BOOLEAN
mother: PERSON -> PEOPLE
father: PERSON -> PEOPLE
title: JOB -> STRING
company: JOB -> STRING
salary: JOB -> INTEGER
empoyee: JOB -> PERSON
Then I would like to calculate functions like:
childcount: PERSON -> INTEGER
childcount(P) = |{ Q in PERSON : father(Q) = P or mather(Q) = P }|
income: PERSON -> INTEGER
income(P) = SUM { salary(J) : J in JOB and empoyee(J) = P }
incomeperchild: PERSON -> INTEGER
incomeperchild(P) = income(P) / childcount(P)
parent: PERSON x PERSON -> BOOLEAN
person(P,Q) = (P = father(Q)) or (P = mother(Q))
error: PERSON -> BOOLEAN
error(P) = (female(P) and (exists Q in PERSON)(father(Q) = P))
or (not female(P) and (exists Q in PERSON)(mother(Q) = P))
or (exists Q in PERSON)(parent(P,Q) and error(Q))
So essentially I would like to have calculated columns in tables that are automatically updated whenever values in the tables change. Similar things could be expressed with SQL triggers, but I would like to have such functionality built into a language and executed in memory. The propagation of changes need to be optimized. Are there frameworks to do this?
The observer patter and reactive programming focuses on individual objects. But I do not want to maintain pointers and extra structure for each row in my tables as there could be million of rows. All the rules are generic (although they can refer to different rows via parent/children relations, etc), so some form of recursion is required.
One way to approach this is via attribute grammars: http://www.haskell.org/haskellwiki/Attribute_grammar