MiniZinc: build a connectivity matrix - minizinc

In MiniZinc, I have an array of boolean representing an oriented connection between nodes of a graph:
array[Variants,Variants] of bool : VariantIsDirectlyUpwardOf;
VariantIsDirectlyUpwardOf[v1,v2] = true if there is an oriented arc "v1 -> v2".
now I want to build
array[Variants,Variants] of bool VariantIsUpwardOf;
where VariantIsUpwardOf[v1,v2] = true if there is an oriented path "v1 -> ... -> v2" where "..." is a sequence of nodes defining an oriented path of any length going from v1 to v2.
My first try was to define a transitive kind of constraint
array[Variants,Variants] of var bool : VariantIsUpwardOf;
constraint forall (v1 in Variants, v2 in Variants)(VariantIsDirectlyUpwardOf[v1,v2]->VariantIsUpwardOf[v1,v2]);
constraint forall (v1 in Variants, v2 in Variants, v3 in Variants)( VariantIsUpwardOf[v1,v2] /\ VariantIsUpwardOf[v2,v3] -> VariantIsUpwardOf[v1,v3]);
but I think this is incorrect because if all values of VariantIsUpwardOf[v1,v2] were true, then my constraints would be satisfied and the result would be incorrect.
Following the comment (thanks Axel), I made a second unsuccessful test using predicate dpath, here is my very basic test calling dpath::
include "path.mzn";
enum MyNodes={N1,N2};
array [int] of MyNodes: EdgeFrom=[N1];
array [int] of MyNodes: EdgeTo= [N2];
array [MyNodes] of bool: NodesInSubGraph = [true, true];
array [int] of bool: EdgesInSubGraph = [true];
var bool : MyTest = dpath(EdgeFrom,EdgeTo,N1,N2,NodesInSubGraph,EdgesInSubGraph);
output [show(MyTest)];
it produces the following error:
Running MiniTest.mzn
221msec
fzn_dpath_enum_reif:3.3-52
in call 'abort'
MiniZinc: evaluation error: Abort: Reified dpath constraint is not supported
Process finished with non-zero exit code 1.
Finished in 221msec.

The following MiniZinc model demonstrates the usage of the dpath() predicate to find a directed path in a graph.
I took the directed graph from Wikipedia as example:
The model:
include "globals.mzn";
int: Nodes = 4;
bool: T = true; % abbreviate typing
bool: F = false;
set of int: Variants = 1..Nodes;
% VariantIsDirectlyUpwardOf[v1,v2] = true if there is an oriented arc "v1 -> v2".
% Example from https://en.wikipedia.org/wiki/Directed_graph
array[Variants,Variants] of bool : VariantIsDirectlyUpwardOf =
[| F, T, T, F,
| F, F, F, F,
| F, T, F, T,
| F, F, T, F |];
% count the number of Edges as 2D array sum
int: NoOfEdges = sum(VariantIsDirectlyUpwardOf);
set of int: Edges = 1..NoOfEdges;
% for dpath(), the graph has to be represented as two
% 'from' 'to' arrays of Nodes
% cf. https://www.minizinc.org/doc-2.6.4/en/lib-globals-graph.html
array[Edges] of Variants: fromNodes =
[row | row in Variants, col in Variants
where VariantIsDirectlyUpwardOf[row, col]];
array[Edges] of Variants: toNodes =
[col | row in Variants, col in Variants
where VariantIsDirectlyUpwardOf[row, col]];
% arbitrary choice of Nodes to be connected by a directed path
Variants: sourceNode = 4;
Variants: destNode = 2;
% decision variables as result of the path search
array[Variants] of var bool: nodesInPath;
array[Edges] of var bool: edgesInPath;
constraint dpath(fromNodes, toNodes, sourceNode, destNode, nodesInPath, edgesInPath);
% determine next node after nd in path
function int: successor(int: nd) =
min([s | s in Variants, e in Edges where
fix(nodesInPath[s]) /\ fix(edgesInPath[e]) /\
(fromNodes[e] = nd) /\ (toNodes[e] = s)]);
function string: showPath(int: nd) =
if nd = destNode then "\(nd)" else "\(nd)->" ++ showPath(successor(nd)) endif;
output [showPath(sourceNode)];
Resulting output:
4->3->2

