"""Utility / helper functions for j-UFLP: used save / load / draw instances."""
import json
from jUFLP_cavemen import jUFLPEncoder
[docs]def save_inst(i1, i2, join_map, filename):
    """Saves the jUFLP instance to ``.json`` file.
    The file contains the following objects
    - ``inst1`` and ``inst2`` -- description of the two
      sub-instances, with identical structure containing
      the following records:
       - `S`: a list of neighborhood lists,
       - `f`: a list of lists of overlap costs,
       - `c`: a list of facility location costs.
       - `caves`: a parameter describing the points allocated to each "cave"
         (was used in legacy experiments)
    """
    with open(filename, "w") as fout:
        fout.write(json.dumps({
            'inst1':{
                'S':i1[0],
                'f':i1[1],
                'c':i1[2],
                'caves': i1[3]},
            'inst2':{
                'S':i2[0],
                'f':i2[1],
                'c':i2[2],
                'caves': i2[3]},
            'jmap':{int(j): join_map[j] for j in join_map}},
                              cls=jUFLPEncoder)) 
[docs]def load_inst(filename):
    """Loads a jUFLP instance from ``.json`` file.
    Returns:
      [[S,f,c,caves], [S2,f2,c2,caves], jmap]
    """
    with open(filename, "r") as fin:
        json_inst = fin.read()
    json_dct = json.loads(json_inst)
    return [[json_dct[f'inst{i}']['S'],
            json_dct[f'inst{i}']['f'],
            json_dct[f'inst{i}']['c'],
            json_dct[f'inst{i}']['caves']]
            for i in [1, 2]] + [{int(j1): json_dct['jmap'][j1]
                                 for j1 in json_dct['jmap']}] 
[docs]def draw_jUFLP_inst(i1, i2, link, filename="tmp/jUFLP.dot"):
    """Saves an instance to a ``.dot`` file."""
    with open(filename, "w") as fout:
        fout.write("graph G {\n")
        for (inst, no, pref) in [(i1, 1, 'f'), (i2, 2, 's')]:
            S, f, c, caves = inst
            fout.write(f"    subgraph cluster_{no-1}" +
                       " {\n")  # encoding a sub-instance
            fout.write(f'        color=blue; label="sub-UFLP-{no}";')
            added = set([])
            for i in range(len(S)):
                for j in S[i]:
                    if ((i+1) != j) and not (((j, (i+1)) in added)
                                             or ((i+1, j) in added)):
                        fout.write(f"        {pref}{i+1}--{pref}{j};\n")
                        added.add(((i+1), j))
            fout.write("    };\n")  # end of sub-instance
        for j in link:
            fout.write(f"    f{j} -- s{link[j]}[color=red, style=dashed, penwidth=1];\n")
        fout.write("}")