package inport.ConversionUtils; import inport.*; import java.io.*; import java.util.*; public class MZnResultsResolver { private static int resolveDimension(String str) { str = str.trim(); if (str.equals("{}")) { return 0; } int pos = str.indexOf(".."); int lim1 = Integer.parseInt(str.substring(0, pos)); int lim2 = Integer.parseInt(str.substring(pos + 2, str.length())); return lim2 - lim1 + 1; } public static ArrayList> parse2dArray(int pos, String line, TaskCase taskCase) { int index = line.indexOf("array", pos); if (line.indexOf("[[", pos) != -1) { // Из opl. if (line.contains("[[[")) { return null; } index = line.indexOf("[[", pos); index++; ArrayList> res = new ArrayList<>(); while (true) { int i1 = line.indexOf("[", index); int i2 = line.indexOf("]", index); if (i1 == -1) { break; } res.add(new ArrayList<>()); for (String val : line.substring(i1 + 1, i2).split(" ")) { res.get(res.size() - 1).add(val.trim()); } index = i2 + 1; } return res; } if (index >= pos) { // Из flatzinc-а. if (line.charAt(index + "array".length()) == '2') { String[] values = line.substring(line.indexOf('[') + 1, line.indexOf(']')).split(","); String[] items = line.substring(line.indexOf('(', pos) + 1, line.indexOf('[')).split(","); int dim1 = resolveDimension(items[0]); int dim2 = resolveDimension(items[1]); ArrayList> res = new ArrayList<>(); for (int i = 0; i < dim1; i++) { res.add(new ArrayList<>()); for (int j = 0; j < dim2; j++) { res.get(i).add(values[i * dim2 + j].trim()); } } return res; } } else { // Из minizinc-а while ((pos < line.length()) && (line.charAt(pos) != '[') && (line.charAt(pos) != '{')) { pos++; } if (pos == line.length()) { return null; } int arrayFirstDim = ((int) taskCase.getPlanningInterval()) + 2; if (line.charAt(pos) == '{') { pos++; int nextPos = pos; while (line.charAt(nextPos) != '}') { nextPos++; } String[] dimensions = line.substring(pos, nextPos).trim().split(" "); if (dimensions.length > 0) { arrayFirstDim = Integer.valueOf(dimensions[0].trim()); } pos = nextPos + 1; while (line.charAt(pos) != '[') { pos++; } } int pos2 = pos; while ((pos2 < line.length()) && (line.charAt(pos2) != ']')) { pos2++; } String values = line.substring(pos + 1, pos2); ArrayList elements = new ArrayList<>(); for (String val : values.split(",")) { elements.add(val.trim()); } if ((arrayFirstDim != 0) && (elements.size() % arrayFirstDim == 0)) { ArrayList> res = new ArrayList<>(); for (int i = 0; i < elements.size(); i += arrayFirstDim) { ArrayList subRes = new ArrayList<>(); for (int j = 0; j < arrayFirstDim; j++) { subRes.add(elements.get(i + j)); } res.add(subRes); } return res; } } return null; } public static void resolveMiniZincResults(TaskCase taskCase, String fileName) { ArrayList operations = null; Integer result = null; try (FileInputStream fstream = new FileInputStream(fileName)) { BufferedReader br = new BufferedReader(new InputStreamReader(fstream)); Map>> arrays = new TreeMap<>(); ArrayList lines = new ArrayList<>(); { StringBuilder stringBuilder = new StringBuilder(); String line; while (((line = br.readLine()) != null)) { if ((line.length() > 0) && (line.charAt(0) == ' ')) { stringBuilder.append(line); } else { lines.add(stringBuilder.toString()); stringBuilder = new StringBuilder(line); } } lines.add(stringBuilder.toString()); } for (String line : lines) { line = line.trim(); if (line.equals("")) { continue; } int pos = 0; while ((pos < line.length()) && (line.charAt(pos) != ' ')) { pos++; } String name = line.substring(0, pos); if (name.equals("=====UNSATISFIABLE=====")) { result = -1; break; } if (name.equals("----------")) { break; } if ((name.matches("\\d+")) || (name.equals("//"))) { continue; } { ArrayList> res = parse2dArray(pos, line, taskCase); if (res != null) { arrays.put(name, res); } } } for (String keyArray : Arrays.asList("op_status", "participation_as_resource")) { if (! arrays.containsKey(keyArray)) { if ((result != null) && (result == -1)) { operations = new ArrayList<>(); } else { throw new ParserException("No \"" + keyArray + "\" in input"); } } } for (ArrayList a : arrays.get("op_status")) { // Если op_status из opl. for (int i = 0; i < a.size(); i++) { if (a.get(i).trim().equals("0")) { a.set(i, "false"); } else if (a.get(i).trim().equals("1")) { a.set(i, "true"); } } } if (result == null) { ArrayList> opStatus = arrays.get("op_status"); result = 0; for (ArrayList a : opStatus) { for (int i = 0; i < a.size(); i++) { if (a.get(i).trim().equals("true")) { result = Math.max(result, i); } } } } if (result != -1) { Task task = new Task(taskCase, ""); operations = new ArrayList<>(); ArrayList> opStatus = arrays.get("op_status"); ArrayList templates = new ArrayList<>(taskCase.getTemplates()); if (taskCase.isTypified()) { templates = Task.renumberOperations(taskCase); } ArrayList> cargoOpIntensity; if (arrays.containsKey("cargo_op_intensity")) { // Явные нецелые операции. cargoOpIntensity = arrays.get("cargo_op_intensity"); } else if (arrays.containsKey("real_cargo_value")) { // Жадный алгоритм. cargoOpIntensity = arrays.get("real_cargo_value"); for (ArrayList a : cargoOpIntensity) { for (int i = 0; i < a.size(); i++) { a.set(i, Integer.toString(Math.abs(Integer.valueOf(a.get(i))))); } } } else { cargoOpIntensity = new ArrayList<>(); for (int opNo = 0; opNo < opStatus.size(); opNo++) { cargoOpIntensity.add(new ArrayList<>()); for (String val : opStatus.get(opNo)) { if (val.equals("true") && (templates.get(opNo - 1) instanceof LoadingTemplate)) { LoadingTemplate op = (LoadingTemplate)templates.get(opNo - 1); cargoOpIntensity.get(opNo).add(Integer.toString((int)Math.ceil(Math.abs(op.getIntensity())))); } else { cargoOpIntensity.get(opNo).add("0"); } } } } Map operationById = new TreeMap<>(); for (OperationTemplate operation : taskCase.getTemplates()) { operationById.put(operation.getId(), operation); } Map objByNo = new TreeMap<>(); ArrayList> isFixed; for (MovingObject obj : task.getMovingObjects()) { objByNo.put(task.getMObjNumberById().get(obj.getId()), obj); } isFixed = task.getIsFixedArray(); Set oldSolution = new TreeSet<>(); for (Operation op : taskCase.getFixedOperations()) { if (op.getFixation()) { oldSolution.add(op.toString()); } } for (int opNo = 1; opNo < opStatus.size(); opNo++) { int duration = 0; int t = 1; boolean lastFixation = false; while (t < opStatus.get(opNo).size()) { boolean isOpLogicallyInterrupted = false; if (opStatus.get(opNo).get(t).equals("true") && (lastFixation != isFixed.get(opNo).get(t)) && (duration != 0)) { // У операции изменилась фиксация. isOpLogicallyInterrupted = true; } if (opStatus.get(opNo).get(t).equals("false") && (duration != 0)) { // Операция просто закончилась. isOpLogicallyInterrupted = true; } if ((! cargoOpIntensity.get(opNo).get(t - 1).equals(cargoOpIntensity.get(opNo).get(t))) && (duration != 0)) { // Изменилась интенсивность погрузки. isOpLogicallyInterrupted = true; } if (isOpLogicallyInterrupted) { // Добавляем новую операцию. Operation op = new Operation(); op.setStart(t - duration - 1); op.setDuration(duration); op.setTemplate(operationById.get(templates.get(opNo - 1).getId())); if (taskCase.isTypified()) { op.setExecutor(Utils.getExecutor(templates.get(opNo - 1))); ArrayList resources = new ArrayList<>(); // TODO ускорить. ArrayList> opOfResource = arrays.get("participation_as_resource"); for (int obj = 1; obj < opOfResource.size(); obj++) { if (opOfResource.get(obj).get(t - 1).equals(Integer.toString(opNo))) { resources.add(objByNo.get(obj - 1)); } } op.setResources(resources); } { // Установка бункеровщика. OperationTemplate template = templates.get(opNo - 1); if (template instanceof LoadingTemplate) { LoadingTemplate operation = (LoadingTemplate)template; if (operation.getBunker().isPresent()) { op.setBunker(operation.getBunker()); } } } if (! cargoOpIntensity.get(opNo).get(t - 1).equals("0")) { int intensity = Integer.valueOf(cargoOpIntensity.get(opNo).get(t - 1)); if (((LoadingTemplate)op.getTemplate()).getIntensity() < 0) { intensity *= -1; } op.setIntensity(Optional.of(intensity)); } op.setFixation(true); if (! oldSolution.contains(op.toString())) { op.setFixation(false); } operations.add(op); duration = 0; } if (opStatus.get(opNo).get(t).equals("true") && (lastFixation != isFixed.get(opNo).get(t))) { // Остаёмся на месте. lastFixation = isFixed.get(opNo).get(t); continue; } if (opStatus.get(opNo).get(t).equals("true")) { duration++; } else { duration = 0; } if ((0 <= t) && (t < isFixed.get(opNo).size())) { lastFixation = isFixed.get(opNo).get(t); } t++; } } } taskCase.setSolution(operations); taskCase.setSolution_result(result); } catch (IOException e) { throw new UncheckedIOException(e); } } }