AnyMath 文档
Notebook

Engee函数中的掩码和字符串

在Engee中,您可以向块添加简单的用户界面。 这称为块掩蔽。 掩模可用于向用户隐藏单元的内部结构。 这是一个很棒的技术,让我们从[最后一篇文章](https://engee.com/community/ru/catalogs/projects/prodvinutaia-razrabotka-blokov-engee )。

我们使用的EF_pdist2函数有一个可选参数,即计算模式(度量)。 在项目期间,我们将让用户有机会通过掩码进行控制。

In [ ]:
include("PDIST2.jl");

让我们记住模块代码的样子。:

In [ ]:
;cat PDIST2.jl
module PDIST2

mode_dict_t = Dict(1=>"euclidean",2=>"squaredeuclidean",3=>"manhattan",4=>"cosine")

function EF_pdist2(X::Matrix{Float64}, Y::Matrix{Float64}; metric::String="euclidean")
    m, n = size(X)
    p, n2 = size(Y)
    n == n2 || throw(DimensionMismatch("Number of columns in X and Y must match"))

    if metric == "euclidean"
        XX = sum(X.^2, dims=2)
        YY = sum(Y.^2, dims=2)
        D = XX .+ YY' .- 2 .* (X * Y')
        return sqrt.(max.(D, 0))
    
    elseif metric == "squaredeuclidean"
        XX = sum(X.^2, dims=2)
        YY = sum(Y.^2, dims=2)
        D = XX .+ YY' .- 2 .* (X * Y')
        return max.(D, 0)
    
    elseif metric == "manhattan"
        D = zeros(m, p)
        for j in 1:p
            for i in 1:m
                D[i, j] = sum(abs.(X[i, :] .- Y[j, :]))
            end
        end
        return D
    
    elseif metric == "cosine"
        XX = sqrt.(sum(X.^2, dims=2))
        YY = sqrt.(sum(Y.^2, dims=2))
        norms = XX .* YY'
        XY = X * Y'
        
        # Handle division by zero: set invalid entries to 0, then correct cases where both vectors are zero
        sim = zeros(size(XY))
        valid = norms .> 0
        sim[valid] .= XY[valid] ./ norms[valid]
        
        # Identify pairs where both vectors are zero (cosine similarity = 1)
        both_zero = (XX .== 0) .& (YY' .== 0)
        sim[both_zero] .= 1
        
        return 1 .- sim
    
    else
        throw(ArgumentError("Unknown metric: $metric. Supported metrics are 'euclidean', 'squaredeuclidean', 'manhattan', 'cosine'"))
    end
end


end

如何将字符串从掩码传递给Engee函数?

在屏蔽Engee函数之前,有必要考虑一个功能限制-Engee函数不能使用类型参数。 String. 但计算方法是由字符串设置的。 因此,我们需要用一定的数字对选定的方法进行编码,将这个数字作为参数传递给Engee函数,然后对其进行解码。 换句话说,掩码将不需要一个参数,而是两个。 然后你可以实现这样的方案:

image.png

我们将使用字典解码计算模式,因为Dict(字典)数据类型实现了键值对的集合。 在这种情况下,密钥可以是任何基本类型。 因此,甚至可以制作这样的字典。:

mode_dict_t = Dict(1=>"euclidean",2=>"squaredeuclidean",3=>"manhattan",4=>"cosine")

可以看出,这里的key是一个整数,value是一个字符串。 这使我们能够执行以下操作:

In [ ]:
EF_mode = PDIST2.mode_dict_t[1]
Out[0]:
"euclidean"

现在让我们来看看Engee功能块方法的代码。:

include("/user/start/examples/base_simulation/advanced_block_masking/PDIST2.jl")

mutable struct Block <: AbstractCausalComponent
	cache::Matrix{Float64};
	modeC::Int64
	function Block()
    		c = zeros(Float64,INPUT_SIGNAL_ATTRIBUTES[1].dimensions);
    		info("Allocated $(Base.summarysize(c)) bytes for pdist2")
    		info("Selected $(PDIST2.mode_dict_t[mode])")
    		new(c,mode)
	end
end

function (c::Block)(t::Real, in1, in2)
    try
        c.cache = PDIST2.EF_pdist2(in1,in2;metric=PDIST2.mode_dict_t[c.modeC]);
    catch
        error("Matrix Dimensions should be equal!")
        stop_simulation()
    end

    return c.cache
end

modeC是一个从掩码中获取数字变量值的参数(请参阅)。 因此,我们可以将计算方法传递给我们的PDIST2函数为

PDIST2.mode_dict_t[c.modeC]

我们将通过从下拉列表中回调"真实"参数来获取数字。:

if mask.parameters.mask_mode.value == "euclidean"
    mask.parameters.mask_mode_int.value = 1;
elseif mask.parameters.mask_mode.value == "squaredeuclidean"
    mask.parameters.mask_mode_int.value = 2;
elseif mask.parameters.mask_mode.value == "manhattan"
    mask.parameters.mask_mode_int.value = 3;
elseif mask.parameters.mask_mode.value == "cosine"
    mask.parameters.mask_mode_int.value = 4;
end

所以面具会是这样的:

image.png

请注意,mask_mode_int参数必须是可计算的。 它是隐藏的,因为我们不想让用户破坏任何东西。

image.png

最后,我们将在所有模式下打开并运行最终模型。:

In [ ]:
demoroot = @__DIR__
mdl = engee.open(joinpath(demoroot,"EF_DF.engee"))
Out[0]:
System(
    name: root,
    id: be446814-cf00-421d-ad5b-484c5f63ca08,
    path: EF_DF
)
In [ ]:
for k in keys(PDIST2.mode_dict_t)
    println("使用$模式(PDIST2)运行模型。mode_dict_t[k])")
    engee.set_param!("EF_DF/PDIST2", "mask_mode"=>PDIST2.mode_dict_t[k])
    engee.run(mdl;verbose=true);
end
Запускаем модель с режимом cosine
Building...
Progress 0%
Progress 100%
Progress 100%
Запускаем модель с режимом squaredeuclidean
Building...
Progress 0%
Progress 100%
Progress 100%
Запускаем модель с режимом manhattan
Building...
Progress 0%
Progress 100%
Progress 100%
Запускаем модель с режимом euclidean
Building...
Progress 0%
Progress 100%
Progress 100%

结论

在项目期间,我们学习了如何将字符串参数放入Engee函数中,并且还以标准的方式使用字典,尽管不显眼。