text:
using Plots

data = readdlm(IOBuffer("""
    1 |        100000000 |        1.069432 |    2.2441811441
    2 |        100000000 |        0.573543 |    4.1845140477
    4 |        100000000 |        0.381410 |    6.2924386313
    8 |        100000000 |        0.133315 |   18.0024743951
   16 |        100000000 |        0.087866 |   27.3143817048
   32 |        100000000 |        0.094582 |   25.3748789460
   64 |        100000000 |        0.082351 |   29.1436764549
   """), '|')

mpidata = readdlm(IOBuffer("""
1.          4791.9     0.506998     0.500844     0.515415
2.          9366.9     0.256951     0.256222     0.257966
4.         18607.7     0.153044     0.128979     0.243534
8.         37209.9     0.095361     0.064499     0.206526
16         43776.9     0.081599     0.054823     0.129850
32         65392.5     0.061542     0.036701     0.082718
64         81010.2     0.056582     0.029626     0.081922
"""))

mpidata[:,2] ./= 1024 #Convert from MB/s to GB/s

plot([1,64], [mpidata[1,2], mpidata[1,2]*64], c=:lightgrey, label="ideal MPI")
plot!(mpidata[:,1], mpidata[:,2], c=:red, label="C/MPI")
scatter!(mpidata[:,1], mpidata[:,2], c=:red, label="")
plot!([1,64], [data[1,4], data[1,4]*64], c=:grey, label="ideal Julia")
plot!(data[:,1], data[:,4], xlabel="# cores", ylabel="Gflops", c=:blue, label="Julia", ylims=(0, 90), xlims=(0, 80))
scatter!(data[:,1], data[:,4], c=:blue, label="")
png("../plots/triad")


text:
################################
# Coded by Julien Pascal
# Last modification : 16/04/2016
# Replication of the the following paper:

####################################################################################
# "On the Dynamics of Unemployment and Wage Distributions"
# Paper from Jean Marc Robin (2011)
# Available here: https://sites.google.com/site/jmarcrobin/research/publications
####################################################################################

