Question

I have an algorithm that finds the minimum of function/n on Rn. And I have a constrain manifold, that is given in a form of singular cube image. Mapping singular cube inner space to Rn and more importantly vice versa is quite trivial and can be done with unar function from_R_to_01 applied to every coordinate.

So what I want to do is to take my target function F of some arity, and make another function of the same arity, which will be the same F, except its' coordinates are to be mapped from Rn to a constrain manifold Man. Therefore I can give it to my minimization algorithm, get a pair of coordinates in Rn and then map them too to the same manifold to get "real world" coordinates. Therefore to reduce nonlinear programming task to unconstrained optimization.

Well, back to the question. I have this piece of code working for a 2-ar case.

minn_man2(F, Man) ->
    OnRn = fun (X, Y) ->  # this is the limiting part
        OnMan = Man( from_R_to_01( X ), from_R_to_01( Y ) ),
        apply( F, OnMan )
    end,
    [X | [ Y | []]] = minn( OnRn ),
    Man( from_R_to_01( X ), from_R_to_01( Y ) ).

How can I make it more general? The hardest part is making an anonymous function of Fs' arity. Have no idea how to do this at all.

Was it helpful?

Solution 2

Think I've got it! If I need to have an explicit declaration of OnRn for each certain arity, why don't I make them.

First I have manually wrote two separate declarations for unar and binar Mans in a single 'case MA of' statement. Then I've got lazy and used python to generate me a whole bunch of these. Then I looked for a some kind of eval to make Erlang generate and evaluate the appropriate declaration on the run. And here it is. Works like a charm.

minn_man(F, Man) ->
    MA = proplists:get_value( arity, erlang:fun_info( Man )),
    R1 = fun (X) -> from_R_to_01(X) end,

    XiStr = string:join(["X" ++ integer_to_list(I) || I <- lists:seq(1, MA)], ", "),
    RiXiStr = string:join(["R1(X" ++ integer_to_list(I) ++ ")" || I <- lists:seq(1, MA)], ", "),
    FunStr = "fun (" ++ XiStr ++ ") -> apply( F, Man(" ++ RiXiStr ++")) end.",

    {ok, Tokens, _} = erl_scan:string(FunStr),
    {ok, [Form]} = erl_parse:parse_exprs(Tokens),
    Binding1 = erl_eval:add_binding('F', F, erl_eval:new_bindings()), 
    Binding2 = erl_eval:add_binding('Man', Man, Binding1), 
    Binding3 = erl_eval:add_binding('R1', R1, Binding2),
    {value, OnRn, _} = erl_eval:expr(Form, Binding3),

    XY = minn( OnRn ),
    apply(Man, lists:map(fun from_R_to_01/1, XY ) ).

OTHER TIPS

You can only simulate have functions (anonymous or not) with variable arity by giving them a single argument that is a list. Then you can use apply/2 on it to evaluate it.

Your example could be (not tested or optimized at all) something like

minn_man(F, Man) ->
    OnRn = fun (L) ->  
        OnMan = apply(Man, [from_R_to_01( X ) || X<-L]),
        apply( F, OnMan )
    end,
Man( [from_R_to_01( X ) || X<-minn( OnRn )).

Of course, Man should return the values in an adequate format, too.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top