1 # -------------------------------------------------------------------------
2 # Copyright (c) 2018 AT&T Intellectual Property
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # -------------------------------------------------------------------------
21 from collections import defaultdict
24 from .pci_utils import get_id,mapping
26 BASE_DIR = os.path.dirname(__file__)
27 cell_id_mapping = dict()
28 id_cell_mapping = dict()
30 def pci_optimize(network_cell_info, cell_info_list, request_json):
31 global cell_id_mapping, id_cell_mapping
32 cell_id_mapping, id_cell_mapping = mapping(network_cell_info)
33 original_pcis = get_original_pci_list(network_cell_info)
34 unchangeable_pcis = get_ids_of_fixed_pci_cells(request_json['cellInfo'].get('fixedPCICells', []))
35 neighbor_edges = get_neighbor_list(network_cell_info)
36 second_level_edges = get_second_level_neighbor(network_cell_info)
37 ignorable_links = get_ignorable_links(network_cell_info, request_json)
38 anr_flag = is_anr(request_json)
40 dzn_data = build_dzn_data(cell_info_list, ignorable_links, neighbor_edges, second_level_edges, anr_flag, original_pcis, unchangeable_pcis)
42 return build_pci_solution(dzn_data, ignorable_links, anr_flag)
44 def get_ids_of_fixed_pci_cells(fixed_pci_list):
46 for cell in fixed_pci_list:
47 fixed_pci_ids.add(cell_id_mapping[cell])
51 def get_cell_id_pci_mapping(network_cell_info):
52 original_pcis = dict()
53 for cell in network_cell_info['cell_list']:
54 for nbr in cell['nbr_list']:
55 if cell_id_mapping[nbr['targetCellId']] not in original_pcis:
56 original_pcis[cell_id_mapping[nbr['targetCellId']]] = nbr['pciValue']
60 def get_original_pci_list(network_cell_info):
61 cell_id_pci_mapping = get_cell_id_pci_mapping(network_cell_info)
62 original_pcis_list = []
63 for i in range(len(cell_id_pci_mapping)):
64 original_pcis_list.append(cell_id_pci_mapping.get(i))
65 return original_pcis_list
68 def build_pci_solution(dzn_data, ignorable_links, anr_flag):
69 mzn_solution = solve(get_mzn_model(anr_flag), dzn_data)
70 if mzn_solution == 'UNSATISFIABLE':
72 solution = {'pci': mzn_solution[0]['pci']}
75 removables = defaultdict(list)
76 used_ignorables = mzn_solution[0]['used_ignorables']
78 for i in ignorable_links:
79 if used_ignorables[index] > 0:
80 removables[i[0]].append(i[1])
82 solution['removables'] = removables
86 def build_dzn_data(cell_info_list, ignorable_links, neighbor_edges, second_level_edges, anr_flag,original_pcis, unchangeable_pcis):
88 'NUM_NODES': len(cell_info_list),
89 'NUM_PCIS': len(cell_info_list),
90 'NUM_NEIGHBORS': len(neighbor_edges),
91 'NEIGHBORS': get_list(neighbor_edges),
92 'NUM_SECOND_LEVEL_NEIGHBORS': len(second_level_edges),
93 'SECOND_LEVEL_NEIGHBORS': get_list(second_level_edges),
94 'PCI_UNCHANGEABLE_CELLS': unchangeable_pcis,
95 'ORIGINAL_PCIS': original_pcis
98 dzn_data['NUM_IGNORABLE_NEIGHBOR_LINKS'] = len(ignorable_links)
99 dzn_data['IGNORABLE_NEIGHBOR_LINKS'] = get_list(ignorable_links)
103 def get_mzn_model(anr_flag):
105 mzn_model = os.path.join(BASE_DIR, 'min_confusion_inl.mzn')
107 mzn_model = os.path.join(BASE_DIR, 'no_conflicts_no_confusion.mzn')
111 def is_anr(request_json):
112 return 'pci-anr' in request_json["requestInfo"]["optimizers"]
115 def get_list(edge_list):
118 array_list.append([s[0], s[1]])
119 return sorted(array_list)
122 def solve(mzn_model, dzn_data):
123 return pymzn.minizinc(mzn=mzn_model, data=dzn_data)
126 def get_neighbor_list(network_cell_info):
127 neighbor_list = set()
128 for cell in network_cell_info['cell_list']:
129 add_to_neighbor_list(network_cell_info, cell, neighbor_list)
133 def add_to_neighbor_list(network_cell_info, cell, neighbor_list):
134 for nbr in cell.get('nbr_list', []):
136 nbr_id = get_id(network_cell_info, nbr['targetCellId'])
137 if nbr_id and host_id != nbr_id:
138 neighbor_list.add((host_id, nbr_id))
141 def get_second_level_neighbor(network_cell_info):
142 second_neighbor_list = set()
143 for cell in network_cell_info['cell_list']:
144 comb_list = build_second_level_list(network_cell_info, cell)
145 for comb in comb_list:
146 if comb[0] and comb[1]:
147 second_neighbor_list.add((comb[0], comb[1]))
148 return sorted(second_neighbor_list)
151 def build_second_level_list(network_cell_info, cell):
153 for nbr in cell.get('nbr_list', []):
154 second_nbr_list.append(get_id(network_cell_info, nbr['targetCellId']))
155 return [list(elem) for elem in list(itertools.combinations(second_nbr_list, 2))]
158 def get_ignorable_links(network_cell_info, request_json):
159 ignorable_list = set()
160 anr_input_list = request_json["cellInfo"].get('anrInputList', [])
162 for anr_info in anr_input_list:
163 cell_id = get_id(network_cell_info, anr_info['cellId'])
164 anr_removable = anr_info.get('removeableNeighbors', [])
165 for anr in anr_removable:
166 ignorable_list.add((cell_id, get_id(network_cell_info, anr)))
167 return ignorable_list