#######################################################################################
# Module that estimates the parameters of the model by the method of simulated moments
module estimate_parameters

	#################################
	# PATHS
	# change "path_main" if necessary
	path_main = "/home/julien/Final-Project-Julien-Pascal"
	path_table = string(path_main,"/tables/")  #the path tables
	path_surpluses = string(path_main,"/surpluses/")#path to precalculated objects, to speed up the process

    using PyPlot, Distributions, StatsFuns, JLD, HDF5, DataFrames, Copulas, NLopt, BlackBoxOptim
   	include("objective_function.jl") #To use package NLopt
   	include("objective_function_2.jl") #To use with BlackBoxOptim and the simulated annhealing procedure
   	include("objective_function_3.jl") #To compute the optimal weighting matrix
   	include("simulated_annealing/samin.jl")#simulated annealing module

	if isfile(string(path_surpluses,"random_numbers.jld")) #load it if exists
	        println(string(path_surpluses,"random_numbers.jld"," found"))
	        println("loading it")
	        file_random_numbers =  jldopen(string(path_surpluses,"random_numbers.jld"), "r")
		    random_numbers = read(file_random_numbers, "random_numbers")
	else
	    println("creating a series of random draws to be held fixed during the optimization")
	    n_years = 2500; # years to simulate
		number_periods = n_years*4; # one period = one quarter
	    random_numbers = zeros(number_periods)#column vector is length number_periods with the numers coming from the random generator. Type Array{Float64,1}

	    for t=1:number_periods
	    	random_numbers[t] = rand()
	    end

	    #Save the results in a JLD file:
		jldopen(string(path_surpluses,"random_numbers.jld"), "w") do file
		    write(file, "random_numbers", random_numbers)
		end
	end

    export MSM

    function MSM(routine = "NLopt", steps = "1Step")
    	tic()

    	params_name =["z0", "sigma", "lambda0", "eta", "mu", "x_lower_bar"] #parameters to be estimated
		number_parameters = 6 #number of parameters

    	#params_name =["z0", "sigma", "lambda0", "eta", "mu", "x_lower_bar", "alpha", "delta"] #parameters to be estimated
		#number_parameters = 8 #number of parameters

		#params_name = ["z0", "sigma", "rho", "lambda0", "eta", "mu", "x_lower_bar", "delta"] #parameters to be estimated
		#number_parameters = 8 #number of parameters

		#params_name = ["z0", "sigma", "rho", "lambda0", "eta", "mu", "x_lower_bar"] #parameters to be estimated
		#number_parameters = 7 #number of parameters

		#Paper and initial values:
		#params_opt = [0.77, 0.023, 0.94, 0.99, 2.00, 5.56, 0.73, 0.042] #optimal parameters in the paper
		#params0 = [0.77, 0.023, 0.94, 0.99, 2.00, 5.5, 0.70, 0.046] #starting values for the optimization
		#params0 = [0.408512, 0.0678116, 0.674442, 0.726062, 2.6711, 1.61011, 0.73, 0.046]
		#params0 =    [0.77, 0.067, 0.90, 2.67, 1.6, 0.73]

		params0 = [ 0.9573874974174598, 0.02376049264005116, 0.9090148634236118, 5.628756473043127, 3.8906895043507066, 0.6827425005901246]
		params_opt = [0.77, 0.023, 0.99, 2.00, 5.56, 0.73]

		#Bounds of the parameters space:
		#lb = [0.70, 0.01, 0.70, 1.00, 1.00, 0.60, 0.60] #lower bound
		#ub = [0.99, 0.10, 0.99, 4.00, 6.00, 0.90, 0.80] #upper bound
		lb = [0.01, 0.01, 0.01, 1.00, 1.00, 0.01] #lower bound
		ub = [0.99, 0.99, 0.999, 6.00, 6.00, 0.99] #upper bound

		# Eta and sigma and delta may be binding

		# Empirical moments to match:
		# mean productivity, std productivity, mean unemployment rate, std unemployment rate, mean job finding rate, std job finding rate, mean job separation rate, std separation rate
		# One which worked well with DE:
		#b0 = [1.0; 0.023;  0.059;  0.210; 0.761; 0.085; 0.046; 0.156]
		#number_moments = 8

		b0 = [1.0; 0.023;  0.059;  0.210; 0.761; 0.085; 0.046]
		number_moments = 7

		#Checks:
			#check dimensions:
		if size(lb,1)!= number_parameters
			error("Dimension lower bound misspecified")
		elseif size(ub,1)!= number_parameters
			error("Dimension upper bound misspecified")
		elseif size(params0,1)!= number_parameters
			error("Dimension parameter starting values misspecified")
		elseif size(params_name,1)!= number_parameters
			error("Dimension parameter names misspecified")
		elseif size(params_name,1)!= number_parameters
			error("Dimension the vector of parameters misspecified")
		elseif size(b0,1)!= number_moments
			error("Dimension the vector of empirical moments misspecified")
		end
			#check whether the starting value is within the bounds:
		for i=1:number_parameters
			if params0[i] > ub[i]
				println(i)
				error("Starting value above the upper bound")
			end
			if params0[i] < lb[i]
				println(i)
				error("Starting value below the lower bound")
			end
		end

		#Create the search range for the package DEoptim:
		#creates the bounds:
		Search_range = Array{Tuple{Float64,Float64},1}(number_parameters) #Type for Deoptim
		for i=1:number_parameters
			Search_range[i] = (lb[i], ub[i])
		end
		println("Search range")
		println(Search_range)

		if routine == "NLopt"
			println("NLopt")

			if steps == "1Step"
				##########################################
				# 1-Step procedure using the package NLopt
				##########################################
				println("1-Step procedure")

				###################################
				# A. Global Optimization Algorithms
				###################################

				#Controlled Random Search (CRS) with local mutation:
				# take 636.5 seconds seconds to run on my computer
				# 3689.061901 seconds on the last run
				println("Controlled Random Search (CRS) with local mutation:")
				opt1 = Opt(:GN_CRS2_LM, number_parameters) #
				lower_bounds!(opt1, lb)
				upper_bounds!(opt1, ub)
				xtol_rel!(opt1,1e-1)
				maxtime!(opt1, 3600)
				Weighting_matrix = eye(number_moments,number_moments)./(b0.*b0) #Use the Identity as a weighting matrix
				min_objective!(opt1, (x,g)->objective_function(x,g,Weighting_matrix, random_numbers, b0))
				@time (minf1,minx1,ret1) = optimize(opt1, params0) #start at params0

				df_global = DataFrame()
				df_global[:Paramater] = params_name
				df_global[:Value] = minx1
				df_global[:Minf] = minf1
				println("Step 1.1. Global Optimization Results with W = Identity")
				println(df_global)
				writetable("tables/estimated_parameters_1step_CRS.csv", df_global)
				writetable("tables/estimated_parameters.csv", df_global)

			elseif steps == "2Step"
				#############################################
				# 2-Step procedure using the package NLopt
				#############################################
				println("2-Step procedure")

				###################################
				# 1st step: use the identity matrix
				# as the identity
				##################################
				println("STEP 1. Global minimization with W = I")

				#Controlled Random Search (CRS) with local mutation:
				# take 636.5 seconds seconds to run on my computer
				# 3689.061901 seconds on the last run
				println("Controlled Random Search (CRS) with local mutation:")
				opt1 = Opt(:GN_CRS2_LM, number_parameters)
				lower_bounds!(opt1, lb)
				upper_bounds!(opt1, ub)
				xtol_rel!(opt1,1e-1)
				maxtime!(opt1, 3600)
				Weighting_matrix = eye(number_moments,number_moments) #Use the Identity as a weighting matrix
				min_objective!(opt1, (x,g)->objective_function(x,g,Weighting_matrix, random_numbers, b0))
				@time (minf1,minx1,ret1) = optimize(opt1, params0) #start at params0

				df_step1 = DataFrame()
				df_step1[:Paramater] = params_name
				df_step1[:Value] = minx1
				df_step1[:Minf] = minf1
				println("Step 1.1. Global Optimization Results with W = Identity")
				println(df_global)
				writetable("tables/estimated_parameters_step1_CRS.csv", df_step1)
				writetable("tables/estimated_parameters_step1.csv", df_step1)

				############################################
				# 2nd step: use the optimal weighting matrix
				############################################
				println("Step 2. Global minimization with W = Optimal weighting matrix")
				println("Step 2.0 Calculating the Optimal weighting matrix")
				intermediate_step = objective_function_3(minx1) #returns a dictionary with 3 elements: ("St"=> St, "inverse_St" => inverse_St, "simulated_moments"=> simulated_moments)
				Optimal_weighting_matrix = intermediate_step["inverse_St"]

				println("Optimal weighting matrix:")
				println(intermediate_step["inverse_St"])
				writedlm("tables/optimal_weighting_matrix.txt") #Save the optimal weighting matrix into a txt file

				println("Step 2.1. Global Optimization Results with W = Optimal weighting matrix")
				println("Controlled Random Search (CRS) with local mutation:")  #Takes 2277.229133 seconds
				opt2 = Opt(:GN_CRS2_LM, number_parameters)
				lower_bounds!(opt2, lb)
				upper_bounds!(opt2, ub)
				xtol_rel!(opt2,1e-1)
				maxtime!(opt2, 3600)
				min_objective!(opt2, (x,g)->objective_function(x,g,Optimal_weighting_matrix, random_numbers, b0)) #Optimal weighting matrix as an input
				@time (minf2,minx2,ret2) = optimize(opt2, minx1) #start with the mimimum of step 1

				df_step2 = DataFrame()
				df_step2[:Paramater] = params_name
				df_step2[:Value] = minx2
				df_step2[:Minf] = minf2
				println("MSM results:")
				println(df)
				writetable("tables/estimated_parameters_step2_CRS.csv", df_step2)
				writetable("tables/estimated_parameters.csv", df_step2)

			else
				error("Incorrect name for the second argument of MSM()")
			end
		elseif routine == "DE"
		########################
		# Differential Evolution
		########################
		println("Differential Evolution")

			if steps == "1Step"
				##################################################
				# 1-Step procedure using the package BlackBoxOptim
				##################################################
				println("1-Step procedure")

				Weighting_matrix = eye(number_moments,number_moments)./(b0.*b0) #Square of percentage deviations. Could use the identity matrix as well.
				#set the time limit to be = 3600 seconds
				#Tolerance = 0.01

				opt_DE = bbsetup(x->objective_function_2(x, Weighting_matrix, random_numbers, b0); Method=:dxnes, SearchRange = Search_range, NumDimensions = number_parameters, ϵ=0.01, MaxTime =  3600)

				res_DE = bboptimize(opt_DE)
				bs = best_candidate(res_DE) #best "candidate" = vector the minimizes the objective function
				bf = best_fitness(res_DE) #value of

				df= DataFrame()
				df[:Paramater] = params_name
				df[:Value] = bs
				df[:Minf] = bf
				println("Step 1. MSM results:")
				println(df)
				writetable("tables/estimated_parameters_step1_DE.csv", df)
				writetable("tables/estimated_parameters.csv", df)

			elseif steps == "2Step"
				##################################################
				# 2-Step procedure using the package BlackBoxOptim
				##################################################
				println("2-Step procedure")

				###################################
				# 1st step: use the identity matrix
				# as the identity
				##################################
				println("STEP 1. Global minimization with W = I")

				Weighting_matrix = eye(number_moments,number_moments) #Use the Identity as a weighting matrix
				#set the time limit to be = 3600 seconds
				#Tolerance = 0.01
				opt_DE = bbsetup(x->objective_function_2(x, Weighting_matrix, random_numbers, b0); Method=:xnes, SearchRange = Search_range, NumDimensions = number_parameters, ϵ=0.01, MaxTime =  3600)

				res_DE = bboptimize(opt_DE)
				bs = best_candidate(res_DE) #best "candidate" = vector the minimizes the objective function
				bf = best_fitness(res_DE) #value of

				df_step1 = DataFrame()
				df_step1[:Paramater] = params_name
				df_step1[:Value] = bs
				df_step1[:Minf] = bf
				println("Step 1. MSM results:")
				println(df)
				writetable("tables/estimated_parameters_step1_DE.csv", df_step1)
				writetable("tables/estimated_parameters_step1.csv", df_step1)

				############################################
				# 2nd step: use the optimal weighting matrix
				############################################
				println("Step 2. Global minimization with W = Optimal weighting matrix")
				println("Step 2.0 Calculating the Optimal weighting matrix")
				intermediate_step = objective_function_3(bs) #returns a dictionary with 3 elements: ("St"=> St, "inverse_St" => inverse_St, "simulated_moments"=> simulated_moments)
				Optimal_weighting_matrix = intermediate_step["inverse_St"]

				println("Optimal weighting matrix:")
				println(intermediate_step["inverse_St"])

				#7241.939754208 seconds
				println("Step 2.1 Global Optimization Results with W = Optimal weighting matrix")
				opt_DE2 = bbsetup(x->objective_function_2(x, Optimal_weighting_matrix, random_numbers, b0); Method=:xnes, SearchRange = Search_range, NumDimensions = number_parameters, ϵ=0.01, MaxTime =  3600)

				res_DE2 = bboptimize(opt_DE2)
				bs2 = best_candidate(res_DE2) #best "candidate" = vector the minimizes the objective function
				bf2 = best_fitness(res_DE2) #value of

				df_step2 = DataFrame()
				df_step2[:Paramater] = params_name
				df_step2[:Value] = bs2
				df_step2[:Minf] = bf2
				println("Step 2. MSM results:")
				println(df_step2)
				writetable("tables/estimated_parameters.csv", df_step2)
				writetable("tables/estimated_parameters_step2_DE.csv", df_step2)
			else
				error("Incorrect name for the second argument of MSM()")
			end

		elseif routine == "SA"
		######################
		# Simulated Annealing
		######################
		println("Simulated Annealing")

		#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		#!!! THIS PART HAS TO BE CHANGED
		#!!! NOT COHERENT ANYMORE with obective_function_2

			#Boundaries of the problem and starting value:
			lb = [0.7, 0.01, 0.8, 0.8, 1.5, 5.0]
			initial=[0.70, 0.01, 0.9, 0.90, 2.0, 5.3]
			ub = [0.99, 0.99, 0.99, 0.99, 2.5, 6.0]

			xopt = samin(objective_function_2, initial, lb, ub, maxevals = 300, verbosity=2)
			#1537.63419783 seconds for 300 iterations

			# Save the result in a csv file:
			df = DataFrame()
			df[:Paramater] = params_name
			df[:Value] = xopt[1]
			df[:Minf] = objective_function_2(xopt[1])
			println("MSM results:")
			println(df)

			writetable("tables/estimated_parameters.csv", df)
		elseif routine == "LOCAL" #To refine a Global equilibrium

			println("LOCAL OPTIMIZATION: COBYLA")
			opt1 = Opt(:LN_COBYLA, number_parameters)
			lower_bounds!(opt1, lb)
			upper_bounds!(opt1, ub)
			xtol_rel!(opt1,1e-1)
			maxtime!(opt1, 3600)
			Weighting_matrix = eye(number_moments,number_moments)./(b0.*b0) #Use the Identity as a weighting matrix
			min_objective!(opt1, (x,g)->objective_function(x,g,Weighting_matrix, random_numbers, b0))
			@time (minf1,minx1,ret1) = optimize(opt1, params0) #start at params0

			df_global = DataFrame()
			df_global[:Paramater] = params_name
			df_global[:Value] = minx1
			df_global[:Minf] = minf1
			println("LOCAL OPTIMIZATION COBYLA")
			println(df_global)
			writetable("tables/estimated_parameters_COBYLA.csv", df_global)
			writetable("tables/estimated_parameters.csv", df_global)

			#compare the global and the local min:
			println("Global min")
			min0 = objective_function(params0, params0, Weighting_matrix, random_numbers, b0)
			println(min0)

			println("Local min")
			println(minf1)

		else
			error("Incorrect name for the first argument of MSM()")
			println("Either NLopt, DE, SA, or LOCAL")
		end

	toc()
	end
