I'm trying to see if I can get Alloy to return the largest possible answer for a particular set. So, in this example, I would like the answers x={}, x=A, and x=B to not be generated by the model finder.
abstract sig X{}
one sig A extends X{}
one sig B extends X{}
pred(x: set X) {
x in A + B
}
I have tried something along the lines of:
pred(x: set X) {
x in A + B and
no y : set X |
y in A + B and #(y) > #(x)
}
but I get an error that analysis is not possible since it requires higher-order quantification.
I was wondering if there is a possible (or simpler) way to do this?
Alloy does not currently have any built-in functionality to produce maximal or minimal solutions. And yes, you're right that specifying that a solution is maximal generally requires higher order quantification. However, you can ensure that the solution is at least locally maximal with a first order quantification:
pred p (x: set X) {...}
pred locally_maximal_p (x: set X) {
p(x)
no e: X - x | p(x + e)
}
Related
I'm learning Alloy and experimenting with creating predicates for relations being injective and surjective. I tried this in Alloy using the following model:
sig A {}
sig B {}
pred injective(r: A -> B) {
all disj a, a': r.B | no (a.r & a'.r)
}
pred inj {
no r: A -> B | injective[r]
}
run inj for 8
However, I get this error on no r:
Analysis cannot be performed since it requires higher-order
quantification that could not be skolemized.
I've read the portions of Software Abstractions about skolemization and some other SO questions but it's not clear to me what the issue is here. Can I fix this by rephrasing or have I hit a fundamental limitation?
EDIT:
After some experimenting the issue seems to be associated with the negation. Asking for some r: A -> B | injective[r] immediately produces an injective example. This makes conceptual sense as a generally harder problem, but they seem like more or less isomorphic questions in a small scope.
EDIT2:
I've found using the following model that Alloy gives me examples which also satisfy the commented predicate that gives me the error.
sig A {}
sig B {}
pred injective(r: A -> B) {
all disj a, a': r.B | no (a.r & a'.r)
}
pred surjective(r: A -> B) {
B = A.r
}
pred function(f: A -> B) {
all a: f.B | one a.f
}
pred inj {
some s: A -> B | function[s] && surjective[s]
// no r: A -> B | function[r] && injective[r]
}
run inj for 8
Think of it like this: every Alloy analysis involves model finding, in which the solution is a model (called an instance in Alloy) that maps names to relations. To show that no model exists at all for a formula, you can run it and if Alloy finds no solution, then there is no model (in that scope). So if you run
some s: A -> B | function[s] && surjective[s]
and you get no solution, you know there is no surjective function in that scope.
But if you ask Alloy to find a model such that no relation exists with respect to that model, that's a very different question, and requires a higher order analysis, because the solver can't just find a solution: it needs to show that there is no extension of that solution satisfying the negated constraint. Your initial example is like that.
So, yes, it's a fundamental limitation in the sense that higher order logic is fundamentally less tractable. But whether that's a limitation for you in practice is another matter. What analysis do you actually need?
One compelling use of higher order formulas is synthesis. A typical synthesis problem takes the form "find me a program structure P such that there is no counterexample to the specification S". This requires higher order analysis, and is the kind of problem that Alloy* was designed to solve.
But there's generally no reason to use Alloy* for standard verification/simulation problems.
The problem is to find a schedule for some people to play golf (or whatever) in groups of a fixed size.
We have to guarantee that every player is only in one group at a time.
Here is my code:
int: gr; % number of groups
int: sz; % size of groups
int: we; % number of weeks
int: n=gr*sz; % number of players
set of int: G=1..gr; % set of group indices
set of int: P=1..n; % set of players
set of int: W=1..we; % set of weeks
% test instance
gr = 2;
sz = 2;
we = 2;
array[G,W] of var set of P: X;
%X[g,w] is the set of people that form group with index g in week w
% forall group x, |x| = sz
constraint forall (g in G, w in W)
(card (X[g,w]) = sz);
% one person cannot play in two groups simultaneously
constraint forall (g in G, w in W, p in X[g,w], g2 in (g+1..gr))
(not(p in X[g2,w]));
solve satisfy;
My problem now is that if I use the G12 lazyfd solver, i.e.
$ minizinc -b lazy this.mzn
I get
X = array2d(1..2 ,1..2 ,[1..2, 1..2, 1..2, 1..2]);
----------
which seems to ignore my second constraint.
On the other hand, using G12 without the lazy option, i.e.
$ minizinc this.mzn
yields
X = array2d(1..2 ,1..2 ,[1..2, 1..2, 3..4, 3..4]);
----------
which is correct.
G12 MIP and Gecode also give a correct result.
How is this possible? And how can I use the lazy solver such that I can rely on it? Or is it just my installation that is messed up somehow?
G12/lazyFD is known to be broken in various places. The problem is that the G12 solvers are no longer being developed and will most likely be removed from the distributions soon.
I would offer Chuffed as an alternative. Chuffed is FD solver written in C++ with lazy clause generation. It should be correct and will perform better then the G12 solver (at least when the solutions are correct).
Chuffed and other MiniZinc solvers can be found on the software page of the MiniZinc website.
I'm learning Haskell and want to see explore the best practic coding functions with probabilitics distributions.
When coding with probablistic functions, it is typical that a function should return a Float value witin in [0, 1].
Is it possible to define a "Probability" data type that can only take values within that range ?
Thanks very much!
Tao
What you ask is not simple. Personally, I would rather use a function like this one:
checkBounds :: (Real a, Show a) => a -> a
checkBounds x | 0 <= x && x <= 1 = x
| otherwise = error $ show x ++ " is not in [0,1]"
But if you want to go further, have a look at this article, the probability package and this code snippet, maybe they could help.
The following model produces instances with exactly 2 address relations when the number of Books is limited to 1, however, if more Books are allowed it will create instances with 0-3 address relations. My misunderstanding of how Alloy works?
sig Name{}
sig Addr{}
sig Book { addr: Name -> lone Addr }
pred show(b:Book) { #b.addr = 2 }
// nr. of address relations in every Book should be 2
run show for 3 but 2 Book
// works as expected with 1 Book
Each instance of show should include one Book, labeled as being the b of show, which has two address pairs. But show does not say that every book must have two address pairs, only that at least one must have two address pairs.
[Postscript]
When you ask Alloy to show you an instance of a predicate, for example by the command run show, then Alloy should show you an instance: that is (quoting section 5.2.1 of Software abstractions, which you already have open) "an assignment of values to the variables of the constraint for which the constraint evaluates to true." In any given universe, there may be many other possible assignments of values to the variables for which the constraint evaluates to false; the existence of such possible non-suitable assignments is unavoidable in any universe with more than one atom.
Informally, we can think of a run command for a predicate P with arguments X, Y, Z as requesting that Alloy show us universes which satisfy the expression
some X, Y, Z : univ | P[X, Y, Z]
The run command does not amount to the expression
all X, Y, Z : univ | P[X, Y, Z]
If you want to see only universes in which every book has two pairs in its addr relation, then say so:
pred all_books_have_2 { all b : Book | #b.addr = 2 }
I think it's better that run have implicit existential quantification, rather than implicit universal quantification. One way to see why is to imagine a model that defines trees, such as:
sig Node { parent : lone Node }
fact parent_acyclic { no n : Node | n in n.^parent }
Suppose we get tired of seeing universes in which every tree is trivial and contains a single node. I'd like to be able to define a predicate that guarantees at least one tree with depth greater than 1, by writing
pred nontrivial[n : Node]{ some n.parent }
Given the constraint that trees be acyclic, there can never be a non-empty universe in which the predicate nontrivial holds for all nodes. So if run and pred had the semantics you have been supposing, we could not use nontrivial to find universes containing non-trivial trees.
I hope this helps.
I have a "simple" problem with JAGS that drives me crazy. In essence, consider the following example that works:
x2[i] ~ dnorm(mu[i,1], tau1);
u[i] ~ dnorm(mu[i,2], tau2);
Here, x2 is an observable variable (that is, data), while u is a latent variable. In the example, both are drawn independently from two distinct normal distributions.
However, I want them to be (possibly) dependent, that is, to be drawn from one multivariate normal distribution. So I would like to do:
c(x2[i], u[i]) ~ dmnorm(mu[i,1:2], Omega[1:2,1:2]);
Unfortunately, this doesn't work because this syntax is not correct. However, having tried many different syntaxes, neither of them does work. E.g.,
y[i,1] <- x2[i];
y[i,2] <- u[i];
y[i,1:2] ~ dmnorm(mu[i,1:2], Omega[1:2,1:2]);
leads to the error Node y[1,1:2] overlaps previously defined nodes, what is obvious.
So what can I do? Please, help me, I'm getting mad...
UPDATE: I figured out that I can at least do the following:
(in R:)
p <- 1/(1+exp(-x2));
t <- rep(10000, length(x2));
s <- rbinom(length(x2), t, p2);
(in JAGS:)
nul[i,1] <- 0;
nul[i,2] <- 0;
e[i,1:2] ~ dmnorm(nul[i,1:2], Omega[1:2,1:2]);
u[i] <- mu[i,2] + e[i,2];
x2g[i] <- mu[i,1] + e[i,1];
pg[i] <- 1/(1+exp(-x2g[i]));
s[i] ~ dbin(pg[i], t[i]);
This works (a bit), but looses of course efficiency since an observable variable (x2) is treated as if it was only indirectly observable (through s).
You are defining y twice Once in:
y[i,1] <- x2[i];
y[i,2] <- u[i];
And once in
y[i,1:2] ~ dmnorm(mu[i,1:2], Omega[1:2,1:2]);
You might be able to get away with:
x2[i] <- y[i,1];
Or you might be able to simply write out the regression (after all it is bivariate, so not that difficulty).
You also might get a faster response on the JAGS mailing list (which Martyn Plummer regularly monitors).
You can use the data block as follows:
data{
for(i in 1:length(x2)) {
y[i,1] <- x2[i]
y[i,2] <- u[i]
}
}
model{
for(i in 1:length(x2)) {
y[i,1:2] ~ dmnorm(mu[i,], Tau)
}
# ... definition of mu, Tau, and their prior distribution
}
However, be sure there are no missing values in x2 or u, since a multivariate node cannot be partly observed.
Regards! :)