diff --git a/src/merge.jl b/src/merge.jl index dcf7f7c..d7d97b8 100644 --- a/src/merge.jl +++ b/src/merge.jl @@ -1,4 +1,5 @@ export merge_graphs; +export split_lincomb!; # Change a symbol name using prefix & postfix function translate_keyname(key, prefix, postfix, skip_basic, input) @@ -115,3 +116,71 @@ function merge_graphs( return Compgraph{T}(operations, parents, coeffs, outputs) end + + +""" + (g,cref_modified,new_crefs)=split_lincomb!(g,node,ind2; + newnode=node_new, + cref_list=[]) + +Takes the lincomb operation in node and splits it into two lincombs, by +creating a new node newnode. The new node consists of the linear combination +of the coefficients moving (node, ind2[1]),... (node,ind2[end]) and the +old lincomb object has the old coefficients and an additional term pointing +to newnode. The cref_list is updated to the new coefficient pointers. The +new_crefs list contains all the new coefficient pointers. + + +In this way, the graph is unchanged but one of the linear combinations is +split up into two. + +""" +function split_lincomb!(g,node,ind2; + newnode=Symbol("$(node)_new"), + cref_list=[]) + + @show newnode + # get ind1 = complement of ind2 + nof_lincombs=size(g.coeffs[node],1); + @show nof_lincombs + ind1=map(i -> !(i in ind2), 1:nof_lincombs) + + org_parents=g.parents[node]; + org_coeffs=g.coeffs[node]; + + @show org_coeffs + + # Move ind2 to a new lincomb + add_lincomb!(g,newnode,org_coeffs[ind2],org_parents[ind2]) + + @show newnode + # Store ind1 lincomb info + new_parents1=[org_parents[ind1];newnode] + new_coeffs1=[org_coeffs[ind1];1] + + # Update the node lincomb data to point ind2 + newnode + empty!(g.coeffs[node]); + push!(g.coeffs[node], new_coeffs1...) + empty!(g.parents[node]); + push!(g.parents[node], new_parents1...) + + + # Update the cref_list + + new_crefs=[]; + replace_list=Dict(); + for (j,i)=enumerate(ind2); + replace_list[(node,i)]=(newnode,j) + push!(new_crefs,(newnode,j)); + end + + + for (cref_old,cref_new) in replace_list + @show cref_old + @show cref_new + ii=findall( [cref_old] .== cref_list ) + map(j -> cref_list[j]=cref_new, ii); + end + + return (g,cref_list,new_crefs) +end diff --git a/test/merge_graphs.jl b/test/merge_graphs.jl index a92bf4c..7ff9eee 100644 --- a/test/merge_graphs.jl +++ b/test/merge_graphs.jl @@ -37,3 +37,48 @@ using LinearAlgebra ) @test eval_graph(graph_4, A) ≈ eval_graph(graph, eval_graph(graph, A)) end +@testset "split_lincomb" begin + + A=[ + 0.196064 -1.18798 0.0 0.0 0.0 0.0 0.0 + 0.342678 0.793844 0.684638 0.0 0.0 0.0 0.0 + 1.26005 0.819614 -1.21473 -0.16794 0.0 0.0 0.0 + -0.10478 1.50713 0.138891 0.652377 -0.580547 0.0 0.0 + -0.803933 -1.96458 0.679152 -0.0471995 -0.0454885 -0.715895 0.0 + -0.327724 -1.89847 -0.435685 1.44764 -0.928145 3.06844 1.19071]; + B=[1.46284 0.594921 0.0 0.0 0.0 0.0 0.0 + 0.71404 -0.492136 -0.481715 0.0 0.0 0.0 0.0 + 0.237897 -0.946491 0.0070323 1.87826 0.0 0.0 0.0 + 0.0444275 -1.77078 -0.772886 0.89719 1.55139 0.0 0.0 + -0.310057 -1.13217 1.40868 0.864775 -1.14717 -0.662986 0.0 + -0.160165 -0.525442 0.676407 -0.934459 0.259851 -0.608684 -0.381333]; + c=[-0.5210883864869685 + -0.5011935108466905 + 0.9989082416364822 + 1.1643621428307982 + -1.4603489516355923 + 2.405378746857791 + 1.7841340060684932 + 0.233340850959019]; + + degopt=Degopt(A,B,c); + n=size(A,1); + (g,cref)=graph_degopt(degopt); + g_org=deepcopy(g); + node=cref[50][1];; + ind2=[3;6]; + (g,crefs,new_crefs)=split_lincomb!(g,node,ind2; + newnode=Symbol("$(node)_new"), + cref_list=[]) + + # Check that it is unmodified + @test eval_graph(g,0.1) ≈ eval_graph(g_org,0.1) + + + # Check that changing a variable has the same effect + set_coeffs!(g_org,[3.3],[(node,ind2[1])]) + set_coeffs!(g,[3.3],[new_crefs[1]]) + + @test eval_graph(g,0.3) ≈ eval_graph(g_org,0.3) + +end