Alloy assert check - assert

I'm trying to write an assert statement to the effect that once a mark is entered for
any student then the student always has a mark for that course (although it's possible the
mark may change). I already know how to check if the student has the mark or not, but i don't know how to do it in case the student doesn't have any mark to begin with. Also, how can i write a check statement for this assert statement?
sig Student, Tutor, Mark {}
sig Course {
reg : set Student,
alloc : Student -> Tutor,
result : Student -> Mark
}
This is what i tried
assert chekmark
{all c:Course | let c' = CO/next[c] |
some Student.(c.Result) => some Student.(c.Result)}
check checkmark for 3
But somehow it says: This expression failed to be typechecked.
Am i right or wrong,and how can i fix it if i'm right?

The problem is that the ordering on Courses is not going to be a solution for your problem. Using the ordering module simply places a total order on all courses (so CO/next[c] just returns the course immediately following c in that order), whereas you probably want to have a sequence of marks for each (Course, Student) pair.
Maybe something like this
sig Student, Tutor, Mark {}
sig Course {
reg : set Student,
alloc : Student -> Tutor,
result : set Grade
}
sig Grade {
student: one Student,
marks: seq Mark
}
Using Alloy sequences automatically gives you the property you want, that is, if the marks field is non-empty, then it is going to contain a sequence of Marks so no nulls in the middle are possible.
With this model, you might want to add a fact that enforces at most one grade per student per course.
fact oneGradePerStudentPerCourse {
all c: Course {
all s: c.reg |
lone {g: c.result | g.student = s}
}
}

Related

Adding to list from hashmap key kotlin

I'm practicing leetcode problems to perfect my kotlin syntax and am wondering why this code doesn't work. My question specifically is why doesn't my courses hashmap populate with this code.
Prerequisites is an array in this form [[0,1][0,3][4,5][6,7]] and if I print my variables for pre and post they print what I expect
But I'm trying to turn courses into an adjacency matrix like this {0: [1,3], 4: [5], 6: [7]}
and instead it just prints an empty set every time
class Solution {
fun canFinish(numCourses: Int, prerequisites: Array<IntArray>): Boolean {
val courses = HashMap<Int, MutableList<Int>>().withDefault{ mutableListOf<Int>() }
for ((pre, post) in prerequisites){
courses[pre]?.add(post)
}
print(courses)
return false
}
}
stdout: {}
[] does not give you the default value
From the docs of withDefault:
This implicit default value is used when the original map doesn't contain a value for the key specified and a value is obtained with Map.getValue function
If you want to get the default value, you need to use getValue instead of the index operator.
Using the index operator, you would just get null and because of the the null-safe operator, the add operation would not even be executed.
If you take a look at the relevant source code, you can see that the funxtionality get is not changed when using .withDefault but only getOrImplicitDefault returns the default value.
Getting the default does not set anything
Furthermore, when accessing courses.getValue(pre) in the loop, the Map will be empty. Because of the withDefault, it will return a MutableList where you can add elements but getting such a list and adding elements to it will not add the list to the Map. Reading and accessing an element does not insert it.
Simple solution
If you want to make sure the element is present in the Map, you can use courses[pre]=course.getValue(pre) before reading courses[pre]?:
class Solution {
fun canFinish(numCourses: Int, prerequisites: Array<IntArray>): Boolean {
val courses = HashMap<Int, MutableList<Int>>().withDefault{ mutableListOf<Int>() }
for ((pre, post) in prerequisites){
courses[pre] = courses.getValue(pre)
courses[pre]?.add(post)
}
print(courses)
return false
}
}
If the entry is set already, it will be set to itself (no change) and if it isn't set, it will be set to the default value (empty list).
dan1st's answer covers it - your default list is just returned, not put and returned, so it's not part of the map - but here's a different take to get that functionality:
val courses = HashMap<Int, MutableList<Int>>().run {
withDefault{ key ->
mutableListOf<Int>().also { put(key, it) }
}
}
So basically using the withDefault wrapper, using run so the map is this in the default value function, so you can add your list to the map before returning it. Then when you call courses.getValue(69) you'll get back a list that's already been inserted into the map
If you like, there's also a function that'll do this grouping for you, groupBy
val nums = arrayOf(
intArrayOf(0,1),
intArrayOf(0,3),
intArrayOf(4,5),
intArrayOf(6,7)
)
val groups = nums.groupBy(keySelector = { it[0] }, valueTransform = { it[1] })
println(groups)
>> {0=[1, 3], 4=[5], 6=[7]}