end

#########################
# Other NLopt Algorithms
#########################

##################################
# B. Gloabl optimization algorithms
##################################

#=
#DIRECT-L: J. M. Gablonsky and C. T. Kelley, "A locally-biased form of the DIRECT algorithm," J. Global Optimization, vol. 21 (1), p. 27-37 (2001).
:GN_DIRECT_L
=#

#ISRES (Improved Stochastic Ranking Evolution Strategy)
#=
:GN_ISRES
=#

#ESCH (evolutionary algorithm)
#=
:GN_ESCH
=#

##################################
# B. Local optimization algorithms
##################################

#=
#Using the Nelder-Mead Simplex
:LN_NELDERMEAD
=#

# Tom Rowan's "Subplex" algorithm:
#=
:LN_SBPLX
=#

ext: jl


text:
# init utils for tree based inference

export resetCliqSolve!
export addLikelihoodsDifferential!
export addLikelihoodsDifferentialCHILD!

## =============================================================================
# short preamble funcions
## =============================================================================

convert(::Type{BallTreeDensity}, src::TreeBelief) = manikde!(src.val, src.bw[:,1], src.variableType)

"""
    $(SIGNATURES)

Construct a BallTreeDensity KDE object from an IIF.TreeBelief object.

Related

manikde!, getKDE, getKDEMax, getKDEMean, TreeBelief
"""
function kde!(em::TreeBelief)
  # return AMP.manikde!(em.val, em.bw, em.manifolds)
  return convert(BallTreeDensity, em)
end
manikde!(em::TreeBelief) = convert(BallTreeDensity, em)

## =============================================================================
# helper functions for tree message channels
## =============================================================================

"""
    $SIGNATURES

Reset the state of all variables in a clique to not initialized.

Notes
- resets numberical values to zeros.

Dev Notes
- TODO not all kde manifolds will initialize to zero.
- FIXME channels need to be consolidated
"""
function resetCliqSolve!( dfg::AbstractDFG,
                          treel::AbstractBayesTree,
                          cliq::TreeClique;
                          solveKey::Symbol=:default)
  #
  cda = getCliqueData(cliq)
  vars = getCliqVarIdsAll(cliq)
  for varis in vars
    resetVariable!(dfg, varis, solveKey=solveKey)
  end
  # TODO remove once consolidation with upMsgs is done
  putCliqueMsgUp!(cda, LikelihoodMessage() )

  # cda.dwnMsg = LikelihoodMessage()
  putCliqueInitMsgDown!(cda, LikelihoodMessage() )

  setCliqueStatus!(cliq, :null)
  setCliqueDrawColor!(cliq, "")
  return nothing
end

function resetCliqSolve!( dfg::AbstractDFG,
                          treel::AbstractBayesTree,
                          frt::Symbol;
                          solveKey::Symbol=:default  )
  #
  resetCliqSolve!(dfg, treel, getClique(treel, frt), solveKey=solveKey)
