Extract all elements of a set which have a certain attribute (are in relation with a certain value) - alloy

I am trying to write an Alloy function to retrieve all elements of a certain type that are in relation with the parameter of the function (let me say, that have that value for one of their "fields/attributes"). I have tried in various ways, none of them worked.
It's something like
fun get[a:A] : set X{
(x.name :> a)
}
but this return a set of A while I want a set of X

You can do this more simply:
name.a
returns the set of X's that map under name to an element in a.
Checking equivalence to your version:
sig A { }
sig X {
name: set A
}
fun get [a:A] : set X{
((X <: name) :> a).A
}
fun get' [a:A] : set X{
name.a
}
check {
all a: A | get[a] = get'[a]
}

This works, hope will be useful for someone:
fun get[a:A] : set X{
((X <: name) :> a).A
}

Related

How to update a Data attribute defined with Maybe

I'm playing with Haskell using https://hackage.haskell.org/package/cursor library. I have this data definition:
data TuidoState =
TuidoState { tuidoStateEntries :: Maybe (NonEmptyCursor Entry) }
And I have this function:
buildNewItem :: TuidoState -> TuidoState
buildNewItem s =
let nextID = 10 -- TODO update here to function to return ID
headerTitle = "Test new item"
newEntry = Entry { entryHeader= Header { headerTitle= headerTitle }
, entryBody= Just (Body { bodyTitle= headerTitle })
, entryTags= [Tag {tagName= headerTitle}]
}
actualEntries = (tuidoStateEntries s)
ne = NE.nonEmpty [newEntry]
in
case actualEntries of
Nothing ->
s { tuidoStateEntries = Just(makeNonEmptyCursor ne) }
Just value -> s { tuidoStateEntries = Just(value) } -- possible here I will want to just add the new Entry to the existing list
But, I cannot understand the error:
• Couldn't match expected type ‘NE.NonEmpty Entry’
with actual type ‘Maybe (NE.NonEmpty Entry)’
• In the first argument of ‘makeNonEmptyCursor’, namely ‘ne’
In the first argument of ‘Just’, namely ‘(makeNonEmptyCursor ne)’
In the ‘tuidoStateEntries’ field of a record
|
327 | s { tuidoStateEntries = Just(makeNonEmptyCursor ne) }
Could someone help me with it?
nonEmpty takes an arbitrary list, and so cannot guarantee it returns a non-empty list. Instead, it returns a Maybe (NonEmpty a) to indicate that it may either return a nonempty list or cause an error.
Consider using NonEmpty's constructor, (:|), directly instead.
ne = newEntry NE.:| []

Alloy Analyzer element comparision from set

Some background: my project is to make a compiler that compiles from a c-like language to Alloy. The input language, that has c-like syntax, must support contracts. For now, I am trying to implement if statements that support pre and post condition statements, similar to the following:
int x=2
if_preCondition(x>0)
if(x == 2){
x = x + 1
}
if_postCondtion(x>0)
The problem is that I am a bit confused with the results of Alloy.
sig Number{
arg1: Int,
}
fun addOneConditional (x : Int) : Number{
{ v : Number |
v.arg1 = ((x = 2 ) => x.add[1] else x)
}
}
assert conditionalSome {
all n: Number| (n.arg1 = 2 ) => (some field: addOneConditional[n.arg1] | { field.arg1 = n.arg1.add[1] })
}
assert conditionalAll {
all n: Number| (n.arg1 = 2 ) => (all field: addOneConditional[n.arg1] | { field.arg1 = n.arg1.add[1] })
}
check conditionalSome
check conditionalAll
In the above example, conditionalAll does not generate any Counterexample. However, conditionalSomegenerates Counterexamples. If I understand all and some quantifiers correctly then there is a mistake. Because from mathematical logic we have Ɐx expr(x) => ∃x expr(x) ( i.e. If expression expr(x) is true for all values of x then there exist a single x for which expr(x) is true)
The first thing is that you need to model your pre-, post- and operations. Functions are terrible for that because they cannot not return something that indicates failure. You, therefore, need to model the operation as a predicate. The value of a predicate indicates if the pre/post are satisfied, the arguments and return values can be modeled as parameters.
This is as far as I can understand your operation:
pred add[ x : Int, x' : Int ] {
x > 0 -- pre condition
x = 2 =>
x'=x.plus[1]
else
x'=x
x' > 0 -- post condition
}
Alloy has no writable variables (Electrum has) so you need to model the before and after state with a prime (') character.
We can now use this predicate to calculate the set of solutions to your problem:
fun solutions : set Int {
{ x' : Int | some x : Int | add[ x,x' ] }
}
We create a set with integers for which we have a result. The prime character is nothing special in Alloy, it is only a convention for the post-state. I am abusing it slightly here.
This is more than enough Alloy source to make mistakes so let's test this.
run { some solutions }
If you run this then you'll see in the Txt view:
skolem $solutions={1, 3, 4, 5, 6, 7}
This is as expected. The add operation only works for positive numbers. Check. If the input is 2, the result is 3. Ergo, 2 can never be a solution. Check.
I admit, I am slight confused by what you're doing in your asserts. I've tried to replicate them faithfully, although I've removed unnecessary things, at least I think we're unnecessary. First your some case. Your code was doing an all but then selecting on 2. So removed the outer quantification and hardcoded 2.
check somen {
some x' : solutions | 2.plus[1] = x'
}
This indeed does not give us any counterexample. Since solutions was {1, 3, 4, 5, 6, 7}, 2+1=3 is in the set, i.e. the some condition is satisfied.
check alln {
all x' : solutions | 2.plus[1] = x'
}
However, not all solutions have 3 as the answer. If you check this, I get the following counter-example:
skolem $alln_x'={7}
skolem $solutions={1, 3, 4, 5, 6, 7}
Conclusion. Daniel Jackson advises not to learn Alloy with Ints. Looking at your Number class you took him literally: you still base your problem on Ints. What he meant is not use Int, don't hide them under the carpet in a field. I understand where Daniel is coming from but Ints are very attractive since we're so familiar with them. However, if you use Ints, let them at least use their full glory and don't hide them.
Hope this helps.
And the whole model:
pred add[ x : Int, x' : Int ] {
x > 0 -- pre condition
x = 2 =>
x'=x.plus[1]
else
x'=x
x' > 0 -- post condition
}
fun solutions : set Int { { x' : Int | some x : Int | add[ x,x' ] } }
run { some solutions }
check somen { some x' : solutions | x' = 3 }
check alln { all x' : solutions | x' = 3 }

