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?