end

## =============================================================================
# helper functions to add tree messages to subgraphs
## =============================================================================

function updateSubFgFromDownMsgs!(sfg::G,
                                  dwnmsgs::LikelihoodMessage,
                                  seps::Vector{Symbol} ) where G <: AbstractDFG
  #
  # sanity check basic Bayes (Junction) tree property
  # length(setdiff(keys(dwnmsgs), seps)) == 0 ? nothing : error("updateSubFgFromDownMsgs! -- separators and dwnmsgs not consistent")

  # update specific variables in sfg from msgs
  for (key,beldim) in dwnmsgs.belief
    if key in seps
      setValKDE!(sfg, key, manikde!(beldim.val,beldim.bw[:,1],getManifolds(beldim.variableType)), false, beldim.inferdim)
    end
  end

  nothing
end

function generateMsgPrior(belief_::TreeBelief, ::NonparametricMessage)
  kdePr = manikde!(belief_.val, belief_.bw[:,1], getManifolds(belief_.variableType))
  MsgPrior(kdePr, belief_.inferdim)
end

function generateMsgPrior(belief_::TreeBelief, ::ParametricMessage)
  msgPrior = if size(belief_.val, 2) == 1 && size(belief_.val, 1) == 1
    MsgPrior(Normal(belief_.val[1], sqrt(belief_.bw[1])), belief_.inferdim)
  elseif size(belief_.val, 2) == 1 && 1 != size(belief_.val, 1)
    mvnorm = createMvNormal(belief_.val[:,1], belief_.bw)
    mvnorm !== nothing ? nothing : (return DFGFactor[])
    MsgPrior(mvnorm, belief_.inferdim)
  end
  return msgPrior
end

"""
    $SIGNATURES

Return `Dict{Int, Vector{Symbol}}` where each `Int` is a new subgraph and the vector contains all variables
connected to that subgraph.  Subgraphs connectivity is defined by factors of the [`selectFactorType`](@ref)
type -- e.g. `Pose2` variables connected by a chain of `Pose2Pose2` factors is connected, but not if a link
is `Pose2Pose2Range`.  This function is specifically intended for use with `MessageRelativeLikelihoods` in mind
to determine which relative and prior factors should be included in an upward belief propagation (joint) message.
Each returned subgraph should receive a `MsgPrior` on the dominant variable.

Notes
- Disconnected subgraphs in the separator variables of a clique should instead be connected by a
  `TangentAtlasFactor` approximation -- i.e. when analytical `selectFactorType`s cannot be used.
- Internally does `getfield(Main, Symbol(factorname::Core.TypeName))` which might cause unique situations with weird user functions
  - As well as a possible speed penalty -- TODO, investigate

Related

[`_calcCandidatePriorBest`](@ref)
"""
function _findSubgraphsFactorType(dfg_::AbstractDFG,
                                  jointrelatives::MsgRelativeType,
                                  separators::Vector{Symbol} )
  #
  commonJoints = []
  subClassify = Dict{Symbol,Int}()
  newClass = 0

  # 1. count separtor connectivity in UPWARD_DIFFERENTIAL
  sepsCount = Dict{Symbol, Int}()
  map(x->(sepsCount[x]=0), separators)
  # tagsFilter = [:__LIKELIHOODMESSAGE__;]
  # tflsf = lsf(fg, tags=tagsFilter)
  for likl in jointrelatives
    for vari in likl.variables
      sepsCount[vari] += 1
    end
  end

  # 2. start with 0's as subgraphs
  for (id, count) in sepsCount
    if count == 0
      # also keep second list just to be sure based on labels
      newClass += 1
      subClassify[id] = newClass
    end
  end

  # 3. then < 0 and search all paths, adding each hit to subgraph classifications
  for key1 in setdiff(keys(sepsCount), keys(subClassify))
    if !(key1 in keys(subClassify))
      newClass += 1
      subClassify[key1] = newClass
    end
    # if sepsCount[key1] == 1
      # search connectivity throughout remaining variables, some duplicate computation occurring
      for key2 in setdiff(keys(sepsCount), keys(subClassify))
        defaultFct = selectFactorType(dfg_, key1, key2)
        # @show key1, key2, defaultFct
        # TODO validate getfield Main here
        # resname = defaultFct isa UnionAll ? getfield(Main, defaultFct.body.name |> Symbol) : defaultFct
        resname = defaultFct isa UnionAll ? getfield(Main, nameof(defaultFct.body)) : defaultFct
        pth = findShortestPathDijkstra(dfg_, key1, key2, typeFactors=[resname;], initialized=true)
        # check if connected to existing subClass
        if 0 == length(pth)
          # not connected, so need new class
          newClass += 1
          subClassify[key2] = newClass
        else
          # is connected, so add existing class of key1
          subClassify[key2] = subClassify[key1]
        end
      end
    # end
  end

  # 4. inverse classification dictionary
  allClasses = Dict{Int, Vector{Symbol}}()
  for (key, cls) in subClassify
    if isInitialized(dfg_, key)
      !haskey(allClasses, cls) ? (allClasses[cls] = Symbol[key;]) : union!(allClasses[cls],[key;])
    end
  end

  #
  return allClasses
end

"""
    $SIGNATURES

Build from a `LikelihoodMessage` a temporary distributed factor graph object containing differential
information likelihood factors based on values in the messages.

Notes
- Modifies tfg argument by adding `:__UPWARD_DIFFERENTIAL__` factors.

DevNotes
- Initial version which only works for Pose2 and Point2 at this stage.
"""
function addLikelihoodsDifferential!( msgs::LikelihoodMessage,
                                      cliqSubFG::AbstractDFG,
                                      tfg::AbstractDFG=initfg() )
  # create new local dfg and add all the variables with data

  for difflikl in msgs.jointmsg.relatives
    addFactor!(cliqSubFG, difflikl.variables, difflikl.likelihood, graphinit=false, tags=[:__LIKELIHOODMESSAGE__; :__UPWARD_DIFFERENTIAL__] )
  end

  # listVarByDim = Symbol[]
  # for (label, val) in msgs.belief
  #   push!(listVarByDim, label)
  #   if !exists(tfg, label)
  #     addVariable!(tfg, label, val.variableType)
  #     @debug "New variable added to subfg" _group=:check_addLHDiff #TODO JT remove debug.
  #   end
  #   initManual!(tfg, label, manikde!(val))
  # end

  # # list all variables in order of dimension size
  # alreadylist = Symbol[]
  # listDims = getDimension.(getVariable.(tfg,listVarByDim))
  # per = sortperm(listDims, rev=true)
  # listVarDec = listVarByDim[per]
  # listVarAcc = reverse(listVarDec)
  # # add all differential factors (without deconvolution values)
  # for sym1_ in listVarDec
  #   push!(alreadylist, sym1_)
  #   for sym2_ in setdiff(listVarAcc, alreadylist)
  #     nfactype = selectFactorType(tfg, sym1_, sym2_)
  #     # assume default helper function # buildFactorDefault(nfactype)
  #     nfct = nfactype()
  #     afc = addFactor!(tfg, [sym1_;sym2_], nfct, graphinit=false, tags=[:DUMMY;])
  #     # calculate the general deconvolution between variables
  #     pts = solveFactorMeasurements(tfg, afc.label)
  #     newBel = manikde!(pts[1], getManifolds(nfactype))
  #     # replace dummy factor with real deconv factor using manikde approx belief measurement
  #     fullFct = nfactype(newBel)
  #     deleteFactor!(tfg, afc.label)
  #     addFactor!( cliqSubFG, [sym1_;sym2_], fullFct, graphinit=false, tags=[:__LIKELIHOODMESSAGE__; :__UPWARD_DIFFERENTIAL__] )
  #   end
  # end

  return tfg