Nested comprehension in Kotlin

Suppose I have the following nested for loop:
val test = mutableSetOf<Set<Int>>()
for (a in setA) {
for (b in setB) {
if (a.toString().slice(2..3) == b.toString().slice(0..1)) {
test.add(setOf(a,b))
}
}
}
In python, I could do a simple comprehension as
test = {[a,b] for a in setA for b in setB if a.str()[2:3] == b.str[0:1]}
I'm having a helluva time converting this to Kotlin syntax. I know for a single for loop with a conditional, I could use a filter and map to get the desired results (using the idiom: newSet = oldSet.filter{ conditional }.map { it }, but I cannot for the life of me figure out how to do the nesting this way.
This is what IDEA proposes:
for (a in setA)
setB
.filter { a.toString().slice(2..3) == it.toString().slice(0..1) }
.mapTo(test) { setOf(a, it) }
I do not think there is much to do about it. I think their is no native approach that is similar to the Python one, but it already actually is in terms of length very similar because only the functions and their names make it that long.
If we take a look a this hypothetical example:
for (a in setA) setB.f { a.t().s(2..3) == it.t().s(0..1) }.m(test) { setOf(a, it) }
It is not far from the Python example. The Python syntax is just very different.
(functions for that hypothesis)
fun <T> Iterable<T>.f(predicate: (T) -> Boolean) = filter(predicate)
fun String.s(range: IntRange) = slice(range)
fun <T, R, C : MutableCollection<in R>> Iterable<T>.m(destination: C, transform: (T) -> R) = mapTo(destination, transform)
fun Int.t() = toString()
If Kotlin doesn't have it, add it. Here is a cartesian product of the two sets as a sequence:
fun <F,S> Collection<F>.cartesian(other: Collection<S>): Sequence<Pair<F,S>> =
this.asSequence().map { f -> other.asSequence().map { s-> f to s } }.flatten()
Then use that in one of many ways:
// close to your original nested loop version:
setA.cartesian(setB).filter { (a,b) ->
a.toString().slice(2..3) == b.toString().slice(0..1)
}.forEach{ (a,b) -> test.add(setOf(a,b)) }
// or, add the pair instead of a set if that makes sense as alternative
setA.cartesian(setB).filter { (a,b) ->
a.toString().slice(2..3) == b.toString().slice(0..1)
}.forEach{ test2.add(it) }
// or, add the results of the full expression to the set at once
test.addAll(setA.cartesian(setB).filter { (a,b) ->
a.toString().slice(2..3) == b.toString().slice(0..1)
}.map { (a,b) -> setOf(a,b) } )
// or, the same as the last using a pair instead of 2 member set
test2.addAll(setA.cartesian(setB).filter { (a,b) ->
a.toString().slice(2..3) == b.toString().slice(0..1)
})
The above examples use these variables:
val test = mutableSetOf<Set<Int>>()
val test2 = mutableSetOf<Pair<Int,Int>>()
val setA = setOf<Int>()
val setB = setOf<Int>()

