Given a MxN matrix A with M observations and N features, as well as a non-linear distance function f
, with observations being identical (f(A[i, :], A[j, :]) == 0.0
for each i,j). I would like to disturb the observations such that they have a desired target distance D to each other with regards to f
. Additionally, I would like to only optimize values in A that are not zero to begin with.
I thought it would be nice to try JuMP for this, but I’m unsure about the correct specification. I started like this:
using JuMP, Ipopt
# dummy data with 2 observations
A = [0.0 0.0 0.2 0.8;
0.0 0.4 0.0 0.6]
m = Model(solver=IpoptSolver(print_level=0))
M, N = size(A)
#target distance
D = 0.1
# set bounds for all variables, such that variables corresponding to zeroes in A
# have no wiggle room
minval = minimum(A[.!iszero.(A)])
maxval = maximum(A)
@variable(m, x[1:M, 1:N])
for i in 1:M, j in 1:N
if iszero(A[i,j])
lb = ub = 0.0
else
lb = minval
ub = maxval
end
setlowerbound(x[i,j], lb)
setupperbound(x[i,j], ub)
end
The objective would then ideally be something like
function obj(x, D=D)
M = size(x, 1)
# all pairwise comparisons between observations, w/o repetitions
obj_val = 0.0
for i1 in 1:M-1
for i2 in i1+1:M
obj_val += f(x[i1, :], x[i2, :]) - D
end
end
obj_val
end
JuMP.register(m, :obj, 1, obj, autodiff=true)
@NLobjective(m, :Min, obj(x))
However, this fails with the following stacktrace:
as far as I can figure because user defined functions need scalars, i.e. cannot work with expressions including arrays of variables. What would be the canonical way to express this?