end
# default verbNoun API spec (dest, src)
addLikelihoodsDifferential!(subfg::AbstractDFG, msgs::LikelihoodMessage) = addLikelihoodsDifferential!(msgs, subfg)

# child CSM calculates the differential factors that should be sent up
# FIXME, must be renamed and standardized
function addLikelihoodsDifferentialCHILD!(cliqSubFG::AbstractDFG,
                                          seps::Vector{Symbol},
                                          tfg::AbstractDFG=initfg() )
  #
  # return list of differential factors the parent should add as part upward partial joint posterior
  retlist = MsgRelativeType()

  # create new local dfg and add all the variables with data
  for label in seps
    if !exists(tfg, label)
      addVariable!(tfg, label, getVariableType(cliqSubFG, label))
      @debug "New variable added to subfg" _group=:check_addLHDiff #TODO JT remove debug.
    end
    initManual!(tfg, label, getBelief(cliqSubFG, label))
  end

  # list all variables in order of dimension size
  alreadylist = Symbol[]
  listDims = getDimension.(getVariable.(tfg, seps))
  per = sortperm(listDims, rev=true)
  listVarDec = seps[per]
  listVarAcc = reverse(listVarDec)
  # add all differential factors (without deconvolution values)
  for sym1_ in listVarDec
    push!(alreadylist, sym1_)
    for sym2_ in setdiff(listVarAcc, alreadylist)
      isHom, ftyps = isPathFactorsHomogeneous(cliqSubFG, sym1_, sym2_)
      # chain of user factors are of the same type
      if isHom
        _sft = selectFactorType(tfg, sym1_, sym2_)
        sft = _sft()
        # only take factors that are homogeneous with the generic relative
        if typeof(sft).name == ftyps[1]
          # assume default helper function # buildFactorDefault(nfactype)
          afc = addFactor!(tfg, [sym1_;sym2_], sft, graphinit=false, tags=[:DUMMY;])
          # calculate the general deconvolution between variables
          pts, = approxDeconv(tfg, afc.label)  # solveFactorMeasurements
          # @show sft
          newBel = manikde!(pts, sft) # getManifolds(sft)
          # replace dummy factor with real deconv factor using manikde approx belief measurement
          fullFct = _sft(newBel)
          deleteFactor!(tfg, afc.label)
          push!(retlist, (;variables=[sym1_;sym2_], likelihood=fullFct))
        end
      end
    end
  end

  return retlist
end

# use variableList to select a sub-subgraph -- useful for disconnected segments of graph
# NOTE expect msgbeliefs to contain all required keys passed in via special variableList
function _calcCandidatePriorBest( subfg::AbstractDFG,
                                  msgbeliefs::Dict,
                                  # msgs::LikelihoodMessage,
                                  variableList::Vector{Symbol}=collect(keys(msgbeliefs))  )
  #
  ## TODO repackage as new function for wider use
  len = length(variableList)
  dims = Vector{Int}(undef, len)
  syms = Vector{Symbol}(undef, len)
  biAdj = Vector{Int}(undef, len)
  # TODO, not considering existing priors for MsgPrior placement at this time
  # priors = Vector{Int}(undef, len)
  i = 0
  for (label, val) in msgbeliefs
    # skip elements not in variableList
    (label in variableList) ? nothing : continue
    # do calculations based on dimension
    i += 1
    dims[i] = getDimension(val.variableType)
    syms[i] = label
    biAdj[i] = ls(subfg, label) |> length
  end
  # work only with highest dimension variable
  maxDim = maximum(dims)
  dimMask = dims .== maxDim
  mdAdj = biAdj[dimMask]
  pe = sortperm(mdAdj, rev=true) # decending

  # @show variableList, keys(msgbeliefs)
  # @show syms
  return (syms[dimMask])[pe][1]
end

"""
    $SIGNATURES

Generate `MsgPriors` required for upward message joint.  Follows which relative factors ("differentials")
should also be added.

Notes
- Might skip some priors based on `msg.hasPriors`
- This might still be hard to work with, will be clear once engaged in codebase
- TODO obviously much consolidation to do here

Related

[`_findSubgraphsFactorType`](@ref), [`_calcCandidatePriorBest`](@ref)
"""
function _generateSubgraphMsgPriors(subfg::AbstractDFG,
                                    allClasses::Dict{Int, Vector{Symbol}},
                                    msgbeliefs::Dict,
                                    msgHasPriors::Bool,
                                    msgType::MessageType  )
  #
  priorsJoint = MsgPriorType()

  # 5. find best variable of each of allClasses to place MsgPrior
  for (id, syms) in allClasses
    # if any `jointmsg per variable && !msg.hasPriors`, then dont add a prior
    if (1 == length(syms) || msgHasPriors) && 0 < length(msgbeliefs)
      whichVar = IIF._calcCandidatePriorBest(subfg, msgbeliefs, syms)
      priorsJoint[whichVar] = IIF.generateMsgPrior(TreeBelief(getVariable(subfg, whichVar)), msgType)
    end
  end

  # return the required priors
  return priorsJoint
end

"""
    $SIGNATURES

Generate relative and prior factors that make up the joint msg likelihood.

DevNotes
- Non-standard relative likelihoods will be populated by TAF factors, removing priors assumption.
"""
function _generateMsgJointRelativesPriors(cfg::AbstractDFG,
                                          cliq::TreeClique  )
  #
  separators = getCliqSeparatorVarIds(cliq)
  jointrelatives = addLikelihoodsDifferentialCHILD!( cfg, separators )
  allClasses = IIF._findSubgraphsFactorType( cfg, jointrelatives, separators )
  hasPriors = 0 < length( intersect(getCliquePotentials(cliq), lsfPriors(cfg)) )

  msgbeliefs = Dict{Symbol, TreeBelief}()
  IIF._buildTreeBeliefDict!(msgbeliefs, cfg, cliq )

  # @show cliq.id, ls(cfg), keys(msgbeliefs), allClasses
  upmsgpriors = IIF._generateSubgraphMsgPriors( cfg, allClasses, msgbeliefs, hasPriors, IIF.NonparametricMessage())

  _MsgJointLikelihood(relatives=jointrelatives, priors=upmsgpriors)
end