How do I use groovy's AS keyword

This may be a duplicate but "as" is an INCREDABLY hard keyword to google, even S.O. ignores "as" as part of query.
So I'm wondering how to implement a class that supports "as" reflexively. For an example class:
class X {
private val
public X(def v) {
val=v
}
public asType(Class c) {
if (c == Integer.class)
return val as Integer
if(c == String.class)
return val as String
}
}
This allows something like:
new X(3) as String
to work, but doesn't help with:
3 as X
I probably have to attach/modify the "asType" on String and Integer somehow, but I feel any changes like this should be confined to the "X" class... Can the X class either implement a method like:
X fromObject(object)
or somehow modify the String/Integer class from within X. This seems tough since it won't execute any code in X until X is actually used... what if my first usage of X is "3 as X", will X get a chance to override Integer's asType before Groovy tries to call is?
As you say, it's not going to be easy to change the asType method for Integer to accept X as a new type of transformation (especially without destroying the existing functionality).
The best I can think of is to do:
Integer.metaClass.toX = { -> new X( delegate ) }
And then you can call:
3.toX()
I can't think how 3 as X could be done -- as you say, the other way; new X('3') as Integer is relatively easy.
Actually, you can do this:
// Get a handle on the old `asType` method for Integer
def oldAsType = Integer.metaClass.getMetaMethod( "asType", [Class] as Class[] )
// Then write our own
Integer.metaClass.asType = { Class c ->
if( c == X ) {
new X( delegate )
}
else {
// if it's not an X, call the original
oldAsType.invoke( delegate, c )
}
}
3 as X
This keeps the functionality out of the Integer type, and minimizes scope of the effect (which is good or bad depending on what you're looking for).
This category will apply asType from the Integer side.
class IntegerCategory {
static Object asType(Integer inty, Class c) {
if(c == X) return new X(inty)
else return inty.asType(c)
}
}
use (IntegerCategory) {
(3 as X) instanceof X
}

Dotted strings to properties

I've got a hash of strings similar to this:
Map map = ['a.b.c': 'Hi']
... that I need to use in gradle to expand an expression like this:
This is a greeting: ${a.b.c}
If I use the gradle copy task with expand I will get an error message 'No such property: a'.
Is there any way to get gradle/groovy to convert that map into the properties I need to resolve?
I couldn't find a built-in answer, but it here is a complete, self-contained method that can be used as a meta method on Map to do what you want:
Map map = ['a.b.c': 'Hi', 'a.b.d': 'Yo', 'f.g.h': 'Howdy']
Map.metaClass.expandKeys = { separator = '.' ->
def mergeMaps = { a, b ->
b.each{ k, v ->
if(a[k] && (v instanceof Map)) {
mergeMaps(a[k], v)
} else {
a[k] = v
}
}
a
}
delegate.inject([:]){ result, k, v ->
mergeMaps(result, k.tokenize(separator).reverse().inject(v){last, subkey -> [(subkey):last] })
}
}
assert map.expandKeys() == [a:[b:[c:"Hi", d:"Yo"]], f:[g:[h:"Howdy"]]]
It also allows for different separators than ., just pass the separator into the expandKeys method
If you want to use it like a normal function, then you can do this instead:
Map map = ['a.b.c': 'Hi', 'a.b.d': 'Yo', 'f.g.h': 'Howdy']
def expandKeys = { Map input, separator = '.' ->
def mergeMaps = { a, b ->
b.each{ k, v ->
if(a[k] && (v instanceof Map)) {
mergeMaps(a[k], v)
} else {
a[k] = v
}
}
a
}
input.inject([:]){ result, k, v ->
mergeMaps(result, k.tokenize(separator).reverse().inject(v){last, subkey -> [(subkey):last] })
}
}
assert expandKeys(map) == [a:[b:[c:"Hi", d:"Yo"]], f:[g:[h:"Howdy"]]]
The main trick, besides merging the maps, is to split then reverse each key. Then the final hierarchy can be built up backwards. Also, there may be a better way to handle the merge, because I don't like the hanging a at the end.
I don't know anything about Gradle but maybe this will help....
If you have a Map
Map map = ['a.b.c': 'Hi']
Then you can't retrieve the value 'Hi' using
map.a.b.c
Instead, you must use:
map.'a.b.c'
or
map['a.b.c']
I'm not exactly sure what your needs are, but if you just need to replace property-like tokens and don't need the full power of Groovy templates, the filter() method in combination with Ant's ReplaceTokens class is a safer (and faster) bet than expand(). See Filtering files in the Gradle User Guide.

Resources