Related

Double pendulum animation

I'm trying to obtain animated double pendulum. Though I can obtain animation for any (one) mass, I can't obtain it for both.
restart;
with(DEtools, odeadvisor);
with(plots);
with(plottools);
Sys := [2*(diff(T1(t), t, t))+cos(T1(t)-T2(t))*(diff(T2(t), t, t))+sin(T1(t)-T2(t))*(diff(T2(t), t))^2+19.6*sin(T1(t)) = 0, diff(T2(t), t, t)+cos(T1(t)-T2(t))*(diff(T1(t), t, t))-sin(T1(t)-T2(t))*(diff(T1(t), t))+9.8*sin(T2(t)) = 0, T1(0) = 1, (D(T1))(0) = 0, T2(0) = 1, (D(T2))(0) = 1];
sol := dsolve(Sys, type = numeric, range = 0 .. 20, output = listprocedure);
odeplot(sol, [T1(t), T2(t)], 0 .. 20, refine = 1);
TT1, TT2 := op(subs(sol, [T1(t), T2(t)]));
f := proc (t) options operator, arrow; pointplot([cos(TT1(t)), sin(TT1(t))], color = blue, symbol = solidcircle, symbolsize = 25) end proc;
p := proc (t) options operator, arrow; pointplot([cos(TT2(t)), sin(TT2(t))], color = red, symbol = solidcircle, symbolsize = 25) end proc;
Any help would be appreciated.
You have provided no explanation of the way your equations are intended to model a physical system, which is not helpful.
So I have made some guesses about your intentions and your model. Please don't blame me if my guesses are not on the mark.
restart;
with(plots):
Sys := [2*(diff(T1(t), t, t))+cos(T1(t)-T2(t))*(diff(T2(t), t, t))
+sin(T1(t)-T2(t))*(diff(T2(t), t))^2+19.6*sin(T1(t)) = 0,
diff(T2(t), t, t)+cos(T1(t)-T2(t))*(diff(T1(t), t, t))
-sin(T1(t)-T2(t))*(diff(T1(t), t))+9.8*sin(T2(t)) = 0,
T1(0) = 1, (D(T1))(0) = 0, T2(0) = 1, (D(T2))(0) = 1]:
sol := dsolve(Sys, numeric, range = 0 .. 20, output = listprocedure):
TT1, TT2 := op(subs(sol, [T1(t), T2(t)])):
fp := t -> plots:-display(
pointplot([sin(TT1(t))+sin(TT2(t)), -cos(TT1(t))-cos(TT2(t))],
color = red, symbol = solidcircle, symbolsize = 25),
pointplot([sin(TT1(t)), -cos(TT1(t))],
color = blue, symbol = solidcircle, symbolsize = 25),
plottools:-line([0,0],[sin(TT1(t)), -cos(TT1(t))]),
plottools:-line([sin(TT1(t)), -cos(TT1(t))],
[sin(TT1(t))+sin(TT2(t)), -cos(TT1(t))-cos(TT2(t))]),
scaling=constrained
):
animate(fp, [t], t=0..10, frames=200);
I don't know whether this kind of stacked view is what you're after, as a representation of the position of "both" masses. It's not really clear what you mean by that.
But perhaps the key thing is that, if the two-element lists you are using within your pointplot calls represent (displacement) vectors, then you can get the stacked/cumulative effect on the second mass by adding those two vectors elementwise. That's how the red point gets its position in my animation. Hopefully this will allow you to get the cumulative effect with both masses, in your own choice of representation.

SSP Algorithm minimal subset of length k