"""
    $SIGNATURES

Place a single message likelihood prior on the highest dimension variable with highest connectivity in existing subfg.
"""
function addLikelihoodPriorCommon!( subfg::AbstractDFG,
                                    msg::LikelihoodMessage;
                                    tags::Vector{Symbol}=Symbol[]  )
  #
  tags__ = union(Symbol[:__LIKELIHOODMESSAGE__;:__UPWARD_COMMON__], tags)
  # find if any orphaned variables exist
  for (lbl, msgpr) in msg.jointmsg.priors
    # don't add numerical gauge reference unless absolutely necessary
    if msg.hasPriors || 0 == length(ls(subfg, lbl))
      # finally add the single AbstractPrior from LikelihoodMessage
      addFactor!(subfg, [lbl], msgpr, graphinit=false, tags=tags__)
    end
  end

  # # find max dimension variable, which also has highest biadjacency
  # topCandidate = _calcCandidatePriorBest(subfg, msg.belief)

  # # get prior for top candidate
  # msgPrior = generateMsgPrior(msg.belief[topCandidate], msg.msgType)

  # # get ready
  # tags__ = union(Symbol[:__LIKELIHOODMESSAGE__;:__UPWARD_COMMON__], tags)
  # # finally add the single AbstractPrior from LikelihoodMessage
  # addFactor!(subfg, [topCandidate], msgPrior, graphinit=false, tags=tags__)
end

"""
    $SIGNATURES

Special function to add a few variables and factors to the clique sub graph required for downward solve in CSM.

Dev Notes
- There is still some disparity on whether up and down solves of tree should use exactly the same subgraph...  'between for up and frontal connected for down'
"""
function addDownVariableFactors!( dfg::AbstractDFG,
                                  subfg::InMemoryDFGTypes,
                                  cliq::TreeClique,
                                  logger=ConsoleLogger();
                                  solvable::Int=1  )
  #
  # determine which variables and factors needs to be added
  currsyms = ls(subfg)
  allclsyms = getCliqVarsWithFrontalNeighbors(dfg, cliq, solvable=solvable)
  newsyms = setdiff(allclsyms, currsyms)
  with_logger(logger) do
    @info "addDownVariableFactors!, cliq=$(cliq.id), newsyms=$newsyms"
  end
  frtls = getCliqFrontalVarIds(cliq)
  with_logger(logger) do
    @info "addDownVariableFactors!, cliq=$(cliq.id), frtls=$frtls"
  end
  allnewfcts = union(map(x->findFactorsBetweenFrom(dfg,union(currsyms, newsyms),x), frtls)...)
  newfcts = setdiff(allnewfcts, lsf(subfg))
  with_logger(logger) do
    @info "addDownVariableFactors!, cliq=$(cliq.id), newfcts=$newfcts, allnewfcts=$allnewfcts"
  end

  #TODO solvable?
  DFG.mergeGraph!(subfg, dfg, newsyms, newfcts)

  return newsyms, newfcts
end

"""
    $SIGNATURES

Modify the `subfg::AbstractDFG` to include `msgs` as priors that are used
during clique inference.

Notes
- May be used initialization or inference, in both upward and downward directions.
- `msgs` are identified by variable label `::Symbol`, and my consist of multiple beliefs.
- Message sets from different cliques are identified by clique id `::Int`.
- assume lower limit on number of particles is 5.
- messages from children stored in vector or dict.

DevNotes
- TODO Split dispatch on `dir`, rather than internal `if` statement.

Related

`deleteMsgFactors!`
"""
function addMsgFactors!(subfg::AbstractDFG,
                        msg::LikelihoodMessage,
                        dir::Type{<:MessagePassDirection};
                        tags::Vector{Symbol}=Symbol[],
                        attemptPriors::Bool=true  )
  #
  # add messages as priors to this sub factor graph
  msgfcts = DFGFactor[]
  # TODO, expand -- this deconv approach only works for NonparametricMessage at this time.
  if  getSolverParams(subfg).useMsgLikelihoods &&
      dir == UpwardPass &&
      msg.msgType isa NonparametricMessage
    #
    if 0 < length(msg.belief)
      # currently only works for nonparametric
      addLikelihoodsDifferential!(subfg, msg)          # :__UPWARD_DIFFERENTIAL__
      if attemptPriors
        # will only be added based on internal tests
        prFcts = addLikelihoodPriorCommon!(subfg, msg)   # :__UPWARD_COMMON__
      end
    end
  else
    svars = DFG.listVariables(subfg)
    tags__ = union(Symbol[:__LIKELIHOODMESSAGE__;], tags)
    dir == DownwardPass ? push!(tags__, :__DOWNWARD_COMMON__) : nothing
    for (msym, belief_) in msg.belief
      if msym in svars
        msgPrior = generateMsgPrior(belief_, msg.msgType)
        fc = addFactor!(subfg, [msym], msgPrior, graphinit=false, tags=tags__)
        push!(msgfcts, fc)
      end
    end
  end
  return msgfcts
end

function addMsgFactors!(subfg::AbstractDFG,
                        allmsgs::Dict{Int,LikelihoodMessage},
                        dir::Type{<:MessagePassDirection};
                        tags::Vector{Symbol}=Symbol[] )
  #
  allfcts = DFGFactor[]
  for (cliqid, msgs) in allmsgs
    # do each dict in array separately
    newfcts = addMsgFactors!(subfg, msgs, dir, tags=tags)
    union!( allfcts, newfcts )
  end
  return allfcts
end

"""
    $SIGNATURES

Delete from the subgraph`::AbstractDFG` prior belief `msgs` that could/would be used
during clique inference.

DevNotes
- TODO make `::Vector{Symbol}` version.

Related

`addMsgFactors!`
"""
function deleteMsgFactors!( subfg::AbstractDFG,
                            fcts::Vector{DFGFactor} )
  #
  for fc in fcts
    deleteFactor!(subfg, fc.label)
  end
end
# deleteMsgFactors!(::LightDFG{SolverParams,DFGVariable,DFGFactor}, ::Array{DFGFactor{CommonConvWrapper{MsgPrior{BallTreeDensity}},1},1})

function deleteMsgFactors!( subfg::AbstractDFG,
                            tags::Vector{Symbol}=[:__LIKELIHOODMESSAGE__])
  # remove msg factors that were added to the subfg
  facs = lsf(subfg, tags=tags)
  deleteFactor!.(subfg, facs)
  return facs
end

#TODO JT can be removed, used as sanity check
function removeSeparatorPriorsFromSubgraph!(cliqSubFg::AbstractDFG, cliq::TreeClique)
  cliqSeparatorVarIds = getCliqSeparatorVarIds(cliq)
  priorIds = Symbol[]
  for v in cliqSeparatorVarIds
    facs = getNeighbors(cliqSubFg, v)
    for f in facs
      isprior = length(getFactor(cliqSubFg, f)._variableOrderSymbols) == 1
      isprior && push!(priorIds, f)
      isprior && DFG.deleteFactor!(cliqSubFg, f)
    end
  end
  return priorIds
end

## =============================================================================
## Prepare Clique Up or Down Msgs
## =============================================================================

