diff --git a/hens/.gitignore b/hens/.gitignore new file mode 100644 index 0000000..02f1af6 --- /dev/null +++ b/hens/.gitignore @@ -0,0 +1,11 @@ +.DS_Store +*.swp +adaptive_model_mixer/model1/* +adaptive_model_mixer/model2/* +adaptive_model_mixer/model3/* +adaptive_model_mixer/gurobi.log +beta_adaptive_model_mixer/model1/* +beta_adaptive_model_mixer/model2/* +beta_adaptive_model_mixer/model3/* +beta_adaptive_model_mixer/gurobi.log +**/__pycache__/* diff --git a/hens/README.md b/hens/README.md new file mode 100644 index 0000000..46d2d1e --- /dev/null +++ b/hens/README.md @@ -0,0 +1,27 @@ +The code works for: + - python 3.5.2 + - Pyomo 5.0.1 + - PyLaTex 1.0.0 (optional) + - Gurobi + +There are two algorithms in directories: + - ``adaptive_model_mixer`` + - ``beta_adaptive_model_mixer`` + +To find out how to use the code, run from terminal: +```sh + cd + python iterative.py -h +``` +where ``directory`` is one of: + - ``adaptive_model_mixer`` + - ``beta_adaptive_model_mixer`` + +To add your own datafile: + put it in the ``datafiles`` directory and give it the extension ``.dat`` + e.g. if ``example.dat`` is in ``datafiles`` then +```sh + cd adaptive_model_mixer + python iterative.py example anyAlphaNumericThingCanGoHere +``` +should work and a directory named ``example`` containing the results will be created. diff --git a/hens/adaptive_model_mixer/iterative.py b/hens/adaptive_model_mixer/iterative.py new file mode 100644 index 0000000..20bc37e --- /dev/null +++ b/hens/adaptive_model_mixer/iterative.py @@ -0,0 +1,258 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import pyomo.environ +import sys, os, copy, time, socket + +from multiprocessing import Process, cpu_count + +from pyomo.opt import SolverFactory +from pprint import pprint + +from lib.iterations_helper import * +from lib.results_generator.results_builder import build_heat_exchanger_results +from lib.constants import * + + +def can_terminate_absolute(epsilons, max_errors): + if epsilons[balancing_ref] <= max_errors[balancing_ref][absolute_error]: + return False + if epsilons[reclmtd_ref] <= max_errors[reclmtd_ref][absolute_error]: + return False + if epsilons[area_ref] <= max_errors[area_ref][absolute_error]: + return False + if epsilons[beta_ref] <= max_errors[beta_ref][absolute_error]: + return False + return True + + +def can_terminate_relative(epsilons, max_errors): + if epsilons[balancing_ref] <= max_errors[balancing_ref][relative_error]: + print('balancing: %s, %s' % (str(max_errors[balancing_ref][relative_error]),str(epsilons[balancing_ref]))) + return False + if epsilons[reclmtd_ref] <= max_errors[reclmtd_ref][relative_error]: + print('lmtd: %s, %s' % (str(max_errors[reclmtd_ref][relative_error]),str(epsilons[reclmtd_ref]))) + return False + if epsilons[area_ref] <= max_errors[area_ref][relative_error]: + print('area: %s, %s' % (str(max_errors[area_ref][relative_error]),str(epsilons[area_ref]))) + return False + if epsilons[beta_ref] <= max_errors[beta_ref][relative_error]: + print('beta: %s, %s' % (str(max_errors[beta_ref][relative_error]),str(epsilons[beta_ref]))) + return False + return True + +termination_func = can_terminate_relative + +start = time.time() + +maxIters = 500 + +number_of_cores = cpu_count() + +argparser = initialise_parser() +args = argparser.parse_args() + +validate_and_assign_args(args) + +folders = create_output_dir('.', args.model, args.run_name) + +output_file = open(os.path.join(folders[append_folder], 'output.txt'), 'w') +results_file = open(os.path.join(folders[append_folder], 'results.csv'), 'w') + +results_file.write('iteration, tac, time, total_time\n') + +datafile = '../datafiles/' + args.model + '.dat' + +solver = 'gurobi' +opt = SolverFactory(solver) +if args.num_threads: + opt.options[ 'threads' ] = min(number_of_cores, args.num_threads) + +opt.options[ 'MIPFocus' ] = 1 + +tolerances = { + 'IntFeasTol': -1, + 'FeasibilityTol': -1, + 'OptimalityTol': -1 +} + +if args.tighten_tol: + opt.options[ 'IntFeasTol' ] = 0.000000001 + opt.options[ 'FeasibilityTol' ] = 0.000000001 + opt.options[ 'OptimalityTol' ] = 0.000000001 + tolerances['IntFeasTol'] = 0.000000001 + tolerances['FeasibilityTol'] = 0.000000001 + tolerances['OptimalityTol'] = 0.000000001 +else: + if args.IntFeasTol: + opt.options[ 'IntFeasTol' ] = args.IntFeasTol + tolerances[ 'IntFeasTol' ] = args.IntFeasTol + if args.FeasibilityTol: + opt.options[ 'FeasibilityTol' ] = args.FeasibilityTol + tolerances[ 'FeasibilityTol' ] = args.FeasibilityTol + if args.OptimalityTol: + opt.options[ 'OptimalityTol' ] = args.OptimalityTol + tolerances[ 'OptimalityTol' ] = args.OptimalityTol + if args.MarkowitzTol: + opt.options[ 'MarkowitzTol' ] = args.MarkowitzTol + tolerances[ 'MarkowitzTol' ] = args.MarkowitzTol + +model = initialise_hx_model(datafile) + +warmstart = False + +default_eps = 0.0001 + +epsilons = { + balancing_ref: default_eps, + reclmtd_ref: default_eps, + area_ref: default_eps, + beta_ref: default_eps +} + +if args.all_error: + eps = args.all_error + epsilons[balancing_ref] = eps + epsilons[reclmtd_ref] = eps + epsilons[area_ref] = eps + epsilons[beta_ref] = eps +else: + if args.bal_eps: + epsilons[balancing_ref] = args.bal_eps + if args.lmtd_eps: + epsilons[reclmtd_ref] = args.lmtd_eps + if args.area_eps: + epsilons[area_ref] = args.area_eps + if args.beta_eps: + epsilons[beta_ref] = args.beta_eps + +if args.absolute: + termination_func = can_terminate_absolute + +iterations = 1 + +new_points = copy.deepcopy(get_all_points()) + +output_file.write('Running:\n') +output_file.write('\tAdaptive Model\n') +output_file.write('\t' + args.model + '\n') +output_file.write('on: '+ socket.gethostname() + '\n\n') + +iter_finish = start + +for run in range(1, maxIters): + iter_start = iter_finish + + print('Running iteration ', run) + + instance = model.create_instance(datafile) + output_file.write('----------------------------------\n') + output_file.write('---- Run: ' + str(run) + '\n') + output_file.write('----------------------------------\n') + + opt.options[ 'LogFile' ] = os.path.join(folders[ logs_folder ], 'gur' + str(run).zfill(len(str(maxIters))) + '.log') + + results = opt.solve(instance, tee=False) + + instance.solutions.load_from(results) + + old_points = new_points + + active_hx, inactive_hx = get_active_hx(instance) + + new_tangent_points = get_new_tangent_points(instance, active_hx) + added_tangents = add_new_tangent_points(new_tangent_points) + new_q_breakpoints = get_new_q_breakpoints(instance, active_hx) + new_beta_breakpoints = get_new_beta_breakpoints(instance, active_hx) + new_balancing_breakpoints = get_new_balancing_breakpoints(instance, active_hx, inactive_hx, args.weaken) + + new_points = copy.deepcopy(get_all_points()) + + output_file.write('----------------------------------\n') + output_file.write('---- TAC: ' + str(value(instance.TAC)) + '\n') + output_file.write('----------------------------------\n') + output_file.write('\n') + output_file.write('Found ActiveHx:\n') + pprint(active_hx, output_file) + output_file.write('\n') + output_file.write('Adding Tangents at:\n') + pprint(added_tangents, output_file) + output_file.write('\n') + output_file.write('Adding Balancing breakpoints at:\n') + pprint(new_balancing_breakpoints, output_file) + output_file.write('\n') + output_file.write('Adding q breakpoints at:\n') + pprint(new_q_breakpoints, output_file) + output_file.write('\n') + output_file.write('Adding area beta breakpoints at:\n') + pprint(new_beta_breakpoints, output_file) + output_file.write('\n') + + output_file.flush() + + iter_finish = time.time() + + local_time = iter_finish-iter_start + total_time = iter_finish-start + + print('\tTAC: %f' % value(instance.TAC)) + print('\tTook: %.2fs' % local_time) + print('\tTotal: %.2fs' % total_time) + + results_file.write('%d, %s, %s, %s\n' % (run, str(value(instance.TAC)), str(local_time), str(total_time))) + + results_file.flush() + + errors = summarise_errors(instance, active_hx, inactive_hx, args.weaken) + max_errors = get_max_errors(errors, active_hx, inactive_hx, args.weaken) + + filename = 'iteration' + str(run).zfill(len(str(maxIters))) + t = Process(target=build_heat_exchanger_results, args=(instance, folders, args.run_name, run, args.model, filename, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances), kwargs={'iteration': True}) + t.start() + + if termination_func(epsilons, max_errors): + print('/*/*/*/*//*/*/*/*//*/*/*/*//*/*/*/') + print('----------------------------------') + print('---- Completed Within Error') + print('----------------------------------') + print('/*/*/*/*//*/*/*/*//*/*/*/*//*/*/*/') + break + + if len(added_tangents) == 0 \ + and len(new_beta_breakpoints) == 0\ + and len(new_q_breakpoints) == 0\ + and len(new_balancing_breakpoints) == 0: + print('/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/') + print('---------------------------------------------------') + print('---- Completed No new tangents or breakpoints -----') + print('---------------------------------------------------') + print('/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/') + break + + if args.cont: + if iterations == 1: + var = raw_input('Ran %d iterations. How many more?\n' % run) + while True: + try: + iters = int(var) + except ValueError: + var = raw_input('\'%s\' is not an integer. How many more?\n' % var) + else: + break + + if iters <= 0: + print('/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/') + print('-----------------------------------') + print('---- Completed Not Continuing -----') + print('-----------------------------------') + print('/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/') + break + else: + iterations = iters + 1 + iterations = iterations - 1 + +if args.print_instance: + instance.pprint() + +output_file.close() +results_file.close() diff --git a/hens/adaptive_model_mixer/lib/__init__.py b/hens/adaptive_model_mixer/lib/__init__.py new file mode 100644 index 0000000..f757ec9 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/__init__.py @@ -0,0 +1,2 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London diff --git a/hens/adaptive_model_mixer/lib/constants.py b/hens/adaptive_model_mixer/lib/constants.py new file mode 100644 index 0000000..4b1ab07 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/constants.py @@ -0,0 +1,165 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +stream_hx = 'stream_hx' +cu_hx = 'cu_hx' +hu_hx = 'hu_hx' + +bal_eps = 'bal_eps' +lmtd_eps = 'lmtd_eps' +area_eps = 'area_eps' +beta_eps = 'beta_eps' + +balancing_ref = 'balancing_ref' +reclmtd_ref = 'reclmtd_ref' +area_ref = 'area_ref' +beta_ref = 'beta_ref' + +breakpoints = 'breakpoints' + +lbl_model = 'model' + +model1 = lbl_model + '1' +model2 = lbl_model + '2' +model3 = lbl_model + '3' + +active_lb = 0.9 + +default_stream_tangent_weights = \ + [\ + (1,0,0),\ + (0,1,0),\ + (0,0,1),\ + (0.5,0.5,0),\ + # (0.75,0.25,0),\ + # (0.25,0.75, 0),\ + # (1/3, 1/3, 1/3),\ + # (1/2, 1/4, 1/4),\ + # (1/4, 1/2, 1/4),\ + # (1/4, 1/4, 1/2)\ + ] + +default_utility_tangent_weights = \ + [\ + (1,0),\ + (0,1),\ + # (0.75,0.25),\ + (0.5,0.5),\ + # (0.25,0.75)\ + ] + +defaultTangentWeights = \ + {\ + stream_hx: default_stream_tangent_weights,\ + cu_hx: default_utility_tangent_weights,\ + hu_hx: default_utility_tangent_weights\ + } + +iterations = 'iterations' +logs = 'logs' + +model_folder = 'model_folder' +append_folder = 'append_folder' +iterations_folder = 'iterations_folder' +logs_folder = 'logs_folder' + +absolute_error = 'absolute_error' +relative_error = 'relative_error' + +reclmtd_error = 'reclmtd_error' +area_error = 'area_error' +area_beta_error = 'area_beta_error' +bhin_error = 'bhin_error' +bhout_error = 'bhout_error' +bcin_error = 'bcin_error' +bcout_error = 'bcout_error' + +tangent_points = 'tangent_points' +q_points = 'q_points' +area_beta_points = 'area_beta_points' +th_points = 'th_points' +thx_points = 'thx_points' +tc_points = 'tc_points' +tcx_points = 'tcx_points' + +index_i = 'i' +index_j = 'j' +index_k = 'k' + +index_m = 'm' +index_n = 'n' + +#Dictionary Keys +latex_label = 'latex_label' +latex_subscript = 'latex_subscript' +latex_superscript = 'latex_superscript' +subscript_indices = 'subscript_indices' +superscript_indices = 'superscript_indices' +all_indices = 'all_indices' + +#Model Labels +area = 'area' +area_cu = 'area_cu' +area_hu = 'area_hu' + +area_beta = 'area_beta' +area_cu_beta = 'area_cu_beta' +area_hu_beta = 'area_hu_beta' + +bh_in = 'bh_in' +bh_out = 'bh_out' +bc_in = 'bc_in' +bc_out = 'bc_out' + +dt = 'dt' +dt_cu = 'dt_cu' +dt_hu = 'dt_hu' + +fh = 'fh' +fc = 'fc' + +reclmtd = 'reclmtd' +reclmtd_cu = 'reclmtd_cu' +reclmtd_hu = 'reclmtd_hu' + +q = 'q' +q_cu = 'q_cu' +q_hu = 'q_hu' + +th = 'th' +tc = 'tc' + +thx = 'thx' +tcx = 'tcx' + +z = 'z' +z_cu = 'z_cu' +z_hu = 'z_hu' + +z_q = 'z_q' +z_q_cu = 'z_q_cu' +z_q_hu = 'z_q_hu' + +var_delta_reclmtd = 'var_delta_reclmtd' +var_delta_reclmtd_cu = 'var_delta_reclmtd_cu' +var_delta_reclmtd_hu = 'var_delta_reclmtd_hu' + +z_th = 'z_th' +z_thx = 'z_thx' +z_tc = 'z_tc' +z_tcx = 'z_tcx' + +var_delta_fh = 'var_delta_fh' +var_delta_fhx = 'var_delta_fhx' +var_delta_fc = 'var_delta_fc' +var_delta_fcx = 'var_delta_fcx' + +z_area_beta = 'z_area_beta' +z_area_cu_beta = 'z_area_cu_beta' +z_area_hu_beta = 'z_area_hu_beta' + +model_map = {\ + 'model1': 'http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen1.html',\ + 'model2': 'http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen2.html',\ + 'model3': 'http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen3.html'\ + } diff --git a/hens/adaptive_model_mixer/lib/iterations_helper.py b/hens/adaptive_model_mixer/lib/iterations_helper.py new file mode 100644 index 0000000..d973be5 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/iterations_helper.py @@ -0,0 +1,748 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import os, sys, bisect + +from argparse import ArgumentParser, RawTextHelpFormatter + +from pprint import pprint + +from pyomo.core.base.numvalue import value +from .model_declarations.model_builder import create_model +from .model_declarations.helper_functions import two_point_generator, three_point_generator, lmtd_inv + +from .constants import * + +stream_tangent_points = {} +cu_tangent_points = {} +hu_tangent_points = {} + +stream_q_points = {} +cu_q_points = {} +hu_q_points = {} + +stream_area_betas = {} +cu_area_betas = {} +hu_area_betas = {} + +th_breakpoints = {} +thx_breakpoints = {} +tc_breakpoints = {} +tcx_breakpoints = {} + +def create_output_dir(root, model, append): + model_dir = root + os.sep + model + append_dir = model_dir + os.sep + append + iterations_dir = append_dir + os.sep + iterations + log_dir = iterations_dir + os.sep + logs + + if not os.path.exists(model_dir): + os.makedirs(model_dir) + + if not os.path.exists(append_dir): + os.makedirs(append_dir) + + if not os.path.exists(iterations_dir): + os.makedirs(iterations_dir) + + if not os.path.exists(log_dir): + os.makedirs(log_dir) + + return {\ + model_folder : model_dir,\ + append_folder : append_dir,\ + iterations_folder: iterations_dir,\ + logs_folder : log_dir,\ + } + +def initialise_parser(): + parser = ArgumentParser() + parser.add_argument('model', help='The model you wish to run e.g. model1 for datafile: ../datafiles/model1.dat') + parser.add_argument('run_name', help='The name of the run you are running the results will be placed in a directory with this name') + parser.add_argument('-i', '--print-instance', help='print instance of final run', action='store_true') + parser.add_argument('-t', '--num-threads', type=int, help='Number of cpu cores used. If this value is larger than the number of cores available the maximum number of cores will be used. Must be a positive integer.') + parser.add_argument('-c', '--cont', help='Get continuation message. Requires feedback after the first 50 iterations.', action='store_true') + parser.add_argument('-w', '--weaken', help='If set doesn\'t add breakpoints for inactive balancing constraints.', action='store_true') + parser.add_argument('-a', '--absolute', help='Use absolute error', action='store_true') + parser.add_argument('--lmtd-eps', help='Max absolute lmtd error, a negative value will terminate when no new tangents are placed. DEFAULT=0.0001', type=float) + parser.add_argument('--bal-eps', help='Max absolute error for balancing bilinearities. DEFAULT=0.0001', type=float) + parser.add_argument('--area-eps', help='Max absolute error for area bilinearities. DEFAULT=0.0001', type=float) + parser.add_argument('--beta-eps', help='Max absolute error for area betas. DEFAULT=0.0001', type=float) + parser.add_argument('-e', '--all-error', help='Max absolute error for all approximations, a negative value will terminate when no new tangents are placed. DEFAULT=0.0001', type=float) + parser.add_argument('-m', '--tighten-tol', help='Tightens tolerances. Sets: IntFeasTol = 1e-9, FeasibilityTol = 1e-9, OptimalityTol = 1e-9', action='store_true') + parser.add_argument('--IntFeasTol', type=float, help='Sets integer feasibility tolerance. Min=1e-9. Default=1e-5. Max=1e-2. Overridden by m flag.') + parser.add_argument('--FeasibilityTol', type=float, help='Sets primal feasibility tolerance. Min=1e-9. Default=1e-6. Max=1e-2. Overridden by m flag.') + parser.add_argument('--OptimalityTol', type=float, help='Sets dual feasibility tolerance. Min=1e-9. Default=1e-6. Max=1e-2. Overridden by m flag.') + parser.add_argument('--MarkowitzTol', type=float, help='Sets threshold pivoting tolerance. Min=1e-4. Default=0.0078125. Max=0.999. Overridden by m flag.') + return parser + +def validate_and_assign_args(args): + if args.num_threads: + if args.num_threads <= 0: + raise ValueError('The number of threads must be positive') + +def add_initial_th_breakpoints(instance): + for i in instance.HP: + for k in instance.ST: + global th_breakpoints + th_breakpoints[i,k] = [m for m in instance.Th_breakpoints[i,k]] + +def add_initial_thx_breakpoints(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global thx_breakpoints + thx_breakpoints[i,j,k] = [m for m in instance.Thx_breakpoints[i,j,k]] + +def add_initial_tc_breakpoints(instance): + for j in instance.CP: + for k in instance.K_Take_First_Stage: + global tc_breakpoints + tc_breakpoints[j,k] = [m for m in instance.Tc_breakpoints[j,k]] + +def add_initial_tcx_breakpoints(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global tcx_breakpoints + tcx_breakpoints[i,j,k] = [m for m in instance.Tcx_breakpoints[i,j,k]] + +def add_initial_stream_tangent_points(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global stream_tangent_points + stream_tangent_points[i,j,k] = three_point_generator(defaultTangentWeights[stream_hx], instance.dt[i,j,k].bounds) + +def add_initial_cu_tangent_points(instance): + for i in instance.HP: + global cu_tangent_points + cu_tangent_points[i] = two_point_generator(defaultTangentWeights[cu_hx], instance.dt_cu[i].bounds) + +def add_initial_hu_tangent_points(instance): + for j in instance.CP: + global hu_tangent_points + hu_tangent_points[j] = two_point_generator(defaultTangentWeights[hu_hx], instance.dt_hu[j].bounds) + +def add_initial_stream_area_beta_points(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global stream_area_betas + stream_area_betas[i,j,k] = [m for m in instance.Area_beta_breakpoints[i,j,k]] + +def add_initial_cu_area_beta_points(instance): + for i in instance.HP: + global cu_area_betas + cu_area_betas[i] = [m for m in instance.Area_cu_beta_breakpoints[i]] + +def add_initial_hu_area_beta_points(instance): + for j in instance.CP: + global hu_area_betas + hu_area_betas[j] = [m for m in instance.Area_hu_beta_breakpoints[j]] + +def add_initial_stream_q_points(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global stream_q_points + stream_q_points[i,j,k] = [m for m in instance.Q_breakpoints[i,j,k]] + +def add_initial_cu_q_points(instance): + for i in instance.HP: + global cu_q_points + cu_q_points[i] = [m for m in instance.Q_cu_breakpoints[i]] + +def add_initial_hu_q_points(instance): + for j in instance.CP: + global hu_q_points + hu_q_points[j] = [m for m in instance.Q_hu_breakpoints[j]] + +def declare_th_breakpoints(model, i, k): + global th_breakpoints + return th_breakpoints[i,k] + +def declare_thx_breakpoints(model, i, j, k): + global thx_breakpoints + return thx_breakpoints[i,j,k] + +def declare_tc_breakpoints(model, j, k): + global tc_breakpoints + return tc_breakpoints[j,k] + +def declare_tcx_breakpoints(model, i, j, k): + global tcx_breakpoints + return tcx_breakpoints[i,j,k] + +def declare_stream_tangent_points(model, i, j, k): + global stream_tangent_points + return stream_tangent_points[i,j,k] + +def declare_cu_tangent_points(model, i): + global cu_tangent_points + return cu_tangent_points[i] + +def declare_hu_tangent_points(model, j): + global hu_tangent_points + return hu_tangent_points[j] + +def declare_stream_q_breakpoints(model, i, j, k): + global stream_q_points + return stream_q_points[i,j,k] + +def declare_cu_q_breakpoints(model, i): + global cu_q_points + return cu_q_points[i] + +def declare_hu_q_breakpoints(model, j): + global hu_q_points + return hu_q_points[j] + +def declare_stream_area_beta_breakpoints(model, i, j, k): + global stream_area_betas + return stream_area_betas[i,j,k] + +def declare_cu_area_beta_breakpoints(model, i): + global cu_area_betas + return cu_area_betas[i] + +def declare_hu_area_beta_breakpoints(model, j): + global hu_area_betas + return hu_area_betas[j] + +def initialise_hx_model(datafile): + model = create_model() + instance = model.create_instance(datafile) + + add_initial_th_breakpoints(instance) + add_initial_thx_breakpoints(instance) + add_initial_tc_breakpoints(instance) + add_initial_tcx_breakpoints(instance) + + add_initial_stream_tangent_points(instance) + add_initial_cu_tangent_points(instance) + add_initial_hu_tangent_points(instance) + + add_initial_stream_q_points(instance) + add_initial_cu_q_points(instance) + add_initial_hu_q_points(instance) + + add_initial_stream_area_beta_points(instance) + add_initial_cu_area_beta_points(instance) + add_initial_hu_area_beta_points(instance) + + model.Th_breakpoints.initialize = declare_th_breakpoints + model.Thx_breakpoints.initialize = declare_thx_breakpoints + model.Tc_breakpoints.initialize = declare_tc_breakpoints + model.Tcx_breakpoints.initialize = declare_tcx_breakpoints + + model.Reclmtd_gradient_points.initialize = declare_stream_tangent_points + model.Reclmtd_cu_gradient_points.initialize = declare_cu_tangent_points + model.Reclmtd_hu_gradient_points.initialize = declare_hu_tangent_points + + model.Q_breakpoints.initialize = declare_stream_q_breakpoints + model.Q_cu_breakpoints.initialize = declare_cu_q_breakpoints + model.Q_hu_breakpoints.initialize = declare_hu_q_breakpoints + + model.Area_beta_breakpoints.initialize = declare_stream_area_beta_breakpoints + model.Area_cu_beta_breakpoints.initialize = declare_cu_area_beta_breakpoints + model.Area_hu_beta_breakpoints.initialize = declare_hu_area_beta_breakpoints + + return model + +def get_active_hx(instance): + active_hx = { + stream_hx : [], + cu_hx : [], + hu_hx : [] + } + inactive_hx = { + stream_hx : [], + cu_hx : [], + hu_hx : [] + } + for index in instance.z: + if value(instance.z[index]) >= active_lb: + active_hx[stream_hx].append(index) + else: + inactive_hx[stream_hx].append(index) + + for index in instance.z_cu: + if value(instance.z_cu[index]) >= active_lb: + active_hx[cu_hx].append(index) + else: + inactive_hx[cu_hx].append(index) + + for index in instance.z_hu: + if value(instance.z_hu[index]) >= active_lb: + active_hx[hu_hx].append(index) + else: + inactive_hx[hu_hx].append(index) + + return active_hx, inactive_hx + +def get_new_tangent_points(instance, active_hx): + new_tangents = { + stream_hx : {}, + cu_hx : {}, + hu_hx : {} + } + for index in active_hx[stream_hx]: + x_index = index + y_index = (index[0], index[1], index[2]+1) + x = instance.dt[x_index].value + y = instance.dt[y_index].value + new_tangent_point = (x,y) if x >= y else (y,x) + new_tangents[stream_hx][index] = new_tangent_point + + for index in active_hx[cu_hx]: + x = instance.dt_cu[index].value + new_tangents[cu_hx][index] = x + + for index in active_hx[hu_hx]: + x = instance.dt_hu[index].value + new_tangents[hu_hx][index] = x + + return new_tangents + +def get_new_balancing_breakpoints(instance, active_hx, inactive_hx, weaken): + new_th_breakpoints = {} + new_thx_breakpoints = {} + new_tc_breakpoints = {} + new_tcx_breakpoints = {} + + active_th_indices = list(set((i, k) for i, _, k in active_hx[stream_hx])) + active_tc_indices = list(set((j, k+1) for _, j, k in active_hx[stream_hx])) + + for index in active_th_indices: + breakpoint = instance.th[index].value + if breakpoint not in th_breakpoints[index]: + bisect.insort(th_breakpoints[index], breakpoint) + new_th_breakpoints[index] = breakpoint + + for index in active_hx[stream_hx]: + breakpoint = instance.thx[index].value + if breakpoint not in thx_breakpoints[index]: + bisect.insort(thx_breakpoints[index], breakpoint) + new_thx_breakpoints[index] = breakpoint + + for index in active_tc_indices: + breakpoint = instance.tc[index].value + if breakpoint not in tc_breakpoints[index]: + bisect.insort(tc_breakpoints[index], breakpoint) + new_tc_breakpoints[index] = breakpoint + + for index in active_hx[stream_hx]: + breakpoint = instance.tcx[index].value + if breakpoint not in tcx_breakpoints[index]: + bisect.insort(tcx_breakpoints[index], breakpoint) + new_tcx_breakpoints[index] = breakpoint + + if not weaken: + for index in inactive_hx[stream_hx]: + if instance.bh_out[index].value > 0.000001: + breakpoint = instance.thx[index].value + if breakpoint not in thx_breakpoints[index]: + bisect.insort(thx_breakpoints[index], breakpoint) + new_thx_breakpoints[index] = breakpoint + if instance.bc_out[index].value > 0.000001: + breakpoint = instance.tcx[index].value + if breakpoint not in tcx_breakpoints[index]: + bisect.insort(tcx_breakpoints[index], breakpoint) + new_tcx_breakpoints[index] = breakpoint + + + new_balancing_breakpoints = {} + if not len(new_th_breakpoints) == 0: + new_balancing_breakpoints['th'] = new_th_breakpoints + + if not len(new_thx_breakpoints) == 0: + new_balancing_breakpoints['thx'] = new_thx_breakpoints + + if not len(new_tc_breakpoints) == 0: + new_balancing_breakpoints['tc'] = new_tc_breakpoints + + if not len(new_tcx_breakpoints) == 0: + new_balancing_breakpoints['tcx'] = new_tcx_breakpoints + + return new_balancing_breakpoints + +def get_new_q_breakpoints(instance, active_hx): + new_stream_breakpoints = {} + new_cu_breakpoints = {} + new_hu_breakpoints = {} + + for index in active_hx[stream_hx]: + breakpoint = instance.q[index].value + if breakpoint not in stream_q_points[index]: + bisect.insort(stream_q_points[index], breakpoint) + new_stream_breakpoints[index] = breakpoint + + for index in active_hx[cu_hx]: + breakpoint = instance.q_cu[index].value + if breakpoint not in cu_q_points[index]: + bisect.insort(cu_q_points[index], breakpoint) + new_cu_breakpoints[index] = breakpoint + + for index in active_hx[hu_hx]: + breakpoint = instance.q_hu[index].value + if breakpoint not in hu_q_points[index]: + bisect.insort(hu_q_points[index], breakpoint) + new_hu_breakpoints[index] = breakpoint + + new_q_breakpoints = {} + if not len(new_stream_breakpoints) == 0: + new_q_breakpoints[stream_hx] = new_stream_breakpoints + + if not len(new_cu_breakpoints) == 0: + new_q_breakpoints[cu_hx] = new_cu_breakpoints + + if not len(new_hu_breakpoints) == 0: + new_q_breakpoints[hu_hx] = new_hu_breakpoints + + return new_q_breakpoints + +def get_new_beta_breakpoints(instance, active_hx): + new_stream_breakpoints = {} + new_cu_breakpoints = {} + new_hu_breakpoints = {} + + for index in active_hx[stream_hx]: + breakpoint = instance.area[index].value + if breakpoint not in stream_area_betas[index]: + bisect.insort(stream_area_betas[index], breakpoint) + new_stream_breakpoints[index] = breakpoint + + for index in active_hx[cu_hx]: + breakpoint = instance.area_cu[index].value + if breakpoint not in cu_area_betas[index]: + bisect.insort(cu_area_betas[index], breakpoint) + new_cu_breakpoints[index] = breakpoint + + for index in active_hx[hu_hx]: + breakpoint = instance.area_hu[index].value + if breakpoint not in hu_area_betas[index]: + bisect.insort(hu_area_betas[index], breakpoint) + new_hu_breakpoints[index] = breakpoint + + new_beta_breakpoints = {} + if not len(new_stream_breakpoints) == 0: + new_beta_breakpoints[stream_hx] = new_stream_breakpoints + + if not len(new_cu_breakpoints) == 0: + new_beta_breakpoints[cu_hx] = new_cu_breakpoints + + if not len(new_hu_breakpoints) == 0: + new_beta_breakpoints[hu_hx] = new_hu_breakpoints + + return new_beta_breakpoints + +def add_new_tangent_points(new_tangent_points): + added_tangents = { + } + for index, tangent_point in new_tangent_points[stream_hx].items(): + if not tangent_point in stream_tangent_points[index]: + if not stream_hx in added_tangents: + added_tangents[stream_hx] = {} + stream_tangent_points[index].append(tangent_point) + added_tangents[stream_hx][index] = [tangent_point] + if not tangent_point[0] == tangent_point[1]: + stream_tangent_points[index].append((tangent_point[1], tangent_point[0])) + added_tangents[stream_hx][index].append((tangent_point[1], tangent_point[0])) + + for index, tangent_point in new_tangent_points[cu_hx].items(): + if not tangent_point in cu_tangent_points[index]: + if not cu_hx in added_tangents: + added_tangents[cu_hx] = {} + cu_tangent_points[index].append(tangent_point) + added_tangents[cu_hx][index] = [tangent_point] + + for index, tangent_point in new_tangent_points[hu_hx].items(): + if not tangent_point in hu_tangent_points[index]: + if not hu_hx in added_tangents: + added_tangents[hu_hx] = {} + hu_tangent_points[index].append(tangent_point) + added_tangents[hu_hx][index] = [tangent_point] + + return added_tangents + +def calculate_reclmtd_error(x, y, reclmtd_estimate): + reclmtd_correct = lmtd_inv(x, y) + error = reclmtd_correct - reclmtd_estimate + rel_error = error/reclmtd_correct + abs_error = abs(error) + return {\ + absolute_error: abs_error,\ + relative_error: rel_error,\ + } + +def calculate_stream_reclmtd_error(instance, i, j, k): + dt_hot = instance.dt[(i,j,k)].value + dt_cold = instance.dt[(i,j,k+1)].value + reclmtd_estimate = instance.reclmtd[(i,j,k)].value + return calculate_reclmtd_error(dt_hot, dt_cold, reclmtd_estimate) + +def calculate_cu_reclmtd_error(instance, i): + dt = instance.dt_cu[i].value + dt2 = instance.Th_out[i] - instance.T_cu_in + reclmtd_estimate = instance.reclmtd_cu[i].value + return calculate_reclmtd_error(dt, dt2, reclmtd_estimate) + +def calculate_hu_reclmtd_error(instance, j): + dt = instance.dt_hu[j].value + dt2 = instance.T_hu_in - instance.Tc_out[j] + reclmtd_estimate = instance.reclmtd_hu[j].value + return calculate_reclmtd_error(dt, dt2, reclmtd_estimate) + +def calculate_area_beta_errors(area, beta, area_beta_estimate): + area_beta_correct = pow(area, beta) + error = area_beta_correct - area_beta_estimate + rel_error = error/area_beta_correct + abs_error = abs(error) + return {\ + absolute_error: abs_error,\ + relative_error: rel_error,\ + } + +def calculate_stream_area_beta_error(instance, i, j, k): + area = instance.area[i,j,k].value + beta = instance.Beta + area_beta_estimate = instance.area_beta[i,j,k].value + return calculate_area_beta_errors(area, beta, area_beta_estimate) + +def calculate_cu_area_beta_error(instance, i): + area = instance.area_cu[i].value + beta = instance.Beta + area_beta_estimate = instance.area_cu_beta[i].value + return calculate_area_beta_errors(area, beta, area_beta_estimate) + +def calculate_hu_area_beta_error(instance, j): + area = instance.area_hu[j].value + beta = instance.Beta + area_beta_estimate = instance.area_hu_beta[j].value + return calculate_area_beta_errors(area, beta, area_beta_estimate) + +def calculate_area_errors(q, reclmtd, u, area_estimate): + area_correct = u*q*reclmtd + error = area_correct - area_estimate + rel_error = error/area_correct + abs_error = abs(error) + return {\ + absolute_error: abs_error,\ + relative_error: rel_error,\ + } + +def calculate_stream_area_error(instance, i, j, k): + q = instance.q[i,j,k].value + reclmtd = instance.reclmtd[i,j,k].value + u = instance.U[i,j] + area_estimate = instance.area[i,j,k].value + return calculate_area_errors(q, reclmtd, u, area_estimate) + +def calculate_cu_area_error(instance, i): + q = instance.q_cu[i].value + reclmtd = instance.reclmtd_cu[i].value + u = instance.U_cu[i] + area_estimate = instance.area_cu[i].value + return calculate_area_errors(q, reclmtd, u, area_estimate) + +def calculate_hu_area_error(instance, j): + q = instance.q_hu[j].value + reclmtd = instance.reclmtd_hu[j].value + u = instance.U_hu[j] + area_estimate = instance.area_hu[j].value + return calculate_area_errors(q, reclmtd, u, area_estimate) + +def calculate_bilinear_errors(f, t, bilinear_estimate): + bilinear_correct = f*t + if bilinear_correct < 0.000001: + return {\ + absolute_error: 0,\ + relative_error: 0,\ + } + error = bilinear_estimate - bilinear_correct + rel_error = error/bilinear_correct if not t == 0 else 0 + abs_error = abs(error) + return {\ + absolute_error: abs_error,\ + relative_error: rel_error,\ + } + +def calculate_bhin(instance, i, j, k): + f = instance.fh[i,j,k].value + t = instance.th[i,k].value + bhin = instance.bh_in[i,j,k].value + return calculate_bilinear_errors(f, t, bhin) + +def calculate_bhout(instance, i, j, k): + f = instance.fh[i,j,k].value + t = instance.thx[i,j,k].value + bhout = instance.bh_out[i,j,k].value + return calculate_bilinear_errors(f, t, bhout) + +def calculate_bcin(instance, i, j, k): + f = instance.fc[i,j,k].value + t = instance.tc[j,k+1].value + bcin = instance.bc_in[i,j,k].value + return calculate_bilinear_errors(f, t, bcin) + +def calculate_bcout(instance, i, j, k): + f = instance.fc[i,j,k].value + t = instance.tcx[i,j,k].value + bcout = instance.bc_out[i,j,k].value + return calculate_bilinear_errors(f, t, bcout) + +def get_all_points(): + return {\ + stream_hx: {\ + tangent_points: stream_tangent_points,\ + q_points: stream_q_points,\ + area_beta_points: stream_area_betas,\ + th_points: th_breakpoints,\ + thx_points: thx_breakpoints,\ + tc_points: tc_breakpoints,\ + tcx_points: tcx_breakpoints,\ + },\ + cu_hx: {\ + tangent_points: cu_tangent_points,\ + q_points: cu_q_points,\ + area_beta_points: cu_area_betas,\ + },\ + hu_hx: {\ + tangent_points: hu_tangent_points,\ + q_points: hu_q_points,\ + area_beta_points: hu_area_betas,\ + },\ + } + +def summarise_errors(instance, active_hx, inactive_hx, weaken): + errors = {} + + errors[stream_hx] = {} + errors[cu_hx] = {} + errors[hu_hx] = {} + + errors[stream_hx][reclmtd_error] = {} + errors[cu_hx][reclmtd_error] = {} + errors[hu_hx][reclmtd_error] = {} + + errors[stream_hx][area_error] = {} + errors[cu_hx][area_error] = {} + errors[hu_hx][area_error] = {} + + errors[stream_hx][area_beta_error] = {} + errors[cu_hx][area_beta_error] = {} + errors[hu_hx][area_beta_error] = {} + + errors[stream_hx][bhin_error] = {} + errors[stream_hx][bhout_error] = {} + errors[stream_hx][bcin_error] = {} + errors[stream_hx][bcout_error] = {} + + for (i,j,k) in active_hx[stream_hx]: + errors[stream_hx][reclmtd_error][i,j,k] = calculate_stream_reclmtd_error(instance, i, j, k) + errors[stream_hx][area_error][i,j,k] = calculate_stream_area_error(instance, i, j, k) + errors[stream_hx][area_beta_error][i,j,k] = calculate_stream_area_beta_error(instance, i, j, k) + errors[stream_hx][bhin_error][i,j,k] = calculate_bhin(instance, i, j, k) + errors[stream_hx][bhout_error][i,j,k] = calculate_bhout(instance, i, j, k) + errors[stream_hx][bcin_error][i,j,k] = calculate_bcin(instance, i, j, k) + errors[stream_hx][bcout_error][i,j,k] = calculate_bcout(instance, i, j, k) + + if not weaken: + for (i,j,k) in inactive_hx[stream_hx]: + errors[stream_hx][bhout_error][i,j,k] = calculate_bhout(instance, i, j, k) + errors[stream_hx][bcout_error][i,j,k] = calculate_bcout(instance, i, j, k) + + for i in active_hx[cu_hx]: + errors[cu_hx][reclmtd_error][i] = calculate_cu_reclmtd_error(instance, i) + errors[cu_hx][area_error][i] = calculate_cu_area_error(instance, i) + errors[cu_hx][area_beta_error][i] = calculate_cu_area_beta_error(instance, i) + + for j in active_hx[hu_hx]: + errors[hu_hx][reclmtd_error][j] = calculate_hu_reclmtd_error(instance, j) + errors[hu_hx][area_error][j] = calculate_hu_area_error(instance, j) + errors[hu_hx][area_beta_error][j] = calculate_hu_area_beta_error(instance, j) + + return errors + +def get_max_errors(errors, active_hx, inactive_hx, weaken): + + max_errors = { + balancing_ref: { + absolute_error: -1, \ + relative_error: -1, \ + }, + reclmtd_ref: { + absolute_error: -1, \ + relative_error: -1, \ + }, + area_ref: { + absolute_error: -1, \ + relative_error: -1, \ + }, + beta_ref: { + absolute_error: -1, \ + relative_error: -1, \ + }, + } + + for (i,j,k) in active_hx[stream_hx]: + max_bilinear_error_abs = max( \ + errors[stream_hx][bhin_error][i,j,k][absolute_error], \ + errors[stream_hx][bhout_error][i,j,k][absolute_error], \ + errors[stream_hx][bcin_error][i,j,k][absolute_error], \ + errors[stream_hx][bcout_error][i,j,k][absolute_error], \ + ) + + max_bilinear_error_rel = max( \ + abs(errors[stream_hx][bhin_error][i,j,k][relative_error]), \ + abs(errors[stream_hx][bhout_error][i,j,k][relative_error]), \ + abs(errors[stream_hx][bcin_error][i,j,k][relative_error]), \ + abs(errors[stream_hx][bcout_error][i,j,k][relative_error]), \ + ) + + if max_errors[balancing_ref][absolute_error] < max_bilinear_error_abs: + max_errors[balancing_ref][absolute_error] = max_bilinear_error_abs + + if max_errors[balancing_ref][relative_error] < max_bilinear_error_rel: + max_errors[balancing_ref][relative_error] = max_bilinear_error_rel + + if not weaken: + for (i,j,k) in inactive_hx[stream_hx]: + max_bilinear_error_abs = max( \ + errors[stream_hx][bhout_error][i,j,k][absolute_error], \ + errors[stream_hx][bcout_error][i,j,k][absolute_error], \ + ) + + max_bilinear_error_rel = max( \ + abs(errors[stream_hx][bhout_error][i,j,k][relative_error]), \ + abs(errors[stream_hx][bcout_error][i,j,k][relative_error]), \ + ) + + if max_errors[balancing_ref][absolute_error] < max_bilinear_error_abs: + max_errors[balancing_ref][absolute_error] = max_bilinear_error_abs + + if max_errors[balancing_ref][relative_error] < max_bilinear_error_rel: + max_errors[balancing_ref][relative_error] = max_bilinear_error_rel + + for check_set in [stream_hx, cu_hx, hu_hx]: + for index in active_hx[check_set]: + if max_errors[reclmtd_ref][absolute_error] < errors[check_set][reclmtd_error][index][absolute_error]: + max_errors[reclmtd_ref][absolute_error] = errors[check_set][reclmtd_error][index][absolute_error] + + if max_errors[reclmtd_ref][relative_error] < errors[check_set][reclmtd_error][index][relative_error]: + max_errors[reclmtd_ref][relative_error] = errors[check_set][reclmtd_error][index][relative_error] + + if max_errors[area_ref][absolute_error] < errors[check_set][area_error][index][absolute_error]: + max_errors[area_ref][absolute_error] = errors[check_set][area_error][index][absolute_error] + + if max_errors[area_ref][relative_error] < errors[check_set][area_error][index][relative_error]: + max_errors[area_ref][relative_error] = errors[check_set][area_error][index][relative_error] + + if max_errors[beta_ref][absolute_error] < errors[check_set][area_beta_error][index][absolute_error]: + max_errors[beta_ref][absolute_error] = errors[check_set][area_beta_error][index][absolute_error] + + if max_errors[beta_ref][relative_error] < errors[check_set][area_beta_error][index][relative_error]: + max_errors[beta_ref][relative_error] = errors[check_set][area_beta_error][index][relative_error] + + return max_errors diff --git a/hens/adaptive_model_mixer/lib/model_declarations/__init__.py b/hens/adaptive_model_mixer/lib/model_declarations/__init__.py new file mode 100644 index 0000000..76b1662 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/__init__.py @@ -0,0 +1,4 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from __future__ import absolute_import, division, print_function diff --git a/hens/adaptive_model_mixer/lib/model_declarations/bound_generators.py b/hens/adaptive_model_mixer/lib/model_declarations/bound_generators.py new file mode 100644 index 0000000..6ce781b --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/bound_generators.py @@ -0,0 +1,105 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from .helper_functions import lmtd_inv + +def area_bounds(model, i, j, *k): + _, q_upper = q_bounds(model, i, j) + _, reclmtd_upper = reclmtd_bounds(model, i, j) + + area_lower = 0 + area_upper = q_upper*reclmtd_upper*model.U[i,j] + + return (area_lower, area_upper) + +def area_cu_bounds(model, i): + _, q_cu_upper = q_cu_bounds(model, i) + _, reclmtd_cu_upper = reclmtd_cu_bounds(model, i) + + area_cu_lower = 0 + area_cu_upper = q_cu_upper*reclmtd_cu_upper*model.U_cu[i] + + return (area_cu_lower, area_cu_upper) + +def area_hu_bounds(model, j): + _, q_hu_upper = q_hu_bounds(model, j) + _, reclmtd_hu_upper = reclmtd_hu_bounds(model, j) + + area_hu_lower = 0 + area_hu_upper = q_hu_upper*reclmtd_hu_upper*model.U_hu[j] + + return (area_hu_lower, area_hu_upper) + +def fh_bounds(model, i, j, k): + return (0, model.Fh[i]) + +def fc_bounds(model, i, j, k): + return (0, model.Fc[j]) + +def thx_bounds(model, i, j, k): + return (model.Th_out[i], model.Th_in[i]) + +def tcx_bounds(model, i, j, k): + return (model.Tc_in[j], model.Tc_out[j]) + +def dt_bounds(model, i, j, k): + return (model.Delta_t_min, model.Th_in[i]-model.Tc_in[j]) + +def dt_cu_bounds(model, i): + return (model.Delta_t_min, model.Th_in[i]-model.T_cu_in) + +def dt_hu_bounds(model, j): + return (model.Delta_t_min, model.T_hu_in - model.Tc_in[j]) + +def reclmtd_bounds(model, i, j, *k): + reclmtd_lower = 1/(model.Th_in[i] - model.Tc_in[j]) + reclmtd_upper = 1/model.Delta_t_min + return (reclmtd_lower, reclmtd_upper) + +def reclmtd_cu_bounds(model, i): + x_min = model.Delta_t_min + x_max = model.Th_in[i] - model.T_cu_out + y = model.Th_out[i] - model.T_cu_in + reclmtd_cu_lower = lmtd_inv(x_max,y) + reclmtd_cu_upper = lmtd_inv(x_min,y) + + return (reclmtd_cu_lower, reclmtd_cu_upper) + +def reclmtd_hu_bounds(model, j): + x_min = model.Delta_t_min + x_max = model.T_hu_out - model.Tc_in[j] + y = model.T_hu_in - model.Tc_out[j] + reclmtd_hu_lower = lmtd_inv(x_max,y) + reclmtd_hu_upper = lmtd_inv(x_min,y) + + return (reclmtd_hu_lower, reclmtd_hu_upper) + +def q_bounds(model, i, j, *k): + q_lower = 0 + + q_upper_hot_side = model.Fh[i]*(model.Th_in[i] - model.Th_out[i]) + q_upper_cold_side = model.Fc[j]*(model.Tc_out[j] - model.Tc_in[j]) + q_upper = min( q_upper_hot_side, q_upper_cold_side ) + return (q_lower, q_upper) + +def q_cu_bounds(model, i): + q_cu_lower = 0 + q_cu_upper = model.Fh[i]*(model.Th_in[i] - model.Th_out[i]) + return (q_cu_lower, q_cu_upper) + +def q_hu_bounds(model, j): + q_hu_lower = 0 + q_hu_upper = model.Fc[j]*(model.Tc_out[j] - model.Tc_in[j]) + return (q_hu_lower, q_hu_upper) + +def th_bounds(model, i, *k): + return (model.Th_out[i], model.Th_in[i]) + +def tc_bounds(model, j, *k): + return (model.Tc_in[j], model.Tc_out[j]) + +def bh_bounds(model, i, j, k): + return (0, model.Th_in[i]*model.Fh[i]) + +def bc_bounds(model, i, j, k): + return (0, model.Tc_out[j]*model.Fc[j]) diff --git a/hens/adaptive_model_mixer/lib/model_declarations/constraint_rules.py b/hens/adaptive_model_mixer/lib/model_declarations/constraint_rules.py new file mode 100644 index 0000000..08b96c1 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/constraint_rules.py @@ -0,0 +1,521 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from .helper_functions import lmtd_inverse_gradient_calculator, lmtd_inv + +from pyomo.core.base.constraint import Constraint + +def z_th_sum_rule(model, i, k): + return sum(model.z_th[i,k,n] for n in range(1, len(model.Th_breakpoints[i,k])) ) == 1 + +def th_lower_rule(model, i, k): + return model.th[i,k] >= sum(model.Th_breakpoints[i,k][n]*model.z_th[i,k,n] for n in range(1, len(model.Th_breakpoints[i,k]))) + +def th_upper_rule(model, i, k): + return model.th[i,k] <= sum(model.Th_breakpoints[i,k][n+1]*model.z_th[i,k,n] for n in range(1, len(model.Th_breakpoints[i,k]))) + +def var_delta_fh_sum_rule(model, i, j, k): + return model.fh[i,j,k] == sum(model.var_delta_fh[i,j,k,n] for n in range(1, len(model.Th_breakpoints[i,k]))) + +def var_delta_fh_upper_rule(model, i, j, k, n): + return model.var_delta_fh[i,j,k,n] <= model.Fh[i]*model.z_th[i,k,n] + +########################## +def z_thx_sum_rule(model, i, j, k): + return sum(model.z_thx[i,j,k,n] for n in range(1, len(model.Thx_breakpoints[i,j,k])) ) == 1 + +def thx_lower_rule(model, i, j, k): + return model.thx[i,j,k] >= sum(model.Thx_breakpoints[i,j,k][n]*model.z_thx[i,j,k,n] for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def thx_upper_rule(model, i, j, k): + return model.thx[i,j,k] <= sum(model.Thx_breakpoints[i,j,k][n+1]*model.z_thx[i,j,k,n] for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def var_delta_fhx_sum_rule(model, i, j, k): + return model.fh[i,j,k] == sum(model.var_delta_fhx[i,j,k,n] for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def var_delta_fhx_upper_rule(model, i, j, k, n): + return model.var_delta_fhx[i,j,k,n] <= model.Fh[i]*model.z_thx[i,j,k,n] + +########################## +def z_tc_sum_rule(model, j, k): + return sum(model.z_tc[j,k+1,n] for n in range(1, len(model.Tc_breakpoints[j,k+1])) ) == 1 + +def tc_lower_rule(model, j, k): + return model.tc[j,k+1] >= sum(model.Tc_breakpoints[j,k+1][n]*model.z_tc[j,k+1,n] for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def tc_upper_rule(model, j, k): + return model.tc[j,k+1] <= sum(model.Tc_breakpoints[j,k+1][n+1]*model.z_tc[j,k+1,n] for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def var_delta_fc_sum_rule(model, i, j, k): + return model.fc[i,j,k] == sum(model.var_delta_fc[i,j,k,n] for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def var_delta_fc_upper_rule(model, i, j, k, n): + return model.var_delta_fc[i,j,k,n] <= model.Fc[j]*model.z_tc[j,k+1,n] + +########################## +def z_tcx_sum_rule(model, i, j, k): + return sum(model.z_tcx[i,j,k,n] for n in range(1, len(model.Tcx_breakpoints[i,j,k])) ) == 1 + +def tcx_lower_rule(model, i, j, k): + return model.tcx[i,j,k] >= sum(model.Tcx_breakpoints[i,j,k][n]*model.z_tcx[i,j,k,n] for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def tcx_upper_rule(model, i, j, k): + return model.tcx[i,j,k] <= sum(model.Tcx_breakpoints[i,j,k][n+1]*model.z_tcx[i,j,k,n] for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def var_delta_fcx_sum_rule(model, i, j, k): + return model.fc[i,j,k] == sum(model.var_delta_fcx[i,j,k,n] for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def var_delta_fcx_upper_rule(model, i, j, k, n): + return model.var_delta_fcx[i,j,k,n] <= model.Fc[j]*model.z_tcx[i,j,k,n] + +########################## + +########################## +def z_q_sum_rule(model, i, j, k): + return sum(model.z_q[i,j,k,n] for n in range(1, len(model.Q_breakpoints[i,j,k])) ) == 1 + +def q_lower_rule(model, i, j, k): + return model.q[i,j,k] >= sum(model.Q_breakpoints[i,j,k][n]*model.z_q[i,j,k,n] for n in range(1, len(model.Q_breakpoints[i,j,k]))) + +def q_upper_rule(model, i, j, k): + return model.q[i,j,k] <= sum(model.Q_breakpoints[i,j,k][n+1]*model.z_q[i,j,k,n] for n in range(1, len(model.Q_breakpoints[i,j,k]))) + +def var_delta_reclmtd_sum_rule(model, i, j, k): + reclmtd_lower, _ = model.reclmtd[i,j,k].bounds + return model.reclmtd[i,j,k] == reclmtd_lower + sum(model.var_delta_reclmtd[i,j,k,n] for n in range(1, len(model.Q_breakpoints[i,j,k]))) + +def var_delta_reclmtd_upper_rule(model, i, j, k, n): + reclmtd_lower, reclmtd_upper = model.reclmtd[i,j,k].bounds + return model.var_delta_reclmtd[i,j,k,n] <= (reclmtd_upper-reclmtd_lower)*model.z_q[i,j,k,n] + +########################## +def z_q_cu_sum_rule(model, i): + return sum(model.z_q_cu[i,n] for n in range(1, len(model.Q_cu_breakpoints[i])) ) == 1 + +def q_cu_lower_rule(model, i): + return model.q_cu[i] >= sum(model.Q_cu_breakpoints[i][n]*model.z_q_cu[i,n] for n in range(1, len(model.Q_cu_breakpoints[i]))) + +def q_cu_upper_rule(model, i): + return model.q_cu[i] <= sum(model.Q_cu_breakpoints[i][n+1]*model.z_q_cu[i,n] for n in range(1, len(model.Q_cu_breakpoints[i]))) + +def var_delta_reclmtd_cu_sum_rule(model, i): + reclmtd_cu_lower, _ = model.reclmtd_cu[i].bounds + return model.reclmtd_cu[i] == reclmtd_cu_lower + sum(model.var_delta_reclmtd_cu[i,n] for n in range(1, len(model.Q_cu_breakpoints[i]))) + +def var_delta_reclmtd_cu_upper_rule(model, i, n): + reclmtd_cu_lower, reclmtd_cu_upper = model.reclmtd_cu[i].bounds + return model.var_delta_reclmtd_cu[i,n] <= (reclmtd_cu_upper-reclmtd_cu_lower)*model.z_q_cu[i,n] + +########################## +def z_q_hu_sum_rule(model, j): + return sum(model.z_q_hu[j,n] for n in range(1, len(model.Q_hu_breakpoints[j])) ) == 1 + +def q_hu_lower_rule(model, j): + return model.q_hu[j] >= sum(model.Q_hu_breakpoints[j][n]*model.z_q_hu[j,n] for n in range(1, len(model.Q_hu_breakpoints[j]))) + +def q_hu_upper_rule(model, j): + return model.q_hu[j] <= sum(model.Q_hu_breakpoints[j][n+1]*model.z_q_hu[j,n] for n in range(1, len(model.Q_hu_breakpoints[j]))) + +def var_delta_reclmtd_hu_sum_rule(model, j): + reclmtd_hu_lower, _ = model.reclmtd_hu[j].bounds + return model.reclmtd_hu[j] == reclmtd_hu_lower + sum(model.var_delta_reclmtd_hu[j,n] for n in range(1, len(model.Q_hu_breakpoints[j]))) + +def var_delta_reclmtd_hu_upper_rule(model, j, n): + reclmtd_hu_lower, reclmtd_hu_upper = model.reclmtd_hu[j].bounds + return model.var_delta_reclmtd_hu[j,n] <= (reclmtd_hu_upper-reclmtd_hu_lower)*model.z_q_hu[j,n] + +########################## +def overall_heat_balance_hot_rule(model, i): + return ( sum(model.q[i,j,k] for j in model.CP for k in model.ST ) + model.q_cu[i] ) == model.Fh[i]*(model.Th_in[i] - model.Th_out[i]) + +def overall_heat_balance_cold_rule(model, j): + return ( sum(model.q[i,j,k] for i in model.HP for k in model.ST ) + model.q_hu[j] ) == model.Fc[j]*(model.Tc_out[j] - model.Tc_in[j]) + +def energy_balance_hot_rule(model, i, k): + return sum( model.q[i,j,k] for j in model.CP ) == model.Fh[i]*(model.th[i,k] - model.th[i,k+1]) + +def energy_balance_cold_rule(model, j, k): + return sum( model.q[i,j,k] for i in model.HP ) == model.Fc[j]*(model.tc[j,k] - model.tc[j, k+1]) + +def energy_balance_cu_rule(model, i): + return model.Fh[i]*( model.th[i,model.Number_stages+1] - model.Th_out[i] ) == model.q_cu[i] + +def energy_balance_hu_rule(model, j): + return model.Fc[j]*( model.Tc_out[j] - model.tc[j,1] ) == model.q_hu[j] + +def hot_inlet_rule(model, i): + return model.th[i, 1] == model.Th_in[i] + +def cold_inlet_rule(model, j): + return model.tc[j,model.Number_stages+1] == model.Tc_in[j] + +def mass_balance_hot_rule(model, i, k): + return sum( model.fh[i,j,k] for j in model.CP ) == model.Fh[i] + +def mass_balance_cold_rule(model, j, k): + return sum( model.fc[i,j,k] for i in model.HP ) == model.Fc[j] + +def decreasing_hot_rule(model, i, k): + return model.th[i,k+1] <= model.th[i,k] + +def decreasing_cold_rule(model, j, k): + return model.tc[j,k+1] <= model.tc[j,k] + +def hot_upper_bound_rule(model, i): + return model.th[i, model.Number_stages+1] >= model.Th_out[i] + +def cold_lower_bound_rule(model, j): + return model.tc[j,1] <= model.Tc_out[j] + +def q_big_m_rule(model, i, j, k): + return model.q[i,j,k] - model.Omega_ij[i,j]*model.z[i,j,k] <= 0 + +def q_cu_big_m_rule(model, i): + return model.q_cu[i] - model.Omega_i[i]*model.z_cu[i] <= 0 + +def q_hu_big_m_rule(model, j): + return model.q_hu[j] - model.Omega_j[j]*model.z_hu[j] <= 0 + +def temp_app_in_rule(model, i, j, k): + return model.dt[i,j,k] <= model.th[i,k] - model.tc[j,k] + model.Gamma[i,j]*(1 - model.z[i,j,k]) + +def temp_app_out_rule(model, i, j, k): + return model.dt[i,j,k+1] <= model.th[i,k+1] - model.tc[j,k+1] + model.Gamma[i,j]*(1 - model.z[i,j,k]) + +def temp_app_cu_rule(model, i): + return model.dt_cu[i] <= model.th[i,model.Number_stages + 1] - model.T_cu_out + +def temp_app_hu_rule(model, j): + return model.dt_hu[j] <= model.T_hu_out - model.tc[j,1] + +def mccor_convex_h_in_1_rule(model, i, j, k): + return model.bh_in[i,j,k] >=\ + sum(model.Th_breakpoints[i,k][n]*model.var_delta_fh[i,j,k,n] \ + for n in range(1, len(model.Th_breakpoints[i,k]))) + +def mccor_convex_h_in_2_rule(model, i, j, k): + return model.bh_in[i,j,k] >=\ + model.th[i,k]*model.Fh[i] +\ + sum(model.Th_breakpoints[i,k][n+1]*\ + (model.var_delta_fh[i,j,k,n] - model.Fh[i]*model.z_th[i,k,n]) \ + for n in range(1, len(model.Th_breakpoints[i,k]))) + +def mccor_concave_h_in_1_rule(model, i, j, k): + return model.bh_in[i,j,k] <=\ + sum(model.Th_breakpoints[i,k][n+1]*model.var_delta_fh[i,j,k,n] \ + for n in range(1, len(model.Th_breakpoints[i,k]))) + +def mccor_concave_h_in_2_rule(model, i, j, k): + return model.bh_in[i,j,k] <=\ + model.th[i,k]*model.Fh[i] +\ + sum(model.Th_breakpoints[i,k][n]*\ + (model.var_delta_fh[i,j,k,n] - model.Fh[i]*model.z_th[i,k,n]) \ + for n in range(1, len(model.Th_breakpoints[i,k]))) + +def mccor_convex_h_out_1_rule(model, i, j, k): + return model.bh_out[i,j,k] >= \ + sum(model.Thx_breakpoints[i,j,k][n]*model.var_delta_fhx[i,j,k,n] \ + for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def mccor_convex_h_out_2_rule(model, i, j, k): + return model.bh_out[i,j,k] >= \ + model.thx[i,j,k]*model.Fh[i] +\ + sum(model.Thx_breakpoints[i,j,k][n+1]*\ + (model.var_delta_fhx[i,j,k,n] - model.Fh[i]*model.z_thx[i,j,k,n]) \ + for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def mccor_concave_h_out_1_rule(model, i, j, k): + return model.bh_out[i,j,k] <= \ + sum(model.Thx_breakpoints[i,j,k][n+1]*model.var_delta_fhx[i,j,k,n] \ + for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def mccor_concave_h_out_2_rule(model, i, j, k): + return model.bh_out[i,j,k] <= \ + model.thx[i,j,k]*model.Fh[i] +\ + sum(model.Thx_breakpoints[i,j,k][n]*\ + (model.var_delta_fhx[i,j,k,n] - model.Fh[i]*model.z_thx[i,j,k,n]) \ + for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def mccor_convex_c_in_1_rule(model, i, j, k): + return model.bc_in[i,j,k] >=\ + sum(model.Tc_breakpoints[j,k+1][n]*model.var_delta_fc[i,j,k,n] \ + for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def mccor_convex_c_in_2_rule(model, i, j, k): + return model.bc_in[i,j,k] >= \ + model.tc[j,k+1]*model.Fc[j] + \ + sum(model.Tc_breakpoints[j,k+1][n+1]*\ + (model.var_delta_fc[i,j,k,n] - model.Fc[j]*model.z_tc[j,k+1,n]) \ + for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def mccor_concave_c_in_1_rule(model, i, j, k): + return model.bc_in[i,j,k] <= \ + sum(model.Tc_breakpoints[j,k+1][n+1]*model.var_delta_fc[i,j,k,n] \ + for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def mccor_concave_c_in_2_rule(model, i, j, k): + return model.bc_in[i,j,k] <= \ + model.tc[j,k+1]*model.Fc[j] + \ + sum(model.Tc_breakpoints[j,k+1][n]*\ + (model.var_delta_fc[i,j,k,n] - model.Fc[j]*model.z_tc[j,k+1,n]) \ + for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def mccor_convex_c_out_1_rule(model, i, j, k): + return model.bc_out[i,j,k] >= \ + sum(model.Tcx_breakpoints[i,j,k][n]*model.var_delta_fcx[i,j,k,n] \ + for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def mccor_convex_c_out_2_rule(model, i, j, k): + return model.bc_out[i,j,k] >= \ + model.tcx[i,j,k]*model.Fc[j] + \ + sum(model.Tcx_breakpoints[i,j,k][n+1]*\ + (model.var_delta_fcx[i,j,k,n] - model.Fc[j]*model.z_tcx[i,j,k,n]) \ + for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def mccor_concave_c_out_1_rule(model, i, j, k): + return model.bc_out[i,j,k] <= \ + sum(model.Tcx_breakpoints[i,j,k][n+1]*model.var_delta_fcx[i,j,k,n] \ + for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def mccor_concave_c_out_2_rule(model, i, j, k): + return model.bc_out[i,j,k] <= \ + model.tcx[i,j,k]*model.Fc[j] + \ + sum(model.Tcx_breakpoints[i,j,k][n]*\ + (model.var_delta_fcx[i,j,k,n] - model.Fc[j]*model.z_tcx[i,j,k,n])\ + for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def mixer_energy_bal_hot_rule(model, i, k): + return model.Fh[i]*model.th[i,k+1] == sum( model.bh_out[i,j,k] for j in model.CP) + +def mixer_energy_bal_cold_rule(model, j, k): + return model.Fc[j]*model.tc[j,k] == sum( model.bc_out[i,j,k] for i in model.HP) + +def q_energy_bal_hot_rule(model, i, j, k): + return model.q[i,j,k] == (model.bh_in[i,j,k] - model.bh_out[i,j,k]) + +def q_energy_bal_cold_rule(model, i, j, k): + return model.q[i,j,k] == (model.bc_out[i,j,k] - model.bc_in[i,j,k]) + +# A_ijk +def area_mccor_convex_1_rule(model, i, j, k): + reclmtd_lower, _ = model.reclmtd[i,j,k].bounds + return model.area[i,j,k] >= \ + model.U[i,j]*(\ + model.q[i,j,k]*reclmtd_lower +\ + sum( \ + model.Q_breakpoints[i,j,k][n]*model.var_delta_reclmtd[i,j,k,n] \ + for n in range(1, len(model.Q_breakpoints[i,j,k]))) \ + ) + +def area_mccor_convex_2_rule(model, i, j, k): + reclmtd_lower, reclmtd_upper = model.reclmtd[i,j,k].bounds + return model.area[i,j,k] >= \ + model.U[i,j]*(\ + model.q[i,j,k]*reclmtd_upper + \ + sum( \ + model.Q_breakpoints[i,j,k][n+1]* \ + (model.var_delta_reclmtd[i,j,k,n] - (reclmtd_upper-reclmtd_lower)*model.z_q[i,j,k,n])\ + for n in range(1, len(model.Q_breakpoints[i,j,k]))) \ + ) + +def area_mccor_concave_1_rule(model, i, j, k): + reclmtd_lower, _ = model.reclmtd[i,j,k].bounds + return model.area[i,j,k] <= \ + model.U[i,j]*( \ + model.q[i,j,k]*reclmtd_lower + \ + sum( \ + model.Q_breakpoints[i,j,k][n+1]*model.var_delta_reclmtd[i,j,k,n]\ + for n in range(1, len(model.Q_breakpoints[i,j,k])))\ + ) + +def area_mccor_concave_2_rule(model, i, j, k): + reclmtd_lower, reclmtd_upper = model.reclmtd[i,j,k].bounds + return model.area[i,j,k] <= \ + model.U[i,j]*(\ + model.q[i,j,k]*reclmtd_upper + \ + sum( \ + model.Q_breakpoints[i,j,k][n]* \ + (model.var_delta_reclmtd[i,j,k,n] - (reclmtd_upper-reclmtd_lower)*model.z_q[i,j,k,n])\ + for n in range(1, len(model.Q_breakpoints[i,j,k]))) \ + ) + +# A_cui +def area_cu_mccor_convex_1_rule(model, i): + reclmtd_cu_lower, _ = model.reclmtd_cu[i].bounds + return model.area_cu[i] >= \ + model.U_cu[i]*(\ + model.q_cu[i]*reclmtd_cu_lower +\ + sum(\ + model.Q_cu_breakpoints[i][n]*model.var_delta_reclmtd_cu[i,n]\ + for n in range(1, len(model.Q_cu_breakpoints[i])))\ + ) + +def area_cu_mccor_convex_2_rule(model, i): + reclmtd_cu_lower, reclmtd_cu_upper = model.reclmtd_cu[i].bounds + return model.area_cu[i] >= \ + model.U_cu[i]*(\ + model.q_cu[i]*reclmtd_cu_upper +\ + sum(\ + model.Q_cu_breakpoints[i][n+1]*\ + (model.var_delta_reclmtd_cu[i,n] - (reclmtd_cu_upper - reclmtd_cu_lower)*model.z_q_cu[i,n])\ + for n in range(1, len(model.Q_cu_breakpoints[i])))\ + ) + +def area_cu_mccor_concave_1_rule(model, i): + reclmtd_cu_lower, _ = model.reclmtd_cu[i].bounds + return model.area_cu[i] <= \ + model.U_cu[i]*(\ + model.q_cu[i]*reclmtd_cu_lower +\ + sum(\ + model.Q_cu_breakpoints[i][n+1]*model.var_delta_reclmtd_cu[i,n]\ + for n in range(1, len(model.Q_cu_breakpoints[i])))\ + ) + +def area_cu_mccor_concave_2_rule(model, i): + reclmtd_cu_lower, reclmtd_cu_upper = model.reclmtd_cu[i].bounds + return model.area_cu[i] <= \ + model.U_cu[i]*(\ + model.q_cu[i]*reclmtd_cu_upper +\ + sum(\ + model.Q_cu_breakpoints[i][n]*\ + (model.var_delta_reclmtd_cu[i,n] - (reclmtd_cu_upper - reclmtd_cu_lower)*model.z_q_cu[i,n])\ + for n in range(1, len(model.Q_cu_breakpoints[i])))\ + ) + +# A_huj +def area_hu_mccor_convex_1_rule(model, j): + reclmtd_hu_lower, _ = model.reclmtd_hu[j].bounds + return model.area_hu[j] >= \ + model.U_hu[j]*(\ + model.q_hu[j]*reclmtd_hu_lower +\ + sum(\ + model.Q_hu_breakpoints[j][n]*model.var_delta_reclmtd_hu[j,n]\ + for n in range(1, len(model.Q_hu_breakpoints[j])))\ + ) + +def area_hu_mccor_convex_2_rule(model, j): + reclmtd_hu_lower, reclmtd_hu_upper = model.reclmtd_hu[j].bounds + return model.area_hu[j] >= \ + model.U_hu[j]*(\ + model.q_hu[j]*reclmtd_hu_upper +\ + sum(\ + model.Q_hu_breakpoints[j][n+1]*\ + (model.var_delta_reclmtd_hu[j,n] - (reclmtd_hu_upper - reclmtd_hu_lower)*model.z_q_hu[j,n])\ + for n in range(1, len(model.Q_hu_breakpoints[j])))\ + ) + +def area_hu_mccor_concave_1_rule(model, j): + reclmtd_hu_lower, _ = model.reclmtd_hu[j].bounds + return model.area_hu[j] <= \ + model.U_hu[j]*(\ + model.q_hu[j]*reclmtd_hu_lower +\ + sum(\ + model.Q_hu_breakpoints[j][n+1]*model.var_delta_reclmtd_hu[j,n]\ + for n in range(1, len(model.Q_hu_breakpoints[j])))\ + ) + +def area_hu_mccor_concave_2_rule(model, j): + reclmtd_hu_lower, reclmtd_hu_upper = model.reclmtd_hu[j].bounds + return model.area_hu[j] <= \ + model.U_hu[j]*(\ + model.q_hu[j]*reclmtd_hu_upper +\ + sum(\ + model.Q_hu_breakpoints[j][n]*\ + (model.var_delta_reclmtd_hu[j,n] - (reclmtd_hu_upper - reclmtd_hu_lower)*model.z_q_hu[j,n])\ + for n in range(1, len(model.Q_hu_breakpoints[j])))\ + ) + +# LMTD +def grad_reclmtd_rule(model, i, j, k, x0, y0): + if x0 <= 0 or y0 <= 0: + return Constraint.Feasible + gradients = lmtd_inverse_gradient_calculator(x0, y0) + return model.reclmtd[i,j,k] >= lmtd_inv(x0, y0) + gradients[0]*(model.dt[i,j,k] - x0) + gradients[1]*(model.dt[i,j,k+1] - y0) + +def grad_reclmtd_cu_rule(model, i, x0): + y0 = model.Th_out[i] - model.T_cu_in + gradients = lmtd_inverse_gradient_calculator(x0, y0) + return model.reclmtd_cu[i] >= lmtd_inv(x0, y0) + gradients[0]*(model.dt_cu[i] - x0) + +def grad_reclmtd_hu_rule(model, j, x0): + y0 = model.T_hu_in - model.Tc_out[j] + gradients = lmtd_inverse_gradient_calculator(x0, y0) + return model.reclmtd_hu[j] >= lmtd_inv(x0, y0) + gradients[0]*(model.dt_hu[j] - x0) + +def z_area_beta_sum_rule(model, i, j, k): + return sum( model.z_area_beta[i,j,k,m] for m in range(1,len(model.Area_beta_breakpoints[i,j,k]))) == 1 + +def area_low_rule(model, i, j, k): + if model.Beta == 1: + return Constraint.Feasible + else: + area_lower = sum(model.z_area_beta[i,j,k,m]*model.Area_beta_breakpoints[i,j,k][m] for m in range(1,len(model.Area_beta_breakpoints[i,j,k]))) + return model.area[i,j,k] >= area_lower + +def area_up_rule(model, i, j, k): + if model.Beta == 1: + return Constraint.Feasible + else: + area_upper = sum(model.z_area_beta[i,j,k,m]*model.Area_beta_breakpoints[i,j,k][m+1] for m in range(1,len(model.Area_beta_breakpoints[i,j,k]))) + return model.area[i,j,k] <= area_upper + +def area_pow_beta_rule(model, i, j, k): + if model.Beta == 1: + return model.area_beta[i,j,k] == model.area[i,j,k] + else: + aread_lower = sum(model.z_area_beta[i,j,k,m]*model.Area_beta_breakpoints[i,j,k][m] for m in range(1,len(model.Area_beta_breakpoints[i,j,k]))) + aread_exp_lower = sum(model.z_area_beta[i,j,k,m]*model.Area_beta_exp[i,j,k][m] for m in range(1,len(model.Area_beta_breakpoints[i,j,k]))) + gradient = sum(model.z_area_beta[i,j,k,m]*model.Area_beta_gradients[i,j,k][m] for m in range(1,len(model.Area_beta_breakpoints[i,j,k]))) + return model.area_beta[i,j,k] >= aread_exp_lower + gradient*(model.area[i,j,k]- aread_lower) + +def z_area_cu_beta_sum_rule(model, i): + return sum( model.z_area_cu_beta[i,m] for m in range(1,len(model.Area_cu_beta_breakpoints[i]))) == 1 + +def area_cu_low_rule(model, i): + if model.Beta == 1: + return Constraint.Feasible + else: + area_cu_lower = sum(model.z_area_cu_beta[i,m]*model.Area_cu_beta_breakpoints[i][m] for m in range(1,len(model.Area_cu_beta_breakpoints[i]))) + return model.area_cu[i] >= area_cu_lower + +def area_cu_up_rule(model, i): + if model.Beta == 1: + return Constraint.Feasible + else: + area_cu_upper = sum(model.z_area_cu_beta[i,m]*model.Area_cu_beta_breakpoints[i][m+1] for m in range(1,len(model.Area_cu_beta_breakpoints[i]))) + return model.area_cu[i] <= area_cu_upper + +def area_cu_pow_beta_rule(model, i): + if model.Beta == 1: + return model.area_cu_beta[i] == model.area_cu[i] + else: + area_cu_lower = sum(model.z_area_cu_beta[i,m]*model.Area_cu_beta_breakpoints[i][m] for m in range(1,len(model.Area_cu_beta_breakpoints[i]))) + area_cu_exp_lower = sum(model.z_area_cu_beta[i,m]*model.Area_cu_beta_exp[i][m] for m in range(1,len(model.Area_cu_beta_breakpoints[i]))) + gradient = sum(model.z_area_cu_beta[i,m]*model.Area_cu_beta_gradients[i][m] for m in range(1,len(model.Area_cu_beta_breakpoints[i]))) + return model.area_cu_beta[i] >= area_cu_exp_lower + gradient*(model.area_cu[i]- area_cu_lower) + +def z_area_hu_beta_sum_rule(model, j): + return sum( model.z_area_hu_beta[j,m] for m in range(1,len(model.Area_hu_beta_breakpoints[j]))) == 1 + +def area_hu_low_rule(model, j): + if model.Beta == 1: + return Constraint.Feasible + else: + area_hu_lower = sum(model.z_area_hu_beta[j,m]*model.Area_hu_beta_breakpoints[j][m] for m in range(1,len(model.Area_hu_beta_breakpoints[j]))) + return model.area_hu[j] >= area_hu_lower + +def area_hu_up_rule(model, j): + if model.Beta == 1: + return Constraint.Feasible + else: + area_hu_upper = sum(model.z_area_hu_beta[j,m]*model.Area_hu_beta_breakpoints[j][m+1] for m in range(1,len(model.Area_hu_beta_breakpoints[j]))) + return model.area_hu[j] <= area_hu_upper + +def area_hu_pow_beta_rule(model, j): + if model.Beta == 1: + return model.area_hu_beta[j] == model.area_hu[j] + else: + area_hu_lower = sum(model.z_area_hu_beta[j,m]*model.Area_hu_beta_breakpoints[j][m] for m in range(1,len(model.Area_hu_beta_breakpoints[j]))) + area_hu_exp_lower = sum(model.z_area_hu_beta[j,m]*model.Area_hu_beta_exp[j][m] for m in range(1,len(model.Area_hu_beta_breakpoints[j]))) + gradient = sum(model.z_area_hu_beta[j,m]*model.Area_hu_beta_gradients[j][m] for m in range(1,len(model.Area_hu_beta_breakpoints[j]))) + return model.area_hu_beta[j] >= area_hu_exp_lower + gradient*(model.area_hu[j]- area_hu_lower) diff --git a/hens/adaptive_model_mixer/lib/model_declarations/constraints.py b/hens/adaptive_model_mixer/lib/model_declarations/constraints.py new file mode 100644 index 0000000..1416a9f --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/constraints.py @@ -0,0 +1,153 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.constraint import Constraint + +from .index_generators import reclmtd_index, reclmtd_cu_index, reclmtd_hu_index, z_q_index, z_q_cu_index, z_q_hu_index, var_delta_fh_index, var_delta_fhx_index, var_delta_fc_index, var_delta_fcx_index + +from .constraint_rules import * + +def declare_constraints(model): + model.z_th_sum = Constraint(model.HP, model.ST, rule=z_th_sum_rule) + model.th_lower = Constraint(model.HP, model.ST, rule=th_lower_rule) + model.th_upper = Constraint(model.HP, model.ST, rule=th_upper_rule) + + model.var_delta_fh_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_fh_sum_rule) + model.var_delta_fh_upper = Constraint(var_delta_fh_index, rule=var_delta_fh_upper_rule) + + model.z_thx_sum = Constraint(model.HP, model.CP, model.ST, rule=z_thx_sum_rule) + model.thx_lower = Constraint(model.HP, model.CP, model.ST, rule=thx_lower_rule) + model.thx_upper = Constraint(model.HP, model.CP, model.ST, rule=thx_upper_rule) + + model.var_delta_fhx_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_fhx_sum_rule) + model.var_delta_fhx_upper = Constraint(var_delta_fhx_index, rule=var_delta_fhx_upper_rule) + + model.z_tc_sum = Constraint(model.CP, model.ST, rule=z_tc_sum_rule) + model.tc_lower = Constraint(model.CP, model.ST, rule=tc_lower_rule) + model.tc_upper = Constraint(model.CP, model.ST, rule=tc_upper_rule) + + model.var_delta_fc_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_fc_sum_rule) + model.var_delta_fc_upper = Constraint(var_delta_fc_index, rule=var_delta_fc_upper_rule) + + model.z_tcx_sum = Constraint(model.HP, model.CP, model.ST, rule=z_tcx_sum_rule) + model.tcx_lower = Constraint(model.HP, model.CP, model.ST, rule=tcx_lower_rule) + model.tcx_upper = Constraint(model.HP, model.CP, model.ST, rule=tcx_upper_rule) + + model.var_delta_fcx_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_fcx_sum_rule) + model.var_delta_fcx_upper = Constraint(var_delta_fcx_index, rule=var_delta_fcx_upper_rule) + + # Overall heat balance + model.overall_heat_balance_hot = Constraint(model.HP, rule=overall_heat_balance_hot_rule) + model.overall_heat_balance_cold = Constraint(model.CP, rule=overall_heat_balance_cold_rule) + + model.energy_balance_hot = Constraint(model.HP, model.ST, rule=energy_balance_hot_rule, doc="Energy exchanged by hot stream i in stage k" ) + model.energy_balance_cold = Constraint(model.CP, model.ST, rule=energy_balance_cold_rule, doc="Energy exchanged by cold stream j in stage k" ) + model.energy_balance_cu = Constraint(model.HP, rule=energy_balance_cu_rule, doc="Energy exchanged by hot stream i with the cold utility" ) + model.energy_balance_hu = Constraint(model.CP, rule=energy_balance_hu_rule, doc="Energy exchanged by cold stream j with the hot utility" ) + + # Inlet temperatures + model.hot_inlet = Constraint(model.HP, rule=hot_inlet_rule) + model.cold_inlet = Constraint(model.CP, rule=cold_inlet_rule) + + # Mass balance + model.mass_balance_hot = Constraint(model.HP, model.ST, rule=mass_balance_hot_rule) + model.mass_balance_cold = Constraint(model.CP, model.ST, rule=mass_balance_cold_rule) + + # Monotonicity + model.decreasing_hot = Constraint(model.HP, model.ST, rule=decreasing_hot_rule) + model.decreasing_cold = Constraint(model.CP, model.ST, rule=decreasing_cold_rule) + model.hot_upper_bound = Constraint(model.HP, rule=hot_upper_bound_rule) + model.cold_lower_bound = Constraint(model.CP, rule=cold_lower_bound_rule) + + # Heat load big M + model.q_big_m = Constraint(model.HP, model.CP, model.ST, rule=q_big_m_rule) + model.q_cu_big_m = Constraint(model.HP, rule=q_cu_big_m_rule) + model.q_hu_big_m = Constraint(model.CP, rule=q_hu_big_m_rule) + + # Temperature approach big M + model.temp_app_in = Constraint(model.HP, model.CP, model.ST, rule=temp_app_in_rule) + model.temp_app_out = Constraint(model.HP, model.CP, model.ST, rule=temp_app_out_rule) + model.temp_app_cu = Constraint(model.HP, rule=temp_app_cu_rule) + model.temp_app_hu = Constraint(model.CP, rule=temp_app_hu_rule) + + # Bilinear McCormick bounds + model.mccor_convex_h_in_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_h_in_1_rule) + model.mccor_convex_h_in_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_h_in_2_rule) + model.mccor_concave_h_in_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_h_in_1_rule) + model.mccor_concave_h_in_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_h_in_2_rule) + + model.mccor_convex_h_out_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_h_out_1_rule) + model.mccor_convex_h_out_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_h_out_2_rule) + model.mccor_concave_h_out_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_h_out_1_rule) + model.mccor_concave_h_out_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_h_out_2_rule) + + model.mccor_convex_c_in_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_c_in_1_rule) + model.mccor_convex_c_in_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_c_in_2_rule) + model.mccor_concave_c_in_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_c_in_1_rule) + model.mccor_concave_c_in_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_c_in_2_rule) + + model.mccor_convex_c_out_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_c_out_1_rule) + model.mccor_convex_c_out_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_c_out_2_rule) + model.mccor_concave_c_out_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_c_out_1_rule) + model.mccor_concave_c_out_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_c_out_2_rule) + + #Per heat exchanger energy balance + model.q_energy_bal_hot = Constraint(model.HP, model.CP, model.ST, rule=q_energy_bal_hot_rule) + model.q_energy_bal_cold = Constraint(model.HP, model.CP, model.ST, rule=q_energy_bal_cold_rule) + + #Per mixer energy balance + model.mixer_energy_bal_hot = Constraint(model.HP, model.ST, rule=mixer_energy_bal_hot_rule) + model.mixer_energy_bal_cold = Constraint(model.CP, model.ST, rule=mixer_energy_bal_cold_rule) + + model.grad_reclmtd = Constraint(reclmtd_index, rule=grad_reclmtd_rule) + model.grad_reclmtd_cu = Constraint(reclmtd_cu_index, rule=grad_reclmtd_cu_rule) + model.grad_reclmtd_hu = Constraint(reclmtd_hu_index, rule=grad_reclmtd_hu_rule) + + # Area McCormick bounds + model.z_q_sum = Constraint(model.HP, model.CP, model.ST, rule=z_q_sum_rule) + model.q_lower = Constraint(model.HP, model.CP, model.ST, rule=q_lower_rule) + model.q_upper = Constraint(model.HP, model.CP, model.ST, rule=q_upper_rule) + model.var_delta_reclmtd_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_reclmtd_sum_rule) + model.var_delta_reclmtd_upper = Constraint(z_q_index, rule=var_delta_reclmtd_upper_rule) + + model.area_mccor_convex_1 = Constraint(model.HP, model.CP, model.ST, rule=area_mccor_convex_1_rule) + model.area_mccor_convex_2 = Constraint(model.HP, model.CP, model.ST, rule=area_mccor_convex_2_rule) + model.area_mccor_concave_1 = Constraint(model.HP, model.CP, model.ST, rule=area_mccor_concave_1_rule) + model.area_mccor_concave_2 = Constraint(model.HP, model.CP, model.ST, rule=area_mccor_concave_2_rule) + + model.z_q_cu_sum = Constraint(model.HP, rule=z_q_cu_sum_rule) + model.q_cu_lower = Constraint(model.HP, rule=q_cu_lower_rule) + model.q_cu_upper = Constraint(model.HP, rule=q_cu_upper_rule) + model.var_delta_reclmtd_cu_sum = Constraint(model.HP, rule=var_delta_reclmtd_cu_sum_rule) + model.var_delta_reclmtd_cu_upper = Constraint(z_q_cu_index, rule=var_delta_reclmtd_cu_upper_rule) + + model.area_cu_mccor_convex_1 = Constraint(model.HP, rule=area_cu_mccor_convex_1_rule) + model.area_cu_mccor_convex_2 = Constraint(model.HP, rule=area_cu_mccor_convex_2_rule) + model.area_cu_mccor_concave_1 = Constraint(model.HP, rule=area_cu_mccor_concave_1_rule) + model.area_cu_mccor_concave_2 = Constraint(model.HP, rule=area_cu_mccor_concave_2_rule) + + model.z_q_hu_sum = Constraint(model.CP, rule=z_q_hu_sum_rule) + model.q_hu_lower = Constraint(model.CP, rule=q_hu_lower_rule) + model.q_hu_upper = Constraint(model.CP, rule=q_hu_upper_rule) + model.var_delta_reclmtd_hu_sum = Constraint(model.CP, rule=var_delta_reclmtd_hu_sum_rule) + model.var_delta_reclmtd_hu_upper = Constraint(z_q_hu_index, rule=var_delta_reclmtd_hu_upper_rule) + + model.area_hu_mccor_convex_1 = Constraint(model.CP, rule=area_hu_mccor_convex_1_rule) + model.area_hu_mccor_convex_2 = Constraint(model.CP, rule=area_hu_mccor_convex_2_rule) + model.area_hu_concave_mccor_1 = Constraint(model.CP, rule=area_hu_mccor_concave_1_rule) + model.area_hu_concave_mccor_2 = Constraint(model.CP, rule=area_hu_mccor_concave_2_rule) + + model.z_area_beta_sum = Constraint(model.HP, model.CP, model.ST, rule=z_area_beta_sum_rule) + model.area_low = Constraint(model.HP, model.CP, model.ST, rule=area_low_rule) + model.area_up = Constraint(model.HP, model.CP, model.ST, rule=area_up_rule) + model.area_pow_beta = Constraint(model.HP, model.CP, model.ST, rule=area_pow_beta_rule) + + model.z_area_cu_beta_sum = Constraint(model.HP, rule=z_area_cu_beta_sum_rule) + model.area_cu_low = Constraint(model.HP, rule=area_cu_low_rule) + model.area_cu_up = Constraint(model.HP, rule=area_cu_up_rule) + model.area_cu_pow_beta = Constraint(model.HP, rule=area_cu_pow_beta_rule) + + model.z_area_hu_beta_sum = Constraint(model.CP, rule=z_area_hu_beta_sum_rule) + model.area_hu_low = Constraint(model.CP, rule=area_hu_low_rule) + model.area_hu_up = Constraint(model.CP, rule=area_hu_up_rule) + model.area_hu_pow_beta = Constraint(model.CP, rule=area_hu_pow_beta_rule) diff --git a/hens/adaptive_model_mixer/lib/model_declarations/helper_functions.py b/hens/adaptive_model_mixer/lib/model_declarations/helper_functions.py new file mode 100644 index 0000000..316c092 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/helper_functions.py @@ -0,0 +1,37 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from math import log + +def two_point_generator(points, bounds): + lower, upper = bounds + ret_set = [] + for pa, pb in points: + x = lower*pa + upper*pb + ret_set.append(x) + return ret_set + +def three_point_generator(points, bounds): + lower, upper = bounds + ax, ay = lower, lower + bx, by = upper, upper + cx, cy = upper, lower + ret_set = [] + for pa, pb, pc in points: + x0 = ax*pa + bx*pb + cx*pc + y0 = ay*pa + by*pb + cy*pc + ret_set.append((x0,y0)) + if not x0 == y0: + ret_set.append((y0,x0)) + return ret_set + +def lmtd_inv(x, y): + return log(x/y)/(x-y) if (x != y) else 1/x + +def lmtd_inverse_gradient_calculator(x0, y0): + if x0 == y0: + return (-1/(2*pow(x0,2)),-1/(2*pow(y0,2))) + else: + w = x0/y0 + scale = 1/(pow((x0-y0),2)) + return (scale*(1-(1/w)-log(w)), scale*(1+log(w)-w)) diff --git a/hens/adaptive_model_mixer/lib/model_declarations/index_generators.py b/hens/adaptive_model_mixer/lib/model_declarations/index_generators.py new file mode 100644 index 0000000..d14b5b9 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/index_generators.py @@ -0,0 +1,141 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +def z_th_index(model): + for i in model.HP: + for k in model.ST: + for point in range(1, len(model.Th_breakpoints[i,k])): + yield (i,k, point) + +z_th_index.dimen = 3 + +def z_thx_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Thx_breakpoints[i,j,k])): + yield (i,j,k,point) + +z_thx_index.dimen = 4 + +def z_tc_index(model): + for j in model.CP: + for k in model.K_Take_First_Stage: + for point in range(1, len(model.Tc_breakpoints[j,k])): + yield (j,k, point) + +z_tc_index.dimen = 3 + +def z_tcx_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Tcx_breakpoints[i,j,k])): + yield (i,j,k,point) + +z_tcx_index.dimen = 4 + +def var_delta_fh_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Th_breakpoints[i,k])): + yield (i,j,k, point) + +var_delta_fh_index.dimen = 4 + +def var_delta_fhx_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Thx_breakpoints[i,j,k])): + yield (i,j,k, point) + +var_delta_fhx_index.dimen = 4 + +def var_delta_fc_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Tc_breakpoints[j,k+1])): + yield (i,j,k, point) + +var_delta_fc_index.dimen = 4 + +def var_delta_fcx_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Tcx_breakpoints[i,j,k])): + yield (i,j,k, point) + +var_delta_fcx_index.dimen = 4 + +def reclmtd_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in model.Reclmtd_gradient_points[i,j,k]: + yield (i,j,k) + point + +reclmtd_index.dimen = 5 + +def reclmtd_cu_index(model): + for i in model.HP: + for point in model.Reclmtd_cu_gradient_points[i]: + yield (i,point) + +reclmtd_cu_index.dimen = 2 + +def reclmtd_hu_index(model): + for j in model.CP: + for point in model.Reclmtd_hu_gradient_points[j]: + yield (j,point) + +reclmtd_hu_index.dimen = 2 + +def z_q_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Q_breakpoints[i,j,k])): + yield (i,j,k,point) + +z_q_index.dimen = 4 + +def z_q_cu_index(model): + for i in model.HP: + for point in range(1, len(model.Q_cu_breakpoints[i])): + yield (i,point) + +z_q_cu_index.dimen = 2 + +def z_q_hu_index(model): + for j in model.CP: + for point in range(1, len(model.Q_hu_breakpoints[j])): + yield (j,point) + +z_q_hu_index.dimen = 2 + +def z_area_beta_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1,len(model.Area_beta_breakpoints[i,j,k])): + yield (i,j,k,point) + +z_area_beta_index.dimen = 4 + +def z_area_cu_beta_index(model): + for i in model.HP: + for point in range(1,len(model.Area_cu_beta_breakpoints[i])): + yield (i,point) + +z_area_cu_beta_index.dimen = 2 + +def z_area_hu_beta_index(model): + for j in model.CP: + for point in range(1,len(model.Area_hu_beta_breakpoints[j])): + yield (j,point) + +z_area_hu_beta_index.dimen = 2 diff --git a/hens/adaptive_model_mixer/lib/model_declarations/model_builder.py b/hens/adaptive_model_mixer/lib/model_declarations/model_builder.py new file mode 100644 index 0000000..1bb9179 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/model_builder.py @@ -0,0 +1,18 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.PyomoModel import AbstractModel +from pyomo.core.base.sets import Set + +from .parameters import declare_parameters +from .variables import declare_variables +from .objective import declare_objective +from .constraints import declare_constraints + +def create_model(): + model = AbstractModel() + declare_parameters(model) + declare_variables(model) + declare_objective(model) + declare_constraints(model) + return model diff --git a/hens/adaptive_model_mixer/lib/model_declarations/objective.py b/hens/adaptive_model_mixer/lib/model_declarations/objective.py new file mode 100644 index 0000000..251eba0 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/objective.py @@ -0,0 +1,23 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.objective import Objective + +def TAC_rule(model): + total_cu_load = sum( model.q_cu[i] for i in model.HP ) + total_hu_load = sum( model.q_hu[j] for j in model.CP ) + + total_number_of_stream_hx = sum( model.z[i,j,k] for i in model.HP for j in model.CP for k in model.ST ) + total_number_of_cu_hx = sum( model.z_cu[i] for i in model.HP ) + total_number_of_hu_hx = sum( model.z_hu[j] for j in model.CP ) + total_number_of_hx = total_number_of_stream_hx + total_number_of_cu_hx + total_number_of_hu_hx + + total_area_of_stream_hx = sum( model.area_beta[i,j,k] for i in model.HP for j in model.CP for k in model.ST ) + total_area_of_cu_hx = sum( model.area_cu_beta[i] for i in model.HP ) + total_area_of_hu_hx = sum( model.area_hu_beta[j] for j in model.CP ) + total_area_of_hx = total_area_of_stream_hx + total_area_of_cu_hx + total_area_of_hu_hx + + return model.Cost_cu*total_cu_load + model.Cost_hu*total_hu_load + model.Cost_hx*total_number_of_hx + model.Alpha*total_area_of_hx + +def declare_objective(model): + model.TAC = Objective(rule=TAC_rule) diff --git a/hens/adaptive_model_mixer/lib/model_declarations/parameter_initialisation_functions.py b/hens/adaptive_model_mixer/lib/model_declarations/parameter_initialisation_functions.py new file mode 100644 index 0000000..18f4f7c --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/parameter_initialisation_functions.py @@ -0,0 +1,91 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from .bound_generators import area_bounds, area_cu_bounds, area_hu_bounds, q_bounds, q_cu_bounds, q_hu_bounds, th_bounds, thx_bounds, tc_bounds, tcx_bounds + +def u_init(model, i, j): + return (1/model.Hh[i]) + (1/model.Hc[j]) + +def u_cu_init(model, i): + return (1/model.Hh[i]) + (1/model.H_cu) + +def u_hu_init(model, j): + return (1/model.Hc[j]) + (1/model.H_hu) + +def ech_init(model, i): + return model.Fh[i]*(model.Th_in[i] - model.Th_out[i]) + +def ecc_init(model, j): + return model.Fc[j]*(model.Tc_out[j] - model.Tc_in[j]) + +def Omega_ij_init(model, i, j): + return min(model.Ech[i], model.Ecc[j]) + +def Omega_i_init(model, i): + return model.Ech[i] + +def Omega_j_init(model, j): + return model.Ecc[j] + +def Gamma_init(model, i, j): + return max(\ + 0,\ + model.Tc_in[j] - model.Th_in[i],\ + model.Tc_in[j] - model.Th_out[i],\ + model.Tc_out[j] - model.Th_in[i],\ + model.Tc_out[j] - model.Th_out[i]\ + ) + +def th_breakpoints_init(model, i): + return list(th_bounds(model, i)) + +def thx_breakpoints_init(model, i, j, k): + return list(thx_bounds(model, i, j, k)) + +def tc_breakpoints_init(model, j): + return list(tc_bounds(model, j)) + +def tcx_breakpoints_init(model, i, j, k): + return list(tcx_bounds(model, i, j, k)) + +def q_breakpoints_init(model, i, j, *k): + return list(q_bounds(model, i, j)) + +def q_cu_breakpoints_init(model, i): + return list(q_cu_bounds(model, i)) + +def q_hu_breakpoints_init(model, j): + return list(q_hu_bounds(model, j)) + +def area_beta_breakpoints_init(model, i, j, *k): + return list(area_bounds(model, i, j)) + +def area_beta_gradients_init(model, i, j, k): + gradients = [0]*(len(model.Area_beta_breakpoints[i,j,k])-1) + for m in range(1,len(model.Area_beta_breakpoints[i,j,k])): + numerator = model.Area_beta_exp[i,j,k][m+1] - model.Area_beta_exp[i,j,k][m] + denominator = model.Area_beta_breakpoints[i,j,k][m+1] - model.Area_beta_breakpoints[i,j,k][m] + gradients[m-1] = numerator/denominator + return gradients + +def area_cu_beta_breakpoints_init(model, i): + return list(area_cu_bounds(model, i)) + +def area_cu_beta_gradients_init(model, i): + gradients = [0]*(len(model.Area_cu_beta_breakpoints[i])-1) + for m in range(1,len(model.Area_cu_beta_breakpoints[i])): + numerator = model.Area_cu_beta_exp[i][m+1] - model.Area_cu_beta_exp[i][m] + denominator = model.Area_cu_beta_breakpoints[i][m+1] - model.Area_cu_beta_breakpoints[i][m] + gradients[m-1] = numerator/denominator + return gradients + +def area_hu_beta_breakpoints_init(model, j): + return list(area_hu_bounds(model, j)) + +def area_hu_beta_gradients_init(model, j): + gradients = [0]*(len(model.Area_hu_beta_breakpoints[j])-1) + for m in range(1,len(model.Area_hu_beta_breakpoints[j])): + numerator = model.Area_hu_beta_exp[j][m+1] - model.Area_hu_beta_exp[j][m] + denominator = model.Area_hu_beta_breakpoints[j][m+1] - model.Area_hu_beta_breakpoints[j][m] + gradients[m-1] = numerator/denominator + return gradients diff --git a/hens/adaptive_model_mixer/lib/model_declarations/parameters.py b/hens/adaptive_model_mixer/lib/model_declarations/parameters.py new file mode 100644 index 0000000..f34aec9 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/parameters.py @@ -0,0 +1,98 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.param import Param +from pyomo.core.base.sets import Set +from pyomo.core.base.rangeset import RangeSet +from pyomo.core.base.set_types import PositiveReals, NonNegativeReals, PositiveIntegers, PercentFraction + +from .parameter_initialisation_functions import * + +############################################################ +############################################################ +################### Assignment Functions ################### +############################################################ +############################################################ +def declare_parameters(model): + model.Alpha = Param(within=NonNegativeReals, doc="factor for area cost" ) + model.Beta = Param(within=PercentFraction , doc="exponent for the area cost" ) + model.Cost_hx = Param(within=NonNegativeReals, doc="fixed charge for exchangers" ) + model.Cost_cu = Param(within=NonNegativeReals, doc="utility cost coeffiecient for cooling utility j" ) + model.Cost_hu = Param(within=NonNegativeReals, doc="utility cost coeffiecient for heating utility k" ) + model.Delta_t_min = Param(within=NonNegativeReals, doc="minimum temperature approach" ) + + model.Number_stages = Param(within=PositiveIntegers, doc="number of stages" ) + model.Number_hot_stream = Param(within=PositiveIntegers, doc="number of hot streams" ) + model.Number_cold_stream = Param(within=PositiveIntegers, doc="number of cold streams" ) + + model.First_stage = Param(within=PositiveIntegers, default=1, doc='Index of the first stage') + model.Last_stage = Param(within=PositiveIntegers, default=model.Number_stages+1, doc='Index of the last stage' ) + + model.HP = RangeSet(1, model.Number_hot_stream, doc="set of hot process streams i" ) + model.CP = RangeSet(1, model.Number_cold_stream, doc="set of cold process streams j" ) + model.ST = RangeSet(model.First_stage, model.Number_stages, doc="set of stages in the superstructure" ) + model.K = RangeSet(model.First_stage, model.Last_stage, doc="set of temperature locations" ) + model.First_Stage_Set = RangeSet(model.First_stage, model.First_stage) + model.K_Take_First_Stage = model.K - model.First_Stage_Set + + model.Fh = Param(model.HP, doc="flow capicity of hot stream i" ) + model.Fc = Param(model.CP, doc="flow capacity of cold stream j" ) + + model.Hh = Param(model.HP, doc="heat transfer coefficient for hot stream i" ) + model.Hc = Param(model.CP, doc="heat transfer coefficient for cold stream j" ) + model.H_cu = Param( doc="heat transfer coefficient for cold utility" ) + model.H_hu = Param( doc="heat transfer coefficient for hot utility" ) + + model.Th_in = Param(model.HP, doc="inlet temperature of hot stream i" ) + model.Tc_in = Param(model.CP, doc="inlet temperature of cold stream j" ) + model.Th_out = Param(model.HP, doc="outlet temperature of hot stream i" ) + model.Tc_out = Param(model.CP, doc="outlet temperature of cold stream j" ) + + model.T_cu_in = Param(within=PositiveReals, doc="inlet temperature of cold utility" ) + model.T_cu_out = Param(within=PositiveReals, doc="outlet temperature of cold utility" ) + model.T_hu_in = Param(within=PositiveReals, doc="inlet temperature of hot utility" ) + model.T_hu_out = Param(within=PositiveReals, doc="outlet temperature of hot utility" ) + + ############################### + # Initialised Parameters # + ############################### + model.Reclmtd_gradient_points = Set(model.HP, model.CP, model.ST, dimen=2, initialize=[]) + model.Reclmtd_cu_gradient_points = Set(model.HP, dimen=1, initialize=[]) + model.Reclmtd_hu_gradient_points = Set(model.CP, dimen=1, initialize=[]) + + model.U = Param(model.HP, model.CP, within=PositiveReals, initialize=u_init) + model.U_cu = Param(model.HP, within=PositiveReals, initialize=u_cu_init) + model.U_hu = Param(model.CP, within=PositiveReals, initialize=u_hu_init) + + model.Ech = Param(model.HP, within=PositiveReals, initialize=ech_init) + model.Ecc = Param(model.CP, within=PositiveReals, initialize=ecc_init) + + model.Omega_ij = Param(model.HP, model.CP, within=PositiveReals, initialize=Omega_ij_init) + model.Omega_i = Param(model.HP, within=PositiveReals, initialize=Omega_i_init) + model.Omega_j = Param(model.CP, within=PositiveReals, initialize=Omega_j_init) + + model.Gamma = Param(model.HP, model.CP, within=NonNegativeReals, initialize=Gamma_init) + + model.Th_breakpoints = Set(model.HP, model.ST, dimen=1, ordered=True, initialize=lambda model, i, k: th_breakpoints_init(model, i)) + + model.Thx_breakpoints = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=lambda model, i, j, k: thx_breakpoints_init(model, i, j, k)) + + model.Tc_breakpoints = Set(model.CP, model.K_Take_First_Stage, dimen=1, ordered=True, initialize=lambda model, j, k: tc_breakpoints_init(model, j)) + + model.Tcx_breakpoints = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=lambda model, i, j, k: tcx_breakpoints_init(model, i, j, k)) + + model.Q_breakpoints = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=lambda model, i, j, k: q_breakpoints_init(model, i, j)) + model.Q_cu_breakpoints = Set(model.HP, dimen=1, ordered=True, initialize=lambda model, i: q_cu_breakpoints_init(model, i)) + model.Q_hu_breakpoints = Set(model.CP, dimen=1, ordered=True, initialize=lambda model, j: q_hu_breakpoints_init(model, j)) + + model.Area_beta_breakpoints = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=lambda model,i,j,k: area_beta_breakpoints_init(model,i,j)) + model.Area_beta_exp = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=lambda model,i,j,k: map(lambda A: pow(A, model.Beta), model.Area_beta_breakpoints[i,j,k])) + model.Area_beta_gradients = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=area_beta_gradients_init) + + model.Area_cu_beta_breakpoints = Set(model.HP, dimen=1, ordered=True, initialize=lambda model,i: area_cu_beta_breakpoints_init(model,i)) + model.Area_cu_beta_exp = Set(model.HP, dimen=1, ordered=True, initialize=lambda model,i: map(lambda A: pow(A, model.Beta), model.Area_cu_beta_breakpoints[i])) + model.Area_cu_beta_gradients = Set(model.HP, dimen=1, ordered=True, initialize=area_cu_beta_gradients_init) + + model.Area_hu_beta_breakpoints = Set(model.CP, dimen=1, ordered=True, initialize=lambda model,j: area_hu_beta_breakpoints_init(model,j)) + model.Area_hu_beta_exp = Set(model.CP, dimen=1, ordered=True, initialize=lambda model,j: map(lambda A: pow(A, model.Beta), model.Area_hu_beta_breakpoints[j])) + model.Area_hu_beta_gradients = Set(model.CP, dimen=1, ordered=True, initialize=area_hu_beta_gradients_init) diff --git a/hens/adaptive_model_mixer/lib/model_declarations/variables.py b/hens/adaptive_model_mixer/lib/model_declarations/variables.py new file mode 100644 index 0000000..2e84cab --- /dev/null +++ b/hens/adaptive_model_mixer/lib/model_declarations/variables.py @@ -0,0 +1,104 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.var import Var +from pyomo.core.base.set_types import Binary, NonNegativeReals + +from .bound_generators import * +from .index_generators import z_area_beta_index, z_area_cu_beta_index, z_area_hu_beta_index, z_q_index, z_q_cu_index, z_q_hu_index, z_th_index, z_thx_index, z_tc_index, z_tcx_index, var_delta_fh_index, var_delta_fhx_index, var_delta_fc_index, var_delta_fcx_index + +############################################################ +############################################################ +################### Assignment Functions ################### +############################################################ +############################################################ +def declare_variables(model): + # Areas - Make sure that this is declared after q and lmtd + model.area = Var(model.HP, model.CP, model.ST, bounds=area_bounds, initialize = 0,\ + doc="Area for exchanger ijk" ) + model.area_cu = Var(model.HP, bounds=area_cu_bounds, initialize = 0,\ + doc="Area for cooler i" ) + model.area_hu = Var(model.CP, bounds=area_hu_bounds, initialize = 0,\ + doc="Area for heater j" ) + + model.area_beta = Var(model.HP, model.CP, model.ST, initialize = 0, domain=NonNegativeReals) + model.area_cu_beta = Var(model.HP, initialize = 0, domain=NonNegativeReals) + model.area_hu_beta = Var(model.CP, initialize = 0, domain=NonNegativeReals) + + # Flow rates + model.fh = Var(model.HP, model.CP, model.ST, bounds=fh_bounds,\ + doc="Flow rate entering heat exchanger ijk cold side" ) + model.fc = Var(model.HP, model.CP, model.ST, bounds=fc_bounds,\ + doc="Flow rate entering heat exchanger ijk hot side" ) + + # Per exchanger outlet + model.thx = Var(model.HP, model.CP, model.ST, bounds=thx_bounds,\ + doc="Outlet temperature of the heat exchanger ijk hot side" ) + model.tcx = Var(model.HP, model.CP, model.ST, bounds=tcx_bounds,\ + doc="Outlet temperature of the heat exchanger ijk cold side" ) + + # Temperature approaches + model.dt = Var(model.HP, model.CP, model.K, bounds=dt_bounds,\ + doc="Approach between i and j in location k" ) + model.dt_cu = Var(model.HP, bounds=dt_cu_bounds,\ + doc="Approach between i and the cold utility" ) + model.dt_hu = Var(model.CP, bounds=dt_hu_bounds,\ + doc="Approach between j and the hot utility" ) + + # Log mean temperature differences + model.reclmtd = Var(model.HP, model.CP, model.ST, bounds=reclmtd_bounds,\ + doc="Log mean temperature difference between hot stream i and cold stream j at stage k" ) + model.reclmtd_cu = Var(model.HP, bounds=reclmtd_cu_bounds,\ + doc="Log mean temperature difference between hot stream i and cold utility" ) + model.reclmtd_hu = Var(model.CP, bounds=reclmtd_hu_bounds,\ + doc="Log mean temperature difference between cold stream j and hot utility" ) + + # Heat loads + model.q = Var(model.HP, model.CP, model.ST, bounds=q_bounds, initialize = 0,\ + doc="heat load between hot stream i and cold stream j at stage k" ) + model.q_cu = Var(model.HP, bounds=q_cu_bounds, initialize = 0,\ + doc="heat load between hot stream i and cold utility" ) + model.q_hu = Var(model.CP, bounds=q_hu_bounds, initialize = 0,\ + doc="heat load between cold stream j and hot utility" ) + + # Per stage temperatures + model.th = Var(model.HP, model.K, bounds=th_bounds,\ + doc="temperature of hot stream i at hot end of stage k" ) + model.tc = Var(model.CP, model.K, bounds=tc_bounds,\ + doc="temperature of cold stream j at hot end of stage k" ) + + # Binary variables + model.z = Var(model.HP, model.CP, model.ST, initialize = 0, domain=Binary,\ + doc="existence of the match between hot stream i and cold stream j at stage k" ) + model.z_cu = Var(model.HP, initialize = 0, domain=Binary,\ + doc="existence of the match between hot stream i and cold utility" ) + model.z_hu = Var(model.CP, initialize = 0, domain=Binary,\ + doc="existence of the match between cold stream j and hot utility" ) + + model.z_area_beta = Var(z_area_beta_index, domain=Binary) + model.z_area_cu_beta = Var(z_area_cu_beta_index, domain=Binary) + model.z_area_hu_beta = Var(z_area_hu_beta_index, domain=Binary) + + model.z_q = Var(z_q_index, domain=Binary) + model.z_q_cu = Var(z_q_cu_index, domain=Binary) + model.z_q_hu = Var(z_q_hu_index, domain=Binary) + + model.var_delta_reclmtd = Var(z_q_index, domain=NonNegativeReals) + model.var_delta_reclmtd_cu = Var(z_q_cu_index, domain=NonNegativeReals) + model.var_delta_reclmtd_hu = Var(z_q_hu_index, domain=NonNegativeReals) + + # New variables + model.bh_in = Var(model.HP, model.CP, model.ST, bounds=bh_bounds) + model.bh_out = Var(model.HP, model.CP, model.ST, bounds=bh_bounds) + model.bc_in = Var(model.HP, model.CP, model.ST, bounds=bc_bounds) + model.bc_out = Var(model.HP, model.CP, model.ST, bounds=bc_bounds) + + model.z_th = Var(z_th_index, domain=Binary) + model.z_thx = Var(z_thx_index, domain=Binary) + model.z_tc = Var(z_tc_index, domain=Binary) + model.z_tcx = Var(z_tcx_index, domain=Binary) + + model.var_delta_fh = Var(var_delta_fh_index, domain=NonNegativeReals) + model.var_delta_fhx = Var(var_delta_fhx_index, domain=NonNegativeReals) + model.var_delta_fc = Var(var_delta_fc_index, domain=NonNegativeReals) + model.var_delta_fcx = Var(var_delta_fcx_index, domain=NonNegativeReals) diff --git a/hens/adaptive_model_mixer/lib/results_generator/__init__.py b/hens/adaptive_model_mixer/lib/results_generator/__init__.py new file mode 100644 index 0000000..f757ec9 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/results_generator/__init__.py @@ -0,0 +1,2 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London diff --git a/hens/adaptive_model_mixer/lib/results_generator/document_builder.py b/hens/adaptive_model_mixer/lib/results_generator/document_builder.py new file mode 100644 index 0000000..b21d1c8 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/results_generator/document_builder.py @@ -0,0 +1,778 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import json, sys, unicodedata, os, yaml + +from pyomo.environ import * + +from pprint import pprint + +from ..constants import * + +try: + from pylatex import * +except ImportError: + pass + +def check_folder_structure(folders, iteration): + if not os.path.exists(folders[model_folder]): + os.makedirs(folders[model_folder]) + + if not os.path.exists(folders[append_folder]): + os.makedirs(folders[append_folder]) + + if iteration and not os.path.exists(folders[iterations_folder]): + os.makedirs(folders[iterations_folder]) + +def save_pdf(doc, filename, folders, iteration): + if iteration: + path_without_extension = os.path.join(folders[iterations_folder], filename) + else: + path_without_extension = os.path.join(folders[append_folder], filename) + + doc.generate_pdf(path_without_extension, silent=True) + if (len(sys.argv) > 2): + with open(path_without_extension + '.tex', 'w') as tex_file: + tex_file.write(doc.dumps()) + +def add_preamble(doc): + doc.packages.append(Package('float, amsmath, amssymb, supertabular, multicol, url, subcaption, tikz, pgfplots, fancyhdr, morefloats, setspace')) + # \usepackage[parfill]{parskip} + doc.packages.append(Package('parskip', options=['parfill'])) + doc.packages.append(Package('geometry', options=['tmargin=1in', 'lmargin=0.5in', 'rmargin=1in', 'bmargin=20mm'])) + + doc.preamble.append(NoEscape(r'\usetikzlibrary{calc}')) + + # doc.preamble.append(NoEscape(r'\pgfplotsset{compat=1.10}')) + doc.preamble.append(NoEscape(r'\pgfplotsset{samples=500}')) + # doc.preamble.append(NoEscape(r'\usepgfplotslibrary{fillbetween}')) + + doc.preamble.append(NoEscape(r'\renewcommand{\arraystretch}{1.5}')) + doc.preamble.append(NoEscape(r'\setlength{\columnseprule}{0.4pt}')) + + doc.preamble.append(NoEscape(r'\makeatletter')) + doc.preamble.append(NoEscape(r'\let\mcnewpage=\newpage')) + doc.preamble.append(NoEscape(r'\newcommand{\TrickSupertabularIntoMulticols}{%')) + doc.preamble.append(NoEscape(r'\renewcommand\newpage{%')) + doc.preamble.append(NoEscape(r'\if@firstcolumn')) + doc.preamble.append(NoEscape(r'\hrule width\linewidth height0pt')) + doc.preamble.append(NoEscape(r'\columnbreak')) + doc.preamble.append(NoEscape(r'\else')) + doc.preamble.append(NoEscape(r'\mcnewpage')) + doc.preamble.append(NoEscape(r'\fi')) + doc.preamble.append(NoEscape(r'}%')) + doc.preamble.append(NoEscape(r'}')) + doc.preamble.append(NoEscape(r'\makeatother')) + doc.preamble.append(NoEscape(r'\relax')) + doc.preamble.append(NoEscape(r'\pagestyle{fancy}')) + doc.preamble.append(NoEscape(r'\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}')) + +def add_summary(datafile_model, append, iter_num, tac, local_time, total_time, epsilons, tolerances, doc, level): + tab_gap = '\t'*level + # doc.append('\\linespread{1.5}') + doc.append(NoEscape(r'%s\begin{spacing}{1.3}' % (tab_gap))) + doc.append(NoEscape(r'%s\Large' % (tab_gap))) + doc.append(NoEscape(r'%sModel (Run-name): %s (%s)\\' % (tab_gap, datafile_model, append))) + # doc.append(NoEscape(r'%sRun name: %s\\' % append)) + doc.append(NoEscape(r'%sIteration: %d\\' % (tab_gap, iter_num))) + + doc.append(NoEscape(r'%s\textbf{TAC: %s}\\' % (tab_gap, str(tac)))) + doc.append(NoEscape(r'%sTook: %ss\\' % (tab_gap, str(local_time)))) + doc.append(NoEscape(r'%sTotal Time: %ss\\' % (tab_gap, str(total_time)))) + doc.append(NoEscape(r'%sEpsilons:' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item $\varepsilon_{\textsl{LMTD}}$: %s' % (tab_gap, str(epsilons[reclmtd_ref])))) + doc.append(NoEscape(r'%s\item $\varepsilon_{\textsl{Balancing}}$: %s' % (tab_gap, str(epsilons[balancing_ref])))) + doc.append(NoEscape(r'%s\item $\varepsilon_{\textsl{Area}}$: %s' % (tab_gap, str(epsilons[area_ref])))) + doc.append(NoEscape(r'%s\item $\varepsilon_{\textsl{Beta}}$: %s' % (tab_gap, str(epsilons[beta_ref])))) + level = level - 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + doc.append(NoEscape(r'%sGurobi Tolerances:' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item IntFeasTol: %s' % (tab_gap, str(tolerances['IntFeasTol'])))) + doc.append(NoEscape(r'%s\item FeasibilityTol: %s' % (tab_gap, str(tolerances['FeasibilityTol'])))) + doc.append(NoEscape(r'%s\item OptimalityTol: %s' % (tab_gap, str(tolerances['OptimalityTol'])))) + level = level - 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{spacing}' % (tab_gap))) + doc.append(NoEscape(r'%s\normalsize' % (tab_gap))) + + if datafile_model in model_map: + doc.append(NoEscape(r'%sGamsworld Solution: \url{%s}' % (tab_gap, model_map[datafile_model]))) + + doc.append(NoEscape(r'')) + doc.append(NoEscape(r'%s%% hello' % (tab_gap))) + +def add_active_results_table(doc, results, level): + tab_gap = '\t'*level + + doc.append(NoEscape(r'%s\begin{multicols*}{3}' % (tab_gap))) + doc.append(NoEscape(r'%s\TrickSupertabularIntoMulticols' % (tab_gap))) + doc.append(NoEscape(r'%s\tablehead{Variable&Value\\\hline}' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{supertabular}{lr}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + for result in results[0]: + result_row = result.table_row() + doc.append(NoEscape(r'%s%s & %s \\' % (tab_gap, result_row[0], result_row[1]))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{supertabular}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{multicols*}' % (tab_gap))) + +def generate_balancing_list(value, abs_error, rel_error, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item Value: %s' % (tab_gap, str(value)))) + doc.append(NoEscape(r'%s\item Absolute error: %s' % (tab_gap, str(abs_error)))) + doc.append(NoEscape(r'%s\item Relative error: %s' % (tab_gap, str(rel_error)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_balancing_results(instance, active_hx, old_points, errors, doc, level): + tab_gap = '\t'*level + for group in [bhin_error, bhout_error, bcin_error, bcout_error]: + if group == bhin_error: + section_header = r'$b^{\textsl{H},\text{in}}$' + var = instance.bh_in + elif group == bhout_error: + section_header = r'$b^{\textsl{H},\text{out}}$' + var = instance.bh_out + elif group == bcin_error: + section_header = r'$b^{\textsl{C},\text{in}}$' + var = instance.bc_in + elif group == bcout_error: + section_header = r'$b^{\textsl{C},\text{out}}$' + var = instance.bc_out + doc.append(NoEscape(r'%s\subsection{%s}' % (tab_gap, section_header))) + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + for active in active_hx[stream_hx]: + val = var[active].value + abs_error = errors[stream_hx][group][active][absolute_error] + rel_error = errors[stream_hx][group][active][relative_error] + + doc.append(NoEscape(r'%s\item $%s$' % (tab_gap, str(active)))) + generate_balancing_list(val, abs_error, rel_error, doc, level) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_num_line_tikz_preamble(x_min, x_max, y_min, y_max, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s[' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%shide axis,' % (tab_gap))) + doc.append(NoEscape(r'%saxis equal image,' % (tab_gap))) + doc.append(NoEscape(r'%sscale only axis,' % (tab_gap))) + doc.append(NoEscape(r'%swidth=\textwidth,' % (tab_gap))) + doc.append(NoEscape(r'%sxmin=%.15f, xmax=%.15f,' % (tab_gap, x_min, x_max))) + doc.append(NoEscape(r'%symin=%.15f, ymax=%.15f,' % (tab_gap, y_min, y_max))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s]' % (tab_gap))) + +def generate_balancing_graphs(instance, active_hx, old_points, doc, level): + tab_gap = '\t'*level + + for group in [th_points, thx_points, tc_points, tcx_points]: + if group == th_points: + index_extractor = lambda i,_,k: (i,k) + temp_str = 'H' + var = instance.th + elif group == thx_points: + index_extractor = lambda i,j,k: (i,j,k) + temp_str = 'H' + var = instance.thx + elif group == tc_points: + index_extractor = lambda _,j,k: (j,k+1) + temp_str = 'C' + var = instance.tc + elif group == tcx_points: + index_extractor = lambda i,j,k: (i,j,k) + temp_str = 'C' + var = instance.tcx + for active in active_hx[stream_hx]: + break_index = index_extractor(*active) + caption = r'$\textit{t}^{\textsl{(%s)}}$ - $%s$' % (temp_str, str(break_index)) + + breakpoints = old_points[stream_hx][group][break_index] + + x_min, x_max = var[break_index].bounds + val = var[break_index].value + diff = x_max - x_min + delta = diff/30 + y_min = -(1.5*delta) + y_max = (-1)*y_min + + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\resizebox{\linewidth}{!}{' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{axis}' % (tab_gap))) + add_num_line_tikz_preamble(x_min, x_max, y_min, y_max, doc, level) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw (axis cs: %.15f,0) -- (axis cs: %.15f,0);' % (tab_gap, x_min,x_max))) + for x in breakpoints: + lval = (tab_gap, x,delta,x, delta) + doc.append(NoEscape(r'%s\draw (axis cs: %.15f,-%.15f) -- (axis cs: %.15f,%.15f);' % lval)) + + doc.append(NoEscape(r'%s\draw[color=red] (axis cs: %.15f,-%.15f) -- (axis cs: %.15f,%.15f);' % (tab_gap, val,1.5*delta,val,1.5*delta))) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{axis}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{%s}' % (tab_gap, caption))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%'))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + +def generate_reclmtd_list(reclmtd_value, abs_error, rel_error, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item Value: %f' % (tab_gap, reclmtd_value))) + doc.append(NoEscape(r'%s\item Error: %.15f' % (tab_gap, abs_error))) + doc.append(NoEscape(r'%s\item Relative error: %.15f' % (tab_gap, rel_error))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_reclmtd_results(instance, active_hx, errors, doc, level): + doc.append(NoEscape(r'%'*45)) + doc.append(NoEscape(r'%s $\textsl{RecLMTD}^\beta$ Results %s' % ('%'*13, '%'*13))) + doc.append(NoEscape(r'%'*45)) + + doc.append(NoEscape(r'\begin{itemize}')) + level += 1 + tab_gap = '\t'*level + for active in active_hx[stream_hx]: + reclmtd_value = value(instance.reclmtd[active]) + abs_error = errors[stream_hx][reclmtd_error][active][absolute_error] + rel_error = errors[stream_hx][reclmtd_error][active][relative_error] + + doc.append(NoEscape(r'%s\item $%s$' % (tab_gap, str(active)))) + generate_reclmtd_list(reclmtd_value, abs_error, rel_error, doc, level) + + for active in active_hx[cu_hx]: + reclmtd_value = value(instance.reclmtd_cu[active]) + abs_error = errors[cu_hx][reclmtd_error][active][absolute_error] + rel_error = errors[cu_hx][reclmtd_error][active][relative_error] + + doc.append(NoEscape(r'%s\item $\textit{cu},%s$' % (tab_gap, str(active)))) + generate_reclmtd_list(reclmtd_value, abs_error, rel_error, doc, level) + + for active in active_hx[hu_hx]: + reclmtd_value = value(instance.reclmtd_hu[active]) + abs_error = errors[hu_hx][reclmtd_error][active][absolute_error] + rel_error = errors[hu_hx][reclmtd_error][active][relative_error] + + doc.append(NoEscape(r'%s\item $\textit{hu},%s$' % (tab_gap, str(active)))) + generate_reclmtd_list(reclmtd_value, abs_error, rel_error, doc, level) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_reclmtd_tikz_preamble(minn, maxx, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s[' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%saxis lines=middle,' % (tab_gap))) + doc.append(NoEscape(r'%sxmin=%.15f, xmax=%.15f,' % (tab_gap, minn, maxx))) + doc.append(NoEscape(r'%symin=%.15f, ymax=%.15f,' % (tab_gap, minn, maxx))) + doc.append(NoEscape(r'%sxtick=\empty, ytick=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%sxticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%syticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%sxlabel=\empty,ylabel=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%severy axis x label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%sat={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'%sanchor=west,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s},' % (tab_gap))) + doc.append(NoEscape(r'%severy axis y label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%sat={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'%sanchor=south,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s}' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s]' % (tab_gap))) + +def generate_reclmtd_graphs(instance, active_hx, old_points, doc, level): + tab_gap = '\t'*level + iteration = 0 + for active in active_hx[stream_hx]: + breakpoints = old_points[stream_hx][tangent_points][active] + minn, maxx = instance.dt[active].bounds + xv = value(instance.dt[active]) + yv = value(instance.dt[active[0], active[1], active[2]+1]) + + if iteration % 2 == 0: + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + if not iteration == 0: + doc.append(NoEscape(r'%s\ContinuedFloat' % (tab_gap))) + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{subfigure}{0.5\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}[baseline]' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{axis}' % (tab_gap))) + add_reclmtd_tikz_preamble(minn, maxx, doc, level) + + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw[dashed] (axis cs: %.15f,%.15f) -- ( axis cs: %.15f,%.15f);' % (tab_gap, minn, minn, maxx, maxx))) + doc.append('') + doc.append(NoEscape(r'%s\addplot[only marks] table {' % (tab_gap))) + for (x,y) in breakpoints: + doc.append(NoEscape(r'%s%s%.15f %.15f' % (tab_gap, '\t', x,y))) + doc.append(NoEscape(r'%s};' % (tab_gap))) + doc.append('') + doc.append(NoEscape(r'%s\addplot[only marks, mark=+, color=red, thick] table {' % (tab_gap))) + doc.append(NoEscape(r'%s%s%.15f %.15f' % (tab_gap, '\t', xv, yv))) + doc.append(NoEscape(r'%s};' % (tab_gap))) + doc.append('') + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{axis}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{$\textsl{RecLMTD}$ - $%s$}' % (tab_gap, str(active)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%%'))) + if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + iteration += 1 + + if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + + iteration = 0 + for active in active_hx[cu_hx]: + breakpoints = old_points[cu_hx][tangent_points][active] + minn, maxx = instance.dt_cu[active].bounds + val = value(instance.dt_cu[active]) + diff = maxx - minn + delta = diff/30 + + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + if not iteration == 0: + doc.append(NoEscape(r'%s\ContinuedFloat' % (tab_gap))) + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\resizebox{0.95\textwidth}{!}{' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}[baseline]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw (%.15f,0) -- (%.15f,0);' % (tab_gap,minn,maxx))) + for x in breakpoints: + lval = (tab_gap,x,delta,x, delta) + doc.append(NoEscape(r'%s\draw (%.15f,-%.15f) -- (%.15f,%.15f);' % (lval))) + + doc.append(NoEscape(r'%s\draw[color=red] (%.15f,-%.15f) -- (%.15f,%.15f);' % (tab_gap,val,1.5*delta,val,1.5*delta))) + + level -= 1 + tab_gap = '\t'*level + + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{$\textsl{RecLMTD}$ - $\textsl{cu},%s$}' % (tab_gap,str(active)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%%'))) + # if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + iteration += 1 + + iteration = 0 + for active in active_hx[hu_hx]: + breakpoints = old_points[hu_hx][tangent_points][active] + minn, maxx = instance.dt_hu[active].bounds + val = value(instance.dt_hu[active]) + diff = maxx - minn + delta = diff/30 + + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + if not iteration == 0: + doc.append(NoEscape(r'%s\ContinuedFloat' % (tab_gap))) + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\resizebox{0.95\linewidth}{!}{' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}[baseline]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw (%.15f,0) -- (%.15f,0);' % (tab_gap,minn,maxx))) + for x in breakpoints: + lval = (tab_gap,x,delta,x, delta) + doc.append(NoEscape(r'%s\draw (%.15f,-%.15f) -- (%.15f,%.15f);' % (lval))) + + doc.append(NoEscape(r'%s\draw[color=red] (%.15f,-%.15f) -- (%.15f,%.15f);' % (tab_gap,val,1.5*delta,val,1.5*delta))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s}'% (tab_gap))) + doc.append(NoEscape(r'%s\caption{$\textsl{RecLMTD}$ - $\textsl{hu},%s$}' % (tab_gap,str(active)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%%'))) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + iteration += 1 + +def generate_area_list(area_value, abs_error, rel_error, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level +=1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item Value: %f' % (tab_gap, area_value))) + doc.append(NoEscape(r'%s\item Error: %.15f' % (tab_gap, abs_error))) + doc.append(NoEscape(r'%s\item Relative error: %.15f' % (tab_gap, rel_error))) + level -=1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_area_results(instance, active_hx, old_points, errors, doc, level): + tab_gap = '\t'*level + beta = instance.Beta + + for group in [stream_hx, cu_hx, hu_hx]: + if group == stream_hx: + section_header = r'$A$' + index_template = r'%s' + var = instance.area + elif group == cu_hx: + section_header = r'$A_{CU}$' + index_template = r'\textit{cu},%s' + var = instance.area_cu + elif group == hu_hx: + section_header = r'$A_{HU}$' + index_template = r'\textit{hu},%s' + var = instance.area_hu + if len(active_hx[group]) != 0: + doc.append(NoEscape(r'%s\subsection{%s}' % (tab_gap, section_header))) + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + for active in active_hx[group]: + index_str = index_template % (str(active)) + area_value = var[active].value + abs_error = errors[group][area_error][active][absolute_error] + rel_error = errors[group][area_error][active][relative_error] + + doc.append(NoEscape(r'%s\item $%s$' % (tab_gap, index_str))) + generate_area_list(area_value, abs_error, rel_error, doc, level) + level = level - 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_area_graphs(instance, active_hx, old_points, doc, level): + tab_gap = '\t'*level + beta = instance.Beta + iteration = 0 + for group in [stream_hx, cu_hx, hu_hx]: + if group == stream_hx: + index_template = '%s' + var = instance.q + elif group == cu_hx: + index_template = 'cu,%s' + var = instance.q_cu + elif group == hu_hx: + index_template = 'hu,%s' + var = instance.q_hu + for active in active_hx[group]: + index_str = index_template % (str(active)) + + breakpoints = old_points[group][q_points][active] + x_min = 0 + x_max = breakpoints[len(breakpoints)-1] + diff = x_max - x_min + delta = diff/30 + y_min = -(1.5*delta) + y_max = (-1)*y_min + val = var[active].value + + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\resizebox{\linewidth}{!}{' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{axis}' % (tab_gap))) + add_num_line_tikz_preamble(x_min, x_max, y_min, y_max, doc, level) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw (axis cs: %.15f,0) -- (axis cs: %.15f,0);' % (tab_gap, x_min,x_max))) + for x in breakpoints: + lval = (tab_gap, x,delta,x,delta) + doc.append(NoEscape(r'%s\draw (axis cs: %.15f,-%.15f) -- (axis cs: %.15f,%.15f);' % lval)) + + doc.append(NoEscape(r'%s\draw[color=red] (axis cs: %.15f,-%.15f) -- (axis cs: %.15f,%.15f);' % (tab_gap, val,1.5*delta,val,1.5*delta))) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{axis}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{$\textit{A}^{\beta}$ - $%s$}' % (tab_gap, index_str))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%'))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + +def generate_area_beta_list(area_value, area_beta, beta, breakpoints, abs_error, rel_error, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level +=1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item $q$: %f' % (tab_gap, area_value))) + doc.append(NoEscape(r'%s\item $\hat{q}^\beta$: %f' % (tab_gap, area_beta) )) + doc.append(NoEscape(r'%s\item $q^\beta$: %f' % (tab_gap, pow(area_value, beta)))) + doc.append(NoEscape(r'%s\item Breakpoints: %s' % (tab_gap, breakpoints))) + doc.append(NoEscape(r'%s\item Error: %.15f' % (tab_gap, abs_error))) + doc.append(NoEscape(r'%s\item Relative error: %.15f' % (tab_gap, rel_error))) + level -=1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_area_beta_results(instance, active_hx, old_points, errors, doc, level): + beta = instance.Beta + + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + + for group in [stream_hx, cu_hx, hu_hx]: + if group == stream_hx: + index_template = r'$%s$' + area_var = instance.area + area_beta_var = instance.area_beta + elif group == cu_hx: + index_template = r'$\textit{cu},%s$' + area_var = instance.area_cu + area_beta_var = instance.area_cu_beta + elif group == hu_hx: + index_template = r'$\textit{hu},%s$' + area_var = instance.area_hu + area_beta_var = instance.area_hu_beta + + for active in active_hx[group]: + index_str = index_template % (str(active)) + area_value = area_var[active].value + area_beta = area_beta_var[active].value + breakpoints = get_breakpoint_list(old_points[group][area_beta_points][active], area_value) + abs_error = errors[group][area_beta_error][active][absolute_error] + rel_error = errors[group][area_beta_error][active][relative_error] + + doc.append(NoEscape(r'%s\item %s' % (tab_gap, index_str))) + generate_area_beta_list(area_value, area_beta, beta, breakpoints, abs_error, rel_error, doc, level) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_area_beta_tikz_preamble(x_min, x_max, y_min, y_max, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s[' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%saxis lines=middle,' % (tab_gap))) + doc.append(NoEscape(r'%sxmin=%.15f, xmax=%.15f,' % (tab_gap, x_min, x_max))) + doc.append(NoEscape(r'%symin=%.15f, ymax=%.15f,' % (tab_gap, y_min, y_max))) + doc.append(NoEscape(r'%sxtick=\empty, ytick=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%sxticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%syticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%sxlabel=\empty,ylabel=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%severy axis x label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%sat={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'%sanchor=west,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s},' % (tab_gap))) + doc.append(NoEscape(r'%severy axis y label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%sat={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'%sanchor=south,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s}' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s]' % (tab_gap))) + +def add_area_beta_tikz_main(beta, breakpoints, x_min, x_max, y_min, y_max, y_breakpoints, q, index_str, doc, level, iteration): + tab_gap = '\t'*level + if iteration % 2 == 0: + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + if not iteration == 0: + doc.append(NoEscape(r'%s\ContinuedFloat' % (tab_gap))) + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{0.5\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}[baseline]' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{axis}' % (tab_gap))) + + add_area_beta_tikz_preamble(x_min, x_max, y_min, y_max, doc, level) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\addplot[domain=%f:%f, color=blue]{x^%f};' % (tab_gap, x_min, x_max, beta))) + for index in range(0, len(breakpoints)-1): + doc.append(NoEscape(r'%s\draw[dotted, thick] (axis cs: %f, %f) -- (axis cs: %f, %f);' % (tab_gap, breakpoints[index], y_breakpoints[index], breakpoints[index+1], y_breakpoints[index+1]))) + + doc.append(NoEscape(r'%s\draw[dashed, color=red] (axis cs: %f, %f) -- (axis cs: %f, %f);' % (tab_gap, q, 0, q, pow(q, beta)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{axis}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{$q^\beta$ - %s}' % (tab_gap, index_str))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%'))) + if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + return level + +def add_area_beta_graphs(instance, active_hx, old_points, doc, level): + tab_gap = '\t'*level + beta = instance.Beta.value + + for group in [stream_hx, cu_hx, hu_hx]: + iteration = 0 + if group == stream_hx: + index_template = r'$%s$' + var = instance.area + elif group == cu_hx: + index_template = r'$\textit{cu},%s$' + var = instance.area_cu + elif group == hu_hx: + index_template = r'$\textit{hu},%s$' + var = instance.area_hu + for active in active_hx[group]: + breakpoints = old_points[group][area_beta_points][active] + x_min = 0 + x_max = breakpoints[len(breakpoints)-1] + y_min = 0 + y_max = pow(x_max, beta) + y_breakpoints = [pow(area, beta) for area in breakpoints] + # y_breakpoints = map(lambda area: pow(area, beta), breakpoints) + area = var[active].value + index_str = index_template % (str(active)) + level = add_area_beta_tikz_main(beta, breakpoints, x_min, x_max, y_min, y_max, y_breakpoints, area, index_str, doc, level, iteration) + iteration += 1 + if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + +def get_breakpoint_list(breakpoints, value): + same_value = False + index = 0 + for i in range(0,len(breakpoints)): + if breakpoints[i] == value: + same_value = True + index = i + break + elif breakpoints[i] > value: + index = i-1 + break + + # string_breakpoints = map(lambda x: r'$%s$' % str(x), breakpoints) + string_breakpoints = [r'$%s$' % str(x) for x in breakpoints] + + if same_value: + string_breakpoints[index] = r'\textcolor{green}{$%s$}' % (str(breakpoints[index])) + else: + string_breakpoints[index] = r'\textcolor{red}{$%s$}' % (str(breakpoints[index])) + string_breakpoints[index+1] = r'\textcolor{red}{$%s$}' % (str(breakpoints[index+1])) + + return r'$[$%s$]$' % (', '.join(string_breakpoints)) + +def add_inactive_results_table(results, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{multicols*}{3}' % (tab_gap))) + doc.append(NoEscape(r'%s\TrickSupertabularIntoMulticols' % (tab_gap))) + doc.append(NoEscape(r'%s\tablehead{Variable&Value\\\hline}' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{supertabular}{lr}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + for result in results[1]: + result_row = result.table_row() + doc.append(NoEscape(r'%s%s & %s \\' % (tab_gap, result_row[0], result_row[1]))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{supertabular}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{multicols*}' % (tab_gap))) diff --git a/hens/adaptive_model_mixer/lib/results_generator/heat_var.py b/hens/adaptive_model_mixer/lib/results_generator/heat_var.py new file mode 100644 index 0000000..339309f --- /dev/null +++ b/hens/adaptive_model_mixer/lib/results_generator/heat_var.py @@ -0,0 +1,289 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.environ import * + +from ..constants import * + +from pprint import pprint + +def index_identify(index): + return '{{' + index + '}}' + +var_order = [ z, z_cu, z_hu, area_beta, area_cu_beta, area_hu_beta, area, area_cu, area_hu, dt, dt_cu, dt_hu, fh, fc, reclmtd, reclmtd_cu, reclmtd_hu, q, q_cu, q_hu, th, tc, thx, tcx, bh_in, bh_out, bc_in, bc_out] + +ignored_vars = [z_q, z_q_cu, z_q_hu, var_delta_reclmtd, var_delta_reclmtd_cu, var_delta_reclmtd_hu, z_th, z_thx, z_tc, z_tcx, var_delta_fh, var_delta_fhx, var_delta_fc, var_delta_fcx, z_area_beta, z_area_cu_beta, z_area_hu_beta] + +ijk_subscript = '%s,%s,%s' % (index_identify(index_i), index_identify(index_j), index_identify(index_k)) +ijk_indices = [ index_i, index_j, index_k ] + +cui_subscript = 'cu,%s' % index_identify(index_i) +cui_indices = [ index_i ] + +huj_subscript = 'hu,%s' % index_identify(index_j) +huj_indices = [ index_j ] + +ikSubscript = '%s,%s' % (index_identify(index_i), index_identify(index_k)) +ikIndices = [ index_i, index_k ] + +jkSubscript = '%s,%s' % (index_identify(index_j), index_identify(index_k)) +jkIndices = [ index_j, index_k ] + +var_to_subscript_map = {\ + area:{\ + latex_label: 'A',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices : ijk_indices\ + },\ + area_cu:{\ + latex_label: 'A',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + area_hu:{\ + latex_label: 'A',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + area_beta:{\ + latex_label: 'A',\ + latex_superscript: r'\beta',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices : ijk_indices\ + },\ + area_cu_beta:{\ + latex_label: 'A',\ + latex_superscript: r'\beta',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + area_hu_beta:{\ + latex_label: 'A',\ + latex_superscript: r'\beta',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + bc_in:{\ + latex_label: 'b',\ + latex_superscript: 'C,\\text{in}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + bc_out:{\ + latex_label: 'b',\ + latex_superscript: 'C,\\text{out}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + bh_in:{\ + latex_label: 'b',\ + latex_superscript: 'H,\\text{in}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + bh_out:{\ + latex_label: 'b',\ + latex_superscript: 'H,\\text{out}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + dt:{\ + latex_label: 'dt',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + dt_cu:{\ + latex_label: 'dt',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + dt_hu:{\ + latex_label: 'dt',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + fc:{\ + latex_label: 'f',\ + latex_superscript: 'C',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + fh:{\ + latex_label: 'f',\ + latex_superscript: 'H',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + reclmtd:{\ + latex_label: '\\textsl{RecLMTD}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + reclmtd_cu:{\ + latex_label: '\\textsl{RecLMTD}',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + reclmtd_hu:{\ + latex_label: '\\textsl{RecLMTD}',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + q:{\ + latex_label: 'q',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + q_cu:{\ + latex_label: 'q',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + q_hu:{\ + latex_label: 'q',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + tc:{\ + latex_label: 't',\ + latex_superscript: '(C)',\ + latex_subscript: jkSubscript,\ + subscript_indices: jkIndices,\ + all_indices: jkIndices\ + },\ + th:{\ + latex_label: 't',\ + latex_superscript: '(H)',\ + latex_subscript: ikSubscript,\ + subscript_indices: ikIndices,\ + all_indices: ikIndices\ + },\ + tcx:{\ + latex_label: 't',\ + latex_superscript: 'C',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + thx:{\ + latex_label: 't',\ + latex_superscript: 'H',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + z:{\ + latex_label: 'z',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + z_cu:{\ + latex_label: 'z',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + z_hu:{\ + latex_label: 'z',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + } +} + +def order_key(var): + if var.pyomo_label not in var_to_subscript_map: + return (float('inf'),) + return (var_order.index(var.pyomo_label), ) + tuple(var.var_details.get(all_indices)) + + +class HeatVar: + def __init__(self, pyomo_label, index, value): + self.value = value + self.subscripts = [] + self.pyomo_label = pyomo_label + self.index = index if not type(index) == int else (index,) + self.init_latex_data() + + def init_latex_data(self): + if self.pyomo_label in var_to_subscript_map: + self.var_details = var_to_subscript_map.get(self.pyomo_label) + self.index_map = dict(zip(self.var_details.get(all_indices), self.index)) + else: + self.var_details = {} + self.var_details[latex_label] = '(*)' + self.pyomo_label + '-'+ str(self.index) + + def __getitem__(self, item): + return getattr(self, item) + + def to_latex(self): + latex_string = self.var_details[latex_label] + latex_string += self.buildLatexSubscript() + latex_string += self.buildLatexSuperscript() + return latex_string + + def buildLatexSubscript(self): + subscript = self.substitute_indices_into_template(latex_subscript, subscript_indices) + return '_{' + subscript + '}' if not subscript == '' else '' + + def buildLatexSuperscript(self): + superscript = self.substitute_indices_into_template(latex_superscript, superscript_indices) + return '^{' + superscript + '}' if not superscript == '' else '' + + def substitute_indices_into_template(self, template_key, indices_key): + template = self.var_details.get( template_key, '') + indices = self.var_details.get( indices_key, [] ) + for index in indices: + template = template.replace(index_identify(index), str(self.index_map.get(index))) + return template + + def table_row(self): + return ('$' + self.to_latex() + '$', self.value) + +def keep_variable(variable, active_hx): + if variable.pyomo_label in [z, area, q, reclmtd, area_beta, fh, fc, bh_in, bh_out, bc_in, bc_out, thx, tcx]: + return variable.index in active_hx[stream_hx] + elif variable.pyomo_label in [z_cu, area_cu, q_cu, reclmtd_cu, area_cu_beta, dt_cu]: + return variable.index[0] in active_hx[cu_hx] + elif variable.pyomo_label in [z_hu, area_hu, q_hu, reclmtd_hu, area_hu_beta, dt_hu]: + return variable.index[0] in active_hx[hu_hx] + elif variable.pyomo_label in [dt]: + index = variable.index + index2 = (index[0], index[1], index[2]-1) + return index in active_hx[stream_hx] or index2 in active_hx[stream_hx] + return True + +def parse_pyomo_results(instance, active_hx): + results = [] + for var in instance.component_objects(Var): + var_str = var.name + if var_str not in ignored_vars: + for k, v in var.iteritems(): + results.append(HeatVar(var_str, k, v.value)) + + active_variables = sorted([v for v in results if keep_variable(v, active_hx)], key=order_key) + inactive_variables = sorted([v for v in results if not keep_variable(v, active_hx)], key=order_key) + + return (active_variables, inactive_variables) diff --git a/hens/adaptive_model_mixer/lib/results_generator/results_builder.py b/hens/adaptive_model_mixer/lib/results_generator/results_builder.py new file mode 100644 index 0000000..29bbaf4 --- /dev/null +++ b/hens/adaptive_model_mixer/lib/results_generator/results_builder.py @@ -0,0 +1,78 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import json, sys, unicodedata, os, yaml + +from pyomo.environ import * + +from . import heat_var + +from .document_builder import * + +from pprint import pprint + +from ..constants import * + +try: + from pylatex import * + + def build_heat_exchanger_results_doc(results, folders, append, iter_num, datafile_model, filename, instance, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances, iteration): + level = 0 + + beta = instance.Beta + tac = value(instance.TAC) + + check_folder_structure(folders, iteration) + + doc = Document() + add_preamble(doc) + + doc.append(NoEscape(r'\section{Summary}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_summary(datafile_model, append, iter_num, tac, local_time, total_time, epsilons, tolerances, doc, level) + + doc.append(NoEscape(r'\clearpage')) + + doc.append(NoEscape(r'\section{Results}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_active_results_table(doc, results, level) + doc.append(NoEscape(r'\clearpage')) + + doc.append(NoEscape(r'\section{$\textsl{RecLMTD}$ Tangent Points}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_reclmtd_results(instance, active_hx, errors, doc, level) + generate_reclmtd_graphs(instance, active_hx, old_points, doc, level) + + doc.append(NoEscape(r'\clearpage')) + + doc.append(NoEscape(r'\section{Balancing Breakpoints}')) + add_balancing_results(instance, active_hx, old_points, errors, doc, level) + generate_balancing_graphs(instance, active_hx, old_points, doc, level) + + doc.append(NoEscape(r'\clearpage')) + doc.append(NoEscape(r'\section{Area Breakpoints}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_area_results(instance, active_hx, old_points, errors, doc, level) + add_area_graphs(instance, active_hx, old_points, doc, level) + + doc.append(NoEscape(r'\clearpage')) + doc.append(NoEscape(r'\section{$A^\beta$ Breakpoints}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_area_beta_results(instance, active_hx, old_points, errors, doc, level) + add_area_beta_graphs(instance, active_hx, old_points, doc, level) + + doc.append(NoEscape(r'\clearpage')) + doc.append(NoEscape(r'\section{Other variables}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_inactive_results_table(results, doc, level) + + save_pdf(doc, filename, folders, iteration) +except ImportError: + def build_heat_exchanger_results_doc(results, folders, append, iter_num, datafile_model, filename, instance, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances, iteration): + check_folder_structure(folders, iteration) + with open(os.path.join(folders[iterations_folder], filename + '.txt'), 'w') as f: + f.write('You don\'t have pylatex. Install it with pip for results summary.\n') + +def build_heat_exchanger_results(instance, folders, append, iter_num, datafile_model, filename, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances, iteration=False): + results = heat_var.parse_pyomo_results(instance, active_hx) + build_heat_exchanger_results_doc(results, folders, append, iter_num, datafile_model, filename, instance, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances, iteration) diff --git a/hens/beta_adaptive_model_mixer/__init__.py b/hens/beta_adaptive_model_mixer/__init__.py new file mode 100644 index 0000000..f757ec9 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/__init__.py @@ -0,0 +1,2 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London diff --git a/hens/beta_adaptive_model_mixer/iterative.py b/hens/beta_adaptive_model_mixer/iterative.py new file mode 100644 index 0000000..af119f9 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/iterative.py @@ -0,0 +1,269 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import pyomo.environ +import pickle +import sys, os, copy, time, socket + +from multiprocessing import Process, cpu_count + +from pyomo.opt import SolverFactory +from pprint import pprint + +from lib.iterations_helper import * +from lib.results_generator.results_builder import build_heat_exchanger_results +from lib.constants import * + +def can_terminate_absolute(epsilons, max_errors): + if epsilons[balancing_ref] <= max_errors[balancing_ref][absolute_error]: + return False + if epsilons[q_beta_ref] <= max_errors[q_beta_ref][absolute_error]: + return False + if epsilons[lmtd_beta_ref] <= max_errors[lmtd_beta_ref][absolute_error]: + return False + if epsilons[area_beta_ref] <= max_errors[area_beta_ref][absolute_error]: + return False + return True + +def can_terminate_relative(epsilons, max_errors): + if epsilons[balancing_ref] <= max_errors[balancing_ref][relative_error]: + print('balancing: %s, %s' % (str(max_errors[balancing_ref][relative_error]),str(epsilons[balancing_ref]))) + return False + if epsilons[q_beta_ref] <= max_errors[q_beta_ref][relative_error]: + print('beta: %s, %s' % (str(max_errors[q_beta_ref][relative_error]),str(epsilons[q_beta_ref]))) + return False + if epsilons[lmtd_beta_ref] <= max_errors[lmtd_beta_ref][relative_error]: + print('lmtd: %s, %s' % (str(max_errors[lmtd_beta_ref][relative_error]),str(epsilons[lmtd_beta_ref]))) + return False + if epsilons[area_beta_ref] <= max_errors[area_beta_ref][relative_error]: + print('area: %s, %s' % (str(max_errors[area_beta_ref][relative_error]),str(epsilons[area_beta_ref]))) + return False + return True + +termination_func = can_terminate_relative + +model_name = 'Adaptive Beta Model' + +start = time.time() + +max_iters = 500 + +number_of_cores = cpu_count() + +argparser = initialise_parser() +args = argparser.parse_args() + +validate_and_assign_args(args) + +folders = create_output_dir('.', args.model, args.run_name) + +output_file = open(os.path.join(folders[append_folder], 'output.txt'), 'w') +results_file = open(os.path.join(folders[append_folder], 'results.csv'), 'w') + +results_file.write('iteration, tac, time, totalTime\n') + +datafile = '../datafiles/' + args.model + '.dat' + +solver = 'gurobi' +opt = SolverFactory(solver) +if args.num_threads: + opt.options[ 'threads' ] = min(number_of_cores, args.num_threads) + +opt.options[ 'MIPFocus' ] = 1 + +tolerances = { + 'IntFeasTol': -1, + 'FeasibilityTol': -1, + 'OptimalityTol': -1 +} + +if args.tighten_tol: + opt.options[ 'IntFeasTol' ] = 0.000000001 + opt.options[ 'FeasibilityTol' ] = 0.000000001 + opt.options[ 'OptimalityTol' ] = 0.000000001 + tolerances['IntFeasTol'] = 0.000000001 + tolerances['FeasibilityTol'] = 0.000000001 + tolerances['OptimalityTol'] = 0.000000001 +else: + if args.IntFeasTol: + opt.options[ 'IntFeasTol' ] = args.IntFeasTol + tolerances['IntFeasTol'] = args.IntFeasTol + if args.FeasibilityTol: + opt.options[ 'FeasibilityTol' ] = args.FeasibilityTol + tolerances['FeasibilityTol'] = args.FeasibilityTol + if args.OptimalityTol: + opt.options[ 'OptimalityTol' ] = args.OptimalityTol + tolerances['OptimalityTol'] = args.OptimalityTol + if args.MarkowitzTol: + opt.options[ 'MarkowitzTol' ] = args.MarkowitzTol + opt.options[ 'MarkowitzTol' ] = args.MarkowitzTol + +model = initialise_hx_model(datafile) + +warmstart = False +default_eps = 0.0001 + +epsilons = { + balancing_ref: default_eps, + q_beta_ref: default_eps, + lmtd_beta_ref: default_eps, + area_beta_ref: default_eps, +} + +if args.all_error: + eps = args.all_error + epsilons[balancing_ref] = eps + epsilons[q_beta_ref] = eps + epsilons[lmtd_beta_ref] = eps + epsilons[area_beta_ref] = eps +else: + if args.bal_eps: + epsilons[balancing_ref] = args.bal_eps + if args.q_beta_eps: + epsilons[q_beta_ref] = args.q_beta_eps + if args.lmtd_beta_eps: + epsilons[lmtd_beta_ref] = args.lmtd_beta_eps + if args.area_beta_eps: + epsilons[area_beta_ref] = args.area_beta_eps + +if args.absolute: + termination_func = can_terminate_absolute + +iterations = 1 + +new_points = copy.deepcopy(get_all_points()) + +output_file.write('Running:\n') +output_file.write('\t%s\n' % model_name) +output_file.write('\t' + args.model + '\n') +output_file.write('on: '+ socket.gethostname() + '\n\n') + +iter_finish = time.time() + +for run in range(1, max_iters): + iter_start = iter_finish + + print('Running iteration ', run) + + instance = model.create_instance(datafile) + output_file.write('----------------------------------\n') + output_file.write('---- Run: ' + str(run) + '\n') + output_file.write('----------------------------------\n') + + # if not args.z_run: + # instance.z_heat_x_test.deactivate() + + opt.options[ 'LogFile' ] = os.path.join(folders[ logs_folder ], 'gur' + str(run).zfill(len(str(max_iters))) + '.log') + + results = opt.solve(instance, tee=False) + + instance.solutions.load_from(results) + + # with open('%s%sinstance%s.p' % (folders[instances_folder], os.sep, str(run).zfill(len(str(max_iters)))), 'wb') as instanceFile: + # pickle.dump(instance, instanceFile, -1) + + old_points = new_points + + active_hx, inactive_hx = get_active_hx(instance) + + # maxE, relE = checkLMTDEpsilon(instance, active_hx) + new_tangent_points = get_new_tangent_points(instance, active_hx) + added_tangents = add_new_tangent_points(new_tangent_points) + + new_q_beta_breakpoints = get_new_q_beta_breakpoints(instance, active_hx) + new_area_q_beta_breakpoints = get_new_area_q_beta_breakpoints(instance, active_hx) + + # newQBreakpoints = getNewQBreakpoints(instance, active_hx) + # newBetaBreakpoints = getNewBetaBreakpoints(instance, active_hx) + new_balancing_breakpoints = get_new_balancing_breakpoints(instance, active_hx, inactive_hx, args.weaken) + + new_points = copy.deepcopy(get_all_points()) + + output_file.write('----------------------------------\n') + output_file.write('---- TAC: ' + str(value(instance.TAC)) + '\n') + output_file.write('----------------------------------\n') + output_file.write('\n') + output_file.write('Found ActiveHx:\n') + pprint(active_hx, output_file) + output_file.write('\n') + output_file.write('Adding Tangents at:\n') + pprint(added_tangents, output_file) + output_file.write('\n') + output_file.write('Adding Balancing breakpoints at:\n') + pprint(new_balancing_breakpoints, output_file) + output_file.write('\n') + output_file.write('Adding q beta breakpoints at:\n') + pprint(new_q_beta_breakpoints, output_file) + output_file.write('\n') + output_file.write('Adding AREA q-beta breakpoints at:\n') + pprint(new_area_q_beta_breakpoints, output_file) + output_file.write('\n') + + output_file.flush() + + iter_finish = time.time() + + local_time = iter_finish-iter_start + total_time = iter_finish-start + + print('\tTAC: %f' % value(instance.TAC)) + print('\tTook: %.2fs' % local_time) + print('\tTotal: %.2fs' % total_time) + + results_file.write('%d, %s, %s, %s\n' % (run, str(value(instance.TAC)), str(local_time), str(total_time))) + + results_file.flush() + + errors = summarise_errors(instance, active_hx, inactive_hx, args.weaken) + max_errors = get_max_errors(errors, active_hx, inactive_hx, args.weaken) + + filename = 'iteration' + str(run).zfill(len(str(max_iters))) + t = Process(target=build_heat_exchanger_results, args=(instance, folders, args.run_name, run, args.model, filename, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances), kwargs={'iteration': True}) + t.start() + + if termination_func(epsilons, max_errors): + print('/*/*/*/*//*/*/*/*//*/*/*/*//*/*/*/') + print('----------------------------------') + print('---- Completed Within Error') + print('----------------------------------') + print('/*/*/*/*//*/*/*/*//*/*/*/*//*/*/*/') + break + + if len(added_tangents) == 0 \ + and len(new_q_beta_breakpoints) == 0\ + and len(new_area_q_beta_breakpoints) == 0\ + and len(new_balancing_breakpoints) == 0: + print('/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/') + print('---------------------------------------------------') + print('---- Completed No new tangents or breakpoints -----') + print('---------------------------------------------------') + print('/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/') + break + + if args.cont: + if iterations == 1: + var = raw_input('Ran %d iterations. How many more?\n' % run) + while True: + try: + iters = int(var) + except ValueError: + var = raw_input('\'%s\' is not an integer. How many more?\n' % var) + else: + break + + if iters <= 0: + print('/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/') + print('-----------------------------------') + print('---- Completed Not Continuing -----') + print('-----------------------------------') + print('/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/') + break + else: + iterations = iters + 1 + iterations = iterations - 1 + +if args.print_instance: + instance.pprint() + +output_file.close() +results_file.close() diff --git a/hens/beta_adaptive_model_mixer/lib/__init__.py b/hens/beta_adaptive_model_mixer/lib/__init__.py new file mode 100644 index 0000000..f757ec9 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/__init__.py @@ -0,0 +1,2 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London diff --git a/hens/beta_adaptive_model_mixer/lib/constants.py b/hens/beta_adaptive_model_mixer/lib/constants.py new file mode 100644 index 0000000..f364b6a --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/constants.py @@ -0,0 +1,219 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +stream_hx = 'stream_hx' +cu_hx = 'cu_hx' +hu_hx = 'hu_hx' + +bal_eps = 'bal_eps' +lmtd_beta_eps = 'lmtd_beta_eps' +area_beta_eps = 'area_beta_eps' +q_beta_eps = 'q_beta_eps' + +balancing_ref = 'balancing_ref' +lmtd_beta_ref = 'lmtd_beta_ref' +area_beta_ref = 'area_beta_ref' +q_beta_ref = 'q_beta_ref' + +breakpoints = 'breakpoints' + +lbl_model = 'model' + +model1 = lbl_model + '1' +model2 = lbl_model + '2' +model3 = lbl_model + '3' + +active_lb = 0.9 + +default_stream_tangent_weights = \ + [\ + (1,0,0),\ + (0,1,0),\ + (0,0,1),\ + (0.5,0.5,0),\ + # (0.75,0.25,0),\ + # (0.25,0.75, 0),\ + # (1/3, 1/3, 1/3),\ + # (1/2, 1/4, 1/4),\ + # (1/4, 1/2, 1/4),\ + # (1/4, 1/4, 1/2)\ + ] + +default_utility_tangent_weights = \ + [\ + (1,0),\ + (0,1),\ + # (0.75,0.25),\ + (0.5,0.5),\ + # (0.25,0.75)\ + ] + +default_tangent_weights = \ + {\ + stream_hx: default_stream_tangent_weights,\ + cu_hx: default_utility_tangent_weights,\ + hu_hx: default_utility_tangent_weights\ + } + +iterations = 'iterations' +logs = 'logs' +instances = 'instances' + +model_folder = 'model_folder' +append_folder = 'append_folder' +iterations_folder = 'iterations_folder' +logs_folder = 'logs_folder' +instances_folder = 'instances_folder' + +absolute_error = 'absolute_error' +relative_error = 'relative_error' + +reclmtd_beta_error = 'reclmtd_beta_error' +# area_error = 'area_error' +q_beta_error = 'q_beta_error' +area_beta_error = 'area_beta_error' +bhin_error = 'bhin_error' +bhout_error = 'bhout_error' +bcin_error = 'bcin_error' +bcout_error = 'bcout_error' + +tangent_points = 'tangent_points' +q_beta_points = 'q_beta_points' +area_q_beta_points = 'area_q_beta_points' +# q_points = 'q_points' +# area_beta_points = 'area_beta_points' +th_points = 'th_points' +thx_points = 'thx_points' +tc_points = 'tc_points' +tcx_points = 'tcx_points' + +index_i = 'i' +index_j = 'j' +index_k = 'k' + +index_m = 'm' +index_n = 'n' + +#Dictionary Keys +latex_label = 'latex_label' +latex_subscript = 'latex_subscript' +latex_superscript = 'latex_superscript' +subscript_indices = 'subscript_indices' +superscript_indices = 'superscript_indices' +all_indices = 'all_indices' + +#Model Labels +area = 'area' +area_cu = 'area_cu' +area_hu = 'area_hu' + +area_beta = 'area_beta' +area_cu_beta = 'area_cu_beta' +area_hu_beta = 'area_hu_beta' + +bh_in = 'bh_in' +bh_out = 'bh_out' +bc_in = 'bc_in' +bc_out = 'bc_out' + +dt = 'dt' +dt_cu = 'dt_cu' +dt_hu = 'dt_hu' + +fh = 'fh' +fc = 'fc' + +reclmtd = 'reclmtd' +reclmtd_CU = 'reclmtd_CU' +reclmtd_HU = 'reclmtd_HU' + +reclmtd_beta = 'reclmtd_beta' +reclmtd_cu_beta = 'reclmtd_cu_beta' +reclmtd_hu_beta = 'reclmtd_hu_beta' + +q = 'q' +q_cu = 'q_cu' +q_hu = 'q_hu' + +q_beta = 'q_beta' +q_cu_beta = 'q_cu_beta' +q_hu_beta = 'q_hu_beta' + +th = 'th' +tc = 'tc' + +thx = 'thx' +tcx = 'tcx' + +z = 'z' +z_cu = 'z_cu' +z_hu = 'z_hu' + +z_A = 'z_A' +z_A_CU = 'z_A_CU' +z_A_HU = 'z_A_HU' + +z_q = 'z_q' +z_q_CU = 'z_q_CU' +z_q_HU = 'z_q_HU' + +z_th = 'z_th' +z_thx = 'z_thx' +z_tc = 'z_tc' +z_tcx = 'z_tcx' + +var_delta_fh = 'var_delta_fh' +var_delta_fhx = 'var_delta_fhx' +var_delta_fc = 'var_delta_fc' +var_delta_fcx = 'var_delta_fcx' + +z_q_beta = 'z_q_beta' +z_q_cu_beta = 'z_q_cu_beta' +z_q_hu_beta = 'z_q_hu_beta' + +var_delta_reclmtd_beta = 'var_delta_reclmtd_beta' +var_delta_reclmtd_cu_beta = 'var_delta_reclmtd_cu_beta' +var_delta_reclmtd_hu_beta = 'var_delta_reclmtd_hu_beta' + +z_area_beta_q = 'z_area_beta_q' +z_area_beta_q_cu = 'z_area_beta_q_cu' +z_area_beta_q_hu = 'z_area_beta_q_hu' + +z_A_beta = 'z_A_Beta' +z_A_CU_beta = 'z_A_CU_Beta' +z_A_HU_beta = 'z_A_HU_Beta' + +stream_keep_variables = [ + z, + area, area_beta, + q, q_beta, + reclmtd, reclmtd_beta, + fh, fc, + bh_in, bh_out, + bc_in, bc_out, + thx, tcx +] + +cu_keep_variables = [ + z_cu, + area_cu, area_cu_beta, + q_cu, q_cu_beta, + reclmtd_CU, reclmtd_cu_beta, + dt_cu +] + +hu_keep_variables = [ + z_hu, + area_hu, area_hu_beta, + q_hu, q_hu_beta, + reclmtd_HU, reclmtd_hu_beta, + dt_hu +] + +ltx_beta = r'\beta' + +model_map = {\ + 'model1': 'http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen1.html',\ + 'model2': 'http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen2.html',\ + 'model3': 'http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen3.html'\ + } diff --git a/hens/beta_adaptive_model_mixer/lib/iterations_helper.py b/hens/beta_adaptive_model_mixer/lib/iterations_helper.py new file mode 100644 index 0000000..197bbb5 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/iterations_helper.py @@ -0,0 +1,759 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import os, sys, bisect + +from argparse import ArgumentParser, RawTextHelpFormatter + +from pprint import pprint + +from pyomo.core.base.numvalue import value + +from .model_declarations.model_builder import create_model +from .model_declarations.helper_functions import two_point_generator, three_point_generator, lmtd_inv_beta +from .constants import * + +stream_tangent_points = {} +cu_tangent_points = {} +hu_tangent_points = {} + +stream_q_beta_breakpoints = {} +cu_q_beta_breakpoints = {} +hu_q_beta_breakpoints = {} + +stream_area_q_beta_breakpoints = {} +cu_area_q_beta_breakpoints = {} +hu_area_q_beta_breakpoints = {} + +th_breakpoints = {} +thx_breakpoints = {} +tc_breakpoints = {} +tcx_breakpoints = {} + +def create_output_dir(root, model, append): + model_dir = root + os.sep + model + append_dir = model_dir + os.sep + append + iterations_dir = append_dir + os.sep + iterations + log_dir = iterations_dir + os.sep + logs + instance_dir = iterations_dir + os.sep + instances + + if not os.path.exists(model_dir): + os.makedirs(model_dir) + + if not os.path.exists(append_dir): + os.makedirs(append_dir) + + if not os.path.exists(iterations_dir): + os.makedirs(iterations_dir) + + if not os.path.exists(log_dir): + os.makedirs(log_dir) + + if not os.path.exists(instance_dir): + os.makedirs(instance_dir) + + return {\ + model_folder : model_dir,\ + append_folder : append_dir,\ + iterations_folder: iterations_dir,\ + logs_folder : log_dir,\ + instances_folder : instance_dir,\ + } + +def initialise_parser(): + parser = ArgumentParser() + parser.add_argument('model', help='The model you wish to run e.g. model1 for datafile: ../datafiles/model1.dat') + parser.add_argument('run_name', help='The name of the run you are running the results will be placed in a directory with this name') + parser.add_argument('-i', '--print-instance', help='print instance of final run', action='store_true') + parser.add_argument('-t', '--num-threads', type=int, help='Number of cpu cores used. If this value is larger than the number of cores available the maximum number of cores will be used. Must be a positive integer.') + parser.add_argument('-c', '--cont', help='Get continuation message. Requires feedback after the first 50 iterations.', action='store_true') + parser.add_argument('-w', '--weaken', help='If set doesn\'t add breakpoints for inactive balancing constraints.', action='store_true') + parser.add_argument('-a', '--absolute', help='Use absolute error', action='store_true') + parser.add_argument('--lmtd-beta-eps', help='Max absolute lmtd error, a negative value will terminate when no new tangents are placed. DEFAULT=0.0001', type=float) + parser.add_argument('--bal-eps', help='Max absolute error for balancing bilinearities. DEFAULT=0.0001', type=float) + parser.add_argument('--q-beta-eps', help='Max absolute error for area bilinearities. DEFAULT=0.0001', type=float) + parser.add_argument('--area-beta-eps', help='Max absolute error for area betas. DEFAULT=0.0001', type=float) + parser.add_argument('-e', '--all-error', help='Max absolute error for all approximations, a negative value will terminate when no new tangents are placed. DEFAULT=0.0001', type=float) + parser.add_argument('-m', '--tighten-tol', help='Tightens tolerances. Sets: IntFeasTol = 1e-9, FeasibilityTol = 1e-9, OptimalityTol = 1e-9', action='store_true') + parser.add_argument('--IntFeasTol', type=float, help='Sets integer feasibility tolerance. Min=1e-9. Default=1e-5. Max=1e-2. Overridden by m flag.') + parser.add_argument('--FeasibilityTol', type=float, help='Sets primal feasibility tolerance. Min=1e-9. Default=1e-6. Max=1e-2. Overridden by m flag.') + parser.add_argument('--OptimalityTol', type=float, help='Sets dual feasibility tolerance. Min=1e-9. Default=1e-6. Max=1e-2. Overridden by m flag.') + parser.add_argument('--MarkowitzTol', type=float, help='Sets threshold pivoting tolerance. Min=1e-4. Default=0.0078125. Max=0.999. Overridden by m flag.') + return parser + +def validate_and_assign_args(args): + if args.num_threads: + if args.num_threads <= 0: + raise ValueError('The number of threads must be positive') + +def add_initial_th_breakpoints(instance): + for i in instance.HP: + for k in instance.ST: + global th_breakpoints + th_breakpoints[i,k] = [m for m in instance.Th_breakpoints[i,k]] + +def add_initial_thx_breakpoints(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global thx_breakpoints + thx_breakpoints[i,j,k] = [m for m in instance.Thx_breakpoints[i,j,k]] + +def add_initial_tc_breakpoints(instance): + for j in instance.CP: + for k in instance.K_Take_First_Stage: + global tc_breakpoints + tc_breakpoints[j,k] = [m for m in instance.Tc_breakpoints[j,k]] + +def add_initial_tcx_breakpoints(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global tcx_breakpoints + tcx_breakpoints[i,j,k] = [m for m in instance.Tcx_breakpoints[i,j,k]] + +def add_initial_q_beta_breakpoints(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global stream_q_beta_breakpoints + stream_q_beta_breakpoints[i,j,k] = [m for m in instance.Q_beta_breakpoints[i,j,k]] + +def add_initial_q_cu_beta_breakpoints(instance): + for i in instance.HP: + global cu_q_beta_breakpoints + cu_q_beta_breakpoints[i] = [m for m in instance.Q_cu_beta_breakpoints[i]] + +def add_initial_q_hu_beta_breakpoints(instance): + for j in instance.CP: + global hu_q_beta_breakpoints + hu_q_beta_breakpoints[j] = [m for m in instance.Q_hu_beta_breakpoints[j]] + +def add_initial_stream_tangent_points(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global stream_tangent_points + stream_tangent_points[i,j,k] = three_point_generator(default_tangent_weights[stream_hx], instance.dt[i,j,k].bounds) + +def add_initial_cu_tangent_points(instance): + for i in instance.HP: + global cu_tangent_points + cu_tangent_points[i] = two_point_generator(default_tangent_weights[cu_hx], instance.dt_cu[i].bounds) + +def add_initial_hu_tangent_points(instance): + for j in instance.CP: + global hu_tangent_points + hu_tangent_points[j] = two_point_generator(default_tangent_weights[hu_hx], instance.dt_hu[j].bounds) + +def add_initial_stream_area_q_beta_breakpoints(instance): + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + global stream_area_q_beta_breakpoints + stream_area_q_beta_breakpoints[i,j,k] = [m for m in instance.Area_beta_q_breakpoints[i,j,k]] + +def add_initial_cu_area_q_beta_breakpoints(instance): + for i in instance.HP: + global cu_area_q_beta_breakpoints + cu_area_q_beta_breakpoints[i] = [m for m in instance.Area_beta_q_cu_breakpoints[i]] + +def add_initial_hu_area_q_beta_breakpoints(instance): + for j in instance.CP: + global hu_area_q_beta_breakpoints + hu_area_q_beta_breakpoints[j] = [m for m in instance.Area_beta_q_hu_breakpoints[j]] + +def declare_th_breakpoints(model, i, k): + global th_breakpoints + return th_breakpoints[i,k] + +def declare_thx_breakpoints(model, i, j, k): + global thx_breakpoints + return thx_breakpoints[i,j,k] + +def declare_tc_breakpoints(model, j, k): + global tc_breakpoints + return tc_breakpoints[j,k] + +def declare_tcx_breakpoints(model, i, j, k): + global tcx_breakpoints + return tcx_breakpoints[i,j,k] + +def declare_stream_tangent_points(model, i, j, k): + global stream_tangent_points + return stream_tangent_points[i,j,k] + +def declare_cu_tangent_points(model, i): + global cu_tangent_points + return cu_tangent_points[i] + +def declare_hu_tangent_points(model, j): + global hu_tangent_points + return hu_tangent_points[j] + +def declare_stream_q_beta_breakpoints(model, i, j, k): + global stream_q_beta_breakpoints + return stream_q_beta_breakpoints[i,j,k] + +def declare_cu_q_beta_breakpoints(model, i): + global cu_q_beta_breakpoints + return cu_q_beta_breakpoints[i] + +def declare_hu_q_beta_breakpoints(model, j): + global hu_q_beta_breakpoints + return hu_q_beta_breakpoints[j] + +def declare_stream_area_q_beta_breakpoints(model, i, j, k): + global stream_area_q_beta_breakpoints + return stream_area_q_beta_breakpoints[i,j,k] + +def declare_cu_area_q_beta_breakpoints(model, i): + global cu_area_q_beta_breakpoints + return cu_area_q_beta_breakpoints[i] + +def declare_hu_area_q_beta_breakpoints(model, j): + global hu_area_q_beta_breakpoints + return hu_area_q_beta_breakpoints[j] + +def initialise_hx_model(datafile): + model = create_model() + instance = model.create_instance(datafile) + + add_initial_th_breakpoints(instance) + add_initial_thx_breakpoints(instance) + add_initial_tc_breakpoints(instance) + add_initial_tcx_breakpoints(instance) + + add_initial_q_beta_breakpoints(instance) + add_initial_q_cu_beta_breakpoints(instance) + add_initial_q_hu_beta_breakpoints(instance) + + add_initial_stream_tangent_points(instance) + add_initial_cu_tangent_points(instance) + add_initial_hu_tangent_points(instance) + + add_initial_stream_area_q_beta_breakpoints(instance) + add_initial_cu_area_q_beta_breakpoints(instance) + add_initial_hu_area_q_beta_breakpoints(instance) + + model.Th_breakpoints.initialize = declare_th_breakpoints + model.Thx_breakpoints.initialize = declare_thx_breakpoints + model.Tc_breakpoints.initialize = declare_tc_breakpoints + model.Tcx_breakpoints.initialize = declare_tcx_breakpoints + + model.Reclmtd_beta_gradient_points.initialize = declare_stream_tangent_points + model.Reclmtd_cu_beta_gradient_points.initialize = declare_cu_tangent_points + model.Reclmtd_hu_beta_gradient_points.initialize = declare_hu_tangent_points + + model.Q_beta_breakpoints.initialize = declare_stream_q_beta_breakpoints + model.Q_cu_beta_breakpoints.initialize = declare_cu_q_beta_breakpoints + model.Q_hu_beta_breakpoints.initialize = declare_hu_q_beta_breakpoints + + model.Area_beta_q_breakpoints.initialize = declare_stream_area_q_beta_breakpoints + model.Area_beta_q_cu_breakpoints.initialize = declare_cu_area_q_beta_breakpoints + model.Area_beta_q_hu_breakpoints.initialize = declare_hu_area_q_beta_breakpoints + + return model + +def get_active_hx(instance): + active_hx = { + stream_hx : [], + cu_hx : [], + hu_hx : [] + } + inactive_hx = { + stream_hx : [], + cu_hx : [], + hu_hx : [] + } + for index in instance.z: + if value(instance.z[index]) >= active_lb: + active_hx[stream_hx].append(index) + else: + inactive_hx[stream_hx].append(index) + + for index in instance.z_cu: + if value(instance.z_cu[index]) >= active_lb: + active_hx[cu_hx].append(index) + else: + inactive_hx[cu_hx].append(index) + + for index in instance.z_hu: + if value(instance.z_hu[index]) >= active_lb: + active_hx[hu_hx].append(index) + else: + inactive_hx[hu_hx].append(index) + + return active_hx, inactive_hx + +def get_new_tangent_points(instance, active_hx): + new_tangents = { + stream_hx : {}, + cu_hx : {}, + hu_hx : {} + } + for index in active_hx[stream_hx]: + x_index = index + y_index = (index[0], index[1], index[2]+1) + x = value(instance.dt[x_index]) + y = value(instance.dt[y_index]) + new_tangent_point = (x,y) if x >= y else (y,x) + new_tangents[stream_hx][index] = new_tangent_point + + for index in active_hx[cu_hx]: + x = value(instance.dt_cu[index]) + new_tangents[cu_hx][index] = x + + for index in active_hx[hu_hx]: + x = value(instance.dt_hu[index]) + new_tangents[hu_hx][index] = x + + return new_tangents + +def get_new_balancing_breakpoints(instance, active_hx, inactive_hx, weaken): + new_th_breakpoints = {} + new_thx_breakpoints = {} + new_tc_breakpoints = {} + new_tcx_breakpoints = {} + + # active_th_indices = list(set(map(lambda (i,j,k): (i,k), active_hx[stream_hx]))) + # active_tc_indices = list(set(map(lambda (i,j,k): (j, k+1), active_hx[stream_hx]))) + + active_th_indices = list(set((i,k) for i,_,k in active_hx[stream_hx])) + active_tc_indices = list(set((j,k+1) for _,j,k in active_hx[stream_hx])) + + for index in active_th_indices: + breakpoint = instance.th[index].value + if breakpoint not in th_breakpoints[index]: + bisect.insort(th_breakpoints[index], breakpoint) + new_th_breakpoints[index] = breakpoint + + for index in active_hx[stream_hx]: + breakpoint = instance.thx[index].value + if breakpoint not in thx_breakpoints[index]: + bisect.insort(thx_breakpoints[index], breakpoint) + new_thx_breakpoints[index] = [breakpoint] + + for index in active_tc_indices: + breakpoint = instance.tc[index].value + if breakpoint not in tc_breakpoints[index]: + bisect.insort(tc_breakpoints[index], breakpoint) + new_tc_breakpoints[index] = breakpoint + + for index in active_hx[stream_hx]: + breakpoint = instance.tcx[index].value + if breakpoint not in tcx_breakpoints[index]: + bisect.insort(tcx_breakpoints[index], breakpoint) + new_tcx_breakpoints[index] = [breakpoint] + + if not weaken: + for index in inactive_hx[stream_hx]: + if instance.bh_out[index].value > 0.000001: + breakpoint = instance.thx[index].value + if breakpoint not in thx_breakpoints[index]: + bisect.insort(thx_breakpoints[index], breakpoint) + new_thx_breakpoints[index] = breakpoint + + if instance.bc_out[index].value > 0.000001: + breakpoint = instance.tcx[index].value + if breakpoint not in tcx_breakpoints[index]: + bisect.insort(tcx_breakpoints[index], breakpoint) + new_tcx_breakpoints[index] = breakpoint + + new_balancing_breakpoints = {} + if not len(new_th_breakpoints) == 0: + new_balancing_breakpoints['th'] = new_th_breakpoints + + if not len(new_thx_breakpoints) == 0: + new_balancing_breakpoints['thx'] = new_thx_breakpoints + + if not len(new_tc_breakpoints) == 0: + new_balancing_breakpoints['tc'] = new_tc_breakpoints + + if not len(new_tcx_breakpoints) == 0: + new_balancing_breakpoints['tcx'] = new_tcx_breakpoints + + return new_balancing_breakpoints + +def get_new_q_beta_breakpoints(instance, active_hx): + new_stream_q_beta_breakpoints = {} + new_cu_q_beta_breakpoints = {} + new_hu_q_beta_breakpoints = {} + + for index in active_hx[stream_hx]: + breakpoint = instance.q[index].value + if breakpoint not in stream_q_beta_breakpoints[index]: + bisect.insort(stream_q_beta_breakpoints[index], breakpoint) + new_stream_q_beta_breakpoints[index] = breakpoint + + for index in active_hx[cu_hx]: + breakpoint = instance.q_cu[index].value + if breakpoint not in cu_q_beta_breakpoints[index]: + bisect.insort(cu_q_beta_breakpoints[index], breakpoint) + new_cu_q_beta_breakpoints[index] = breakpoint + + for index in active_hx[hu_hx]: + breakpoint = instance.q_hu[index].value + if breakpoint not in hu_q_beta_breakpoints[index]: + bisect.insort(hu_q_beta_breakpoints[index], breakpoint) + new_hu_q_beta_breakpoints[index] = breakpoint + + new_q_beta_breakpoints = {} + if not len(new_stream_q_beta_breakpoints) == 0: + new_q_beta_breakpoints[stream_hx] = new_stream_q_beta_breakpoints + + if not len(new_cu_q_beta_breakpoints) == 0: + new_q_beta_breakpoints[cu_hx] = new_cu_q_beta_breakpoints + + if not len(new_hu_q_beta_breakpoints) == 0: + new_q_beta_breakpoints[hu_hx] = new_hu_q_beta_breakpoints + + return new_q_beta_breakpoints + +def get_new_area_q_beta_breakpoints(instance, active_hx): + new_stream_area_q_beta_breakpoints = {} + new_cu_area_q_beta_breakpoints = {} + new_hu_area_q_beta_breakpoints = {} + + for index in active_hx[stream_hx]: + breakpoint = instance.q_beta[index].value + if breakpoint not in stream_area_q_beta_breakpoints[index]: + bisect.insort(stream_area_q_beta_breakpoints[index], breakpoint) + new_stream_area_q_beta_breakpoints[index] = breakpoint + + for index in active_hx[cu_hx]: + breakpoint = instance.q_cu_beta[index].value + if breakpoint not in cu_area_q_beta_breakpoints[index]: + bisect.insort(cu_area_q_beta_breakpoints[index], breakpoint) + new_cu_area_q_beta_breakpoints[index] = breakpoint + + for index in active_hx[hu_hx]: + breakpoint = instance.q_hu_beta[index].value + if breakpoint not in hu_area_q_beta_breakpoints[index]: + bisect.insort(hu_area_q_beta_breakpoints[index], breakpoint) + new_hu_area_q_beta_breakpoints[index] = breakpoint + + new_area_q_beta_breakpoints = {} + if not len(new_stream_area_q_beta_breakpoints) == 0: + new_area_q_beta_breakpoints[stream_hx] = new_stream_area_q_beta_breakpoints + + if not len(new_cu_area_q_beta_breakpoints) == 0: + new_area_q_beta_breakpoints[cu_hx] = new_cu_area_q_beta_breakpoints + + if not len(new_hu_area_q_beta_breakpoints) == 0: + new_area_q_beta_breakpoints[hu_hx] = new_hu_area_q_beta_breakpoints + + return new_area_q_beta_breakpoints + +def add_new_tangent_points(new_tangent_points): + added_tangents = { + } + for index, tangent_point in new_tangent_points[stream_hx].items(): + if not tangent_point in stream_tangent_points[index]: + if not stream_hx in added_tangents: + added_tangents[stream_hx] = {} + stream_tangent_points[index].append(tangent_point) + added_tangents[stream_hx][index] = [tangent_point] + if not tangent_point[0] == tangent_point[1]: + stream_tangent_points[index].append((tangent_point[1], tangent_point[0])) + added_tangents[stream_hx][index].append((tangent_point[1], tangent_point[0])) + + for index, tangent_point in new_tangent_points[cu_hx].items(): + if not tangent_point in cu_tangent_points[index]: + if not cu_hx in added_tangents: + added_tangents[cu_hx] = {} + cu_tangent_points[index].append(tangent_point) + added_tangents[cu_hx][index] = [tangent_point] + + for index, tangent_point in new_tangent_points[hu_hx].items(): + if not tangent_point in hu_tangent_points[index]: + if not hu_hx in added_tangents: + added_tangents[hu_hx] = {} + hu_tangent_points[index].append(tangent_point) + added_tangents[hu_hx][index] = [tangent_point] + + return added_tangents + +def calculate_reclmtd_beta_error(x, y, beta, reclmtd_beta_estimate): + reclmtd_beta_correct = lmtd_inv_beta(x, y, beta) + error = reclmtd_beta_correct - reclmtd_beta_estimate + rel_error = error/reclmtd_beta_correct + abs_error = error + return {\ + absolute_error: abs_error,\ + relative_error: rel_error,\ + } + +def calculate_stream_reclmtd_beta_error(instance, i, j, k): + dt_hot = instance.dt[(i,j,k)].value + dt_cold = instance.dt[(i,j,k+1)].value + beta = instance.Beta + reclmtd_beta_estimate = instance.reclmtd_beta[(i,j,k)].value + return calculate_reclmtd_beta_error(dt_hot, dt_cold, beta, reclmtd_beta_estimate) + +def calculate_cu_reclmtd_beta_error(instance, i): + dt = instance.dt_cu[i].value + dt2 = instance.Th_out[i] - instance.T_cu_in + beta = instance.Beta + reclmtd_beta_estimate = instance.reclmtd_cu_beta[i].value + return calculate_reclmtd_beta_error(dt, dt2, beta, reclmtd_beta_estimate) + +def calculate_hu_reclmtd_beta_error(instance, j): + dt = instance.dt_hu[j].value + dt2 = instance.T_hu_in - instance.Tc_out[j] + beta = instance.Beta + reclmtd_beta_estimate = instance.reclmtd_hu_beta[j].value + return calculate_reclmtd_beta_error(dt, dt2, beta, reclmtd_beta_estimate) + +def calculate_q_beta_errors(q, beta, q_beta_estimate): + q_beta_correct = pow(q, beta) + error = q_beta_correct - q_beta_estimate + rel_error = error/q_beta_correct + abs_error = error + return {\ + absolute_error: abs_error,\ + relative_error: rel_error,\ + } + +def calculate_stream_q_beta_error(instance, i, j, k): + q = instance.q[i,j,k].value + beta = instance.Beta + q_beta_estimate = instance.q_beta[i,j,k].value + return calculate_q_beta_errors(q, beta, q_beta_estimate) + +def calculate_cu_q_beta_error(instance, i): + q_cu = instance.q_cu[i].value + beta = instance.Beta + q_cu_beta_estimate = instance.q_cu_beta[i].value + return calculate_q_beta_errors(q_cu, beta, q_cu_beta_estimate) + +def calculate_hu_q_beta_error(instance, j): + q_hu = instance.q_hu[j].value + beta = instance.Beta + q_hu_beta_estimate = instance.q_hu_beta[j].value + return calculate_q_beta_errors(q_hu, beta, q_hu_beta_estimate) + +def calculate_area_beta_errors(q_beta, reclmtd_beta, u_beta, area_beta_estimate): + area_beta_correct = u_beta*q_beta*reclmtd_beta + error = area_beta_correct - area_beta_estimate + rel_error = error/area_beta_correct + abs_error = error + return {\ + absolute_error: abs_error,\ + relative_error: rel_error,\ + } + +def calculate_stream_area_beta_error(instance, i, j, k): + q_beta = instance.q_beta[i,j,k].value + reclmtd_beta = instance.reclmtd_beta[i,j,k].value + u_beta = instance.U_beta[i,j] + area_beta_estimate = instance.area_beta[i,j,k].value + return calculate_area_beta_errors(q_beta, reclmtd_beta, u_beta, area_beta_estimate) + +def calculate_cu_area_beta_error(instance, i): + q_beta = instance.q_cu_beta[i].value + reclmtd_beta = instance.reclmtd_cu_beta[i].value + u_beta = instance.U_cu_beta[i] + area_beta_estimate = instance.area_cu_beta[i].value + return calculate_area_beta_errors(q_beta, reclmtd_beta, u_beta, area_beta_estimate) + +def calculate_hu_area_beta_error(instance, j): + q_beta = instance.q_hu_beta[j].value + reclmtd_beta = instance.reclmtd_hu_beta[j].value + u_beta = instance.U_hu_beta[j] + area_beta_estimate = instance.area_hu_beta[j].value + return calculate_area_beta_errors(q_beta, reclmtd_beta, u_beta, area_beta_estimate) + +def calculate_bilinear_errors(f, t, bilinear_estimate): + bilinear_correct = f*t + if bilinear_correct < 0.000001: + return {\ + absolute_error: 0,\ + relative_error: 0,\ + } + error = bilinear_estimate - bilinear_correct + rel_error = error/bilinear_correct if not t == 0 else 0 + abs_error = error + return {\ + absolute_error: abs_error,\ + relative_error: rel_error,\ + } + +def calculate_bhin(instance, i, j, k): + f = instance.fh[i,j,k].value + t = instance.th[i,k].value + bhin = instance.bh_in[i,j,k].value + return calculate_bilinear_errors(f, t, bhin) + +def calculate_bhout(instance, i, j, k): + f = instance.fh[i,j,k].value + t = instance.thx[i,j,k].value + bhout = instance.bh_out[i,j,k].value + return calculate_bilinear_errors(f, t, bhout) + +def calculate_bcin(instance, i, j, k): + f = instance.fc[i,j,k].value + t = instance.tc[j,k+1].value + bcin = instance.bc_in[i,j,k].value + return calculate_bilinear_errors(f, t, bcin) + +def calculate_bcout(instance, i, j, k): + f = instance.fc[i,j,k].value + t = instance.tcx[i,j,k].value + bcout = instance.bc_out[i,j,k].value + return calculate_bilinear_errors(f, t, bcout) + +def get_all_points(): + return {\ + stream_hx: {\ + tangent_points: stream_tangent_points,\ + q_beta_points: stream_q_beta_breakpoints,\ + area_q_beta_points: stream_area_q_beta_breakpoints,\ + th_points: th_breakpoints,\ + thx_points: thx_breakpoints,\ + tc_points: tc_breakpoints,\ + tcx_points: tcx_breakpoints,\ + },\ + cu_hx: {\ + tangent_points: cu_tangent_points,\ + q_beta_points: cu_q_beta_breakpoints,\ + area_q_beta_points: cu_area_q_beta_breakpoints,\ + },\ + hu_hx: {\ + tangent_points: hu_tangent_points,\ + q_beta_points: hu_q_beta_breakpoints,\ + area_q_beta_points: hu_area_q_beta_breakpoints,\ + },\ + } + +def summarise_errors(instance, active_hx, inactive_hx, weaken): + errors = {} + + errors[stream_hx] = {} + errors[cu_hx] = {} + errors[hu_hx] = {} + + errors[stream_hx][reclmtd_beta_error] = {} + errors[cu_hx][reclmtd_beta_error] = {} + errors[hu_hx][reclmtd_beta_error] = {} + + errors[stream_hx][q_beta_error] = {} + errors[cu_hx][q_beta_error] = {} + errors[hu_hx][q_beta_error] = {} + + errors[stream_hx][area_beta_error] = {} + errors[cu_hx][area_beta_error] = {} + errors[hu_hx][area_beta_error] = {} + + errors[stream_hx][bhin_error] = {} + errors[stream_hx][bhout_error] = {} + errors[stream_hx][bcin_error] = {} + errors[stream_hx][bcout_error] = {} + + for (i,j,k) in active_hx[stream_hx]: + errors[stream_hx][reclmtd_beta_error][i,j,k] = calculate_stream_reclmtd_beta_error(instance, i, j, k) + errors[stream_hx][q_beta_error][i,j,k] = calculate_stream_q_beta_error(instance, i, j, k) + errors[stream_hx][area_beta_error][i,j,k] = calculate_stream_area_beta_error(instance, i, j, k) + errors[stream_hx][bhin_error][i,j,k] = calculate_bhin(instance, i, j, k) + errors[stream_hx][bhout_error][i,j,k] = calculate_bhout(instance, i, j, k) + errors[stream_hx][bcin_error][i,j,k] = calculate_bcin(instance, i, j, k) + errors[stream_hx][bcout_error][i,j,k] = calculate_bcout(instance, i, j, k) + + if not weaken: + for (i,j,k) in inactive_hx[stream_hx]: + errors[stream_hx][bhout_error][i,j,k] = calculate_bhout(instance, i, j, k) + errors[stream_hx][bcout_error][i,j,k] = calculate_bcout(instance, i, j, k) + + for i in active_hx[cu_hx]: + errors[cu_hx][reclmtd_beta_error][i] = calculate_cu_reclmtd_beta_error(instance, i) + errors[cu_hx][q_beta_error][i] = calculate_cu_q_beta_error(instance, i) + errors[cu_hx][area_beta_error][i] = calculate_cu_area_beta_error(instance, i) + + for j in active_hx[hu_hx]: + errors[hu_hx][reclmtd_beta_error][j] = calculate_hu_reclmtd_beta_error(instance, j) + errors[hu_hx][q_beta_error][j] = calculate_hu_q_beta_error(instance, j) + errors[hu_hx][area_beta_error][j] = calculate_hu_area_beta_error(instance, j) + + return errors + +def get_max_errors(errors, active_hx, inactive_hx, weaken): + + max_errors = { + balancing_ref: { + absolute_error: -1, \ + relative_error: -1, \ + }, + q_beta_ref: { + absolute_error: -1, \ + relative_error: -1, \ + }, + lmtd_beta_ref: { + absolute_error: -1, \ + relative_error: -1, \ + }, + area_beta_ref: { + absolute_error: -1, \ + relative_error: -1, \ + }, + } + + for (i,j,k) in active_hx[stream_hx]: + max_bilinear_error_abs = max( \ + errors[stream_hx][bhin_error][i,j,k][absolute_error], \ + errors[stream_hx][bhout_error][i,j,k][absolute_error], \ + errors[stream_hx][bcin_error][i,j,k][absolute_error], \ + errors[stream_hx][bcout_error][i,j,k][absolute_error], \ + ) + + max_bilinear_error_rel = max( \ + abs(errors[stream_hx][bhin_error][i,j,k][relative_error]), \ + abs(errors[stream_hx][bhout_error][i,j,k][relative_error]), \ + abs(errors[stream_hx][bcin_error][i,j,k][relative_error]), \ + abs(errors[stream_hx][bcout_error][i,j,k][relative_error]), \ + ) + + if max_errors[balancing_ref][absolute_error] < max_bilinear_error_abs: + max_errors[balancing_ref][absolute_error] = max_bilinear_error_abs + + if max_errors[balancing_ref][relative_error] < max_bilinear_error_rel: + max_errors[balancing_ref][relative_error] = max_bilinear_error_rel + + if not weaken: + for (i,j,k) in inactive_hx[stream_hx]: + max_bilinear_error_abs = max( \ + errors[stream_hx][bhout_error][i,j,k][absolute_error], \ + errors[stream_hx][bcout_error][i,j,k][absolute_error], \ + ) + + max_bilinear_error_rel = max( \ + abs(errors[stream_hx][bhout_error][i,j,k][relative_error]), \ + abs(errors[stream_hx][bcout_error][i,j,k][relative_error]), \ + ) + + if max_errors[balancing_ref][absolute_error] < max_bilinear_error_abs: + max_errors[balancing_ref][absolute_error] = max_bilinear_error_abs + + if max_errors[balancing_ref][relative_error] < max_bilinear_error_rel: + max_errors[balancing_ref][relative_error] = max_bilinear_error_rel + + for check_set in [stream_hx, cu_hx, hu_hx]: + for index in active_hx[check_set]: + if max_errors[q_beta_ref][absolute_error] < errors[check_set][q_beta_error][index][absolute_error]: + max_errors[q_beta_ref][absolute_error] = errors[check_set][q_beta_error][index][absolute_error] + + if max_errors[q_beta_ref][relative_error] < errors[check_set][q_beta_error][index][relative_error]: + max_errors[q_beta_ref][relative_error] = errors[check_set][q_beta_error][index][relative_error] + + if max_errors[lmtd_beta_ref][absolute_error] < errors[check_set][reclmtd_beta_error][index][absolute_error]: + max_errors[lmtd_beta_ref][absolute_error] = errors[check_set][reclmtd_beta_error][index][absolute_error] + + if max_errors[lmtd_beta_ref][relative_error] < errors[check_set][reclmtd_beta_error][index][relative_error]: + max_errors[lmtd_beta_ref][relative_error] = errors[check_set][reclmtd_beta_error][index][relative_error] + + if max_errors[area_beta_ref][absolute_error] < errors[check_set][area_beta_error][index][absolute_error]: + max_errors[area_beta_ref][absolute_error] = errors[check_set][area_beta_error][index][absolute_error] + + if max_errors[area_beta_ref][relative_error] < errors[check_set][area_beta_error][index][relative_error]: + max_errors[area_beta_ref][relative_error] = errors[check_set][area_beta_error][index][relative_error] + + return max_errors diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/__init__.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/__init__.py new file mode 100644 index 0000000..f757ec9 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/__init__.py @@ -0,0 +1,2 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/bound_generators.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/bound_generators.py new file mode 100644 index 0000000..c516be4 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/bound_generators.py @@ -0,0 +1,96 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from .helper_functions import lmtd_inv_beta + +def fh_bounds(model, i, j, k): + return (0, model.Fh[i]) + +def fc_bounds(model, i, j, k): + return (0, model.Fc[j]) + +def thx_bounds(model, i, j, k): + return (model.Th_out[i], model.Th_in[i]) + +def tcx_bounds(model, i, j, k): + return (model.Tc_in[j], model.Tc_out[j]) + +def dt_bounds(model, i, j, k): + return (model.Delta_t_min, model.Th_in[i]-model.Tc_in[j]) + +def dt_cu_bounds(model, i): + return (model.Delta_t_min, model.Th_in[i]-model.T_cu_in) + +def dt_hu_bounds(model, j): + return (model.Delta_t_min, model.T_hu_in - model.Tc_in[j]) + +def reclmtd_beta_bounds(model, i, j, *k): + xy_min = model.Delta_t_min + xy_max = model.Th_in[i] - model.Tc_in[j] + + reclmtd_beta_lower = lmtd_inv_beta(xy_max, xy_max, model.Beta) + reclmtd_beta_upper = lmtd_inv_beta(xy_min, xy_min, model.Beta) + + return (reclmtd_beta_lower, reclmtd_beta_upper) + +def reclmtd_cu_beta_bounds(model, i): + x_min = model.Delta_t_min + x_max = model.Th_in[i] - model.T_cu_out + y = model.Th_out[i] - model.T_cu_in + + reclmtd_beta_cu_lower = lmtd_inv_beta(x_max, y, model.Beta) + reclmtd_beta_cu_upper = lmtd_inv_beta(x_min, y, model.Beta) + + return (reclmtd_beta_cu_lower, reclmtd_beta_cu_upper) + +def reclmtd_hu_beta_bounds(model, j): + x_min = model.Delta_t_min + x_max = model.T_hu_out - model.Tc_in[j] + y = model.T_hu_in - model.Tc_out[j] + + reclmtd_beta_hu_lower = lmtd_inv_beta(x_max, y, model.Beta) + reclmtd_beta_hu_upper = lmtd_inv_beta(x_min, y, model.Beta) + + return (reclmtd_beta_hu_lower, reclmtd_beta_hu_upper) + +def q_bounds(model, i, j, *k): + q_lower = 0 + + q_upper_hot_side = model.Fh[i]*(model.Th_in[i] - model.Th_out[i]) + q_upper_cold_side = model.Fc[j]*(model.Tc_out[j] - model.Tc_in[j]) + q_upper = min( q_upper_hot_side, q_upper_cold_side ) + return (q_lower, q_upper) + +def q_cu_bounds(model, i): + q_cu_lower = 0 + q_cu_upper = model.Fh[i]*(model.Th_in[i] - model.Th_out[i]) + return (q_cu_lower, q_cu_upper) + +def q_hu_bounds(model, j): + q_hu_lower = 0 + q_hu_upper = model.Fc[j]*(model.Tc_out[j] - model.Tc_in[j]) + return (q_hu_lower, q_hu_upper) + +def q_beta_bounds(model, i, j, *k): + q_bounds_val = q_bounds(model, i, j) + return q_bounds_val if (model.Beta == 1) else tuple(map(lambda q: pow(q, model.Beta), q_bounds_val)) + +def q_cu_beta_bounds(model, i): + q_cu_bounds_val = q_cu_bounds(model, i) + return q_cu_bounds_val if (model.Beta == 1) else tuple(map(lambda q: pow(q, model.Beta), q_cu_bounds_val)) + +def q_hu_beta_bounds(model, j): + q_hu_bounds_val = q_hu_bounds(model, j) + return q_hu_bounds_val if (model.Beta == 1) else tuple(map(lambda q: pow(q, model.Beta), q_hu_bounds_val)) + +def th_bounds(model, i, *k): + return (model.Th_out[i], model.Th_in[i]) + +def tc_bounds(model, j, *k): + return (model.Tc_in[j], model.Tc_out[j]) + +def bh_bounds(model, i, j, k): + return (0, model.Th_in[i]*model.Fh[i]) + +def bc_bounds(model, i, j, k): + return (0, model.Tc_out[j]*model.Fc[j]) diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/constraint_rules.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/constraint_rules.py new file mode 100644 index 0000000..f6c0aa1 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/constraint_rules.py @@ -0,0 +1,562 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.constraint import Constraint + +from .helper_functions import lmtd_inv_beta, lmtd_inverse_beta_gradient_calculator + +def z_th_sum_rule(model, i, k): + return sum(model.z_th[i,k,n] for n in range(1, len(model.Th_breakpoints[i,k])) ) == 1 + +def th_lower_rule(model, i, k): + return model.th[i,k] >= sum(model.Th_breakpoints[i,k][n]*model.z_th[i,k,n] for n in range(1, len(model.Th_breakpoints[i,k]))) + +def th_upper_rule(model, i, k): + return model.th[i,k] <= sum(model.Th_breakpoints[i,k][n+1]*model.z_th[i,k,n] for n in range(1, len(model.Th_breakpoints[i,k]))) + +def var_delta_fh_sum_rule(model, i, j, k): + return model.fh[i,j,k] == sum(model.var_delta_fh[i,j,k,n] for n in range(1, len(model.Th_breakpoints[i,k]))) + +def var_delta_fh_upper_rule(model, i, j, k, n): + return model.var_delta_fh[i,j,k,n] <= model.Fh[i]*model.z_th[i,k,n] + +########################## +def z_thx_sum_rule(model, i, j, k): + return sum(model.z_thx[i,j,k,n] for n in range(1, len(model.Thx_breakpoints[i,j,k])) ) == 1 + +def thx_lower_rule(model, i, j, k): + return model.thx[i,j,k] >= sum(model.Thx_breakpoints[i,j,k][n]*model.z_thx[i,j,k,n] for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def thx_upper_rule(model, i, j, k): + return model.thx[i,j,k] <= sum(model.Thx_breakpoints[i,j,k][n+1]*model.z_thx[i,j,k,n] for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def var_delta_fhx_sum_rule(model, i, j, k): + return model.fh[i,j,k] == sum(model.var_delta_fhx[i,j,k,n] for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def var_delta_fhx_upper_rule(model, i, j, k, n): + return model.var_delta_fhx[i,j,k,n] <= model.Fh[i]*model.z_thx[i,j,k,n] + +########################## +def z_tc_sum_rule(model, j, k): + return sum(model.z_tc[j,k+1,n] for n in range(1, len(model.Tc_breakpoints[j,k+1])) ) == 1 + +def tc_lower_rule(model, j, k): + return model.tc[j,k+1] >= sum(model.Tc_breakpoints[j,k+1][n]*model.z_tc[j,k+1,n] for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def tc_upper_rule(model, j, k): + return model.tc[j,k+1] <= sum(model.Tc_breakpoints[j,k+1][n+1]*model.z_tc[j,k+1,n] for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def var_delta_fc_sum_rule(model, i, j, k): + return model.fc[i,j,k] == sum(model.var_delta_fc[i,j,k,n] for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def var_delta_fc_upper_rule(model, i, j, k, n): + return model.var_delta_fc[i,j,k,n] <= model.Fc[j]*model.z_tc[j,k+1,n] + +########################## +def z_tcx_sum_rule(model, i, j, k): + return sum(model.z_tcx[i,j,k,n] for n in range(1, len(model.Tcx_breakpoints[i,j,k])) ) == 1 + +def tcx_lower_rule(model, i, j, k): + return model.tcx[i,j,k] >= sum(model.Tcx_breakpoints[i,j,k][n]*model.z_tcx[i,j,k,n] for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def tcx_upper_rule(model, i, j, k): + return model.tcx[i,j,k] <= sum(model.Tcx_breakpoints[i,j,k][n+1]*model.z_tcx[i,j,k,n] for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def var_delta_fcx_sum_rule(model, i, j, k): + return model.fc[i,j,k] == sum(model.var_delta_fcx[i,j,k,n] for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def var_delta_fcx_upper_rule(model, i, j, k, n): + return model.var_delta_fcx[i,j,k,n] <= model.Fc[j]*model.z_tcx[i,j,k,n] + +########################## +def z_area_beta_q_sum_rule(model, i, j, k): + return sum(model.z_area_beta_q[i,j,k,n] for n in range(1, len(model.Area_beta_q_breakpoints[i,j,k]))) == 1 + +def area_beta_q_lower_rule(model, i, j, k): + return model.q_beta[i,j,k] >= sum(model.Area_beta_q_breakpoints[i,j,k][n]*model.z_area_beta_q[i,j,k,n] for n in range(1, len(model.Area_beta_q_breakpoints[i,j,k]))) + +def area_beta_q_upper_rule(model, i, j, k): + return model.q_beta[i,j,k] <= sum(model.Area_beta_q_breakpoints[i,j,k][n+1]*model.z_area_beta_q[i,j,k,n] for n in range(1, len(model.Area_beta_q_breakpoints[i,j,k]))) + +def var_delta_reclmtd_beta_sum_rule(model, i, j, k): + reclmtd_beta_lower, _ = model.reclmtd_beta[i,j,k].bounds + return model.reclmtd_beta[i,j,k] == reclmtd_beta_lower + sum(model.var_delta_reclmtd_beta[i,j,k,n] for n in range(1, len(model.Area_beta_q_breakpoints[i,j,k]))) + +def var_delta_reclmtd_beta_upper_rule(model, i, j, k, n): + reclmtd_beta_lower, reclmtd_beta_upper = model.reclmtd_beta[i,j,k].bounds + return model.var_delta_reclmtd_beta[i,j,k,n] <= (reclmtd_beta_upper - reclmtd_beta_lower)*model.z_area_beta_q[i,j,k,n] + +########################## +def z_area_beta_q_cu_sum_rule(model, i): + return sum(model.z_area_beta_q_cu[i,n] for n in range(1, len(model.Area_beta_q_cu_breakpoints[i]))) == 1 + +def area_beta_q_cu_lower_rule(model, i): + return model.q_cu_beta[i] >= sum(model.Area_beta_q_cu_breakpoints[i][n]*model.z_area_beta_q_cu[i,n] for n in range(1, len(model.Area_beta_q_cu_breakpoints[i]))) + +def area_beta_q_cu_upper_rule(model, i): + return model.q_cu_beta[i] <= sum(model.Area_beta_q_cu_breakpoints[i][n+1]*model.z_area_beta_q_cu[i,n] for n in range(1, len(model.Area_beta_q_cu_breakpoints[i]))) + +def var_delta_reclmtd_cu_beta_sum_rule(model, i): + reclmtd_cu_beta_lower, _ = model.reclmtd_cu_beta[i].bounds + return model.reclmtd_cu_beta[i] == reclmtd_cu_beta_lower + sum(model.var_delta_reclmtd_cu_beta[i,n] for n in range(1, len(model.Area_beta_q_cu_breakpoints[i]))) + +def var_delta_reclmtd_cu_beta_upper_rule(model, i, n): + reclmtd_cu_beta_lower, reclmtd_cu_beta_upper = model.reclmtd_cu_beta[i].bounds + return model.var_delta_reclmtd_cu_beta[i,n] <= (reclmtd_cu_beta_upper - reclmtd_cu_beta_lower)*model.z_area_beta_q_cu[i,n] + +########################## +def z_area_beta_q_hu_sum_rule(model, j): + return sum(model.z_area_beta_q_hu[j,n] for n in range(1, len(model.Area_beta_q_hu_breakpoints[j]))) == 1 + +def area_beta_q_hu_lower_rule(model, j): + return model.q_hu_beta[j] >= sum(model.Area_beta_q_hu_breakpoints[j][n]*model.z_area_beta_q_hu[j,n] for n in range(1, len(model.Area_beta_q_hu_breakpoints[j]))) + +def area_beta_q_hu_upper_rule(model, j): + return model.q_hu_beta[j] <= sum(model.Area_beta_q_hu_breakpoints[j][n+1]*model.z_area_beta_q_hu[j,n] for n in range(1, len(model.Area_beta_q_hu_breakpoints[j]))) + +def var_delta_reclmtd_hu_beta_sum_rule(model, j): + reclmtd_hu_beta_lower, _ = model.reclmtd_hu_beta[j].bounds + return model.reclmtd_hu_beta[j] == reclmtd_hu_beta_lower + sum(model.var_delta_reclmtd_hu_beta[j,n] for n in range(1, len(model.Area_beta_q_hu_breakpoints[j]))) + +def var_delta_reclmtd_hu_beta_upper_rule(model, j, n): + reclmtd_hu_beta_lower, reclmtd_hu_beta_upper = model.reclmtd_hu_beta[j].bounds + return model.var_delta_reclmtd_hu_beta[j,n] <= (reclmtd_hu_beta_upper - reclmtd_hu_beta_lower)*model.z_area_beta_q_hu[j,n] + +def overall_heat_balance_hot_rule(model, i): + return ( sum(model.q[i,j,k] for j in model.CP for k in model.ST ) + model.q_cu[i] ) == model.Fh[i]*(model.Th_in[i] - model.Th_out[i]) + +def overall_heat_balance_cold_rule(model, j): + return ( sum(model.q[i,j,k] for i in model.HP for k in model.ST ) + model.q_hu[j] ) == model.Fc[j]*(model.Tc_out[j] - model.Tc_in[j]) + +def energy_balance_hot_rule(model, i, k): + return sum( model.q[i,j,k] for j in model.CP ) == model.Fh[i]*(model.th[i,k] - model.th[i,k+1]) + +def energy_balance_cold_rule(model, j, k): + return sum( model.q[i,j,k] for i in model.HP ) == model.Fc[j]*(model.tc[j,k] - model.tc[j, k+1]) + +def energy_balance_cu_rule(model, i): + return model.Fh[i]*( model.th[i,model.Number_stages+1] - model.Th_out[i] ) == model.q_cu[i] + +def energy_balance_hu_rule(model, j): + return model.Fc[j]*( model.Tc_out[j] - model.tc[j,1] ) == model.q_hu[j] + +def hot_inlet_rule(model, i): + return model.th[i, 1] == model.Th_in[i] + +def cold_inlet_rule(model, j): + return model.tc[j,model.Number_stages+1] == model.Tc_in[j] + +def mass_balance_hot_rule(model, i, k): + return sum( model.fh[i,j,k] for j in model.CP ) == model.Fh[i] + +def mass_balance_cold_rule(model, j, k): + return sum( model.fc[i,j,k] for i in model.HP ) == model.Fc[j] + +def decreasing_hot_rule(model, i, k): + return model.th[i,k+1] <= model.th[i,k] + +def decreasing_cold_rule(model, j, k): + return model.tc[j,k+1] <= model.tc[j,k] + +def hot_upper_bound_rule(model, i): + return model.th[i, model.Number_stages+1] >= model.Th_out[i] + +def cold_lower_bound_rule(model, j): + return model.tc[j,1] <= model.Tc_out[j] + +def q_big_m_rule(model, i, j, k): + return model.q[i,j,k] - model.Omega_ij[i,j]*model.z[i,j,k] <= 0 + +def q_cu_big_m_rule(model, i): + return model.q_cu[i] - model.Omega_i[i]*model.z_cu[i] <= 0 + +def q_hu_big_m_rule(model, j): + return model.q_hu[j] - model.Omega_j[j]*model.z_hu[j] <= 0 + +def temp_app_in_rule(model, i, j, k): + return model.dt[i,j,k] <= model.th[i,k] - model.tc[j,k] + model.Gamma[i,j]*(1 - model.z[i,j,k]) + +def temp_app_out_rule(model, i, j, k): + return model.dt[i,j,k+1] <= model.th[i,k+1] - model.tc[j,k+1] + model.Gamma[i,j]*(1 - model.z[i,j,k]) + +def temp_app_cu_rule(model, i): + return model.dt_cu[i] <= model.th[i,model.Number_stages + 1] - model.T_cu_out + +def temp_app_hu_rule(model, j): + return model.dt_hu[j] <= model.T_hu_out - model.tc[j,1] + +def mccor_convex_h_in_1_rule(model, i, j, k): + return model.bh_in[i,j,k] >=\ + sum(model.Th_breakpoints[i,k][n]*model.var_delta_fh[i,j,k,n] \ + for n in range(1, len(model.Th_breakpoints[i,k]))) + +def mccor_convex_h_in_2_rule(model, i, j, k): + return model.bh_in[i,j,k] >=\ + model.th[i,k]*model.Fh[i] +\ + sum(model.Th_breakpoints[i,k][n+1]*\ + (model.var_delta_fh[i,j,k,n] - model.Fh[i]*model.z_th[i,k,n]) \ + for n in range(1, len(model.Th_breakpoints[i,k]))) + +def mccor_concave_h_in_1_rule(model, i, j, k): + return model.bh_in[i,j,k] <=\ + sum(model.Th_breakpoints[i,k][n+1]*model.var_delta_fh[i,j,k,n] \ + for n in range(1, len(model.Th_breakpoints[i,k]))) + +def mccor_concave_h_in_2_rule(model, i, j, k): + return model.bh_in[i,j,k] <=\ + model.th[i,k]*model.Fh[i] +\ + sum(model.Th_breakpoints[i,k][n]*\ + (model.var_delta_fh[i,j,k,n] - model.Fh[i]*model.z_th[i,k,n]) \ + for n in range(1, len(model.Th_breakpoints[i,k]))) + +def mccor_convex_h_out_1_rule(model, i, j, k): + return model.bh_out[i,j,k] >= \ + sum(model.Thx_breakpoints[i,j,k][n]*model.var_delta_fhx[i,j,k,n] \ + for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def mccor_convex_h_out_2_rule(model, i, j, k): + return model.bh_out[i,j,k] >= \ + model.thx[i,j,k]*model.Fh[i] +\ + sum(model.Thx_breakpoints[i,j,k][n+1]*\ + (model.var_delta_fhx[i,j,k,n] - model.Fh[i]*model.z_thx[i,j,k,n]) \ + for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def mccor_concave_h_out_1_rule(model, i, j, k): + return model.bh_out[i,j,k] <= \ + sum(model.Thx_breakpoints[i,j,k][n+1]*model.var_delta_fhx[i,j,k,n] \ + for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def mccor_concave_h_out_2_rule(model, i, j, k): + return model.bh_out[i,j,k] <= \ + model.thx[i,j,k]*model.Fh[i] +\ + sum(model.Thx_breakpoints[i,j,k][n]*\ + (model.var_delta_fhx[i,j,k,n] - model.Fh[i]*model.z_thx[i,j,k,n]) \ + for n in range(1, len(model.Thx_breakpoints[i,j,k]))) + +def mccor_convex_c_in_1_rule(model, i, j, k): + return model.bc_in[i,j,k] >=\ + sum(model.Tc_breakpoints[j,k+1][n]*model.var_delta_fc[i,j,k,n] \ + for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def mccor_convex_c_in_2_rule(model, i, j, k): + return model.bc_in[i,j,k] >= \ + model.tc[j,k+1]*model.Fc[j] + \ + sum(model.Tc_breakpoints[j,k+1][n+1]*\ + (model.var_delta_fc[i,j,k,n] - model.Fc[j]*model.z_tc[j,k+1,n]) \ + for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def mccor_concave_c_in_1_rule(model, i, j, k): + return model.bc_in[i,j,k] <= \ + sum(model.Tc_breakpoints[j,k+1][n+1]*model.var_delta_fc[i,j,k,n] \ + for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def mccor_concave_c_in_2_rule(model, i, j, k): + return model.bc_in[i,j,k] <= \ + model.tc[j,k+1]*model.Fc[j] + \ + sum(model.Tc_breakpoints[j,k+1][n]*\ + (model.var_delta_fc[i,j,k,n] - model.Fc[j]*model.z_tc[j,k+1,n]) \ + for n in range(1, len(model.Tc_breakpoints[j,k+1]))) + +def mccor_convex_c_out_1_rule(model, i, j, k): + return model.bc_out[i,j,k] >= \ + sum(model.Tcx_breakpoints[i,j,k][n]*model.var_delta_fcx[i,j,k,n] \ + for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def mccor_convex_c_out_2_rule(model, i, j, k): + return model.bc_out[i,j,k] >= \ + model.tcx[i,j,k]*model.Fc[j] + \ + sum(model.Tcx_breakpoints[i,j,k][n+1]*\ + (model.var_delta_fcx[i,j,k,n] - model.Fc[j]*model.z_tcx[i,j,k,n]) \ + for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def mccor_concave_c_out_1_rule(model, i, j, k): + return model.bc_out[i,j,k] <= \ + sum(model.Tcx_breakpoints[i,j,k][n+1]*model.var_delta_fcx[i,j,k,n] \ + for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def mccor_concave_c_out_2_rule(model, i, j, k): + return model.bc_out[i,j,k] <= \ + model.tcx[i,j,k]*model.Fc[j] + \ + sum(model.Tcx_breakpoints[i,j,k][n]*\ + (model.var_delta_fcx[i,j,k,n] - model.Fc[j]*model.z_tcx[i,j,k,n])\ + for n in range(1, len(model.Tcx_breakpoints[i,j,k]))) + +def mixer_energy_balance_hot_rule(model, i, k): + return model.Fh[i]*model.th[i,k+1] == sum( model.bh_out[i,j,k] for j in model.CP) + +def mixer_energy_balance_cold_rule(model, j, k): + return model.Fc[j]*model.tc[j,k] == sum( model.bc_out[i,j,k] for i in model.HP) + +def q_energy_balance_hot_rule(model, i, j, k): + return model.q[i,j,k] == (model.bh_in[i,j,k] - model.bh_out[i,j,k]) + +def q_energy_balance_cold_rule(model, i, j, k): + return model.q[i,j,k] == (model.bc_out[i,j,k] - model.bc_in[i,j,k]) + +def z_q_beta_sum_rule(model, i, j, k): + return sum( model.z_q_beta[i,j,k,m] for m in range(1,len(model.Q_beta_breakpoints[i,j,k]))) == 1 + +def q_low_rule(model, i, j, k): + if model.Beta == 1: + return Constraint.Feasible + else: + q_lower = sum(model.z_q_beta[i,j,k,m]*model.Q_beta_breakpoints[i,j,k][m] \ + for m in range(1,len(model.Q_beta_breakpoints[i,j,k]))) + return model.q[i,j,k] >= q_lower + +def q_high_rule(model, i, j, k): + if model.Beta == 1: + return Constraint.Feasible + else: + q_upper = sum(model.z_q_beta[i,j,k,m]*model.Q_beta_breakpoints[i,j,k][m+1] \ + for m in range(1, len(model.Q_beta_breakpoints[i,j,k]))) + return model.q[i,j,k] <= q_upper + +def q_pow_beta_rule(model, i, j, k): + if model.Beta == 1: + return model.q_beta[i,j,k] == model.q[i,j,k] + else: + q_lower = sum(model.z_q_beta[i,j,k,m]*model.Q_beta_breakpoints[i,j,k][m] \ + for m in range(1, len(model.Q_beta_breakpoints[i,j,k]))) + q_exp_lower = sum(model.z_q_beta[i,j,k,m]*model.Q_beta_exp[i,j,k][m] \ + for m in range(1, len(model.Q_beta_breakpoints[i,j,k]))) + gradient = sum(model.z_q_beta[i,j,k,m]*model.Q_beta_gradients[i,j,k][m] \ + for m in range(1, len(model.Q_beta_breakpoints[i,j,k]))) + return model.q_beta[i,j,k] >= q_exp_lower + gradient*(model.q[i,j,k] - q_lower) + +def z_q_cu_beta_sum_rule(model, i): + return sum( model.z_q_cu_beta[i,m] for m in range(1, len(model.Q_cu_beta_breakpoints[i]))) == 1 + +def q_cu_low_rule(model, i): + if model.Beta == 1: + return Constraint.Feasible + else: + q_cu_lower = sum(model.z_q_cu_beta[i,m]*model.Q_cu_beta_breakpoints[i][m] \ + for m in range(1, len(model.Q_cu_beta_breakpoints[i]))) + return model.q_cu[i] >= q_cu_lower + +def q_cu_high_rule(model, i): + if model.Beta == 1: + return Constraint.Feasible + else: + q_cu_upper = sum(model.z_q_cu_beta[i,m]*model.Q_cu_beta_breakpoints[i][m+1] \ + for m in range(1, len(model.Q_cu_beta_breakpoints[i]))) + return model.q_cu[i] <= q_cu_upper + +def q_cu_pow_beta_rule(model, i): + if model.Beta == 1: + return model.q_cu_beta[i] == model.q_cu[i] + else: + q_cu_lower = sum(model.z_q_cu_beta[i,m]*model.Q_cu_beta_breakpoints[i][m] \ + for m in range(1, len(model.Q_cu_beta_breakpoints[i]))) + q_cu_exp_lower = sum(model.z_q_cu_beta[i,m]*model.Q_cu_beta_exp[i][m] \ + for m in range(1, len(model.Q_cu_beta_breakpoints[i]))) + gradient = sum(model.z_q_cu_beta[i,m]*model.Q_cu_beta_gradients[i][m] \ + for m in range(1, len(model.Q_cu_beta_breakpoints[i]))) + return model.q_cu_beta[i] >= q_cu_exp_lower + gradient*(model.q_cu[i] - q_cu_lower) + +def z_q_hu_beta_sum_rule(model, j): + return sum( model.z_q_hu_beta[j,m] for m in range(1, len(model.Q_hu_beta_breakpoints[j]))) == 1 + +def q_hu_low_rule(model, j): + if model.Beta == 1: + return Constraint.Feasible + else: + q_hu_lower = sum(model.z_q_hu_beta[j,m]*model.Q_hu_beta_breakpoints[j][m] \ + for m in range(1, len(model.Q_hu_beta_breakpoints[j]))) + return model.q_hu[j] >= q_hu_lower + +def q_hu_high_rule(model, j): + if model.Beta == 1: + return Constraint.Feasible + else: + q_hu_upper = sum(model.z_q_hu_beta[j,m]*model.Q_hu_beta_breakpoints[j][m+1] \ + for m in range(1, len(model.Q_hu_beta_breakpoints[j]))) + return model.q_hu[j] <= q_hu_upper + +def q_hu_pow_beta_rule(model, j): + if model.Beta == 1: + return model.q_hu_beta[j] == model.q_hu[j] + else: + q_hu_lower = sum(model.z_q_hu_beta[j,m]*model.Q_hu_beta_breakpoints[j][m] \ + for m in range(1, len(model.Q_hu_beta_breakpoints[j]))) + q_hu_exp_lower = sum(model.z_q_hu_beta[j,m]*model.Q_hu_beta_exp[j][m] \ + for m in range(1, len(model.Q_hu_beta_breakpoints[j]))) + gradient = sum(model.z_q_hu_beta[j,m]*model.Q_hu_beta_gradients[j][m] \ + for m in range(1, len(model.Q_hu_beta_breakpoints[j]))) + return model.q_hu_beta[j] >= q_hu_exp_lower + gradient*(model.q_hu[j] - q_hu_lower) + +# LMTD Beta +def grad_reclmtd_beta_rule(model, i, j, k, x0, y0): + if x0 <= 0 or y0 <= 0: + return Constraint.Feasible + gradients = lmtd_inverse_beta_gradient_calculator(x0, y0, model.Beta) + return model.reclmtd_beta[i,j,k] >= lmtd_inv_beta(x0, y0, model.Beta) + gradients[0]*(model.dt[i,j,k] - x0) + gradients[1]*(model.dt[i,j,k+1] - y0) + +def grad_reclmtd_cu_beta_rule(model, i, x0): + y0 = model.Th_out[i] - model.T_cu_in + gradients = lmtd_inverse_beta_gradient_calculator(x0, y0, model.Beta) + return model.reclmtd_cu_beta[i] >= lmtd_inv_beta(x0, y0, model.Beta) + gradients[0]*(model.dt_cu[i] - x0) + +def grad_reclmtd_hu_beta_rule(model, j, x0): + y0 = model.T_hu_in - model.Tc_out[j] + gradients = lmtd_inverse_beta_gradient_calculator(x0, y0, model.Beta) + return model.reclmtd_hu_beta[j] >= lmtd_inv_beta(x0, y0, model.Beta) + gradients[0]*(model.dt_hu[j] - x0) + +# Area to the beta-th power McCormick +def area_beta_mccor_convex_1_rule(model, i, j, k): + reclmtd_beta_lower, _ = model.reclmtd_beta[i,j,k].bounds + return model.area_beta[i,j,k] >= \ + model.U_beta[i,j]*(\ + model.q_beta[i,j,k]*reclmtd_beta_lower +\ + sum( \ + model.Area_beta_q_breakpoints[i,j,k][n]*model.var_delta_reclmtd_beta[i,j,k,n] \ + for n in range(1, len(model.Area_beta_q_breakpoints[i,j,k]))) \ + ) + +def area_beta_mccor_convex_2_rule(model, i, j, k): + reclmtd_beta_lower, reclmtd_beta_upper = model.reclmtd_beta[i,j,k].bounds + return model.area_beta[i,j,k] >= \ + model.U_beta[i,j]*(\ + model.q_beta[i,j,k]*reclmtd_beta_upper + \ + sum( \ + model.Area_beta_q_breakpoints[i,j,k][n+1]* \ + (model.var_delta_reclmtd_beta[i,j,k,n] - (reclmtd_beta_upper - reclmtd_beta_lower)*model.z_area_beta_q[i,j,k,n]) \ + for n in range(1, len(model.Area_beta_q_breakpoints[i,j,k]))) \ + ) + +def area_beta_mccor_concave_1_rule(model, i, j, k): + reclmtd_beta_lower, _ = model.reclmtd_beta[i,j,k].bounds + return model.area_beta[i,j,k] <= \ + model.U_beta[i,j]*( \ + model.q_beta[i,j,k]*reclmtd_beta_lower + \ + sum( \ + model.Area_beta_q_breakpoints[i,j,k][n+1]* \ + model.var_delta_reclmtd_beta[i,j,k,n] \ + for n in range(1, len(model.Area_beta_q_breakpoints[i,j,k]))) \ + ) + +def area_beta_mccor_concave_2_rule(model, i, j, k): + reclmtd_beta_lower, reclmtd_beta_upper = model.reclmtd_beta[i,j,k].bounds + return model.area_beta[i,j,k] <= \ + model.U_beta[i,j]*( \ + model.q_beta[i,j,k]*reclmtd_beta_upper + + sum( \ + model.Area_beta_q_breakpoints[i,j,k][n]* \ + (model.var_delta_reclmtd_beta[i,j,k,n] - (reclmtd_beta_upper - reclmtd_beta_lower)*model.z_area_beta_q[i,j,k,n]) \ + for n in range(1, len(model.Area_beta_q_breakpoints[i,j,k]))) \ + ) + +def area_cu_beta_mccor_convex_1_rule(model, i): + reclmtd_cu_beta_lower, _ = model.reclmtd_cu_beta[i].bounds + return model.area_cu_beta[i] >= \ + model.U_cu_beta[i]*(\ + model.q_cu_beta[i]*reclmtd_cu_beta_lower +\ + sum( \ + model.Area_beta_q_cu_breakpoints[i][n]*model.var_delta_reclmtd_cu_beta[i,n] \ + for n in range(1, len(model.Area_beta_q_cu_breakpoints[i]))) \ + ) + +def area_cu_beta_mccor_convex_2_rule(model, i): + reclmtd_cu_beta_lower, reclmtd_cu_beta_upper = model.reclmtd_cu_beta[i].bounds + return model.area_cu_beta[i] >= \ + model.U_cu_beta[i]*(\ + model.q_cu_beta[i]*reclmtd_cu_beta_upper + \ + sum( \ + model.Area_beta_q_cu_breakpoints[i][n+1]* \ + (model.var_delta_reclmtd_cu_beta[i,n] - (reclmtd_cu_beta_upper - reclmtd_cu_beta_lower)*model.z_area_beta_q_cu[i,n]) \ + for n in range(1, len(model.Area_beta_q_cu_breakpoints[i]))) \ + ) + +def area_cu_beta_mccor_concave_1_rule(model, i): + reclmtd_cu_beta_lower, _ = model.reclmtd_cu_beta[i].bounds + return model.area_cu_beta[i] <= \ + model.U_cu_beta[i]*( \ + model.q_cu_beta[i]*reclmtd_cu_beta_lower + \ + sum( \ + model.Area_beta_q_cu_breakpoints[i][n+1]* \ + model.var_delta_reclmtd_cu_beta[i,n] \ + for n in range(1, len(model.Area_beta_q_cu_breakpoints[i]))) \ + ) + +def area_cu_beta_mccor_concave_2_rule(model, i): + reclmtd_cu_beta_lower, reclmtd_cu_beta_upper = model.reclmtd_cu_beta[i].bounds + return model.area_cu_beta[i] <= \ + model.U_cu_beta[i]*( \ + model.q_cu_beta[i]*reclmtd_cu_beta_upper + + sum( \ + model.Area_beta_q_cu_breakpoints[i][n]* \ + (model.var_delta_reclmtd_cu_beta[i,n] - (reclmtd_cu_beta_upper - reclmtd_cu_beta_lower)*model.z_area_beta_q_cu[i,n]) \ + for n in range(1, len(model.Area_beta_q_cu_breakpoints[i]))) \ + ) + +def area_hu_beta_mccor_convex_1_rule(model, j): + reclmtd_hu_beta_lower, _ = model.reclmtd_hu_beta[j].bounds + return model.area_hu_beta[j] >= \ + model.U_hu_beta[j]*(\ + model.q_hu_beta[j]*reclmtd_hu_beta_lower +\ + sum( \ + model.Area_beta_q_hu_breakpoints[j][n]*model.var_delta_reclmtd_hu_beta[j,n] \ + for n in range(1, len(model.Area_beta_q_hu_breakpoints[j]))) \ + ) + +def area_hu_beta_mccor_convex_2_rule(model, j): + reclmtd_hu_beta_lower, reclmtd_hu_beta_upper = model.reclmtd_hu_beta[j].bounds + return model.area_hu_beta[j] >= \ + model.U_hu_beta[j]*(\ + model.q_hu_beta[j]*reclmtd_hu_beta_upper + \ + sum( \ + model.Area_beta_q_hu_breakpoints[j][n+1]* \ + (model.var_delta_reclmtd_hu_beta[j,n] - (reclmtd_hu_beta_upper - reclmtd_hu_beta_lower)*model.z_area_beta_q_hu[j,n]) \ + for n in range(1, len(model.Area_beta_q_hu_breakpoints[j]))) \ + ) + +def area_hu_beta_mccor_concave_1_rule(model, j): + reclmtd_hu_beta_lower, _ = model.reclmtd_hu_beta[j].bounds + return model.area_hu_beta[j] <= \ + model.U_hu_beta[j]*( \ + model.q_hu_beta[j]*reclmtd_hu_beta_lower + \ + sum( \ + model.Area_beta_q_hu_breakpoints[j][n+1]* \ + model.var_delta_reclmtd_hu_beta[j,n] \ + for n in range(1, len(model.Area_beta_q_hu_breakpoints[j]))) \ + ) + +def area_hu_beta_mccor_concave_2_rule(model, j): + reclmtd_hu_beta_lower, reclmtd_hu_beta_upper = model.reclmtd_hu_beta[j].bounds + return model.area_hu_beta[j] <= \ + model.U_hu_beta[j]*( \ + model.q_hu_beta[j]*reclmtd_hu_beta_upper + + sum( \ + model.Area_beta_q_hu_breakpoints[j][n]* \ + (model.var_delta_reclmtd_hu_beta[j,n] - (reclmtd_hu_beta_upper - reclmtd_hu_beta_lower)*model.z_area_beta_q_hu[j,n]) \ + for n in range(1, len(model.Area_beta_q_hu_breakpoints[j]))) \ + ) + +############################################ +############### Z Constraint ############### +############################################ +def z_active_rule(model, i, j, k): + # activeSet = [(1,1,2), (2,1,1), (2,2,1), (3, 5, 2), (4,3,2), (5,4,1)] + active_set = [(1,1,2), (2,1,1), (2,2,1), (3, 5, 1), (4,3,1), (5,4,1)] + if (i,j,k) in active_set: + return model.z[i,j,k] == 1 + else: + return model.z[i,j,k] == 0 + +def z_cu_active_rule(model, i): + # active_set = [2,3,5] + # return Constraint.Feasible + active_set = [1,3,5] + if i in active_set: + return model.z_cu[i] == 1 + else: + return model.z_cu[i] == 0 + +def z_hu_active_rule(model, j): + # return Constraint.Skip + active_set = [] + if j in active_set: + return model.z_hu[j] == 1 + else: + return model.z_hu[j] == 0 diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/constraints.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/constraints.py new file mode 100644 index 0000000..1a08a20 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/constraints.py @@ -0,0 +1,158 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.constraint import Constraint + +from .index_generators import * +from .constraint_rules import * + +def declare_constraints(model): + model.z_th_sum = Constraint(model.HP, model.ST, rule=z_th_sum_rule) + model.th_lower = Constraint(model.HP, model.ST, rule=th_lower_rule) + model.th_upper = Constraint(model.HP, model.ST, rule=th_upper_rule) + + model.var_delta_fh_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_fh_sum_rule) + model.var_delta_fh_upper = Constraint(var_delta_fh_index, rule=var_delta_fh_upper_rule) + + model.z_thx_sum = Constraint(model.HP, model.CP, model.ST, rule=z_thx_sum_rule) + model.thx_lower = Constraint(model.HP, model.CP, model.ST, rule=thx_lower_rule) + model.thx_upper = Constraint(model.HP, model.CP, model.ST, rule=thx_upper_rule) + + model.var_delta_fhx_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_fhx_sum_rule) + model.var_delta_fhx_upper = Constraint(var_delta_fhx_index, rule=var_delta_fhx_upper_rule) + + model.z_tc_sum = Constraint(model.CP, model.ST, rule=z_tc_sum_rule) + model.tc_lower = Constraint(model.CP, model.ST, rule=tc_lower_rule) + model.tc_upper = Constraint(model.CP, model.ST, rule=tc_upper_rule) + + model.var_delta_fc_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_fc_sum_rule) + model.var_delta_fc_upper = Constraint(var_delta_fc_index, rule=var_delta_fc_upper_rule) + + model.z_tcx_sum = Constraint(model.HP, model.CP, model.ST, rule=z_tcx_sum_rule) + model.tcx_lower = Constraint(model.HP, model.CP, model.ST, rule=tcx_lower_rule) + model.tcx_upper = Constraint(model.HP, model.CP, model.ST, rule=tcx_upper_rule) + + model.var_delta_fcx_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_fcx_sum_rule) + model.var_delta_fcx_upper = Constraint(var_delta_fcx_index, rule=var_delta_fcx_upper_rule) + + # Overall heat balance + model.overall_heat_balance_hot = Constraint(model.HP, rule=overall_heat_balance_hot_rule) + model.overall_heat_balance_cold = Constraint(model.CP, rule=overall_heat_balance_cold_rule) + + model.energy_balance_hot = Constraint(model.HP, model.ST, rule=energy_balance_hot_rule, doc="Energy exchanged by hot stream i in stage k" ) + model.energy_balance_cold = Constraint(model.CP, model.ST, rule=energy_balance_cold_rule, doc="Energy exchanged by cold stream j in stage k" ) + model.energy_balance_cu = Constraint(model.HP, rule=energy_balance_cu_rule, doc="Energy exchanged by hot stream i with the cold utility" ) + model.energy_balance_hu = Constraint(model.CP, rule=energy_balance_hu_rule, doc="Energy exchanged by cold stream j with the hot utility" ) + + # Inlet temperatures + model.hot_inlet = Constraint(model.HP, rule=hot_inlet_rule) + model.cold_inlet = Constraint(model.CP, rule=cold_inlet_rule) + + # Mass balance + model.mass_balance_hot = Constraint(model.HP, model.ST, rule=mass_balance_hot_rule) + model.mass_balance_cold = Constraint(model.CP, model.ST, rule=mass_balance_cold_rule) + + # Monotonicity + model.decreasing_hot = Constraint(model.HP, model.ST, rule=decreasing_hot_rule) + model.decreasing_cold = Constraint(model.CP, model.ST, rule=decreasing_cold_rule) + model.hot_upper_bound = Constraint(model.HP, rule=hot_upper_bound_rule) + model.cold_lower_bound = Constraint(model.CP, rule=cold_lower_bound_rule) + + # Heat load big M + model.q_big_m = Constraint(model.HP, model.CP, model.ST, rule=q_big_m_rule) + model.q_cu_big_m = Constraint(model.HP, rule=q_cu_big_m_rule) + model.q_hu_big_m = Constraint(model.CP, rule=q_hu_big_m_rule) + + # Temperature approach big M + model.temp_app_in = Constraint(model.HP, model.CP, model.ST, rule=temp_app_in_rule) + model.temp_app_out = Constraint(model.HP, model.CP, model.ST, rule=temp_app_out_rule) + model.temp_app_cu = Constraint(model.HP, rule=temp_app_cu_rule) + model.temp_app_hu = Constraint(model.CP, rule=temp_app_hu_rule) + + # Bilinear McCormick bounds + model.mccor_convex_h_in_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_h_in_1_rule) + model.mccor_convex_h_in_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_h_in_2_rule) + model.mccor_concave_h_in_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_h_in_1_rule) + model.mccor_concave_h_in_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_h_in_2_rule) + + model.mccor_convex_h_out_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_h_out_1_rule) + model.mccor_convex_h_out_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_h_out_2_rule) + model.mccor_concave_h_out_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_h_out_1_rule) + model.mccor_concave_h_out_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_h_out_2_rule) + + model.mccor_convex_c_in_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_c_in_1_rule) + model.mccor_convex_c_in_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_c_in_2_rule) + model.mccor_concave_c_in_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_c_in_1_rule) + model.mccor_concave_c_in_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_c_in_2_rule) + + model.mccor_convex_c_out_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_c_out_1_rule) + model.mccor_convex_c_out_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_convex_c_out_2_rule) + model.mccor_concave_c_out_1 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_c_out_1_rule) + model.mccor_concave_c_out_2 = Constraint(model.HP, model.CP, model.ST, rule=mccor_concave_c_out_2_rule) + + # q-betas + model.z_q_beta_sum = Constraint(model.HP, model.CP, model.ST, rule=z_q_beta_sum_rule) + model.q_low = Constraint(model.HP, model.CP, model.ST, rule=q_low_rule) + model.q_high = Constraint(model.HP, model.CP, model.ST, rule=q_high_rule) + model.q_pow_beta = Constraint(model.HP, model.CP, model.ST, rule=q_pow_beta_rule) + + model.z_q_cu_beta_sum = Constraint(model.HP, rule=z_q_cu_beta_sum_rule) + model.q_cu_low = Constraint(model.HP, rule=q_cu_low_rule) + model.q_cu_high = Constraint(model.HP, rule=q_cu_high_rule) + model.q_cu_pow_beta = Constraint(model.HP, rule=q_cu_pow_beta_rule) + + model.z_q_hu_beta_sum = Constraint(model.CP, rule=z_q_hu_beta_sum_rule) + model.q_hu_low = Constraint(model.CP, rule=q_hu_low_rule) + model.q_hu_high = Constraint(model.CP, rule=q_hu_high_rule) + model.q_hu_pow_beta = Constraint(model.CP, rule=q_hu_pow_beta_rule) + + #Per heat exchanger energy balance + model.q_energy_balance_hot = Constraint(model.HP, model.CP, model.ST, rule=q_energy_balance_hot_rule) + model.q_energy_balance_cold = Constraint(model.HP, model.CP, model.ST, rule=q_energy_balance_cold_rule) + + #Per mixer energy balance + model.mixer_energy_balance_hot = Constraint(model.HP, model.ST, rule=mixer_energy_balance_hot_rule) + model.mixer_energy_balance_cold = Constraint(model.CP, model.ST, rule=mixer_energy_balance_cold_rule) + + # RecLMTD to the beta-th power + model.grad_reclmtd_beta = Constraint(reclmtd_beta_index, rule=grad_reclmtd_beta_rule) + model.grad_reclmtd_cu_beta = Constraint(reclmtd_cu_beta_index, rule=grad_reclmtd_cu_beta_rule) + model.grad_reclmtd_hu_beta = Constraint(reclmtd_hu_beta_index, rule=grad_reclmtd_hu_beta_rule) + + # Area to the beta-th powers + model.z_area_beta_q_sum = Constraint(model.HP, model.CP, model.ST, rule=z_area_beta_q_sum_rule) + model.area_beta_q_lower = Constraint(model.HP, model.CP, model.ST, rule=area_beta_q_lower_rule) + model.area_beta_q_upper = Constraint(model.HP, model.CP, model.ST, rule=area_beta_q_upper_rule) + model.var_delta_reclmtd_beta_sum = Constraint(model.HP, model.CP, model.ST, rule=var_delta_reclmtd_beta_sum_rule) + model.var_delta_reclmtd_beta_upper = Constraint(z_area_beta_q_index, rule=var_delta_reclmtd_beta_upper_rule) + + model.area_beta_mccor_convex_1 = Constraint(model.HP, model.CP, model.ST, rule=area_beta_mccor_convex_1_rule) + model.area_beta_mccor_convex_2 = Constraint(model.HP, model.CP, model.ST, rule=area_beta_mccor_convex_2_rule) + model.area_beta_mccor_concave_1 = Constraint(model.HP, model.CP, model.ST, rule=area_beta_mccor_concave_1_rule) + model.area_beta_mccor_concave_2 = Constraint(model.HP, model.CP, model.ST, rule=area_beta_mccor_concave_2_rule) + + model.z_area_beta_q_cu_sum = Constraint(model.HP, rule=z_area_beta_q_cu_sum_rule) + model.area_beta_q_cu_lower = Constraint(model.HP, rule=area_beta_q_cu_lower_rule) + model.area_beta_q_cu_upper = Constraint(model.HP, rule=area_beta_q_cu_upper_rule) + model.var_delta_reclmtd_cu_beta_sum = Constraint(model.HP, rule=var_delta_reclmtd_cu_beta_sum_rule) + model.var_delta_reclmtd_cu_beta_upper = Constraint(z_area_beta_q_cu_index, rule=var_delta_reclmtd_cu_beta_upper_rule) + + model.area_cu_beta_mccor_convex_1 = Constraint(model.HP, rule=area_cu_beta_mccor_convex_1_rule) + model.area_cu_beta_mccor_convex_2 = Constraint(model.HP, rule=area_cu_beta_mccor_convex_2_rule) + model.area_cu_beta_mccor_concave_1 = Constraint(model.HP, rule=area_cu_beta_mccor_concave_1_rule) + model.area_cu_beta_mccor_concave_2 = Constraint(model.HP, rule=area_cu_beta_mccor_concave_2_rule) + + model.z_area_beta_q_hu_sum = Constraint(model.CP, rule=z_area_beta_q_hu_sum_rule) + model.area_beta_q_hu_lower = Constraint(model.CP, rule=area_beta_q_hu_lower_rule) + model.area_beta_q_hu_upper = Constraint(model.CP, rule=area_beta_q_hu_upper_rule) + model.var_delta_reclmtd_hu_beta_sum = Constraint(model.CP, rule=var_delta_reclmtd_hu_beta_sum_rule) + model.var_delta_reclmtd_hu_beta_upper = Constraint(z_area_beta_q_hu_index, rule=var_delta_reclmtd_hu_beta_upper_rule) + + model.area_hu_beta_mccor_convex_1 = Constraint(model.CP, rule=area_hu_beta_mccor_convex_1_rule) + model.area_hu_beta_mccor_convex_2 = Constraint(model.CP, rule=area_hu_beta_mccor_convex_2_rule) + model.area_hu_beta_mccor_concave_1 = Constraint(model.CP, rule=area_hu_beta_mccor_concave_1_rule) + model.area_hu_beta_mccor_concave_2 = Constraint(model.CP, rule=area_hu_beta_mccor_concave_2_rule) + + # model.z_active = Constraint(model.HP, model.CP, model.ST, rule=z_active_rule) + # model.z_cu_active = Constraint(model.HP, rule=z_cu_active_rule) + # model.z_hu_active = Constraint(model.CP, rule=z_hu_active_rule) diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/helper_functions.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/helper_functions.py new file mode 100644 index 0000000..9df9e38 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/helper_functions.py @@ -0,0 +1,50 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from math import log + +def two_point_generator(points, bounds): + lower, upper = bounds + ret_set = [] + for pa, pb in points: + x = lower*pa + upper*pb + ret_set.append(x) + return ret_set + +def three_point_generator(points, bounds): + lower, upper = bounds + ax, ay = lower, lower + bx, by = upper, upper + cx, cy = upper, lower + ret_set = [] + for pa, pb, pc in points: + x0 = ax*pa + bx*pb + cx*pc + y0 = ay*pa + by*pb + cy*pc + ret_set.append((x0,y0)) + if not x0 == y0: + ret_set.append((y0,x0)) + return ret_set + +def lmtd_inv(x, y): + return log(x/y)/(x-y) if (x != y) else 1/x + +def lmtd_inv_beta(x, y, beta): + lmtd_inv_val = lmtd_inv(x,y) + return lmtd_inv_val if (beta == 1) else pow(lmtd_inv_val, beta) + +def lmtd_inverse_gradient_calculator(x0, y0): + if x0 == y0: + return (-1/(2*pow(x0,2)),-1/(2*pow(y0,2))) + else: + w = x0/y0 + scale = 1/(pow((x0-y0),2)) + return (scale*(1-(1/w)-log(w)), scale*(1+log(w)-w)) + +def lmtd_inverse_beta_gradient_calculator(x0, y0, beta): + if x0 == y0: + value = -beta/(2*pow(x0, beta+1)) + return (value,value) + else: + w = x0/y0 + scale = (beta/(pow((x0-y0),2)))*pow(log(w)/(x0-y0), beta-1) + return (scale*(1-log(w)-(1/w)), scale*(1+log(w)-w)) diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/index_generators.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/index_generators.py new file mode 100644 index 0000000..23856d6 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/index_generators.py @@ -0,0 +1,141 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +def z_th_index(model): + for i in model.HP: + for k in model.ST: + for point in range(1, len(model.Th_breakpoints[i,k])): + yield (i,k, point) + +z_th_index.dimen = 3 + +def z_thx_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Thx_breakpoints[i,j,k])): + yield (i,j,k,point) + +z_thx_index.dimen = 4 + +def z_tc_index(model): + for j in model.CP: + for k in model.K_Take_First_Stage: + for point in range(1, len(model.Tc_breakpoints[j,k])): + yield (j,k, point) + +z_tc_index.dimen = 3 + +def z_tcx_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Tcx_breakpoints[i,j,k])): + yield (i,j,k,point) + +z_tcx_index.dimen = 4 + +def var_delta_fh_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Th_breakpoints[i,k])): + yield (i,j,k, point) + +var_delta_fh_index.dimen = 4 + +def var_delta_fhx_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Thx_breakpoints[i,j,k])): + yield (i,j,k, point) + +var_delta_fhx_index.dimen = 4 + +def var_delta_fc_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Tc_breakpoints[j,k+1])): + yield (i,j,k, point) + +var_delta_fc_index.dimen = 4 + +def var_delta_fcx_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Tcx_breakpoints[i,j,k])): + yield (i,j,k, point) + +var_delta_fcx_index.dimen = 4 + +def reclmtd_beta_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in model.Reclmtd_beta_gradient_points[i,j,k]: + yield (i,j,k) + point + +reclmtd_beta_index.dimen = 5 + +def reclmtd_cu_beta_index(model): + for i in model.HP: + for point in model.Reclmtd_cu_beta_gradient_points[i]: + yield (i, point) + +reclmtd_cu_beta_index.dimen = 2 + +def reclmtd_hu_beta_index(model): + for j in model.CP: + for point in model.Reclmtd_hu_beta_gradient_points[j]: + yield (j, point) + +reclmtd_hu_beta_index.dimen = 2 + +def z_q_beta_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Q_beta_breakpoints[i,j,k])): + yield (i,j,k,point) + +z_q_beta_index.dimen = 4 + +def z_q_cu_beta_index(model): + for i in model.HP: + for point in range(1, len(model.Q_cu_beta_breakpoints[i])): + yield (i,point) + +z_q_cu_beta_index.dimen = 2 + +def z_q_hu_beta_index(model): + for j in model.CP: + for point in range(1, len(model.Q_hu_beta_breakpoints[j])): + yield (j,point) + +z_q_hu_beta_index.dimen = 2 + +def z_area_beta_q_index(model): + for i in model.HP: + for j in model.CP: + for k in model.ST: + for point in range(1, len(model.Area_beta_q_breakpoints[i,j,k])): + yield (i,j,k, point) + +z_area_beta_q_index.dimen = 4 + +def z_area_beta_q_cu_index(model): + for i in model.HP: + for point in range(1, len(model.Area_beta_q_cu_breakpoints[i])): + yield (i, point) + +z_area_beta_q_cu_index.dimen = 2 + +def z_area_beta_q_hu_index(model): + for j in model.CP: + for point in range(1, len(model.Area_beta_q_hu_breakpoints[j])): + yield (j, point) + +z_area_beta_q_hu_index.dimen = 2 diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/model_builder.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/model_builder.py new file mode 100644 index 0000000..1bb9179 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/model_builder.py @@ -0,0 +1,18 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.PyomoModel import AbstractModel +from pyomo.core.base.sets import Set + +from .parameters import declare_parameters +from .variables import declare_variables +from .objective import declare_objective +from .constraints import declare_constraints + +def create_model(): + model = AbstractModel() + declare_parameters(model) + declare_variables(model) + declare_objective(model) + declare_constraints(model) + return model diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/objective.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/objective.py new file mode 100644 index 0000000..251eba0 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/objective.py @@ -0,0 +1,23 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.objective import Objective + +def TAC_rule(model): + total_cu_load = sum( model.q_cu[i] for i in model.HP ) + total_hu_load = sum( model.q_hu[j] for j in model.CP ) + + total_number_of_stream_hx = sum( model.z[i,j,k] for i in model.HP for j in model.CP for k in model.ST ) + total_number_of_cu_hx = sum( model.z_cu[i] for i in model.HP ) + total_number_of_hu_hx = sum( model.z_hu[j] for j in model.CP ) + total_number_of_hx = total_number_of_stream_hx + total_number_of_cu_hx + total_number_of_hu_hx + + total_area_of_stream_hx = sum( model.area_beta[i,j,k] for i in model.HP for j in model.CP for k in model.ST ) + total_area_of_cu_hx = sum( model.area_cu_beta[i] for i in model.HP ) + total_area_of_hu_hx = sum( model.area_hu_beta[j] for j in model.CP ) + total_area_of_hx = total_area_of_stream_hx + total_area_of_cu_hx + total_area_of_hu_hx + + return model.Cost_cu*total_cu_load + model.Cost_hu*total_hu_load + model.Cost_hx*total_number_of_hx + model.Alpha*total_area_of_hx + +def declare_objective(model): + model.TAC = Objective(rule=TAC_rule) diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/parameter_initialisation_functions.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/parameter_initialisation_functions.py new file mode 100644 index 0000000..fb1d6e9 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/parameter_initialisation_functions.py @@ -0,0 +1,100 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from .bound_generators import * + +def u_init(model, i, j): + return (1/model.Hh[i]) + (1/model.Hc[j]) + +def u_cu_init(model, i): + return (1/model.Hh[i]) + (1/model.H_cu) + +def u_hu_init(model, j): + return (1/model.Hc[j]) + (1/model.H_hu) + +def u_beta_init(model, i, j): + return pow(model.U[i,j], model.Beta) + +def u_cu_beta_init(model, i): + return pow(model.U_cu[i], model.Beta) + +def u_hu_beta_init(model, j): + return pow(model.U_hu[j], model.Beta) + +def ech_init(model, i): + return model.Fh[i]*(model.Th_in[i] - model.Th_out[i]) + +def ecc_init(model, j): + return model.Fc[j]*(model.Tc_out[j] - model.Tc_in[j]) + +def omega_ij_init(model, i, j): + return min(model.Ech[i], model.Ecc[j]) + +def omega_i_init(model, i): + return model.Ech[i] + +def omega_j_init(model, j): + return model.Ecc[j] + +def gamma_init(model, i, j): + return max(\ + 0,\ + model.Tc_in[j] - model.Th_in[i],\ + model.Tc_in[j] - model.Th_out[i],\ + model.Tc_out[j] - model.Th_in[i],\ + model.Tc_out[j] - model.Th_out[i]\ + ) + +def th_breakpoints_init(model, i): + return list(th_bounds(model, i)) + +def thx_breakpoints_init(model, i, j, k): + return list(thx_bounds(model, i, j, k)) + +def tc_breakpoints_init(model, j): + return list(tc_bounds(model, j)) + +def tcx_breakpoints_init(model, i, j, k): + return list(tcx_bounds(model, i, j, k)) + +def q_beta_breakpoints_init(model, i, j, *k): + return list(q_bounds(model, i, j)) + +def q_cu_beta_breakpoints_init(model, i): + return list(q_cu_bounds(model, i)) + +def q_hu_beta_breakpoints_init(model, j): + return list(q_hu_bounds(model, j)) + +def q_beta_gradients_init(model, i, j, k): + gradients = [0]*(len(model.Q_beta_breakpoints[i,j,k])-1) + for m in range(1, len(model.Q_beta_breakpoints[i,j,k])): + numerator = model.Q_beta_exp[i,j,k][m+1] - model.Q_beta_exp[i,j,k][m] + denominator = model.Q_beta_breakpoints[i,j,k][m+1] - model.Q_beta_breakpoints[i,j,k][m] + gradients[m-1] = numerator/denominator + return gradients + +def q_cu_beta_gradients_init(model, i): + gradients = [0]*(len(model.Q_cu_beta_breakpoints[i])-1) + for m in range(1, len(model.Q_cu_beta_breakpoints[i])): + numerator = model.Q_cu_beta_exp[i][m+1] - model.Q_cu_beta_exp[i][m] + denominator = model.Q_cu_beta_breakpoints[i][m+1] - model.Q_cu_beta_breakpoints[i][m] + gradients[m-1] = numerator/denominator + return gradients + +def q_hu_beta_gradients_init(model, j): + gradients = [0]*(len(model.Q_hu_beta_breakpoints[j])-1) + for m in range(1, len(model.Q_hu_beta_breakpoints[j])): + numerator = model.Q_hu_beta_exp[j][m+1] - model.Q_hu_beta_exp[j][m] + denominator = model.Q_hu_beta_breakpoints[j][m+1] - model.Q_hu_beta_breakpoints[j][m] + gradients[m-1] = numerator/denominator + return gradients + +def area_beta_q_breakpoints_init(model, i, j, *k): + return list(q_beta_bounds(model, i, j)) + +def area_beta_q_cu_breakpoints_init(model, i): + return list(q_cu_beta_bounds(model, i)) + +def area_beta_q_hu_breakpoints_init(model, j): + return list(q_hu_beta_bounds(model, j)) diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/parameters.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/parameters.py new file mode 100644 index 0000000..5698cff --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/parameters.py @@ -0,0 +1,111 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.param import Param +from pyomo.core.base.sets import Set +from pyomo.core.base.rangeset import RangeSet +from pyomo.core.base.set_types import PositiveReals, NonNegativeReals, PositiveIntegers, PercentFraction + +from .parameter_initialisation_functions import * + +############################################################ +############################################################ +################### Assignment Functions ################### +############################################################ +############################################################ +def declare_parameters(model): + model.Alpha = Param(within=NonNegativeReals, doc="factor for area cost" ) + model.Beta = Param(within=PercentFraction , doc="exponent for the area cost" ) + model.Cost_hx = Param(within=NonNegativeReals, doc="fixed charge for exchangers" ) + model.Cost_cu = Param(within=NonNegativeReals, doc="utility cost coeffiecient for cooling utility j" ) + model.Cost_hu = Param(within=NonNegativeReals, doc="utility cost coeffiecient for heating utility k" ) + model.Delta_t_min = Param(within=NonNegativeReals, doc="minimum temperature approach" ) + + model.Number_stages = Param(within=PositiveIntegers, doc="number of stages" ) + model.Number_hot_stream = Param(within=PositiveIntegers, doc="number of hot streams" ) + model.Number_cold_stream = Param(within=PositiveIntegers, doc="number of cold streams" ) + + model.First_stage = Param(within=PositiveIntegers, default=1, doc='Index of the first stage') + model.Last_stage = Param(within=PositiveIntegers, default=model.Number_stages+1, doc='Index of the last stage' ) + + model.HP = RangeSet(1, model.Number_hot_stream, doc="set of hot process streams i" ) + model.CP = RangeSet(1, model.Number_cold_stream, doc="set of cold process streams j" ) + model.ST = RangeSet(model.First_stage, model.Number_stages, doc="set of stages in the superstructure" ) + model.K = RangeSet(model.First_stage, model.Last_stage, doc="set of temperature locations" ) + model.First_Stage_Set = RangeSet(model.First_stage, model.First_stage) + model.K_Take_First_Stage = model.K - model.First_Stage_Set + + model.Fh = Param(model.HP, doc="flow capicity of hot stream i" ) + model.Fc = Param(model.CP, doc="flow capacity of cold stream j" ) + + model.Hh = Param(model.HP, doc="heat transfer coefficient for hot stream i" ) + model.Hc = Param(model.CP, doc="heat transfer coefficient for cold stream j" ) + model.H_cu = Param( doc="heat transfer coefficient for cold utility" ) + model.H_hu = Param( doc="heat transfer coefficient for hot utility" ) + + model.Th_in = Param(model.HP, doc="inlet temperature of hot stream i" ) + model.Tc_in = Param(model.CP, doc="inlet temperature of cold stream j" ) + model.Th_out = Param(model.HP, doc="outlet temperature of hot stream i" ) + model.Tc_out = Param(model.CP, doc="outlet temperature of cold stream j" ) + + model.T_cu_in = Param(within=PositiveReals, doc="inlet temperature of cold utility" ) + model.T_cu_out = Param(within=PositiveReals, doc="outlet temperature of cold utility" ) + model.T_hu_in = Param(within=PositiveReals, doc="inlet temperature of hot utility" ) + model.T_hu_out = Param(within=PositiveReals, doc="outlet temperature of hot utility" ) + + ############################### + # Initialised Parameters # + ############################### + model.Reclmtd_beta_gradient_points = Set(model.HP, model.CP, model.ST, dimen=2, initialize=[]) + model.Reclmtd_cu_beta_gradient_points = Set(model.HP, dimen=1, initialize=[]) + model.Reclmtd_hu_beta_gradient_points = Set(model.CP, dimen=1, initialize=[]) + + model.U = Param(model.HP, model.CP, within=PositiveReals, initialize=u_init) + model.U_cu = Param(model.HP, within=PositiveReals, initialize=u_cu_init) + model.U_hu = Param(model.CP, within=PositiveReals, initialize=u_hu_init) + + model.U_beta = Param(model.HP, model.CP, within=PositiveReals, initialize=u_beta_init) + model.U_cu_beta = Param(model.HP, within=PositiveReals, initialize=u_cu_beta_init) + model.U_hu_beta = Param(model.CP, within=PositiveReals, initialize=u_hu_beta_init) + + model.Ech = Param(model.HP, within=PositiveReals, initialize=ech_init) + model.Ecc = Param(model.CP, within=PositiveReals, initialize=ecc_init) + + model.Omega_ij = Param(model.HP, model.CP, within=PositiveReals, initialize=omega_ij_init) + model.Omega_i = Param(model.HP, within=PositiveReals, initialize=omega_i_init) + model.Omega_j = Param(model.CP, within=PositiveReals, initialize=omega_j_init) + + model.Gamma = Param(model.HP, model.CP, within=NonNegativeReals, initialize=gamma_init) + + model.Th_breakpoints = Set(model.HP, model.ST, dimen=1, ordered=True, initialize=lambda model, i, k: th_breakpoints_init(model, i)) + + model.Thx_breakpoints = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=lambda model, i, j, k: thx_breakpoints_init(model, i, j, k)) + + model.Tc_breakpoints = Set(model.CP, model.K_Take_First_Stage, dimen=1, ordered=True, initialize=lambda model, j, k: tc_breakpoints_init(model, j)) + + model.Tcx_breakpoints = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=lambda model, i, j, k: tcx_breakpoints_init(model, i, j, k)) + + model.Q_beta_breakpoints = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, + initialize=lambda model, i, j, k: q_beta_breakpoints_init(model, i, j)) + model.Q_beta_exp = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, \ + initialize=lambda model, i, j, k: map(lambda q: pow(q, model.Beta), model.Q_beta_breakpoints[i,j,k])) + model.Q_beta_gradients = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, \ + initialize=q_beta_gradients_init) + + model.Q_cu_beta_breakpoints = Set(model.HP, dimen=1, ordered=True, \ + initialize=lambda model, i: q_cu_beta_breakpoints_init(model, i)) + model.Q_cu_beta_exp = Set(model.HP, dimen=1, ordered=True, \ + initialize=lambda model, i: map(lambda q: pow(q, model.Beta), model.Q_cu_beta_breakpoints[i])) + model.Q_cu_beta_gradients = Set(model.HP, dimen=1, ordered=True, \ + initialize=q_cu_beta_gradients_init) + + model.Q_hu_beta_breakpoints = Set(model.CP, dimen=1, ordered=True, \ + initialize=lambda model, j: q_hu_beta_breakpoints_init(model, j)) + model.Q_hu_beta_exp = Set(model.CP, dimen=1, ordered=True, \ + initialize=lambda model, j: map(lambda q: pow(q, model.Beta), model.Q_hu_beta_breakpoints[j])) + model.Q_hu_beta_gradients = Set(model.CP, dimen=1, ordered=True, \ + initialize=q_hu_beta_gradients_init) + + model.Area_beta_q_breakpoints = Set(model.HP, model.CP, model.ST, dimen=1, ordered=True, initialize=lambda model, i, j, k: area_beta_q_breakpoints_init(model, i, j)) + model.Area_beta_q_cu_breakpoints = Set(model.HP, dimen=1, ordered=True, initialize=lambda model, i: area_beta_q_cu_breakpoints_init(model, i)) + model.Area_beta_q_hu_breakpoints = Set(model.CP, dimen=1, ordered=True, initialize=lambda model, j: area_beta_q_hu_breakpoints_init(model, j)) diff --git a/hens/beta_adaptive_model_mixer/lib/model_declarations/variables.py b/hens/beta_adaptive_model_mixer/lib/model_declarations/variables.py new file mode 100644 index 0000000..ff83fe0 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/model_declarations/variables.py @@ -0,0 +1,104 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.core.base.var import Var +from pyomo.core.base.set_types import Binary, NonNegativeReals + +from .bound_generators import * +from .index_generators import * + +############################################################ +############################################################ +################### Assignment Functions ################### +############################################################ +############################################################ +def declare_variables(model): + model.area_beta = Var(model.HP, model.CP, model.ST, initialize = 0, domain=NonNegativeReals) + model.area_cu_beta = Var(model.HP, initialize = 0, domain=NonNegativeReals) + model.area_hu_beta = Var(model.CP, initialize = 0, domain=NonNegativeReals) + + # Flow rates + model.fh = Var(model.HP, model.CP, model.ST, bounds=fh_bounds,\ + doc="Flow rate entering heat exchanger ijk cold side" ) + model.fc = Var(model.HP, model.CP, model.ST, bounds=fc_bounds,\ + doc="Flow rate entering heat exchanger ijk hot side" ) + + # Per exchanger outlet + model.thx = Var(model.HP, model.CP, model.ST, bounds=thx_bounds,\ + doc="Outlet temperature of the heat exchanger ijk hot side" ) + model.tcx = Var(model.HP, model.CP, model.ST, bounds=tcx_bounds,\ + doc="Outlet temperature of the heat exchanger ijk cold side" ) + + # Temperature approaches + model.dt = Var(model.HP, model.CP, model.K, bounds=dt_bounds,\ + doc="Approach between i and j in location k" ) + model.dt_cu = Var(model.HP, bounds=dt_cu_bounds,\ + doc="Approach between i and the cold utility" ) + model.dt_hu = Var(model.CP, bounds=dt_hu_bounds,\ + doc="Approach between j and the hot utility" ) + + # Log mean temperature differences raised to the beta-th power + model.reclmtd_beta = Var(model.HP, model.CP, model.ST, bounds=reclmtd_beta_bounds,\ + doc="Log mean temperature difference between hot stream i and cold stream j at stage k raised to the beta-th power") + model.reclmtd_cu_beta = Var(model.HP, bounds=reclmtd_cu_beta_bounds,\ + doc="Log mean temperature difference between hot stream i and cold utility raised to the beta-th power") + model.reclmtd_hu_beta = Var(model.CP, bounds=reclmtd_hu_beta_bounds,\ + doc="Log mean temperature difference between cold stream j and hot utility raised to the beta-th power") + + # Heat loads + model.q = Var(model.HP, model.CP, model.ST, bounds=q_bounds, initialize = 0,\ + doc="heat load between hot stream i and cold stream j at stage k" ) + model.q_cu = Var(model.HP, bounds=q_cu_bounds, initialize = 0,\ + doc="heat load between hot stream i and cold utility" ) + model.q_hu = Var(model.CP, bounds=q_hu_bounds, initialize = 0,\ + doc="heat load between cold stream j and hot utility" ) + + # Heat loads to the beta-th power + model.q_beta = Var(model.HP, model.CP, model.ST, bounds=q_beta_bounds, initialize = 0,\ + doc="heat load between hot stream i and cold stream j at stage k raised to the beta-th power" ) + model.q_cu_beta = Var(model.HP, bounds=q_cu_beta_bounds, initialize = 0,\ + doc="heat load between hot stream i and cold utility raised to the beta-th power" ) + model.q_hu_beta = Var(model.CP, bounds=q_hu_beta_bounds, initialize = 0,\ + doc="heat load between cold stream j and hot utility raised to the beta-th power" ) + + # Per stage temperatures + model.th = Var(model.HP, model.K, bounds=th_bounds,\ + doc="temperature of hot stream i at hot end of stage k" ) + model.tc = Var(model.CP, model.K, bounds=tc_bounds,\ + doc="temperature of cold stream j at hot end of stage k" ) + + # Binary variables + model.z = Var(model.HP, model.CP, model.ST, initialize = 0, domain=Binary,\ + doc="existence of the match between hot stream i and cold stream j at stage k" ) + model.z_cu = Var(model.HP, initialize = 0, domain=Binary,\ + doc="existence of the match between hot stream i and cold utility" ) + model.z_hu = Var(model.CP, initialize = 0, domain=Binary,\ + doc="existence of the match between cold stream j and hot utility" ) + + model.z_q_beta = Var(z_q_beta_index, domain=Binary) + model.z_q_cu_beta = Var(z_q_cu_beta_index, domain=Binary) + model.z_q_hu_beta = Var(z_q_hu_beta_index, domain=Binary) + + model.z_area_beta_q = Var(z_area_beta_q_index, domain=Binary) + model.z_area_beta_q_cu = Var(z_area_beta_q_cu_index, domain=Binary) + model.z_area_beta_q_hu = Var(z_area_beta_q_hu_index, domain=Binary) + + model.var_delta_reclmtd_beta = Var(z_area_beta_q_index, domain=NonNegativeReals) + model.var_delta_reclmtd_cu_beta = Var(z_area_beta_q_cu_index, domain=NonNegativeReals) + model.var_delta_reclmtd_hu_beta = Var(z_area_beta_q_hu_index, domain=NonNegativeReals) + + # New variables + model.bh_in = Var(model.HP, model.CP, model.ST, bounds=bh_bounds) + model.bh_out = Var(model.HP, model.CP, model.ST, bounds=bh_bounds) + model.bc_in = Var(model.HP, model.CP, model.ST, bounds=bc_bounds) + model.bc_out = Var(model.HP, model.CP, model.ST, bounds=bc_bounds) + + model.z_th = Var(z_th_index, domain=Binary) + model.z_thx = Var(z_thx_index, domain=Binary) + model.z_tc = Var(z_tc_index, domain=Binary) + model.z_tcx = Var(z_tcx_index, domain=Binary) + + model.var_delta_fh = Var(var_delta_fh_index, domain=NonNegativeReals) + model.var_delta_fhx = Var(var_delta_fhx_index, domain=NonNegativeReals) + model.var_delta_fc = Var(var_delta_fc_index, domain=NonNegativeReals) + model.var_delta_fcx = Var(var_delta_fcx_index, domain=NonNegativeReals) diff --git a/hens/beta_adaptive_model_mixer/lib/results_generator/__init__.py b/hens/beta_adaptive_model_mixer/lib/results_generator/__init__.py new file mode 100644 index 0000000..f757ec9 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/results_generator/__init__.py @@ -0,0 +1,2 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London diff --git a/hens/beta_adaptive_model_mixer/lib/results_generator/document_builder.py b/hens/beta_adaptive_model_mixer/lib/results_generator/document_builder.py new file mode 100644 index 0000000..72f7c47 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/results_generator/document_builder.py @@ -0,0 +1,811 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import json, sys, unicodedata, os, yaml + +from pyomo.environ import * +from pprint import pprint + +from ..constants import * + + +try: + from pylatex import * +except ImportError: + pass + +def check_folder_structure(folders, iteration): + if not os.path.exists(folders[model_folder]): + os.makedirs(folders[model_folder]) + + if not os.path.exists(folders[append_folder]): + os.makedirs(folders[append_folder]) + + if iteration and not os.path.exists(folders[iterations_folder]): + os.makedirs(folders[iterations_folder]) + +def save_pdf(doc, filename, folders, iteration): + if iteration: + path_without_extension = os.path.join(folders[iterations_folder], filename) + else: + path_without_extension = os.path.join(folders[append_folder], filename) + + doc.generate_pdf(path_without_extension, silent=True) + if (len(sys.argv) > 2): + with open(path_without_extension + '.tex', 'w') as tex_file: + tex_file.write(doc.dumps()) + +def add_preamble(doc): + doc.packages.append(Package('float, amsmath, amssymb, supertabular, multicol, url, subcaption, tikz, pgfplots, fancyhdr, morefloats, setspace')) + doc.packages.append(Package('parskip', options=['parfill'])) + doc.packages.append(Package('geometry', options=['tmargin=1in', 'lmargin=0.5in', 'rmargin=1in', 'bmargin=20mm'])) + + doc.preamble.append(NoEscape(r'\usetikzlibrary{calc}')) + + # doc.preamble.append('\pgfplotsset{compat=1.10}') + doc.preamble.append(NoEscape(r'\pgfplotsset{samples=500}')) + # doc.preamble.append('\usepgfplotslibrary{fillbetween}') + + doc.preamble.append(NoEscape(r'\renewcommand{\arraystretch}{1.5}')) + doc.preamble.append(NoEscape(r'\setlength{\columnseprule}{0.4pt}')) + + doc.preamble.append(NoEscape(r'\makeatletter')) + doc.preamble.append(NoEscape(r'\let\mcnewpage=\newpage')) + doc.preamble.append(NoEscape(r'\newcommand{\TrickSupertabularIntoMulticols}{%')) + doc.preamble.append(NoEscape(r'\renewcommand\newpage{%')) + doc.preamble.append(NoEscape(r'\if@firstcolumn')) + doc.preamble.append(NoEscape(r'\hrule width\linewidth height0pt')) + doc.preamble.append(NoEscape(r'\columnbreak')) + doc.preamble.append(NoEscape(r'\else')) + doc.preamble.append(NoEscape(r'\mcnewpage')) + doc.preamble.append(NoEscape(r'\fi')) + doc.preamble.append(NoEscape(r'}%')) + doc.preamble.append(NoEscape(r'}')) + doc.preamble.append(NoEscape(r'\makeatother')) + doc.preamble.append(NoEscape(r'\relax')) + doc.preamble.append(NoEscape(r'\pagestyle{fancy}')) + doc.preamble.append(NoEscape(r'\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}')) + +def add_summary(datafile_model, append, iter_num, tac, local_time, total_time, epsilons, tolerances, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{spacing}{1.3}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\Large' % (tab_gap))) + doc.append(NoEscape(r'%sModel (Run-name): %s (%s)\\' % (tab_gap, datafile_model, append))) + # doc.append('Run name: %s\\\\' % append) + doc.append(NoEscape(r'%sIteration: %d\\' % (tab_gap, iter_num))) + doc.append(NoEscape(r'%s\textbf{TAC: %s}\\' % (tab_gap, str(tac)))) + doc.append(NoEscape(r'%sTook: %ss\\' % (tab_gap, str(local_time)))) + doc.append(NoEscape(r'%sTotal Time: %ss\\' % (tab_gap, str(total_time)))) + doc.append(NoEscape(r'%sEpsilons:' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item $\varepsilon_{\textsl{Balancing}}$: %s' % (tab_gap, str(epsilons[balancing_ref])))) + doc.append(NoEscape(r'%s\item $\varepsilon_{\textsl{q-$\beta$}}$: %s' % (tab_gap, str(epsilons[q_beta_ref])))) + doc.append(NoEscape(r'%s\item $\varepsilon_{\textsl{RecLMTD-$\beta$}}$: %s' % (tab_gap, str(epsilons[lmtd_beta_ref])))) + doc.append(NoEscape(r'%s\item $\varepsilon_{\textsl{Area-$\beta$}}$: %s' % (tab_gap, str(epsilons[area_beta_ref])))) + level = level - 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + doc.append(NoEscape(r'%sGurobi Tolerances:' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item IntFeasTol: %s' % (tab_gap, str(tolerances['IntFeasTol'])))) + doc.append(NoEscape(r'%s\item FeasibilityTol: %s' % (tab_gap, str(tolerances['FeasibilityTol'])))) + doc.append(NoEscape(r'%s\item OptimalityTol: %s' % (tab_gap, str(tolerances['OptimalityTol'])))) + level = level - 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + level = level - 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{spacing}' % (tab_gap))) + # doc.append('\\linespread{1}') + doc.append(NoEscape(r'%s\normalsize' % (tab_gap))) + + if datafile_model in model_map: + doc.append(NoEscape(r'%sGamsworld Solution: \url{%s}' % (tab_gap, model_map[datafile_model]))) + + doc.append('') + doc.append(NoEscape(r'%% hello')) + +def add_active_results_table(doc, results, level): + tab_gap = '\t'*level + + doc.append(NoEscape(r'%s\begin{multicols*}{3}' % (tab_gap))) + doc.append(NoEscape(r'%s\TrickSupertabularIntoMulticols' % (tab_gap))) + doc.append(NoEscape(r'%s\tablehead{Variable&Value\\\hline}' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{supertabular}{lr}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + for result in results[0]: + result_row = result.table_row() + doc.append(NoEscape(r'%s%s & %s \\' % (tab_gap, result_row[0], result_row[1]))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{supertabular}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{multicols*}' % (tab_gap))) + +def generate_balancing_list(value, abs_error, rel_error, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item Value: %s' % (tab_gap, str(value)))) + doc.append(NoEscape(r'%s\item Absolute error: %s' % (tab_gap, str(abs_error)))) + doc.append(NoEscape(r'%s\item Relative error: %s' % (tab_gap, str(rel_error)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_balancing_results(instance, active_hx, old_points, errors, doc, level): + tab_gap = '\t'*level + for group in [bhin_error, bhout_error, bcin_error, bcout_error]: + if group == bhin_error: + section_header = r'$b^{\textsl{H},\text{in}}$' + var = instance.bh_in + elif group == bhout_error: + section_header = r'$b^{\textsl{H},\text{out}}$' + var = instance.bh_out + elif group == bcin_error: + section_header = r'$b^{\textsl{C},\text{in}}$' + var = instance.bc_in + elif group == bcout_error: + section_header = r'$b^{\textsl{C},\text{out}}$' + var = instance.bc_out + doc.append(NoEscape(r'%s\subsection{%s}' % (tab_gap, section_header))) + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + for active in active_hx[stream_hx]: + val = var[active].value + abs_error = errors[stream_hx][group][active][absolute_error] + rel_error = errors[stream_hx][group][active][relative_error] + + doc.append(NoEscape(r'%s\item $%s$' % (tab_gap, str(active)))) + generate_balancing_list(val, abs_error, rel_error, doc, level) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_num_line_tikz_preamble(x_min, x_max, y_min, y_max, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s[' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%shide axis,' % (tab_gap))) + doc.append(NoEscape(r'%saxis equal image,' % (tab_gap))) + doc.append(NoEscape(r'%sscale only axis,' % (tab_gap))) + doc.append(NoEscape(r'%swidth=\textwidth,' % (tab_gap))) + doc.append(NoEscape(r'%sxmin=%.15f, xmax=%.15f,' % (tab_gap, x_min, x_max))) + doc.append(NoEscape(r'%symin=%.15f, ymax=%.15f,' % (tab_gap, y_min, y_max))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s]' % (tab_gap))) + +def generate_balancing_graphs(instance, active_hx, old_points, doc, level): + tab_gap = '\t'*level + + for group in [th_points, thx_points, tc_points, tcx_points]: + if group == th_points: + index_extractor = lambda i,j,k: (i,k) + temp_str = 'H' + var = instance.th + elif group == thx_points: + index_extractor = lambda i,j,k: (i,j,k) + temp_str = 'H' + var = instance.thx + elif group == tc_points: + index_extractor = lambda i,j,k: (j,k+1) + temp_str = 'C' + var = instance.tc + elif group == tcx_points: + index_extractor = lambda i,j,k: (i,j,k) + temp_str = 'C' + var = instance.tcx + for active in active_hx[stream_hx]: + break_index = index_extractor(*active) + caption = r'$\textit{t}^{\textsl{(%s)}}$ - $%s$' % (temp_str, str(break_index)) + + breakpoints = old_points[stream_hx][group][break_index] + + x_min, x_max = var[break_index].bounds + val = var[break_index].value + diff = x_max - x_min + delta = diff/30 + y_min = -(1.5*delta) + y_max = (-1)*y_min + + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\resizebox{\linewidth}{!}{' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{axis}' % (tab_gap))) + add_num_line_tikz_preamble(x_min, x_max, y_min, y_max, doc, level) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw (axis cs: %.15f,0) -- (axis cs: %.15f,0);' % (tab_gap, x_min,x_max))) + for x in breakpoints: + lval = (tab_gap, x,delta,x, delta) + doc.append(NoEscape(r'%s\draw (axis cs: %.15f,-%.15f) -- (axis cs: %.15f,%.15f);' % lval)) + + doc.append(NoEscape(r'%s\draw[color=red] (axis cs: %.15f,-%.15f) -- (axis cs: %.15f,%.15f);' % (tab_gap, val,1.5*delta,val,1.5*delta))) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{axis}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{%s}' % (tab_gap, caption))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%'))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + +def generate_reclmtd_beta_list(reclmtd_beta_value, abs_error, rel_error, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item Value: %f' % (tab_gap, reclmtd_beta_value))) + doc.append(NoEscape(r'%s\item Error: %.15f' % (tab_gap, abs_error))) + doc.append(NoEscape(r'%s\item Relative error: %.15f' % (tab_gap, rel_error))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_reclmtd_beta_results(instance, active_hx, errors, doc, level): + doc.append(NoEscape(r'%'*45)) + doc.append(NoEscape(r'%s $\textsl{RecLMTD}^\beta$ Results %s' % ('%'*13, '%'*13))) + doc.append(NoEscape(r'%'*45)) + + doc.append(NoEscape(r'\begin{itemize}')) + level += 1 + tab_gap = '\t'*level + for active in active_hx[stream_hx]: + reclmtd_beta_value = value(instance.reclmtd_beta[active]) + abs_error = errors[stream_hx][reclmtd_beta_error][active][absolute_error] + rel_error = errors[stream_hx][reclmtd_beta_error][active][relative_error] + + doc.append(NoEscape(r'%s\item $%s$' % (tab_gap, str(active)))) + generate_reclmtd_beta_list(reclmtd_beta_value, abs_error, rel_error, doc, level) + + for active in active_hx[cu_hx]: + reclmtd_beta_value = value(instance.reclmtd_cu_beta[active]) + abs_error = errors[cu_hx][reclmtd_beta_error][active][absolute_error] + rel_error = errors[cu_hx][reclmtd_beta_error][active][relative_error] + + doc.append(NoEscape(r'%s\item $\textit{cu},%s$' % (tab_gap, str(active)))) + generate_reclmtd_beta_list(reclmtd_beta_value, abs_error, rel_error, doc, level) + + for active in active_hx[hu_hx]: + reclmtd_beta_value = value(instance.reclmtd_hu_beta[active]) + abs_error = errors[hu_hx][reclmtd_beta_error][active][absolute_error] + rel_error = errors[hu_hx][reclmtd_beta_error][active][relative_error] + + doc.append(NoEscape(r'%s\item $\textit{hu},%s$' % (tab_gap, str(active)))) + generate_reclmtd_beta_list(reclmtd_beta_value, abs_error, rel_error, doc, level) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_reclmtd_beta_tikz_preamble(minn, maxx, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s[' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%saxis lines=middle,' % (tab_gap))) + doc.append(NoEscape(r'%sxmin=%.15f, xmax=%.15f,' % (tab_gap, minn, maxx))) + doc.append(NoEscape(r'%symin=%.15f, ymax=%.15f,' % (tab_gap, minn, maxx))) + doc.append(NoEscape(r'%sxtick=\empty, ytick=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%sxticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%syticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%sxlabel=\empty,ylabel=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%severy axis x label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%sat={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'%sanchor=west,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s},' % (tab_gap))) + doc.append(NoEscape(r'%severy axis y label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%sat={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'%sanchor=south,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s}' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s]' % (tab_gap))) + +def generate_reclmtd_beta_graphs(instance, active_hx, old_points, doc, level): + tab_gap = '\t'*level + iteration = 0 + for active in active_hx[stream_hx]: + breakpoints = old_points[stream_hx][tangent_points][active] + minn, maxx = instance.dt[active].bounds + xv = value(instance.dt[active]) + yv = value(instance.dt[active[0], active[1], active[2]+1]) + + if iteration % 2 == 0: + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + if not iteration == 0: + doc.append(NoEscape(r'%s\ContinuedFloat' % (tab_gap))) + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{subfigure}{0.5\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}[baseline]' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{axis}' % (tab_gap))) + add_reclmtd_beta_tikz_preamble(minn, maxx, doc, level) + + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw[dashed] (axis cs: %.15f,%.15f) -- ( axis cs: %.15f,%.15f);' % (tab_gap, minn, minn, maxx, maxx))) + doc.append('') + doc.append(NoEscape(r'%s\addplot[only marks] table {' % (tab_gap))) + for (x,y) in breakpoints: + doc.append(NoEscape(r'%s%s%.15f %.15f' % (tab_gap, '\t', x,y))) + doc.append(NoEscape(r'%s};' % (tab_gap))) + doc.append('') + doc.append(NoEscape(r'%s\addplot[only marks, mark=+, color=red, thick] table {' % (tab_gap))) + doc.append(NoEscape(r'%s%s%.15f %.15f' % (tab_gap, '\t', xv, yv))) + doc.append(NoEscape(r'%s};' % (tab_gap))) + doc.append('') + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{axis}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{$\textsl{RecLMTD}$ - $%s$}' % (tab_gap, str(active)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%%'))) + if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + iteration += 1 + + if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + + iteration = 0 + for active in active_hx[cu_hx]: + breakpoints = old_points[cu_hx][tangent_points][active] + minn, maxx = instance.dt_cu[active].bounds + val = value(instance.dt_cu[active]) + diff = maxx - minn + delta = diff/30 + + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + if not iteration == 0: + doc.append(NoEscape(r'%s\ContinuedFloat' % (tab_gap))) + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\resizebox{0.95\textwidth}{!}{' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}[baseline]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw (%.15f,0) -- (%.15f,0);' % (tab_gap,minn,maxx))) + for x in breakpoints: + lval = (tab_gap,x,delta,x, delta) + doc.append(NoEscape(r'%s\draw (%.15f,-%.15f) -- (%.15f,%.15f);' % (lval))) + + doc.append(NoEscape(r'%s\draw[color=red] (%.15f,-%.15f) -- (%.15f,%.15f);' % (tab_gap,val,1.5*delta,val,1.5*delta))) + + level -= 1 + tab_gap = '\t'*level + + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{$\textsl{RecLMTD}$ - $\textsl{cu},%s$}' % (tab_gap,str(active)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%%'))) + # if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + iteration += 1 + + iteration = 0 + for active in active_hx[hu_hx]: + breakpoints = old_points[hu_hx][tangent_points][active] + minn, maxx = instance.dt_hu[active].bounds + val = value(instance.dt_hu[active]) + diff = maxx - minn + delta = diff/30 + + + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + if not iteration == 0: + doc.append(NoEscape(r'%s\ContinuedFloat' % (tab_gap))) + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\resizebox{0.95\linewidth}{!}{' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}[baseline]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw (%.15f,0) -- (%.15f,0);' % (tab_gap,minn,maxx))) + for x in breakpoints: + lval = (tab_gap,x,delta,x, delta) + doc.append(NoEscape(r'%s\draw (%.15f,-%.15f) -- (%.15f,%.15f);' % (lval))) + + doc.append(NoEscape(r'%s\draw[color=red] (%.15f,-%.15f) -- (%.15f,%.15f);' % (tab_gap,val,1.5*delta,val,1.5*delta))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s}'% (tab_gap))) + doc.append(NoEscape(r'%s\caption{$\textsl{RecLMTD}$ - $\textsl{hu},%s$}' % (tab_gap,str(active)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%%'))) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + iteration += 1 + +def generate_q_beta_list(q_value, q_beta, beta, breakpoints, abs_error, rel_error, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level +=1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item $q$: %f' % (tab_gap, q_value))) + doc.append(NoEscape(r'%s\item $\hat{q}^\beta$: %f' % (tab_gap, q_beta) )) + doc.append(NoEscape(r'%s\item $q^\beta$: %f' % (tab_gap, pow(q_value, beta)))) + doc.append(NoEscape(r'%s\item Breakpoints: %s' % (tab_gap, breakpoints))) + doc.append(NoEscape(r'%s\item Error: %.15f' % (tab_gap, abs_error))) + doc.append(NoEscape(r'%s\item Relative error: %.15f' % (tab_gap, rel_error))) + level -=1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_q_beta_results(instance, active_hx, old_points, errors, doc, level): + beta = instance.Beta + + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + + for group in [stream_hx, cu_hx, hu_hx]: + if group == stream_hx: + index_template = r'$%s$' + q_var = instance.q + q_beta_var = instance.q_beta + elif group == cu_hx: + index_template = r'$\textit{cu},%s$' + q_var = instance.q_cu + q_beta_var = instance.q_cu_beta + elif group == hu_hx: + index_template = r'$\textit{hu},%s$' + q_var = instance.q_hu + q_beta_var = instance.q_hu_beta + + for active in active_hx[group]: + index_str = index_template % (str(active)) + q_value = q_var[active].value + q_beta = q_beta_var[active].value + breakpoints = get_breakpoint_list(old_points[group][q_beta_points][active], q_value) + abs_error = errors[group][q_beta_error][active][absolute_error] + rel_error = errors[group][q_beta_error][active][relative_error] + + doc.append(NoEscape(r'%s\item %s' % (tab_gap, index_str))) + generate_q_beta_list(q_value, q_beta, beta, breakpoints, abs_error, rel_error, doc, level) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_q_beta_tikz_preamble(x_min, x_max, y_min, y_max, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s[' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%saxis lines=middle,' % (tab_gap))) + doc.append(NoEscape(r'%sxmin=%.15f, xmax=%.15f,' % (tab_gap, x_min, x_max))) + doc.append(NoEscape(r'%symin=%.15f, ymax=%.15f,' % (tab_gap, y_min, y_max))) + doc.append(NoEscape(r'%sxtick=\empty, ytick=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%sxticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%syticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%sxlabel=\empty,ylabel=\empty,' % (tab_gap))) + doc.append(NoEscape(r'%severy axis x label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%sat={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'%sanchor=west,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s},' % (tab_gap))) + doc.append(NoEscape(r'%severy axis y label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%sat={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'%sanchor=south,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s}' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s]' % (tab_gap))) + +def add_q_beta_tikz_main(beta, breakpoints, x_min, x_max, y_min, y_max, y_breakpoints, q, index_str, doc, level, iteration): + tab_gap = '\t'*level + if iteration % 2 == 0: + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + if not iteration == 0: + doc.append(NoEscape(r'%s\ContinuedFloat' % (tab_gap))) + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{0.5\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}[baseline]' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{axis}' % (tab_gap))) + + add_q_beta_tikz_preamble(x_min, x_max, y_min, y_max, doc, level) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\addplot[domain=%f:%f, color=blue]{x^%f};' % (tab_gap, x_min, x_max, beta))) + for index in range(0, len(breakpoints)-1): + doc.append(NoEscape(r'%s\draw[dotted, thick] (axis cs: %f, %f) -- (axis cs: %f, %f);' % (tab_gap, breakpoints[index], y_breakpoints[index], breakpoints[index+1], y_breakpoints[index+1]))) + + doc.append(NoEscape(r'%s\draw[dashed, color=red] (axis cs: %f, %f) -- (axis cs: %f, %f);' % (tab_gap, q, 0, q, pow(q, beta)))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{axis}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{$q^\beta$ - %s}' % (tab_gap, index_str))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%'))) + if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + return level + +def add_q_beta_graphs(instance, active_hx, old_points, doc, level): + tab_gap = '\t'*level + beta = instance.Beta.value + + for group in [stream_hx, cu_hx, hu_hx]: + iteration = 0 + if group == stream_hx: + index_template = r'$%s$' + var = instance.q + elif group == cu_hx: + index_template = r'$\textit{cu},%s$' + var = instance.q_cu + elif group == hu_hx: + index_template = r'$\textit{hu},%s$' + var = instance.q_hu + for active in active_hx[group]: + breakpoints = old_points[group][q_beta_points][active] + x_min = 0 + x_max = breakpoints[len(breakpoints)-1] + y_min = 0 + y_max = pow(x_max, beta) + y_breakpoints = [pow(q, beta) for q in breakpoints] + q = var[active].value + index_str = index_template % (str(active)) + level = add_q_beta_tikz_main(beta, breakpoints, x_min, x_max, y_min, y_max, y_breakpoints, q, index_str, doc, level, iteration) + iteration += 1 + if iteration % 2 == 1: + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + +def generate_area_beta_list(area_beta_value, abs_error, rel_error, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level +=1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\item Value: %f' % (tab_gap, area_beta_value))) + doc.append(NoEscape(r'%s\item Error: %.15f' % (tab_gap, abs_error))) + doc.append(NoEscape(r'%s\item Relative error: %.15f' % (tab_gap, rel_error))) + level -=1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_area_beta_results(instance, active_hx, old_points, errors, doc, level): + tab_gap = '\t'*level + beta = instance.Beta + + for group in [stream_hx, cu_hx, hu_hx]: + if group == stream_hx: + section_header = r'$A^\beta$' + index_template = r'%s' + var = instance.area_beta + elif group == cu_hx: + section_header = r'$A_{CU}^\beta$' + index_template = r'\textit{cu},%s' + var = instance.area_cu_beta + elif group == hu_hx: + section_header = r'$A_{HU}^\beta$' + index_template = r'\textit{hu},%s' + var = instance.area_hu_beta + if len(active_hx[group]) != 0: + doc.append(NoEscape(r'%s\subsection{%s}' % (tab_gap, section_header))) + doc.append(NoEscape(r'%s\begin{itemize}' % (tab_gap))) + level = level + 1 + tab_gap = '\t'*level + for active in active_hx[group]: + index_str = index_template % (str(active)) + area_beta_value = var[active].value + abs_error = errors[group][area_beta_error][active][absolute_error] + rel_error = errors[group][area_beta_error][active][relative_error] + + doc.append(NoEscape(r'%s\item $%s$' % (tab_gap, index_str))) + generate_area_beta_list(area_beta_value, abs_error, rel_error, doc, level) + level = level - 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{itemize}' % (tab_gap))) + +def add_area_beta_tikz_preamble(x_min, x_max, y_min, y_max, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'[' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'axis lines=middle,' % (tab_gap))) + doc.append(NoEscape(r'xmin=%.15f, xmax=%.15f,' % (tab_gap, x_min, x_max))) + doc.append(NoEscape(r'ymin=%.15f, ymax=%.15f,' % (tab_gap, y_min, y_max))) + doc.append(NoEscape(r'xtick=\empty, ytick=\empty,' % (tab_gap))) + doc.append(NoEscape(r'xticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'yticklabels=\empty,' % (tab_gap))) + doc.append(NoEscape(r'xlabel=\empty,ylabel=\empty,' % (tab_gap))) + doc.append(NoEscape(r'every axis x label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'at={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'anchor=west,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'},' % (tab_gap))) + doc.append(NoEscape(r'every axis y label/.style={' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'at={(ticklabel* cs:1)},' % (tab_gap))) + doc.append(NoEscape(r'anchor=south,' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'}' % (tab_gap))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r']' % (tab_gap))) + +def add_area_beta_graphs(instance, active_hx, old_points, doc, level): + tab_gap = '\t'*level + beta = instance.Beta + iteration = 0 + for group in [stream_hx, cu_hx, hu_hx]: + if group == stream_hx: + index_template = '%s' + var = instance.q_beta + elif group == cu_hx: + index_template = 'cu,%s' + var = instance.q_cu_beta + elif group == hu_hx: + index_template = 'hu,%s' + var = instance.q_hu_beta + for active in active_hx[group]: + index_str = index_template % (str(active)) + + breakpoints = old_points[group][area_q_beta_points][active] + x_min = 0 + x_max = breakpoints[len(breakpoints)-1] + diff = x_max - x_min + delta = diff/30 + y_min = -(1.5*delta) + y_max = (-1)*y_min + val = var[active].value + + doc.append(NoEscape(r'%s\begin{figure}[p]' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + + doc.append(NoEscape(r'%s\begin{subfigure}{\linewidth}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\centering' % (tab_gap))) + doc.append(NoEscape(r'%s\resizebox{\linewidth}{!}{' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{axis}' % (tab_gap))) + add_num_line_tikz_preamble(x_min, x_max, y_min, y_max, doc, level) + level += 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\draw (axis cs: %.15f,0) -- (axis cs: %.15f,0);' % (tab_gap, x_min,x_max))) + for x in breakpoints: + lval = (tab_gap, x,delta,x,delta) + doc.append(NoEscape(r'%s\draw (axis cs: %.15f,-%.15f) -- (axis cs: %.15f,%.15f);' % lval)) + + doc.append(NoEscape(r'%s\draw[color=red] (axis cs: %.15f,-%.15f) -- (axis cs: %.15f,%.15f);' % (tab_gap, val,1.5*delta,val,1.5*delta))) + + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{axis}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{tikzpicture}' % (tab_gap))) + doc.append(NoEscape(r'%s}' % (tab_gap))) + doc.append(NoEscape(r'%s\caption{$\textit{A}^{\beta}$ - $%s$}' % (tab_gap, index_str))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{subfigure}%s' % (tab_gap, '%'))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{figure}' % (tab_gap))) + +def get_breakpoint_list(breakpoints, value): + same_value = False + index = 0 + for i in range(0,len(breakpoints)): + if breakpoints[i] == value: + same_value = True + index = i + break + elif breakpoints[i] > value: + index = i-1 + break + + string_breakpoints = [r'$%s$' % str(x) for x in breakpoints] + + if same_value: + string_breakpoints[index] = r'\textcolor{green}{$%s$}' % (str(breakpoints[index])) + else: + string_breakpoints[index] = r'\textcolor{red}{$%s$}' % (str(breakpoints[index])) + string_breakpoints[index+1] = r'\textcolor{red}{$%s$}' % (str(breakpoints[index+1])) + + return r'$[$%s$]$' % (', '.join(string_breakpoints)) + +def add_inactive_results_table(results, doc, level): + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\begin{multicols*}{3}' % (tab_gap))) + doc.append(NoEscape(r'%s\TrickSupertabularIntoMulticols' % (tab_gap))) + doc.append(NoEscape(r'%s\tablehead{Variable&Value\\\hline}' % (tab_gap))) + doc.append(NoEscape(r'%s\begin{supertabular}{lr}' % (tab_gap))) + level += 1 + tab_gap = '\t'*level + for result in results[1]: + result_row = result.table_row() + doc.append(NoEscape(r'%s%s & %s \\' % (tab_gap, result_row[0], result_row[1]))) + level -= 1 + tab_gap = '\t'*level + doc.append(NoEscape(r'%s\end{supertabular}' % (tab_gap))) + doc.append(NoEscape(r'%s\end{multicols*}' % (tab_gap))) diff --git a/hens/beta_adaptive_model_mixer/lib/results_generator/feasibility_checker.py b/hens/beta_adaptive_model_mixer/lib/results_generator/feasibility_checker.py new file mode 100644 index 0000000..ed8b448 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/results_generator/feasibility_checker.py @@ -0,0 +1,633 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import os + +from pprint import pprint +from math import log + +def check_eq1_feasibility(instance, feas_results): + eq1_results = {} + for i in instance.HP: + local_result = {} + rhs = instance.Fh[i]*(instance.Th_in[i] - instance.Th_out[i]) + lhs = instance.q_cu[i].value + sum(instance.q[i,j,k].value for j in instance.CP for k in instance.ST) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq1_results[i] = local_result + + feas_results['eq01'] = eq1_results + +def check_eq2_feasibility(instance, feas_results): + eq2_results = {} + for j in instance.CP: + local_result = {} + rhs = instance.Fc[j]*(instance.Tc_out[j] - instance.Tc_in[j]) + lhs = instance.q_hu[j].value + sum(instance.q[i,j,k].value for i in instance.HP for k in instance.ST) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq2_results[j] = local_result + + feas_results['eq02'] = eq2_results + +def check_eq3_feasibility(instance, feas_results): + eq3_results = {} + for i in instance.HP: + for k in instance.ST: + local_result = {} + rhs = instance.Fh[i] + lhs = sum(instance.fh[i,j,k].value for j in instance.CP) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq3_results[(i,k)] = local_result + + feas_results['eq03'] = eq3_results + +def check_eq4_feasibility(instance, feas_results): + eq4_results = {} + for j in instance.CP: + for k in instance.ST: + local_result = {} + rhs = instance.Fc[j] + lhs = sum(instance.fc[i,j,k].value for i in instance.HP) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq4_results[(j,k)] = local_result + + feas_results['eq04'] = eq4_results + +def check_eq5_feasibility(instance, feas_results): + eq5_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + rhs = instance.fh[i,j,k].value*(instance.th[i,k].value - instance.thx[i,j,k].value) + lhs = instance.q[i,j,k].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq5_results[(i,j,k)] = local_result + + feas_results['eq05'] = eq5_results + +def check_eq6_feasibility(instance, feas_results): + eq6_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + rhs = instance.fc[i,j,k].value*(instance.tcx[i,j,k].value - instance.tc[j,k+1].value) + lhs = instance.q[i,j,k].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq6_results[(i,j,k)] = local_result + + feas_results['eq06'] = eq6_results + +def check_eq7_feasibility(instance, feas_results): + eq7_results = {} + for i in instance.HP: + for k in instance.ST: + local_result = {} + rhs = 0 + for j in instance.CP: + rhs = sum(instance.fh[i,j,k].value *instance.thx[i,j,k].value for j in instance.CP) + lhs = instance.Fh[i]*instance.th[i,k+1].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq7_results[(i,k)] = local_result + + feas_results['eq07'] = eq7_results + +def check_eq8_feasibility(instance, feas_results): + eq8_results = {} + for j in instance.CP: + for k in instance.ST: + local_result = {} + rhs = sum(instance.fc[i,j,k].value*instance.tcx[i,j,k].value for i in instance.HP) + lhs = instance.Fc[j]*instance.tc[j,k].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq8_results[(j,k)] = local_result + + feas_results['eq08'] = eq8_results + +def check_eq9_feasibility(instance, feas_results): + eq9_results = {} + for i in instance.HP: + local_result = {} + rhs = instance.Th_in[i] + lhs = instance.th[i,1].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq9_results[i] = local_result + + feas_results['eq09'] = eq9_results + +def check_eq10_feasibility(instance, feas_results): + eq10_results = {} + for j in instance.CP: + local_result = {} + rhs = instance.Tc_in[j] + lhs = instance.tc[j,instance.Number_stages+1].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq10_results[j] = local_result + + feas_results['eq10'] = eq10_results + +def check_eq11_feasibility(instance, feas_results): + eq11_results = {} + for i in instance.HP: + local_result = {} + rhs = instance.Fh[i]*(instance.th[i,instance.Number_stages+1].value-instance.Th_out[i]) + lhs = instance.q_cu[i].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq11_results[i] = local_result + + feas_results['eq11'] = eq11_results + +def check_eq12_feasibility(instance, feas_results): + eq12_results = {} + for j in instance.CP: + local_result = {} + rhs = instance.Fc[j]*(instance.Tc_out[j]-instance.tc[j,1].value) + lhs = instance.q_hu[j].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq12_results[j] = local_result + + feas_results['eq12'] = eq12_results + +def check_eq13_feasibility(instance, feas_results): + eq13_results = {} + for i in instance.HP: + for k in instance.ST: + local_result = {} + lhs = instance.th[i,k+1].value + rhs = instance.th[i,k].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq13_results[(i,k)] = local_result + + feas_results['eq13'] = eq13_results + +def check_eq14_feasibility(instance, feas_results): + eq14_results = {} + for j in instance.CP: + for k in instance.ST: + local_result = {} + lhs = instance.tc[j,k+1].value + rhs = instance.tc[j,k].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq14_results[(j,k)] = local_result + + feas_results['eq14'] = eq14_results + +def check_eq15_feasibility(instance, feas_results): + eq15_results = {} + for i in instance.HP: + local_result = {} + lhs = instance.th[i,instance.Number_stages+1].value + rhs = instance.Th_out[i] + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs < rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq15_results[i] = local_result + + feas_results['eq15'] = eq15_results + +def check_eq16_feasibility(instance, feas_results): + eq16_results = {} + for j in instance.CP: + local_result = {} + lhs = instance.tc[j,1].value + rhs = instance.Tc_out[j] + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq16_results[j] = local_result + + feas_results['eq16'] = eq16_results + +def check_eq17_feasibility(instance, feas_results): + eq17_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + lhs = instance.q[i,j,k].value - instance.Omega_ij[i,j]*instance.z[i,j,k].value + rhs = 0 + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq17_results[(i,j,k)] = local_result + + feas_results['eq17'] = eq17_results + +def check_eq18_feasibility(instance, feas_results): + eq18_results = {} + for i in instance.HP: + local_result = {} + lhs = instance.q_cu[i].value - instance.Omega_i[i]*instance.z_cu[i].value + rhs = 0 + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq18_results[i] = local_result + + feas_results['eq18'] = eq18_results + +def check_eq19_feasibility(instance, feas_results): + eq19_results = {} + for j in instance.CP: + local_result = {} + lhs = instance.q_hu[j].value - instance.Omega_j[j]*instance.z_hu[j].value + rhs = 0 + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq19_results[j] = local_result + + feas_results['eq19'] = eq19_results + +def check_eq20_feasibility(instance, feas_results): + eq20_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + lhs = instance.dt[i,j,k].value + rhs = instance.th[i,k].value - instance.tc[j,k].value + instance.Gamma[i,j]*(1-instance.z[i,j,k].value) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq20_results[(i,j,k)] = local_result + + feas_results['eq20'] = eq20_results + +def check_eq21_feasibility(instance, feas_results): + eq21_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + lhs = instance.dt[i,j,k+1].value + rhs = instance.th[i,k+1].value - instance.tc[j,k+1].value + instance.Gamma[i,j]*(1-instance.z[i,j,k].value) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq21_results[(i,j,k)] = local_result + + feas_results['eq21'] = eq21_results + +def check_eq22_feasibility(instance, feas_results): + eq22_results = {} + for i in instance.HP: + local_result = {} + lhs = instance.dt_cu[i].value + rhs = instance.th[i,instance.Number_stages+1].value - instance.T_cu_out + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq22_results[i] = local_result + + feas_results['eq22'] = eq22_results + +def check_eq23_feasibility(instance, feas_results): + eq23_results = {} + for j in instance.CP: + local_result = {} + lhs = instance.dt_hu[j].value + rhs = instance.T_hu_out - instance.tc[j,1].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs > rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq23_results[j] = local_result + + feas_results['eq23'] = eq23_results + +def check_eq24_feasibility(instance, feas_results): + eq24_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + lhs = instance.dt[i,j,k].value + rhs = instance.Delta_t_min.value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs < rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq24_results[(i,j,k)] = local_result + + feas_results['eq24'] = eq24_results + +def check_eq25_feasibility(instance, feas_results): + eq25_results = {} + for i in instance.HP: + local_result = {} + lhs = instance.dt_cu[i].value + rhs = instance.Delta_t_min.value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs < rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq25_results[i] = local_result + + feas_results['eq25'] = eq25_results + +def check_eq26_feasibility(instance, feas_results): + eq26_results = {} + for j in instance.CP: + local_result = {} + lhs = instance.dt_hu[j].value + rhs = instance.Delta_t_min.value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + if lhs < rhs: + local_result['eps'] = eps + else: + local_result['eps'] = 0 + eq26_results[j] = local_result + + feas_results['eq26'] = eq26_results + +####################### +# Note: _feasibility checks for 27, 29, 30 are for reclmtd^{beta} +###################### +def check_eq27_feasibility(instance, feas_results): + eq27_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + lhs = instance.reclmtd_beta[i,j,k].value + x = instance.dt[i,j,k].value + y = instance.dt[i,j,k+1].value + rhs = pow(1/x, instance.Beta) if x == y else pow(log(x/y)/(x-y), instance.Beta) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq27_results[(i,j,k)] = local_result + + feas_results['eq27'] = eq27_results + +####################### +# Note: _feasibility checks for 28, 31, 32 are for A^{beta} +###################### +def check_eq28_feasibility(instance, feas_results): + eq28_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + lhs = instance.area_beta[i,j,k].value + u = pow(1/instance.Hh[i] + 1/instance.Hc[j], instance.Beta) + rhs = instance.q_beta[i,j,k].value*u*instance.reclmtd_beta[i,j,k].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq28_results[(i,j,k)] = local_result + + feas_results['eq28'] = eq28_results + +####################### +# Note: _feasibility checks for 27, 29, 30 are for reclmtd^{beta} +###################### +def check_eq29_feasibility(instance, feas_results): + eq29_results = {} + for i in instance.HP: + local_result = {} + lhs = instance.reclmtd_cu_beta[i].value + x = instance.dt_cu[i].value + y = instance.Th_out[i] - instance.T_cu_in + rhs = pow(1/x, instance.Beta) if x == y else pow(log(x/y)/(x-y), instance.Beta) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq29_results[i] = local_result + + feas_results['eq29'] = eq29_results + +def check_eq30_feasibility(instance, feas_results): + eq30_results = {} + for j in instance.CP: + local_result = {} + lhs = instance.reclmtd_hu_beta[j].value + x = instance.dt_hu[j].value + y = instance.T_hu_in - instance.Tc_out[j] + rhs = pow(1/x, instance.Beta) if x == y else pow(log(x/y)/(x-y), instance.Beta) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq30_results[j] = local_result + + feas_results['eq30'] = eq30_results + +####################### +# Note: _feasibility checks for 28, 31, 32 are for A^{beta} +###################### +def check_eq31_feasibility(instance, feas_results): + eq31_results = {} + for i in instance.HP: + local_result = {} + lhs = instance.area_cu_beta[i].value + u = pow(1/instance.Hh[i] + 1/instance.H_cu, instance.Beta) + rhs = instance.q_cu_beta[i].value*u*instance.reclmtd_cu_beta[i].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq31_results[i] = local_result + + feas_results['eq31'] = eq31_results + +def check_eq32_feasibility(instance, feas_results): + eq32_results = {} + for j in instance.CP: + local_result = {} + lhs = instance.area_hu_beta[j].value + u = pow(1/instance.Hc[j] + 1/instance.H_hu, instance.Beta) + rhs = instance.q_hu_beta[j].value*u*instance.reclmtd_hu_beta[j].value + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq32_results[j] = local_result + + feas_results['eq32'] = eq32_results + +# q_beta (not in synheat model) +def check_eq33_feasibility(instance, feas_results): + eq33_results = {} + for i in instance.HP: + for j in instance.CP: + for k in instance.ST: + local_result = {} + lhs = instance.q_beta[i,j,k].value + if instance.q[i,j,k].value < 0: + rhs = 0 + else: + rhs = pow(instance.q[i,j,k].value, instance.Beta) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq33_results[(i,j,k)] = local_result + feas_results['eq33'] = eq33_results + +def check_eq34_feasibility(instance, feas_results): + eq34_results = {} + for i in instance.HP: + local_result = {} + lhs = instance.q_cu_beta[i].value + if instance.q_cu[i].value < 0: + rhs = 0 + else: + rhs = pow(instance.q_cu[i].value, instance.Beta) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq34_results[i] = local_result + feas_results['eq34'] = eq34_results + +def check_eq35_feasibility(instance, feas_results): + eq35_results = {} + for j in instance.CP: + local_result = {} + lhs = instance.q_hu_beta[j].value + if instance.q_hu[j].value < 0: + rhs = 0 + else: + rhs = pow(instance.q_hu[j].value, instance.Beta) + eps = rhs - lhs + local_result['lhs'] = lhs + local_result['rhs'] = rhs + local_result['eps'] = eps + eq35_results[j] = local_result + feas_results['eq35'] = eq35_results + +def check_feasibility(instance): + feas_results = {} + check_eq1_feasibility(instance, feas_results) + check_eq2_feasibility(instance, feas_results) + check_eq3_feasibility(instance, feas_results) + check_eq4_feasibility(instance, feas_results) + check_eq5_feasibility(instance, feas_results) + check_eq6_feasibility(instance, feas_results) + check_eq7_feasibility(instance, feas_results) + check_eq8_feasibility(instance, feas_results) + check_eq9_feasibility(instance, feas_results) + check_eq10_feasibility(instance, feas_results) + check_eq11_feasibility(instance, feas_results) + check_eq12_feasibility(instance, feas_results) + check_eq13_feasibility(instance, feas_results) + check_eq14_feasibility(instance, feas_results) + check_eq15_feasibility(instance, feas_results) + check_eq16_feasibility(instance, feas_results) + check_eq17_feasibility(instance, feas_results) + check_eq18_feasibility(instance, feas_results) + check_eq19_feasibility(instance, feas_results) + check_eq20_feasibility(instance, feas_results) + check_eq21_feasibility(instance, feas_results) + check_eq22_feasibility(instance, feas_results) + check_eq23_feasibility(instance, feas_results) + check_eq24_feasibility(instance, feas_results) + check_eq25_feasibility(instance, feas_results) + check_eq26_feasibility(instance, feas_results) + check_eq27_feasibility(instance, feas_results) + check_eq28_feasibility(instance, feas_results) + check_eq29_feasibility(instance, feas_results) + check_eq30_feasibility(instance, feas_results) + check_eq31_feasibility(instance, feas_results) + check_eq32_feasibility(instance, feas_results) + check_eq33_feasibility(instance, feas_results) + check_eq34_feasibility(instance, feas_results) + check_eq35_feasibility(instance, feas_results) + + return feas_results diff --git a/hens/beta_adaptive_model_mixer/lib/results_generator/heat_var.py b/hens/beta_adaptive_model_mixer/lib/results_generator/heat_var.py new file mode 100644 index 0000000..4dd67e0 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/results_generator/heat_var.py @@ -0,0 +1,338 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +from pyomo.environ import * + + +from ..constants import * + +def index_identify(index): + return '{{' + index + '}}' + +var_order = [ z, z_cu, z_hu, area_beta, area_cu_beta, area_hu_beta, area, area_cu, area_hu, dt, dt_cu, dt_hu, fh, fc, reclmtd, reclmtd_CU, reclmtd_HU, reclmtd_beta, reclmtd_cu_beta, reclmtd_hu_beta, q, q_cu, q_hu, q_beta, q_cu_beta, q_hu_beta, th, tc, thx, tcx, bh_in, bh_out, bc_in, bc_out] + +ignored_vars = [z_A, z_A_CU, z_A_HU, z_q, z_q_CU, z_q_HU, z_th, z_thx, z_tc, z_tcx, var_delta_fh, var_delta_fhx, var_delta_fc, var_delta_fcx, z_A_beta, z_A_CU_beta, z_A_HU_beta, z_q_beta, z_q_cu_beta, z_q_hu_beta, var_delta_reclmtd_beta, var_delta_reclmtd_cu_beta, var_delta_reclmtd_hu_beta, z_area_beta_q, z_area_beta_q_cu, z_area_beta_q_hu] + +ijk_subscript = '%s,%s,%s' % (index_identify(index_i), index_identify(index_j), index_identify(index_k)) +ijk_indices = [ index_i, index_j, index_k ] + +cui_subscript = 'cu,%s' % index_identify(index_i) +cui_indices = [ index_i ] + +huj_subscript = 'hu,%s' % index_identify(index_j) +huj_indices = [ index_j ] + +ik_subscript = '%s,%s' % (index_identify(index_i), index_identify(index_k)) +ik_indices = [ index_i, index_k ] + +jk_subscript = '%s,%s' % (index_identify(index_j), index_identify(index_k)) +jk_indices = [ index_j, index_k ] + +var_to_subscript_map = {\ + area:{\ + latex_label: 'A',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices : ijk_indices\ + },\ + area_cu:{\ + latex_label: 'A',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + area_hu:{\ + latex_label: 'A',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + area_beta:{\ + latex_label: 'A',\ + latex_superscript: ltx_beta,\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices : ijk_indices\ + },\ + area_cu_beta:{\ + latex_label: 'A',\ + latex_superscript: ltx_beta,\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + area_hu_beta:{\ + latex_label: 'A',\ + latex_superscript: ltx_beta,\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + bc_in:{\ + latex_label: 'b',\ + latex_superscript: 'C,\\text{in}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + bc_out:{\ + latex_label: 'b',\ + latex_superscript: 'C,\\text{out}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + bh_in:{\ + latex_label: 'b',\ + latex_superscript: 'H,\\text{in}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + bh_out:{\ + latex_label: 'b',\ + latex_superscript: 'H,\\text{out}',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + dt:{\ + latex_label: 'dt',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + dt_cu:{\ + latex_label: 'dt',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + dt_hu:{\ + latex_label: 'dt',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + fc:{\ + latex_label: 'f',\ + latex_superscript: 'C',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + fh:{\ + latex_label: 'f',\ + latex_superscript: 'H',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + reclmtd_beta:{\ + latex_label: '\\textsl{RecLMTD}',\ + latex_superscript: ltx_beta,\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + reclmtd_cu_beta:{\ + latex_label: '\\textsl{RecLMTD}',\ + latex_superscript: ltx_beta,\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + reclmtd_hu_beta:{\ + latex_label: '\\textsl{RecLMTD}',\ + latex_superscript: ltx_beta,\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + q:{\ + latex_label: 'q',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + q_cu:{\ + latex_label: 'q',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + q_hu:{\ + latex_label: 'q',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + q_beta:{\ + latex_label: 'q',\ + latex_superscript: ltx_beta,\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + q_cu_beta:{\ + latex_label: 'q',\ + latex_superscript: ltx_beta,\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + q_hu_beta:{\ + latex_label: 'q',\ + latex_superscript: ltx_beta,\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + },\ + tc:{\ + latex_label: 't',\ + latex_superscript: '(C)',\ + latex_subscript: jk_subscript,\ + subscript_indices: jk_indices,\ + all_indices: jk_indices\ + },\ + th:{\ + latex_label: 't',\ + latex_superscript: '(H)',\ + latex_subscript: ik_subscript,\ + subscript_indices: ik_indices,\ + all_indices: ik_indices\ + },\ + tcx:{\ + latex_label: 't',\ + latex_superscript: 'C',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + thx:{\ + latex_label: 't',\ + latex_superscript: 'H',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + z:{\ + latex_label: 'z',\ + latex_subscript: ijk_subscript,\ + subscript_indices: ijk_indices,\ + all_indices: ijk_indices\ + },\ + z_cu:{\ + latex_label: 'z',\ + latex_subscript: cui_subscript,\ + subscript_indices: cui_indices,\ + all_indices: cui_indices\ + },\ + z_hu:{\ + latex_label: 'z',\ + latex_subscript: huj_subscript,\ + subscript_indices: huj_indices,\ + all_indices: huj_indices\ + } +} + +def list_to_delimited_string(values, delimiter): + return str(delimiter).join(map(str, values)) + +def filter_dict(dictionary, keys): + return { k:v for k,v in dictionary.iteritems() if k in keys } + +# def order_var(var1, var2): +# if var1.pyomo_label not in var_to_subscript_map: +# return 1 +# if var2.pyomo_label not in var_to_subscript_map: +# return -1 +# var1_label_order = var_order.index(var1.pyomo_label) +# var2_label_order = var_order.index(var2.pyomo_label) +# if var1_label_order < var2_label_order : +# return -1 +# elif var1_label_order > var2_label_order: +# return 1 +# else: +# indices = var1.var_details.get(all_indices) +# for index in indices: +# if var1.index_map.get(index) < var2.index_map.get(index): +# return -1 +# elif var1.index_map.get(index) > var2.index_map.get(index): +# return 1 +# return 0 + +def order_key(var): + if var.pyomo_label not in var_to_subscript_map: + return (float('inf'),) + return (var_order.index(var.pyomo_label), ) + tuple(var.var_details.get(all_indices)) + + +class HeatVar: + def __init__(self, pyomo_label, index, value): + self.value = value + self.subscripts = [] + self.pyomo_label = pyomo_label + self.index = index if not type(index) == int else (index,) + self.init_latex_data() + + def init_latex_data(self): + if self.pyomo_label in var_to_subscript_map: + self.var_details = var_to_subscript_map.get(self.pyomo_label) + self.index_map = dict(zip(self.var_details.get(all_indices), self.index)) + else: + self.var_details = {} + self.var_details[latex_label] = '(*)' + self.pyomo_label + '-'+ str(self.index) + + def __getitem__(self, item): + return getattr(self, item) + + def to_latex(self): + latex_string = self.var_details[latex_label] + latex_string += self.build_latex_subscript() + latex_string += self.build_latex_superscript() + return latex_string + + def build_latex_subscript(self): + subscript = self.substitute_indices_into_template(latex_subscript, subscript_indices) + return '_{' + subscript + '}' if not subscript == '' else '' + + def build_latex_superscript(self): + superscript = self.substitute_indices_into_template(latex_superscript, superscript_indices) + return '^{' + superscript + '}' if not superscript == '' else '' + + def substitute_indices_into_template(self, template_key, indices_key): + template = self.var_details.get( template_key, '') + indices = self.var_details.get( indices_key, [] ) + for index in indices: + template = template.replace(index_identify(index), str(self.index_map.get(index))) + return template + + def table_row(self): + return ('$' + self.to_latex() + '$', self.value) + +def keep_variable(variable, active_hx): + if variable.pyomo_label in stream_keep_variables: + return variable.index in active_hx[stream_hx] + elif variable.pyomo_label in cu_keep_variables: + return variable.index[0] in active_hx[cu_hx] + elif variable.pyomo_label in hu_keep_variables: + return variable.index[0] in active_hx[hu_hx] + elif variable.pyomo_label in [dt]: + index = variable.index + index2 = (index[0], index[1], index[2]-1) + return index in active_hx[stream_hx] or index2 in active_hx[stream_hx] + return True + +def parse_pyomo_results(instance, active_hx): + results = [] + for var in instance.component_objects(Var): + var_str = var.name + if var_str not in ignored_vars: + for k, v in var.iteritems(): + results.append(HeatVar(var_str, k, v.value)) + + active_variables = sorted([v for v in results if keep_variable(v, active_hx)], key=order_key) + inactive_variables = sorted([v for v in results if not keep_variable(v, active_hx)], key=order_key) + + return (active_variables, inactive_variables) diff --git a/hens/beta_adaptive_model_mixer/lib/results_generator/results_builder.py b/hens/beta_adaptive_model_mixer/lib/results_generator/results_builder.py new file mode 100644 index 0000000..d343bc5 --- /dev/null +++ b/hens/beta_adaptive_model_mixer/lib/results_generator/results_builder.py @@ -0,0 +1,81 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +import json, sys, unicodedata, os, yaml +from pprint import pprint + +from pyomo.environ import * + +from . import heat_var + +from .document_builder import * +from .feasibility_checker import check_feasibility + +from ..constants import * + +try: + from pylatex import * + + def build_heat_exchanger_results_doc(results, folders, append, iter_num, datafile_model, filename, instance, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances, iteration): + + check_feasibility(instance) + level = 0 + + beta = instance.Beta + tac = value(instance.TAC) + + outputFilename = filename + check_folder_structure(folders, iteration) + + doc = Document() + add_preamble(doc) + + doc.append(NoEscape(r'\section{Summary}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_summary(datafile_model, append, iter_num, tac, local_time, total_time, epsilons, tolerances, doc, level) + + doc.append(NoEscape(r'\clearpage')) + + doc.append(NoEscape(r'\section{Results}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_active_results_table(doc, results, level) + doc.append(NoEscape(r'\clearpage')) + + doc.append(NoEscape(r'\section{$\textsl{RecLMTD}^\beta$ Tangent Points}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_reclmtd_beta_results(instance, active_hx, errors, doc, level) + generate_reclmtd_beta_graphs(instance, active_hx, old_points, doc, level) + + doc.append(NoEscape(r'\clearpage')) + + doc.append(NoEscape(r'\section{Balancing Breakpoints}')) + add_balancing_results(instance, active_hx, old_points, errors, doc, level) + generate_balancing_graphs(instance, active_hx, old_points, doc, level) + + doc.append(NoEscape(r'\clearpage')) + doc.append(NoEscape(r'\section{$\text{q}^\beta$ Breakpoints}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_q_beta_results(instance, active_hx, old_points, errors, doc, level) + add_q_beta_graphs(instance, active_hx, old_points, doc, level) + + doc.append(NoEscape(r'\clearpage')) + doc.append(NoEscape(r'\section{Area $q \beta$ Breakpoints}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_area_beta_results(instance, active_hx, old_points, errors, doc, level) + add_area_beta_graphs(instance, active_hx, old_points, doc, level) + + doc.append(NoEscape(r'\clearpage')) + doc.append(NoEscape(r'\section{Other variables}')) + doc.append(NoEscape(r'\thispagestyle{plain}')) + add_inactive_results_table(results, doc, level) + + save_pdf(doc, filename, folders, iteration) +except ImportError: + def build_heat_exchanger_results_doc(results, folders, append, iter_num, datafile_model, filename, instance, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances, iteration): + check_folder_structure(folders, iteration) + with open(os.path.join(folders[iterations_folder], filename + '.txt'), 'w') as f: + f.write('You don\'t have pylatex. Install it with pip for results summary.\n') + +def build_heat_exchanger_results(instance, folders, append, iter_num, datafile_model, filename, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances, iteration=False): + results = heat_var.parse_pyomo_results(instance, active_hx) + build_heat_exchanger_results_doc(results, folders, append, iter_num, datafile_model, filename, instance, active_hx, old_points, errors, local_time, total_time, epsilons, tolerances, iteration) diff --git a/hens/datafiles/model1.dat b/hens/datafiles/model1.dat new file mode 100644 index 0000000..82f9552 --- /dev/null +++ b/hens/datafiles/model1.dat @@ -0,0 +1,33 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +# parameters for model: http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen1.html + +param Alpha := 150; +param Beta := 1; +param Cost_hx := 5500; +param Cost_cu := 15; +param Cost_hu := 80; +param Delta_t_min := 10; + +param Number_stages := 2; +param Number_hot_stream := 2; +param Number_cold_stream := 2; + +param : Th_in Th_out Fh Hh := +1 650 370 10 1 +2 590 370 20 1 +; + +param : Tc_in Tc_out Fc Hc := +1 410 650 15 1 +2 350 500 13 1 +; + +param T_cu_in := 300; +param T_cu_out := 320; +param H_cu := 1; + +param T_hu_in := 680; +param T_hu_out := 680; +param H_hu := 5; diff --git a/hens/datafiles/model2.dat b/hens/datafiles/model2.dat new file mode 100644 index 0000000..5984934 --- /dev/null +++ b/hens/datafiles/model2.dat @@ -0,0 +1,35 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +# parameters for model: http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen2.html + +param Alpha := 1200; +param Beta := 0.6; +param Cost_hx := 5500; +param Cost_cu := 10; +param Cost_hu := 140; +param Delta_t_min := 10; + +param Number_stages := 2; +param Number_hot_stream := 5; +param Number_cold_stream := 1; + +param : Th_in Th_out Fh Hh := +1 500 320 6 2 +2 480 380 4 2 +3 460 360 6 2 +4 380 360 20 2 +5 380 320 12 2 +; + +param : Tc_in Tc_out Fc Hc := +1 290 660 18 2 +; + +param H_cu := 2; +param T_cu_in := 300; +param T_cu_out := 320; + +param H_hu := 2; +param T_hu_in := 700; +param T_hu_out := 700; diff --git a/hens/datafiles/model3.dat b/hens/datafiles/model3.dat new file mode 100644 index 0000000..83d8b37 --- /dev/null +++ b/hens/datafiles/model3.dat @@ -0,0 +1,39 @@ +# Authors: Miten Mistry and Ruth Misener +# Department of Computing, Imperial College London + +# parameters for model: http://www.gamsworld.org/minlp/minlplib2/html/heatexch_gen3.html + +param Alpha := 146; +param Beta := 0.6; +param Cost_hx := 4000; +param Cost_cu := 10; +param Cost_hu := 200; +param Delta_t_min := 10; + +param Number_stages := 2; +param Number_hot_stream := 5; +param Number_cold_stream := 5; + +param : Th_in Th_out Hh Fh := +1 160 93.3 1.7 8.8 +2 248.9 137.8 1.7 10.6 +3 226.7 65.6 1.7 14.8 +4 271.1 148.9 1.7 12.6 +5 198.9 65.6 1.7 17.7 +; + +param : Tc_in Tc_out Hc Fc := +1 60 160 1.7 7.6 +2 115.6 221.7 1.7 6.1 +3 37.8 221.1 1.7 8.4 +4 82.2 176.7 1.7 17.3 +5 93.3 204.4 1.7 13.9 +; + +param H_cu := 1.7; +param T_cu_in := 25; +param T_cu_out := 40; + +param H_hu := 3.4; +param T_hu_in := 240; +param T_hu_out := 240;