Suppose S is a set with t elements modulo n. There are indeed, 2^t subsets of any length. Illustrate a PARI/GP program which finds the smallest subset U (in terms of length) of distinct elements such that the sum of all elements in U is 0 modulo n. It is easy to write a program which searches via brute force, but brute force is infeasible as t and n get larger, so would appreciate help writing a program which doesn't use brute force to solve this instance of the subset sum problem.
Dynamic Approach:
def isSubsetSum(st, n, sm) :
# The value of subset[i][j] will be
# true if there is a subset of
# set[0..j-1] with sum equal to i
subset=[[True] * (sm+1)] * (n+1)
# If sum is 0, then answer is true
for i in range(0, n+1) :
subset[i][0] = True
# If sum is not 0 and set is empty,
# then answer is false
for i in range(1, sm + 1) :
subset[0][i] = False
# Fill the subset table in botton
# up manner
for i in range(1, n+1) :
for j in range(1, sm+1) :
if(j < st[i-1]) :
subset[i][j] = subset[i-1][j]
if (j >= st[i-1]) :
subset[i][j] = subset[i-1][j] or subset[i - 1][j-st[i-1]]
"""uncomment this code to print table
for i in range(0,n+1) :
for j in range(0,sm+1) :
print(subset[i][j],end="")
print(" ")"""
return subset[n][sm];
I got this code from here I don't know weather it seems to work.
function getSummingItems(a,t){
return a.reduce((h,n) => Object.keys(h)
.reduceRight((m,k) => +k+n <= t ? (m[+k+n] = m[+k+n] ? m[+k+n].concat(m[k].map(sa => sa.concat(n)))
: m[k].map(sa => sa.concat(n)),m)
: m, h), {0:[[]]})[t];
}
var arr = Array(20).fill().map((_,i) => i+1), // [1,2,..,20]
tgt = 42,
res = [];
console.time("test");
res = getSummingItems(arr,tgt);
console.timeEnd("test");
console.log("found",res.length,"subsequences summing to",tgt);
console.log(JSON.stringify(res));

Callback in Bender's decomposition

I am learning Bender's decomposition method and I want to use that in a small instance. I started from "bendersatsp.py" example in CPLEX. When I run this example with my problem, I got the following error. Could you please let me know what the problem is and how I can fix it? In the following you can see the modifications in lazy constraints function. I have two decision variables in master problem "z_{ik}" and "u_{k}" that would incorporate as constant in the workerLp.
class BendersLazyConsCallback(LazyConstraintCallback):
def __call__(self):
print("shoma")
v = self.v
u = self.u
z = self.z
print ("u:", u)
print ("z:", z)
workerLP = self.workerLP
boxty = len(u)
#scenarios=self.scenarios2
ite=len(z)
print ("ite:", ite)
print ("boxty:", boxty)
# Get the current x solution
sol1 = []
sol2 = []
sol3 = []
print("okkkk")
for k in range(1, boxty+1):
sol1.append([])
sol1[k-1]= [self.get_values(u[k-1])];
print ("sol1:", sol1[k-1])
for i in range(1, ite+1):
sol2.append([])
sol2[i-1]= self.get_values(z[i-1]);
print ("sol2:", sol2[i-1])
for i in range(1, ite+1):
sol3.append([])
sol3[i-1]= self.get_values(v[i-1]);
#print ("sol3:", sol3[i-1])
# Benders' cut separation
if workerLP.separate(sol3,sol1,sol2,v,u,z):
self.add(cut = workerLP.cutLhs, sense = "G", rhs = workerLP.cutRhs)
CPLEX Error 1006: Error during callback.
benders(sys.argv[1][0], datafile)
cpx.solve()
_proc.mipopt(self._env._e, self._lp)
check_status(env, status)
raise callback_exception
TypeError: unsupported operand type(s) for +: 'int' and 'list'

local variable T conflicts with a static parameter warining