Find first over several streams of different collection Types

public class ImmutableCrazySquares {
private final List<Square> xraySquare;
private final Map<String, Set<Square>> yankeSquare
private final Map<String, Set<Square>> zuloSquare;
.
.
.
#VisibleForTesting
private boolean exists(String squareId) {
boolean matches = yankeSquare.values().stream().anyMatch(squares ->
squares.stream().anyMatch(square -> square.getId().equals(squareId)));
if (!matches) {
matches = xraySquare.stream()
.anyMatch(square -> square.getId().equals(squareId));
}
if (!matches) {
matches = zuloSquare.values().stream().anyMatch(squares ->
squares.stream().anyMatch(square -> square.getId().equals(squareId)));
}
return matches;
}
}
The above class has a dozen methods but right now I just want to focus on this exists methods.
In essence I want to look at the 3 collections xraySquare, yankeSquare, zuloSquare and if the id I sent is in any of them I want to return true.
Sadly the Key on both the Maps are not the Id and therefore cannot be used for this action. To get the Id I need to drill in the values and call getId(). Since this is a method for tests I do not want to pollute the class with an adicional collection with all ids that exist.
Is there an easy way to concurrently look at all 3 collections and stop as soon as 1 finds the result?
concurrently might turn out to be slower than sequentially, so your code IMO is just fine. It can be slightly improved:
return
yankeSquare.values()
.stream()
.flatMap(Set::stream)
.map(Square::getId)
.anyMatch(Predicate.isEqual(squareId)) ||
xraySquare.stream()
.map(Square::getId)
.anyMatch(Predicate.isEqual(squareId)) ||
zuluSquare.values()
.stream()
.flatMap(Set::stream)
.map(Square::getId)
.anyMatch(Predicate.isEqual(squareId))
Or even simpler, but not as lazy as you have it in your code:
Stream.concat(xraySquare.stream(),
Stream.of(yankeSquare, zuloSquare)
.flatMap(map -> map.values().stream().flatMap(Set::stream))
.map(Square::getId)
.anyMatch(Predicate.isEqual(squareId))
)
Basically it flattens all your Collections to Stream<String> and check against that with anyMatch

Caching a processed message for the lifetime of a stream

I am redoing a previous question to make it more focused and clear.
I have the following situation:
case class Hello(u:String) extends A
case class Goodbye extends A
case class GoodbyeAck(u:String) extends B
val myProcessor: Flow[A, B, Unit] = Flow[A]
.map {
case Hello(u:String) => // I want to cache u (the username)
case Goodbye => GoodbyeAck(u)
}
So, at the beginning of the stream I get a Hello(username) and at the end of the stream, I receive a Goodbye. I want to reply with Goodbye(username).
How should I cache the username (u) so it will be available for the lifetime of the stream, so I can have it when it's time to say good bye? Is there some context I can leverage? Or do I need to do it outside the framework?
This seems like one of the few examples where mutable state is necessary. Though not "purely functional", the state can be isolated in such a way as to not allow outside influence but still provide the functionality you are looking for.
Note: your question does not specify what B value should be returned by the map in the case of receiving a Hello. A value of type B is necessary since simply caching is of type Unit. Therefore a flatMapConcat is used to conform to the requirements of the Flow in the question, which is to return nothing when a Hello is received:
def cacheProcessor(defaultString : String = "") : Flow[A, B, Unit] = {
var userCache : String = defaultString
Flow[A] flatMapConcat {
case Hello(u : String) => {
userCache = u
Source.empty[B]
}
case Goodbye => Source.single[B](GoodbyeAck(userCache))
}
}//end def cacheProcessor
Although userCache is mutable state it cannot be accessed outside of the returned Flow.flatMapConcat. One important point is that cacheProcessor has to be a def so that there is a unique userCache for each Flow.

Want to check if object is in groovy list using .contains() or 'in'

