consistency check with contradictory facts in Alloy - alloy

I do not understand how facts in Alloy work. In this small example there is two contradictory facts, but the predicate testWithoutParameters finds an instance (not expected) unlike the predicate testWithParameters that do not (expected). Both asserts not find counterexamples when they should do it. Where is the error in my interpretation? Deputy code and the output of execution.
sig A{
aset: set B
}
sig B{
bset: set B
}
fact Rule_1{
all a: A |
#a.aset < 3
}
fact Rule_2{
all a: A |
#a.aset > 3
}
pred testWithoutParameters[]{
all a:A |
#a.aset = 3
}
pred testWithParameters[a:A, b:B]{
#a.aset = 3
}
assert test_aset{
all a:A |
{
#a.aset = 3
}
}
assert testWithoutSense{
all a: A |
#a.aset > 3 and #a.aset < 3
}
run testWithParameters for 10
run testWithoutParameters for 10
check test_aset for 10
check testWithoutSense for 10
Executing "Run testWithParameters for 10"
Solver=sat4j Bitwidth=0 MaxSeq=0 SkolemDepth=1 Symmetry=20
2910 vars. 240 primary vars. 6294 clauses. 14ms.
No instance found. Predicate may be inconsistent. 3ms.
Executing "Run testWithoutParameters for 10"
Solver=sat4j Bitwidth=0 MaxSeq=0 SkolemDepth=1 Symmetry=20
2602 vars. 220 primary vars. 5499 clauses. 14ms.
. found. Predicate is consistent. 21ms.
Executing "Check test_aset for 10"
Solver=sat4j Bitwidth=0 MaxSeq=0 SkolemDepth=1 Symmetry=20
2834 vars. 230 primary vars. 6162 clauses. 14ms.
No counterexample found. Assertion may be valid. 3ms.
Executing "Check testWithoutSense for 10"
Solver=sat4j Bitwidth=0 MaxSeq=0 SkolemDepth=1 Symmetry=20
2844 vars. 230 primary vars. 6191 clauses. 13ms.
No counterexample found. Assertion may be valid. 7ms.
4 commands were executed. The results are:
#1: No instance found. testWithParameters may be inconsistent.
#2: .testWithoutParameters is consistent.
#3: No counterexample found. test_aset may be valid.
#4: No counterexample found. testWithoutSense may be valid.

Take a look at the solutions to testWithoutParameters: the set A is always empty. Universally quantified formulas are always true for empty sets, so the contradictions do not matter.
testWithParameters on the other hand contains the implicit fact that there is at least one element in A: the parameter a. But there can be no a that fulfills the contradicting facts, so there is no solution for this predicate.
Edit: No counterexample for testWithoutSense is found for the same underlying reason. Because of the contradicting Facts Rule_1 and Rule_2, your model is always constrained to contain no elements in A. With an empty A, the assertion testWithoutSense is trivially true.

Related

show counterexample in Alloy

Maybe it is a silly question, but I am trying to use Allow for testing equivalence of FOL formulas. In the case of counter-models, is there any way to show them? For instance
sig Value {}
pred p [x: Value] {
// ...
}
assert bla {
(all x: Value | p [x]) iff (some x: Value | p [x])
}
// run p for 2 Value
check bla for 5 Value
It says
Executing "Check bla for 5 Value"
Solver=minisat(jni) Bitwidth=0 MaxSeq=0 SkolemDepth=1 Symmetry=20
16 vars. 5 primary vars. 15 clauses. 1ms.
Counterexample found. Assertion is invalid. 2ms.
But when I click in Counterexample, it opens a window with no instances.
I ran your model for you. There is an instance. Notice that it says "Due to your theme settings, every atom is hidden. Please click Theme and adjust your settings". This means that an instance is being shown, and that if it contains any atoms, they're not shown because of the theme that customizes the visualization. In this case, it's because unconnected integers are not shown in the default theme. You can see the instance either by viewing it in a different way (any of the other options -- Txt, Table, Tree), or by changing the theme.

Can I introspect a variable to directly discover what subset it was declared with?