function _buildTreeBeliefDict!( msgdict::Dict{Symbol, TreeBelief},
                                subfg::AbstractDFG,
                                cliq::TreeClique,
                                sdims=getCliqVariableMoreInitDims(subfg, cliq);
                                duplicate::Bool=true )
  #
  # TODO better logging
  # with_logger(logger) do
  #   @info "$(now()), prepCliqInitMsgsUp, seps=$seps, sdims=$sdims"
  # end

  seps = getCliqSeparatorVarIds(cliq)
  for vid in seps
    var = DFG.getVariable(subfg, vid)
    var = duplicate ? deepcopy(var) : var
    if isInitialized(var)
      msgdict[var.label] = TreeBelief(var, solvableDim=sdims[var.label])
    end
  end
  nothing
end

#TODO rename to just prepCliqueMsgUp
"""
    $SIGNATURES

Prepare the upward inference messages from clique to parent and return as `Dict{Symbol}`.

Notes
- Does not require tree message likelihood factors in subfg.
- Also see #579 regarding elimited likelihoods and priors.

DevNotes
- set `msgs.hasPriors=true` only if a prior occurred here or lower down in tree branch.
"""
function prepCliqueMsgUpConsolidated( subfg::AbstractDFG,
                                      cliq::TreeClique,
                                      status::CliqStatus=getCliqueStatus(cliq);
                                      logger=ConsoleLogger(),
                                      duplicate::Bool=true )
  #
  # get the current clique status
  sdims = getCliqVariableMoreInitDims(subfg, cliq)

  # construct init's up msg to place in parent from initialized separator variables
  hasPriors = 0 < (lsfPriors(subfg) |> length)
  msg = LikelihoodMessage(status=status, hasPriors=hasPriors)

  _buildTreeBeliefDict!(msg.belief,subfg,cliq,duplicate=duplicate )

  # seps = getCliqSeparatorVarIds(cliq)
  # for vid in seps
  #   var = DFG.getVariable(subfg, vid)
  #   var = duplicate ? deepcopy(var) : var
  #   if isInitialized(var)
  #     msg.belief[var.label] = TreeBelief(var, solvableDim=sdims[var.label])
  #   end
  # end

  msg.jointmsg = IIF._generateMsgJointRelativesPriors( subfg, cliq )
  # FIXME calculate the new DIFFERENTIAL factors
  # retval = addLikelihoodsDifferentialCHILD!(subfg, getCliqSeparatorVarIds(cliq))
  # msg.jointmsg.relatives = retval

  return msg
end

#TODO rename to just prepCliqueMsgDown
"""
    $SIGNATURES

Calculate new and then set the down messages for a clique in Bayes (Junction) tree.
"""
function prepSetCliqueMsgDownConsolidated!( subfg::AbstractDFG,
                                            cliq::TreeClique,
                                            prntDwnMsgs::LikelihoodMessage,
                                            logger=ConsoleLogger();
                                            status::CliqStatus=getCliqueStatus(cliq)  )
  #
  allvars = getCliqVarIdsAll(cliq)
  allprntkeys = collect(keys(prntDwnMsgs.belief))
  passkeys = intersect(allvars, setdiff(allprntkeys,ls(subfg)))
  remainkeys = setdiff(allvars, passkeys)
  newDwnMsgs = LikelihoodMessage(status=status)

  # some msgs are just pass through from parent
  for pk in passkeys
    newDwnMsgs.belief[pk] = prntDwnMsgs.belief[pk]
  end

  # set solvable dimensions
  # sdims = getCliqVariableMoreInitDims(subfg, cliq)

  # other messages must be extracted from subfg
  for mk in remainkeys
    setVari = getVariable(subfg, mk)
    if isInitialized(setVari)
      newDwnMsgs.belief[mk] = TreeBelief(setVari)  #, solvableDim=sdims[mk] )
    end
  end

  # set the downward keys
  with_logger(logger) do
    @info "cliq $(cliq.id), getSetDownMessagesComplete!, allkeys=$(allvars), passkeys=$(passkeys), msgkeys=$(collect(keys(newDwnMsgs.belief)))"
  end

  return newDwnMsgs
end

## =============================================================================
## Multimessage assemblies from multiple cliques
## =============================================================================
#TODO check as it looks outdated nothing covered after this

#TODO function is currently broken as getUpMsgs does not exist, possibly deprecated?
# DF, I did some digging and got this far
# v0.14 @deprecate getUpMsgs(x...) getMsgsUpThis(x...)
#       @deprecate getMsgsUpThis(x...) getMsgUpThis(x...)
#         getMsgUpThis(cdat::BayesTreeNodeData) = fetch(getMsgUpChannel(cdat))
# v0.16 @deprecate getMsgUpThis(x...;kw...) fetchMsgUpThis(x...;kw...)
# fetchMsgUpThis was never properly deprecated, see #1053
"""
    $SIGNATURES

Return dictionary of all up belief messages currently in a Bayes `tree`.

Notes
- Returns `::Dict{Int,LikelihoodMessage}`

DevNotes
- see #1053, `getUpMsgs` --> `fetchMsgUpThis` v0.16

Related

getUpMsgs
"""
function getTreeCliqUpMsgsAll(tree::AbstractBayesTree)
  allUpMsgs = Dict{Int,LikelihoodMessage}()
  for (idx,cliq) in getCliques(tree)
    msgs = getUpMsgs(cliq)
    allUpMsgs[cliq.id] = LikelihoodMessage()
    for (lbl,msg) in msgs
      # TODO capture the inferred dimension as part of the upward propagation
      allUpMsgs[cliq.id].belief[lbl] = msg
    end
  end
  return allUpMsgs
end

"""
    $SIGNATURES

Convert tree up messages dictionary to a new dictionary relative to variables specific messages and their depth in the tree

Notes
- Used in RoMEPlotting
- Return data in `TempUpMsgPlotting` format:
    Dict{Symbol,   -- is for variable label
      Vector{       -- multiple msgs for the same variable
        Symbol,      -- Clique index
        Int,         -- Depth in tree
        BTD          -- Belief estimate
        inferredDim  -- Information count
      }
"""
function stackCliqUpMsgsByVariable( tree::AbstractBayesTree,
                                    tmpmsgs::Dict{Int, LikelihoodMessage}  )
  #
  # start of the return data structure
  stack = TempUpMsgPlotting()

  # look at all the clique level data
  for (cidx,tmpmsg) in tmpmsgs
    # look at all variables up msg from each clique
    for (sym,msgdim) in tmpmsg.belief
      # create a new object for a particular variable if hasnt been seen before
      if !haskey(stack,sym)
        # FIXME this is an old message type
        stack[sym] = Vector{Tuple{Symbol, Int, BallTreeDensity, Float64}}()
      end
      # assemble metadata
      cliq = getClique(tree,cidx)
      frt = getCliqFrontalVarIds(cliq)[1]
      # add this belief msg and meta data to vector of variable entry
      push!(stack[sym], (frt, getCliqDepth(tree, cliq),msgdim[1], msgdim[2]))
    end
  end

  return stack
end