I'm getting warning that I don't understand.
I first run the following code:
type PDF{T <: Real}
𝛑::Vector{Float64} # K
μs::Matrix{T} # D x K
Σs::Vector{Matrix{T}} # K{D x D}
end
type Q{T <: Real}
w::Union{Float64, Vector{Float64}}
μpair::Union{Vector{T}, Matrix{T}}
Σpair::Union{Matrix{T}, Tuple{Matrix{T}, Matrix{T}} } # K{D x D}
end
type Smod{T <: Real}
H::Matrix{T} # D x D
Σs::Vector{Matrix{T}} # K{D x D}
qs::Vector{Q{T}}
end
type Scale{T <: Real}
μ::Vector{T} # D
Σ::Matrix{T} # D x D
end
type Parameters{T <: Real}
scale::Scale{T}
w::Vector{Float64}
maxNumCompsBeforeCompression::Integer
numComponentsAbsorbed::Integer
end
type KDE{T}
pdf::PDF{T}
smod::Smod{T}
params::Parameters{T}
end
And when after this I run the following snippet in IJulia
function initializeKDE{T <: Real}(x::Vector{T})
d = size(x,1)
T = typeof(x)
𝛑 = ones(Float64, 1)
μs = Array(T, d,1)
μs[:,1] = x
Σs = Array(Matrix{T}, 0)
pdf = PDF(𝛑, μs, Σs)
H = zeros(T, d,d)
qs = Array(Q{T}, 0)
smod = Smod(H, Σs, qs)
scale = Scale(x, H)
w = [0.0, 1.0]
maxNumCompsBeforeCompression = min(10, (0.5d^2 + d))
numComponentsAbsorbed = 0
params = Params(scale, w, maxNumCompsBeforeCompression, numComponentsAbsorbed)
kde = KDE(pdf, smod, params)
return kde::KDE
end
I get the following warning:
WARNING: local variable T conflicts with a static parameter in initializeKDE at In[4]:3.
where In[4]:3 corresponds to the 3rd line of the 2nd snippet.
Can anyone explain in human english what this warning is saying?
This is saying that you are trying to use T in two different ways: once as a "static parameter" and once as a local variable.
Firstly, you are using T as the parameter with which you are parametrising the function initializeKDE:
function initializeKDE{T <: Real}(x::Vector{T})
But then you are trying to redefine a new T in that third line:
T = typeof(x)
What are you trying to do here? If you are trying to define T to be the type of the elements that the vector x contains, then you should just delete this line and everything should just work -- T will automatically take the element type (eltype) of the vector that you pass to the initializeKDE function.

Alloy model an algebraic group

I am trying to model the structure of an algebraic group with Alloy.
A group just has a set of elements and a binary relation with certain properties so I thought it would be a good fit for alloy.
This is what I started with
sig Number{}
/* I call it Number but this is really just a name for some objects that are going to be in the group */
sig Group{
member: set Number,
product: member->member->member, /*This is the part I'm really not sure about the Group is supposed to have a a well-defined binary relation so I thought maybe I could write it like this, sort of as a Curried function...I think it's actually a ternary relation in Alloy language since it takes two members and returns a third member */
}{//I want to write the other group properties as appended facts here.
some e:member | all g:member| g->e->g in product //identity element
all g:member | some i:member| g->i->e in product /* inverses exist I think there's a problem here because i want the e to be the same as in the previous line*/
all a,b,c:member| if a->b->c and c->d->e and b->c->f then a->f->e //transitivity
all a,b:member| a->b->c in product// product is well defined
}
I've only just learned a bit of Alloy myself, but your "inverses exist" problem looks straightforward from a predicate logic perspective; replace your first two properties with
some e:member {
all g:member | g->e->g in product //identity element
all g:member | some i:member | g->i->e in product // inverses exist
}
By putting the inverse property in the scope of the quantifier of e, it is referring to that same e.
I haven't tested this.
Here is one way of encoding groups in Alloy:
module group[E]
pred associative[o : E->E->E]{ all x, y, z : E | (x.o[y]).o[z] = x.o[y.o[z]] }
pred commutative[o : E->E->E]{ all x, y : E | x.o[y] = y.o[x] }
pred is_identity[i : E, o : E->E->E]{ all x : E | (i.o[x] = x and x = x.o[i]) }
pred is_inverse[b : E->E, i : E, o : E->E->E]{ all x : E | (b[x].o[x] = i and i = x.o[b[x]]) }
sig Group{
op : E -> E->one E, inv : E one->one E, id : E
}{
associative[op] and is_identity[id, op] and is_inverse[inv, id, op] }
sig Abelian extends Group{}{ commutative[op] }
unique_identity: check {
all g : Group, id' : E | (is_identity[id', g.op] implies id' = g.id)
} for 13 but exactly 1 Group
unique_inverse: check {
all g : Group, inv' : E->E | (is_inverse[inv', g.id, g.op] implies inv' = g.inv)
} for 13 but exactly 1 Group