Is there a way to introspect a variable to directly find out what subset it was declared with? Here I create a subset, but introspection points me to its base type:
> subset Prime of Int where .is-prime
(Prime)
> my Prime $x = 23
23
> $x.WHICH
Int|23
I know it has to store the information somewhere, because if I try to reassign a value that doesn't match the subset, it fails:
> $x = 24
Type check failed in assignment to $x; expected Prime but got Int (24)
in block <unit> at <unknown file> line 1
I tried searching through the code, but I quickly get down into files like container.c and perl6_ops.c where the C code makes my eyes glaze over. I thought that X::TypeCheck::Assignment might help (see core/Exception.pm), but it's not clear to me where the expected value comes from. (see also this commit)
I feel like I'm missing something obvious.
I can check that something matches a subset, but that doesn't tell me if it were declared with a particular subset:
> my Int $y = 43;
43
> $y ~~ Prime;
True
I'm using Rakudo Star 2017.01
Inspired by a Zoffix's use of subsets in a recent post.
The value that you stored in $x is an Int. It is acceptable to the container (which you typed to Prime) because Prime is a subtype of Int.
So what you're interested in, is not the value in the container, but the type of the container. To get at the container, Perl 6 has the .VAR method. And that has an .of method to get at the type:
$ 6 'subset Prime of Int where .is-prime; my Prime $x; dd $x.VAR.of'
Prime

run command behavior with limitation on number of signatures in alloy

The first code, couldn't find any instances at Alloy Analyzer 4.2, but the second one, finds well!
What is the differences? My expectation is that, # > 0 and # = 1 acts as the same, when I execute "run show for 1".
1:
sig Fruit {}
pred show() { #Fruit > 0}
run show for 1
2:
sig Fruit {}
pred show() { #Fruit = 1}
run show for 1
When you run a command you will see that the bitwidth (which determines the max Int for Alloy) is 0.
Executing "Run show for 1"
Solver=sat4j Bitwidth=0 MaxSeq=0 SkolemDepth=1 Symmetry=20
0 vars. 0 primary vars. 0 clauses. 2ms.
No instance found. Predicate may be inconsistent. 0ms.
You can change this by explicitly changing bitwidth:
sig Fruit {}
pred show() { #Fruit>0}
run show for 1 but 2 int
Executing "Run show for 1 but 2 int"
Solver=sat4j Bitwidth=2 MaxSeq=1 SkolemDepth=1 Symmetry=20
1 vars. 1 primary vars. 1 clauses. 3ms.
. found. Predicate is consistent. 3ms.
I think when you use '>' operator you will need bitwidth but when you use '=' it is not required.
Working with Int is really discouraged in Alloy.

Why does the Alloy analyzer fail to find a counter example to the following assertion?

Checking the following assertion produces no counter examples:
assert G4_3__10
{
all x : Int | (x = 1)
}
check G4_3__10
Produces the following output:
Executing "Check G4_3__10"
Solver=sat4j Bitwidth=0 MaxSeq=0 SkolemDepth=1 Symmetry=20
0 vars. 0 primary vars. 0 clauses. 4ms.
No counterexample found. Assertion may be valid. 0ms.
It does find a counter example when I add facts or signatures that
use Ints (for example, adding
fact { 0 in Int }
Can anyone explain the reason for this behavior?
As you do not enforce the set of Integer to be non-empty in your original model, the analysis will only consider instances with no Integers. Your assertion will thus always hold hence no counter-example will be found.
The fact added in your second attempt pushes Alloy to consider instances where 0 is in the set of Integers. Alloy, will implicitly associate the default bitwith of 4 to Int, so that instances considered now contain integers in the interval [-8,7]. In those instances counter examples will befound.
You could also explicitly specify the Integer bitwidth to be used in your check command (rather than using this dummy fact) to enforce the presence of integers, e.g: check G4_3__10 for 4 Int

Has this function an effect on toplevel?

I would like to know if this function has an effect on top-level symbols?
(defun test (gallon)
(setq cup '(D D D D))
(pop cup) )
If the answer is yes, which one?
And want to know how to fix this function to prevent this side effect?
Thank you for answering!
If you compile this function, you will get the warnings:
WARNING: in TEST : CUP is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
WARNING: in TEST : CUP is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
WARNING: in TEST : CUP is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
WARNING: in TEST : CUP is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
WARNING: in TEST : variable GALLON is not used.
Misspelled or missing IGNORE declaration?
this tells you that you are not binding cup and not using gallon.
What is happening is that you are creating (and modifying) a global variable cup.
To avoid it, you should bind it locally:
(defun test1 (gallon)
(let ((cup '(D D D D)))
(pop cup)))
note that you are still ignoring the gallon argument.
To see the difference, observe
cup
==> undefined variable error
(test)
==> D
cup
==> (D D D)
(setq cup 10)
==> 10
(test1)
==> D
cup
==> 10
i.e., my test1 does not modify the global binding.

Resources