"""
    $SIGNATURES

Return dictionary of down messages consisting of all frontal and separator beliefs of this clique.

Notes:
- Fetches numerical results from `subdfg` as dictated in `cliq`.
- return LikelihoodMessage
"""
function getCliqDownMsgsAfterDownSolve(subdfg::AbstractDFG, cliq::TreeClique)
  # Dict{Symbol, BallTreeDensity}
  # where the return msgs are contained
  container = LikelihoodMessage()

  # go through all msgs one by one
  for sym in getCliqAllVarIds(cliq)
    container.belief[sym] = TreeBelief( getVariable(subdfg, sym) )
  end

  # return the result
  return container
end

"""
    $SIGNATURES

Calculate a new down message from the parent.

DevNotes
- FIXME should be handled in CSM
"""
function convertLikelihoodToVector( prntmsgs::Dict{Int, LikelihoodMessage};
                                    logger=SimpleLogger(stdout) )
  #
  # check if any msgs should be multiplied together for the same variable

  # FIXME type instability
  msgspervar = Dict{Symbol, Vector{TreeBelief}}()
  for (msgcliqid, msgs) in prntmsgs
    # with_logger(logger) do  #   @info "convertLikelihoodToVector -- msgcliqid=$msgcliqid, msgs.belief=$(collect(keys(msgs.belief)))"  # end
    for (msgsym, msg) in msgs.belief
      # re-initialize with new type
      varType = typeof(msg.variableType)
      # msgspervar = msgspervar !== nothing ? msgspervar : Dict{Symbol, Vector{TreeBelief{varType}}}()
      if !haskey(msgspervar, msgsym)
        # there will be an entire list...
        msgspervar[msgsym] = TreeBelief{varType}[]
      end
      # with_logger(logger) do  @info "convertLikelihoodToVector -- msgcliqid=$(msgcliqid), msgsym $(msgsym), inferdim=$(msg.inferdim)"  # end
      push!(msgspervar[msgsym], msg)
    end
  end

  return msgspervar
end

#


text:
using JuMP, EAGO

                     m = Model()

                     EAGO.register_eago_operators!(m)

                     @variable(m, -1 <= x[i=1:4] <= 1)

                     @variable(m, -41.21023060076703 <= q <= 39.01192102445897)

                     add_NL_constraint(m, :(swish(-0.296746779395487 + 0.5509866377924739*swish(-0.36537726371933 + -0.13236748618316563*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.8938439926067105*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.2026514795524368*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.4969096390589627*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + -0.850208463612319*swish(-0.13805861779585626 + 0.8324190447258686*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.45691763611374503*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.0018061937798208305*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.06838129719944464*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.14361846152386626*swish(0.892089992500452 + -0.9262441239021939*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.1220711338530176*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.013243228467184842*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.22830737094249542*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.12455164844812394*swish(-0.09971606472325156 + 0.22050596868305217*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.9537528744420904*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.13795746696872868*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.0643190431003462*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))))) + swish(-0.7906046812278151 + -0.2168623555923963*swish(-0.36537726371933 + -0.13236748618316563*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.8938439926067105*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.2026514795524368*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.4969096390589627*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.3937942437507238*swish(-0.13805861779585626 + 0.8324190447258686*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.45691763611374503*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.0018061937798208305*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.06838129719944464*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.013414887338259796*swish(0.892089992500452 + -0.9262441239021939*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.1220711338530176*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.013243228467184842*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.22830737094249542*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + -0.20160941359718088*swish(-0.09971606472325156 + 0.22050596868305217*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.9537528744420904*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.13795746696872868*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.0643190431003462*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))))) + swish(0.21825887860627402 + 0.23342217391611308*swish(-0.36537726371933 + -0.13236748618316563*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.8938439926067105*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.2026514795524368*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.4969096390589627*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.7638006108327029*swish(-0.13805861779585626 + 0.8324190447258686*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.45691763611374503*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.0018061937798208305*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.06838129719944464*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.4051674738413942*swish(0.892089992500452 + -0.9262441239021939*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.1220711338530176*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.013243228467184842*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.22830737094249542*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.17219310126869347*swish(-0.09971606472325156 + 0.22050596868305217*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.9537528744420904*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.13795746696872868*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.0643190431003462*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))))) + swish(0.8210746038366681 + -0.06951431198870361*swish(-0.36537726371933 + -0.13236748618316563*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.8938439926067105*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.2026514795524368*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.4969096390589627*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.9856384884704164*swish(-0.13805861779585626 + 0.8324190447258686*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.45691763611374503*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.0018061937798208305*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.06838129719944464*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + -0.2856111885860577*swish(0.892089992500452 + -0.9262441239021939*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.1220711338530176*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.013243228467184842*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.22830737094249542*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4])))) + 0.04937870878523665*swish(-0.09971606472325156 + 0.22050596868305217*swish(0.24726246482452874 + -0.2513871312104543*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.4677853214537917*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + -0.10088601735084568*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.6507022966434817*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.9537528744420904*swish(0.30866893537934104 + -0.11067617174498023*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.7749548972944802*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.44318801341623093*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + 0.23547099627350976*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + -0.13795746696872868*swish(-0.39572563026399044 + -0.2902839675147266*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + 0.2975675315855191*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.808554335286296*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.2217074058396178*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))) + 0.0643190431003462*swish(0.8092602903578396 + -0.8861475410157751*swish(-0.7954573007956682 + 0.11924049292543248*$(x[1]) + 0.1731334424011517*$(x[2]) + -0.6758597754938092*$(x[3]) + 0.13301420625435734*$(x[4])) + -0.38211269748902854*swish(-0.7274702539948783 + 0.17282628886946716*$(x[1]) + 0.018302754525115095*$(x[2]) + 0.800298561254523*$(x[3]) + -0.4821070372998202*$(x[4])) + 0.47211467596801615*swish(-0.4299065646425082 + -0.1572016654178685*$(x[1]) + 0.08953552697871814*$(x[2]) + 0.5995804212147959*$(x[3]) + -0.3420773339437706*$(x[4])) + -0.8428121402295612*swish(0.440020919910439 + 0.27581141739825465*$(x[1]) + 0.9904718804451909*$(x[2]) + -0.9775405312317109*$(x[3]) + 0.5010243235294203*$(x[4]))))) - $q <= 0.0))

                     @objective(m, Min, q)

                     return m

max_stars_repo_name: PSORLab/RSActivationFunctions

max_issues_repo_name: PSORLab/RSActivationFunctions

max_forks_repo_name: PSORLab/RSActivationFunctions


text:
export stylesheet

"""
    `function stylesheet(href::String; args...) :: String`

Generates the corresponding HTML `link` tag to reference the CSS stylesheet at `href`.

### Example

```julia
julia> stylesheet("https://fonts.googleapis.com/css?family=Material+Icons")
"<link href=\"https://fonts.googleapis.com/css?family=Material+Icons\" rel=\"stylesheet\" />"
```
"""
function stylesheet(href::String; args...) :: ParsedHTMLString
  Genie.Renderer.Html.link(href=href, rel="stylesheet", args...)
end


text:
# Unit tests for analysis/initialization.jl

@testset "analysis/initialization.jl" begin

end