How can I replace some variables in a BDD by CUDD package? - model-checking

Suppose DdManager has four variables: x, y, x', y' and I have a BDD built by x and y.
Now I want to change x to x', y to y', namely, get an identical BDD built by x' and y'.
How can I get this using the CUDD package? I encountered this problem when I wanted to implement a model checking algorithm. I want to know how to implement this operation or whether I misunderstand the symbolic model checking algorithm?
Thank you very much!

You do this with the function Cudd_bddSwapVariables. It gets the following parameters:
A BDD Manager
The BDD where you want to replace variables by others.
The first array of variables (represented by the BDD nodes that also Cudd_bddNewVar would return)
The second array of variables
The number of variables being swapped.
You will need to allocate and free the arrays yourself.

Example of variable substitution using the Cython bindings to CUDD that are included in the package dd:
from dd import cudd
bdd = cudd.BDD() # instantiate a shared BDD manager
bdd.declare("x", "y", "x'", "y'")
u = bdd.add_expr(r"x \/ y") # create the BDD for the disjunction of x and y
rename = dict(x="x'", y="y'")
v = bdd.let(rename, u) # substitution of x' for x and y' for y
s = bdd.to_expr(v)
print(s) # outputs: "ite(x', TRUE, y')"
# another way to confirm that the result is as expected
v_ = bdd.add_expr(r"x' \/ y'")
assert v == v_

Related

Sympy - Find all expressions of a certain level

in the documentation it is shown, how one can use srepr(expr) to create a string containing all elements of the formula tree.
I would like to have all elements of a certain level of such a tree in a list, not as a string but as sympy objects.
For the example
from sympy import *
x,y,z = symbols('x y z')
expr = sin(x*y)/2 - x**2 + 1/y
s(repr)
"""
gives out
=> "Add(Mul(Integer(-1), Pow(Symbol('x'), Integer(2))), Mul(Rational(1, 2),
sin(Mul(Symbol('x'), Symbol('y')))), Pow(Symbol('y'), Integer(-1)))"
"""
This should lead to
first_level = [sin(x*y)/2,-x**2,1/y]
second_level[0] = [sin(x*y),2]
I assume, the fundamental question is, how to index a sympy expression according to the expression tree such that all higher levels starting from an arbitrary point are sumarized in a list element.
For the first level, it is possible to solve the task
by getting the type of the first level (Add in this case and then run)
print(list(Add.make_args(expr)))
but how does it work for expressions deeper in the tree?
I think the thing you are looking for is .args. For example your example we have:
from sympy import *
x, y, z = symbols('x y z')
expr = sin(x * y) / 2 - x ** 2 + 1 / y
first_level = expr.args
second_level = [e.args for e in first_level]
print(first_level)
print(second_level[0])
"""
(1/y, sin(x*y)/2, -x**2)
(y, -1)
"""
These give tuples, but I trust that you can convert them to lists no problem.
If you want to get directly to the bottom of the tree, use .atoms() which produces a set:
print(expr.atoms())
"""
{x, 2, y, -1, 1/2}
"""
Another thing that seems interesting is perorder_traversal() which seems to give a tree kind of object and if you iterate through it, you get something like a power set:
print([e for e in preorder_traversal(expr)])
"""
[-x**2 + sin(x*y)/2 + 1/y, 1/y, y, -1, sin(x*y)/2, 1/2, sin(x*y), x*y, x, y, -x**2, -1, x**2, x, 2]
"""
Here is the beginning of the docstring of the function:
Do a pre-order traversal of a tree.
This iterator recursively yields nodes that it has visited in a pre-order fashion. That is, it yields the current node then descends through the tree breadth-first to yield all of a node's children's pre-order traversal.
For an expression, the order of the traversal depends on the order of .args, which in many cases can be arbitrary.
If any of these are not what you want then I probably don't understand your question correctly. Apologies for that.

Trying to understand Julia syntax in linear regression code (GLM package)