import groovy.transform.EqualsAndHashCode;
#EqualsAndHashCode(includes="name")
class Activity {
public String name
public buildings = []
public rooms = [] as Set
Activity(name) {
this.name = name
}
}
thisActivity=new Activity("activity")
activityRegistry = []
// is false correct
activityRegistry.contains(thisActivity)
// add new item activity2
activityRegistry << new Activity("activity2")
// is true?????
activityRegistry.contains(thisActivity)
this code is pretty straight forward, I create an activityRegistry list, I compare empty list to object I created. naturally test fails. I create a new object on the fly using new that I insert into the list. I compare the list then to the first object created, which is not part of the list, and contains, or in passes. could someone shed some light on how? or why?
The AST "EqualsAndHashCode" only use 'properties' from the class. Properties, in groovy, are declared without a modifier ('public'), and getter/setter are automatically generated.
In your example, change public String name to String name.
See : What are 'properties' in Groovy?

Insertion and deletion in linked lists in alloy

I had created a simple version of linked list using alloy . Now I want to create a linked list in which I could perform insertion and deletion. I have just begun coding in alloy. for now I am having trouble doing complex operations like using functions and utilities . If I could get some examples of how I could use utilities and functions as well as how I could actually perform insertion and deletion in alloy . I'd appreciate your help.
sig node{}
sig linked
{
ele:set node,
link:ele->lone ele,
head:lone ele
}{
node = ele
all x:ele | x in head.*link && head not in x.link && #x.link <=1
}
fact{
all l:linked| all e:l.ele| e->e not in l.link //no self loop
}
fact
{
all l:linked|no e : l.ele | (e in e.^(l.link )) //acyclic
}
pred a (l:linked,x:node)
{
x in l.ele
}
run a for 6 node,1 linked
Your approach is kind of confusing, it could be much simpler. I would do it like this
sig Node{
next : lone Node
}
one sig Head in Node {} -- head node is still a node
fact{
all n : Node | n not in n.^next -- no cycles
no next.Head -- no node points to Head
all n : Node - Head | some next.n -- for all other nodes, there has to be someone pointing to them
}
run {} for 10
This model is static, in order to make the model dynamic, you need to understand de concept of States. I recommend you'd read Software Abstractions, written by the author of Alloy. A dynamic approach for the linked list would be too complex for you to understand at this point, you should do some simpler exercise.
The basic idea of states is (exercise based on the address book example in the book):
static example:
sig State {}
abstract sig Target {}
sig Email extends Target {}
abstract sig Name extends Email {
name : set State,
addr : Target some -> State
}
sig Group, Alias extends Name {}
fact {
all a : Alias | lone a.addr
no n : Name | n in n.^addr
}
run {}
dynamic example, in the local state idiom (= a way to express the states, there is also a global state idiom and an event idiom). Take a look at the predicates
open util/ordering[State]
sig State {}
abstract sig Target {}
sig Email extends Target {}
abstract sig Name extends Email {
name : set State,
addr : Target -> State
}
sig Group, Alias extends Name {}
fact {
all s : State {
all a : Alias & name.s | lone a.addr.s
no n : name.s | n in n.^(addr.s)
addr.s in name.s -> Target
addr.s :> Name in Name -> name.s
}
}
run {} for 3 but exactly 1 State
-- adding a name n, for a given pre state s and post state s'
pred addName [n : Name, s,s' : State] {
-- the name must not exist in the pre state
n not in name.s
-- the relation names in the post state is what is was
-- in the pre state in addition to the new name
name.s' = name.s + n
-- the address relation stays the same
addr.s' = addr.s
}
run addName for 3 but 2 State
pred addTarget [n : Name, t : Target, s,s' : State] {
t not in n.addr.s
name.s' = name.s
addr.s' = addr.s + n->t
}
run addTarget for 3 but 2 State
You can also take a look at the following slides.
You don't need to make the model "dynamic" in order to model operations like insertion and deletion. Look at this topic (doubly-linked-list-in-alloy) where I gave an answer on how to model the reverse operation for a doubly-linked list, and then let us know if that wasn't helpful enough. The basic idea you'll see there is to create a predicate that takes arguments for both pre-state and post-state, and asserts how the two are related. For example, your insertion predicate could look like
// l - list in the pre-state
// x - node to be inserted
// l' - list in the post-state
pred insert (l: linked, x: node, l': linked) {
l'.ele = l.ele + x
...
}