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
25 from .pci_utils import get_id
27 BASE_DIR = os.path.dirname(__file__)
30 def pci_optimize(network_cell_info, cell_info_list, request_json):
31 neighbor_edges = get_neighbor_list(network_cell_info)
32 second_level_edges = get_second_level_neighbor(network_cell_info)
33 ignorable_links = get_ignorable_links(network_cell_info, request_json)
34 anr_flag = is_anr(request_json)
36 dzn_data = build_dzn_data(cell_info_list, ignorable_links, neighbor_edges, second_level_edges, anr_flag)
38 return build_pci_solution(dzn_data, ignorable_links, anr_flag)
41 def build_pci_solution(dzn_data, ignorable_links, anr_flag):
42 mzn_solution = solve(get_mzn_model(anr_flag), dzn_data)
44 solution = {'pci': mzn_solution[0]['pci']}
47 removables = defaultdict(list)
48 used_ignorables = mzn_solution[0]['used_ignorables']
50 for i in ignorable_links:
51 if used_ignorables[index] > 0:
52 removables[i[0]].append(i[1])
54 solution['removables'] = removables
58 def build_dzn_data(cell_info_list, ignorable_links, neighbor_edges, second_level_edges, anr_flag):
60 'NUM_NODES': len(cell_info_list),
61 'NUM_PCIS': len(cell_info_list),
62 'NUM_NEIGHBORS': len(neighbor_edges),
63 'NEIGHBORS': get_list(neighbor_edges),
64 'NUM_SECOND_LEVEL_NEIGHBORS': len(second_level_edges),
65 'SECOND_LEVEL_NEIGHBORS': get_list(second_level_edges)
68 dzn_data['NUM_IGNORABLE_NEIGHBOR_LINKS'] = len(ignorable_links)
69 dzn_data['IGNORABLE_NEIGHBOR_LINKS'] = get_list(ignorable_links)
73 def get_mzn_model(anr_flag):
75 mzn_model = os.path.join(BASE_DIR, 'min_confusion_inl.mzn')
77 mzn_model = os.path.join(BASE_DIR, 'no_conflicts_no_confusion.mzn')
81 def is_anr(request_json):
82 return 'pci-anr' in request_json["requestInfo"]["optimizers"]
85 def get_list(edge_list):
88 array_list.append([s[0], s[1]])
89 return sorted(array_list)
92 def solve(mzn_model, dzn_data):
93 return pymzn.minizinc(mzn=mzn_model, data=dzn_data)
96 def get_neighbor_list(network_cell_info):
98 for cell in network_cell_info['cell_list']:
99 add_to_neighbor_list(network_cell_info, cell, neighbor_list)
103 def add_to_neighbor_list(network_cell_info, cell, neighbor_list):
104 for nbr in cell.get('nbr_list', []):
106 nbr_id = get_id(network_cell_info, nbr['cellId'])
107 if nbr_id and host_id != nbr_id:
108 neighbor_list.add((host_id, nbr_id))
111 def get_second_level_neighbor(network_cell_info):
112 second_neighbor_list = set()
113 for cell in network_cell_info['cell_list']:
114 comb_list = build_second_level_list(network_cell_info, cell)
115 for comb in comb_list:
116 if comb[0] and comb[1]:
117 second_neighbor_list.add((comb[0], comb[1]))
118 return sorted(second_neighbor_list)
121 def build_second_level_list(network_cell_info, cell):
123 for nbr in cell.get('nbr_list', []):
124 second_nbr_list.append(get_id(network_cell_info, nbr['cellId']))
125 return [list(elem) for elem in list(itertools.combinations(second_nbr_list, 2))]
128 def get_ignorable_links(network_cell_info, request_json):
129 ignorable_list = set()
130 anr_input_list = request_json["cellInfo"].get('anrInputList', [])
132 for anr_info in anr_input_list:
133 cell_id = get_id(network_cell_info, anr_info['cellId'])
134 anr_removable = anr_info.get('removeableNeighbors', [])
135 for anr in anr_removable:
136 ignorable_list.add((cell_id, get_id(network_cell_info, anr)))
137 return ignorable_list