Total Julia noob here (with basic knowledge of Python). I am trying to do linear regression and things I read suggest the GLM package. Here is some sample code I found here:
using DataFrames, GLM
y = 1:10
df = DataFrame(y = y, x1 = y.^2, x2 = y.^3)
sm = GLM.lm( #formula(y ~ x1 + x2), df )
coef(sm)
Can someone explain the syntax here? What does #formula mean? Docs here say #foo means a
macro which I guess is basically just a function, but where do I find the function/macro formula? Just looking at the use here though, I would have thought it is maybe passing y ~ x1 + x2 (whatever that is) as the formula argument to lm? (similar to keyword arguments = in python?)
Next, what is ~ here? General docs say ~ means negation but I'm not seeing how that makes here.
Is there a place in the GLM docs where all of this is explained? I'm not seeing that. Only seeing a few examples but not a full breakdown of each function and all of its arguments.
You have stumbled upon the #formula language that is defined in the StatsModels.jl package and implemented in many statistics/econometrics related packages across the Julia ecosystem.
As you say, #formula is a macro, which transforms the expression given to it (here y ~ x1 + x2) into some other Julia expression. If you want to find out what happens when a macro gets called in Julia - which I admit can often look like magic to new (and sometimes experienced!) users - the #macroexpand macro can help you. In this case:
julia> #macroexpand #formula(y ~ x1 + x2)
:(StatsModels.Term(:y) ~ StatsModels.Term(:x1) + StatsModels.Term(:x2))
The result above is the expression constructed by the #formula macro. We see that the variables in our formula macro are transformed into StatsModels.Term objects. If we were to use StatsModels directly, we could construct this ourselves by doing:
julia> Term(:y) ~ Term(:x1) + Term(:x2)
FormulaTerm
Response:
y(unknown)
Predictors:
x1(unknown)
x2(unknown)
julia> (Term(:y) ~ Term(:x1) + Term(:x2)) == #formula(y ~ x1 + x2)
true
Now what is going on with ~, which as you say can be used for negation in Julia? What has happened here is that StatsModels has defined methods for ~ (which in Julia is and infix operator, that means essentially it is a function that can be written in between its arguments rather than having to be called with its arguments in brackets:
julia> (Term(:y) ~ Term(:x)) == ~(Term(:y), Term(:x))
true
So writing y::Term ~ x::Term is the same as calling ~(y::Term, x::Term), and this method for calling ~ with terms on the left and right hand side is defined by StatsModels (see method no. 6 below):
julia> methods(~)
# 6 methods for generic function "~":
[1] ~(x::BigInt) in Base.GMP at gmp.jl:542
[2] ~(::Missing) in Base at missing.jl:100
[3] ~(x::Bool) in Base at bool.jl:39
[4] ~(x::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8}) in Base at int.jl:254
[5] ~(n::Integer) in Base at int.jl:138
[6] ~(lhs::Union{AbstractTerm, Tuple{Vararg{AbstractTerm,N}} where N}, rhs::Union{AbstractTerm, Tuple{Vararg{AbstractTerm,N}} where N}) in StatsModels at /home/nils/.julia/packages/StatsModels/pMxlJ/src/terms.jl:397
Note that you also find the general negation meaning here (method 3 above, which defines the behaviour for calling ~ on a boolean argument and is in Base Julia).
I agree that the GLM.jl docs maybe aren't the most comprehensive in the world, but one of the reasons for that is that the whole machinery behind #formula actually isn't a GLM.jl thing - so do check out the StatsModels docs linked above which are quite good I think.

How to create a SOC constraints with different Variable vectors's element

I am working on an optimization problem with cvxpy. And I need to create a SOC(second order cone) constraint.
The way described in cvxpy documents is like following:
We use cp.SOC(t, x) to create the SOC constraint ||x||_2 <= t.
where t is the scalar part of the second-order constraint, x is a matrix whose rows/columns are each a cone.
Here is the standard way how cvxpy solve a SOCP problem.
But now i need to extract Variable from different places.
import cvxpy as cvx
Y = cvx.Variable(3)
Z = cvx.Variable(3)
T = cvx.Variable(3)
soc_constraints = []
for in range(3):
t = T[i]
x = np.matrix([Y[i], Z[i]])
soc_constraints += [cvx.SOC(t, x)]
But I get one error here.
AttributeError: 'matrix' object has no attribute 'variables'
I suppose x should be a cvxpy expression. But how can i create a SOC constraint out of different Variable vectors.
Some help would be appreciated.

Is there an equivalent to ppp marks for pp3?

I would like to run a mark correlation function on a simple 3d dataset, but it seems like you cannot assign marks with a pp3... Am I missing something or are there other means?
The function pp3 doesn’t accept a marks argument, but you can assign marks to the resulting object:
x <- runif(100)
y <- runif(100)
z <- runif(100)
X <- pp3(x, y, z, c(0, 1), c(0,1), c(0,1))
marks(X) <- rnorm(100)
This uses the method marks<-.ppx. Methods for class ppx apply to class pp3.
However, mark correlation functions are not yet implemented for pp3 objects. The help for markcorr says that the point pattern must be two-dimensional.

Getting Alloy to find the largest answer for particular sets

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)
}

Resources