From 02cd49706c19f57c812ee032cf865c888d144c5f Mon Sep 17 00:00:00 2001 From: avinashresearch1 Date: Fri, 12 Jul 2024 11:25:18 +0200 Subject: [PATCH] feat: initial point generator [WIP] --- .../Gundersen_4_stream/Gundersen_4_stream.jl | 2 +- Project.toml | 15 +- ext/CompHENSNetworkXPlotsExt.jl | 156 ++++++++++++++++++ src/CompHENS.jl | 2 +- .../conda_networkx_plots.jl | 131 +-------------- .../starting_point_generator.jl | 26 ++- 6 files changed, 190 insertions(+), 142 deletions(-) create mode 100644 ext/CompHENSNetworkXPlotsExt.jl diff --git a/Examples/XLSX_interface/ClassicHENSProblem/Gundersen_4_stream/Gundersen_4_stream.jl b/Examples/XLSX_interface/ClassicHENSProblem/Gundersen_4_stream/Gundersen_4_stream.jl index a9b92dd..1c27687 100644 --- a/Examples/XLSX_interface/ClassicHENSProblem/Gundersen_4_stream/Gundersen_4_stream.jl +++ b/Examples/XLSX_interface/ClassicHENSProblem/Gundersen_4_stream/Gundersen_4_stream.jl @@ -6,7 +6,7 @@ using Plots using JuMP using Test -using BARON +#using BARON #exportall(CompHENS) diff --git a/Project.toml b/Project.toml index d48dc18..875becb 100644 --- a/Project.toml +++ b/Project.toml @@ -4,7 +4,6 @@ authors = ["Avinash Subramanian"] version = "0.1.4" [deps] -BARON = "2e2ca445-9e14-5b13-8677-4410f177f82b" Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" @@ -15,11 +14,16 @@ Kwonly = "18d08c8c-0732-55ee-a446-91a51d7b4206" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" NamedArrays = "86f7a689-2022-50b4-a561-43c23ac3c673" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" XLSX = "fdbf4ff8-1666-58a4-91e7-1b58723a45e0" +[weakdeps] +PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" + +[extensions] +CompHENSNetworkXPlotsExt = "PyCall" + [compat] -BARON = "0.8" +Conda = "1" DataFrames = "1" DocStringExtensions = "0.9" HiGHS = "1" @@ -29,10 +33,9 @@ Kwonly = "0.1" MathOptInterface = "1" NamedArrays = "0.9" Plots = "1" -XLSX = "0.8, 0.9" -julia = "1.6" PyCall = "1" -Conda = "1" +XLSX = "0.8, 0.9" +julia = "1.10" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/ext/CompHENSNetworkXPlotsExt.jl b/ext/CompHENSNetworkXPlotsExt.jl new file mode 100644 index 0000000..49a9108 --- /dev/null +++ b/ext/CompHENSNetworkXPlotsExt.jl @@ -0,0 +1,156 @@ +module CompHENSNetworkXPlotsExt + + using CompHENS + using PyCall + using Conda + + const nx = PyNULL() + const plt = PyNULL() + const back_pdf = PyNULL() + + + function __init__() + copy!(nx, pyimport_conda("networkx", "networkx")) + copy!(plt, pyimport_conda("matplotlib.pyplot", "matplotlib")) + copy!(back_pdf, pyimport_conda("matplotlib.backends.backend_pdf", "matplotlib")) + end + + """ + $(TYPEDSIGNATURES) + The visualization tools for the HEN uses the Python `NetworkX` and `MatPlotlib` packages. + By default, OS-X and Windows users should PyCall configured to use the Miniconda environment installed at `.julia/conda/` (this can be attained by calling `Conda.ROOTENV`). + For Linux users: By default the default system installation is used, and it is necessary to over-ride this as follows: + - Set + ``` + ENV["PYTHON"]="" + using Pkg + Pkg.build("PyCall") + ``` + Then **restart** the Julia process. + """ + function CompHENS.plot_HEN_streamwise(prob::ClassicHENSProblem, model::AbstractModel, overall_network::Dict{String, AbstractSuperstructure}, file_name; digits = 1) + __init__() + pdf = CompHENS.back_pdf.PdfPages(file_name) + for stream in prob.all_names + plt.close() + (g, edge_labels, node_labels, position, node_size) = get_stream_graph(prob.all_dict[stream], prob, model, overall_network[stream]; digits = digits) + nx.draw_networkx(g, position, node_size = node_size, with_labels=false, arrowstyle="->", node_shape = "s") + nx.draw_networkx_labels(g, position, labels = node_labels, font_size = 3, horizontalalignment = "left", verticalalignment = "top") + nx.draw_networkx_edge_labels(g, position, edge_labels = edge_labels, horizontalalignment = "center", verticalalignment = "center", font_size = 2, rotate=false) + pdf.savefig() + end + pdf.close() + end + + """ + + + Gets a NetworkX Digraph for each stream + Returns: (g, edge_labels, node_labels, position, node_size) + """ + function CompHENS.get_stream_graph(stream::AbstractStream, prob::ClassicHENSProblem, model::AbstractModel, superstructure::AbstractSplitSuperstructure; digits = 1) + g = nx.DiGraph() + edge_labels = Dict() + node_labels = Dict() + + # Add nodes to NetworkX graph + for node in superstructure.nodes + g.add_node(node.name) + if node isa HX + match = node.match + if stream isa HotStream + node_labels[node.name] = "match: $(match), Q = $(round((prob.results_dict[:Q][match, stream.name]), digits = digits))" + elseif stream isa ColdStream + node_labels[node.name] = "match: $(match), Q = $(round((prob.results_dict[:Q][stream.name, match]), digits = digits))" + end + end + end + + # Only add edges if f_edge is greater than 0 + for edge in superstructure.edges + if value(model[:f][(stream.name, edge)]) > 0.0 + g.add_edge(edge.in.name, edge.out.name) + edge_labels[(edge.in.name, edge.out.name)] = "m: $(round(value(model[:f][(stream.name, edge)]); digits = digits)) T: $(round(value(model[:t][(stream.name, edge)]); digits = digits))" + end + end + + num_matches = length(prob.results_dict[:HLD_list][stream.name]) + # Copied from SeqHENS.jl + # Setting the coordinates of the nodes + position = Dict() + coordinates = [] # Array to keep pushing paired coordinates to, will then go through and assign to dictionary + bfix = 0.4 # Determines the vertical spacing + + push!(coordinates, (0,0)) + push!(coordinates, (1,0)) + for e in 1:num_matches + push!(coordinates,(2,0-(bfix*(e-1)))) + push!(coordinates,(5,0-(bfix*(e-1)))) + push!(coordinates,(9,0-(bfix*(e-1)))) + end + push!(coordinates,(10,0)) + push!(coordinates,(11,0)) + + i = 0 # hack for now + for node in superstructure.nodes + i += 1 + position[node.name] = coordinates[i] + end + + node_size = fill(1.0, length(superstructure.nodes)) + return(g, edge_labels, node_labels, position, node_size) + end + + function CompHENS.get_stream_graph(stream::AbstractUtility, prob::ClassicHENSProblem, model::AbstractModel, superstructure::AbstractSplitSuperstructure; digits = 1) + g = nx.DiGraph() + edge_labels = Dict() + node_labels = Dict() + + # Add nodes to NetworkX graph + for node in superstructure.nodes + g.add_node(node.name) + if node isa HX + match = node.match + if stream isa HotStream + node_labels[node.name] = "o: $(match), Q = $(round((prob.results_dict[:Q][match, stream.name]), digits = digits))" + elseif stream isa ColdStream + node_labels[node.name] = "o: $(match), Q = $(round((prob.results_dict[:Q][stream.name, match]), digits = digits))" + end + end + end + + # Only add edges if f_edge is greater than 0 + for edge in superstructure.edges + if edge.in isa HX || edge.out isa HX # Only care about edges attached to HX + g.add_edge(edge.in.name, edge.out.name) + edge_labels[(edge.in.name, edge.out.name)] = "T: $(round(value(model[:t][(stream.name, edge)]); digits = digits))" + end + end + + num_matches = length(prob.results_dict[:HLD_list][stream.name]) + # Copied from SeqHENS.jl + # Setting the coordinates of the nodes + position = Dict() + coordinates = [] # Array to keep pushing paired coordinates to, will then go through and assign to dictionary + bfix = 0.4 # Determines the vertical spacing + + push!(coordinates, (0,0)) + push!(coordinates, (1,0)) + for e in 1:num_matches + push!(coordinates,(2,0-(bfix*(e-1)))) + push!(coordinates,(5,0-(bfix*(e-1)))) + push!(coordinates,(9,0-(bfix*(e-1)))) + end + push!(coordinates,(10,0)) + push!(coordinates,(11,0)) + + i = 0 # hack for now + for node in superstructure.nodes + i += 1 + position[node.name] = coordinates[i] + end + + node_size = fill(1.0, length(superstructure.nodes)) + return(g, edge_labels, node_labels, position, node_size) + end +end \ No newline at end of file diff --git a/src/CompHENS.jl b/src/CompHENS.jl index 3527442..2364cdd 100644 --- a/src/CompHENS.jl +++ b/src/CompHENS.jl @@ -103,7 +103,7 @@ include("Superstructures/ParallelSplit.jl") export generate_network!, postprocess_network!, plot_HEN_streamwise, print_stream_results, get_design_area, AreaArithmeticMean, AreaPaterson, CostScaledPaterson, get_stream_graph include("SubProblems/Network_generation/network_generator_JuMP.jl") include("SubProblems/Network_generation/network_postprocess.jl") -include("SubProblems/Network_generation/conda_networkx_plots.jl") +#include("SubProblems/Network_generation/conda_networkx_plots.jl") diff --git a/src/SubProblems/Network_generation/conda_networkx_plots.jl b/src/SubProblems/Network_generation/conda_networkx_plots.jl index 26e395f..85bae41 100644 --- a/src/SubProblems/Network_generation/conda_networkx_plots.jl +++ b/src/SubProblems/Network_generation/conda_networkx_plots.jl @@ -1,16 +1,3 @@ -using Conda, PyCall - -const nx = PyNULL() -const plt = PyNULL() -const back_pdf = PyNULL() - - -function __init__() - copy!(nx, pyimport_conda("networkx", "networkx")) - copy!(plt, pyimport_conda("matplotlib.pyplot", "matplotlib")) - copy!(back_pdf, pyimport_conda("matplotlib.backends.backend_pdf", "matplotlib")) -end - """ $(TYPEDSIGNATURES) The visualization tools for the HEN uses the Python `NetworkX` and `MatPlotlib` packages. @@ -24,18 +11,7 @@ Pkg.build("PyCall") ``` Then **restart** the Julia process. """ -function plot_HEN_streamwise(prob::ClassicHENSProblem, model::AbstractModel, overall_network::Dict{String, AbstractSuperstructure}, file_name; digits = 1) - __init__() - pdf = CompHENS.back_pdf.PdfPages(file_name) - for stream in prob.all_names - plt.close() - (g, edge_labels, node_labels, position, node_size) = get_stream_graph(prob.all_dict[stream], prob, model, overall_network[stream]; digits = digits) - nx.draw_networkx(g, position, node_size = node_size, with_labels=false, arrowstyle="->", node_shape = "s") - nx.draw_networkx_labels(g, position, labels = node_labels, font_size = 3, horizontalalignment = "left", verticalalignment = "top") - nx.draw_networkx_edge_labels(g, position, edge_labels = edge_labels, horizontalalignment = "center", verticalalignment = "center", font_size = 2, rotate=false) - pdf.savefig() - end - pdf.close() +function plot_HEN_streamwise() end """ @@ -44,108 +20,5 @@ end Gets a NetworkX Digraph for each stream Returns: (g, edge_labels, node_labels, position, node_size) """ -function get_stream_graph(stream::AbstractStream, prob::ClassicHENSProblem, model::AbstractModel, superstructure::AbstractSplitSuperstructure; digits = 1) - g = nx.DiGraph() - edge_labels = Dict() - node_labels = Dict() - - # Add nodes to NetworkX graph - for node in superstructure.nodes - g.add_node(node.name) - if node isa HX - match = node.match - if stream isa HotStream - node_labels[node.name] = "match: $(match), Q = $(round((prob.results_dict[:Q][match, stream.name]), digits = digits))" - elseif stream isa ColdStream - node_labels[node.name] = "match: $(match), Q = $(round((prob.results_dict[:Q][stream.name, match]), digits = digits))" - end - end - end - - # Only add edges if f_edge is greater than 0 - for edge in superstructure.edges - if value(model[:f][(stream.name, edge)]) > 0.0 - g.add_edge(edge.in.name, edge.out.name) - edge_labels[(edge.in.name, edge.out.name)] = "m: $(round(value(model[:f][(stream.name, edge)]); digits = digits)) T: $(round(value(model[:t][(stream.name, edge)]); digits = digits))" - end - end - - num_matches = length(prob.results_dict[:HLD_list][stream.name]) - # Copied from SeqHENS.jl - # Setting the coordinates of the nodes - position = Dict() - coordinates = [] # Array to keep pushing paired coordinates to, will then go through and assign to dictionary - bfix = 0.4 # Determines the vertical spacing - - push!(coordinates, (0,0)) - push!(coordinates, (1,0)) - for e in 1:num_matches - push!(coordinates,(2,0-(bfix*(e-1)))) - push!(coordinates,(5,0-(bfix*(e-1)))) - push!(coordinates,(9,0-(bfix*(e-1)))) - end - push!(coordinates,(10,0)) - push!(coordinates,(11,0)) - - i = 0 # hack for now - for node in superstructure.nodes - i += 1 - position[node.name] = coordinates[i] - end - - node_size = fill(1.0, length(superstructure.nodes)) - return(g, edge_labels, node_labels, position, node_size) -end - -function get_stream_graph(stream::AbstractUtility, prob::ClassicHENSProblem, model::AbstractModel, superstructure::AbstractSplitSuperstructure; digits = 1) - g = nx.DiGraph() - edge_labels = Dict() - node_labels = Dict() - - # Add nodes to NetworkX graph - for node in superstructure.nodes - g.add_node(node.name) - if node isa HX - match = node.match - if stream isa HotStream - node_labels[node.name] = "o: $(match), Q = $(round((prob.results_dict[:Q][match, stream.name]), digits = digits))" - elseif stream isa ColdStream - node_labels[node.name] = "o: $(match), Q = $(round((prob.results_dict[:Q][stream.name, match]), digits = digits))" - end - end - end - - # Only add edges if f_edge is greater than 0 - for edge in superstructure.edges - if edge.in isa HX || edge.out isa HX # Only care about edges attached to HX - g.add_edge(edge.in.name, edge.out.name) - edge_labels[(edge.in.name, edge.out.name)] = "T: $(round(value(model[:t][(stream.name, edge)]); digits = digits))" - end - end - - num_matches = length(prob.results_dict[:HLD_list][stream.name]) - # Copied from SeqHENS.jl - # Setting the coordinates of the nodes - position = Dict() - coordinates = [] # Array to keep pushing paired coordinates to, will then go through and assign to dictionary - bfix = 0.4 # Determines the vertical spacing - - push!(coordinates, (0,0)) - push!(coordinates, (1,0)) - for e in 1:num_matches - push!(coordinates,(2,0-(bfix*(e-1)))) - push!(coordinates,(5,0-(bfix*(e-1)))) - push!(coordinates,(9,0-(bfix*(e-1)))) - end - push!(coordinates,(10,0)) - push!(coordinates,(11,0)) - - i = 0 # hack for now - for node in superstructure.nodes - i += 1 - position[node.name] = coordinates[i] - end - - node_size = fill(1.0, length(superstructure.nodes)) - return(g, edge_labels, node_labels, position, node_size) +function get_stream_graph() end diff --git a/src/SubProblems/Network_generation/starting_point_generator.jl b/src/SubProblems/Network_generation/starting_point_generator.jl index d4f0c0e..483f59a 100644 --- a/src/SubProblems/Network_generation/starting_point_generator.jl +++ b/src/SubProblems/Network_generation/starting_point_generator.jl @@ -1,13 +1,13 @@ #[WIP] -#= -exportall(CompHENS) -verbose && @info "Solving the Network Generation subproblem" +#exportall(CompHENS) + +#verbose && @info "Solving the Network Generation subproblem" haskey(prob.results_dict, :y) || error("Stream match data not available. Solve corresponding subproblem first.") haskey(prob.results_dict, :Q) || error("HLD data not available. Solve corresponding subproblem first.") haskey(prob.results_dict, :HLD_list) || error("Match list data not available. Solve corresponding subproblem first.") -haskey(prob.results_dict, :T_bounds) || generate_temperature_bounds!(prob) +haskey(prob.results_dict, :T_bounds) || CompHENS.generate_temperature_bounds!(prob) #y, Q = prob.results_dict[:y], prob.results_dict[:Q] @@ -33,6 +33,22 @@ end @variable(model, 0.0 <= t[all_e_tuple_vec]) @variable(model, 0.0 <= f[stream_e_tuple_vec]) +#TODO: +function test_terminal_match() +end + +function get_utility_match_start_vals() +end + utils_dict = merge(prob.cold_utilities_dict, prob.hot_utilities_dict) + for (k,v) in utils_dict + @show k + end + (k,v) = first(utils_dict) + matched_streams = prob.results_dict[:HX_list][k] + for stream in matched_streams + @show stream + end + #function set_start_values!(prob, EMAT, overall_network; verbose = verbose) # 1. Initialize the required dictionaries for book-keeping: prob.results_dict[:unflagged_matches] = deepcopy(filter(prob.results_dict[:HX_list]) do (k,v) @@ -57,6 +73,6 @@ The, `working_terminal_temp` is changed from `T_out` and calculated for each add #function set_terminal_match!(model::AbstractModel, prob, stream::ColdStream, superstructure::AbstractSplitSuperstructure, match ; verbose = true) # A. Set starting values for the flows: set_start_value(model[:t][(stream.name, only(out_edges(only(superstructure.source), superstructure)))], 69.0) -=# +