/** * The function computes the values of h and d for a given state * * @param state The state for which the values should be computed * @return An array of the form {h, d} */ private double[] _computeHD(TopSpinState state) { double h = -1.0d; double d = -1.0d; double hMax = 0; int index = 0; for (Map.Entry<Integer, SinglePDB> currentPDBEntry : this.pdbs.entrySet()) { SinglePDB currentPDB = currentPDBEntry.getValue(); int zeroToken = currentPDB.getFirstTokenInPattern(); // If the current token is a part of the pattern if (zeroToken >= 0) { this._calculateReflection(this.tokensNumber - zeroToken, state.tokens); try { double currentHValue = currentPDB.getH(this.reflectedTokens); this.allHeuristicValues[index++] = currentHValue; hMax = Math.max(hMax, currentHValue); } catch (InvalidKeyException e) { // Bypass } } } // Finally, calculate the H and D values switch (this.heuristicType) { case MAXING: { h = hMax; break; } case RANDOM: { // Insert some randomness into the calculation ... int hIndex = (Utils.sumOfArrayValues(state.tokens) - state.tokens[0] - state.tokens[3] - state.tokens[5] - state.tokens[7] - state.tokens[9]) % this.actualPDBsCount; h = this.allHeuristicValues[hIndex]; break; } default: { System.out.println( "[ERROR] Unsupported heuristic type for TopSpin puzzle: " + this.heuristicType); } } // Currently: d = h; return new double[] {h, d}; }
@Override public void setAdditionalParameter(String parameterName, String value) { switch (parameterName) { case "heuristic": { switch (value) { case "maxing": { this.heuristicType = HeuristicType.MAXING; break; } case "random-pdb": { if (this.pdbs == null || this.pdbs.size() <= 1) { System.out.println( "[ERROR] Required more than a single PDB in order to " + "allow random heuristic"); throw new IllegalArgumentException(); } this.heuristicType = HeuristicType.RANDOM; break; } default: { System.err.println("Illegal heuristic type for TopSpin domain: " + value); throw new IllegalArgumentException(); } } break; } /* case "pdbs-count": { this.pdbsCount = Integer.parseInt(value); if (this.pdbsCount <= 0 || this.pdbsCount > 2) { System.out.println("[ERROR] Invalid PDBs count: must be between 1 and 2"); throw new IllegalArgumentException(); } break; } */ // The data for a single PDB in the following format: // "<index>|<entries-count>|<tokens-array>|<filename>" case "pdb-data": { if (this.actualPDBsCount >= TopSpin.MAX_PDBS_COUNT) { System.out.println( "[ERROR] Can't deal with more than " + TopSpin.MAX_PDBS_COUNT + " pdbs"); throw new IllegalArgumentException(); } ++this.actualPDBsCount; String[] splittedPDBData = value.split("-"); assert splittedPDBData.length == 4; int index = Integer.parseInt(splittedPDBData[TopSpin.INDEX_OF_PDB_INDEX]); // Check if a PDB for the given index was already read if (this.pdbs.containsKey(index)) { SinglePDB previous = this.pdbs.get(index); System.out.println( "[WARNING] A PDB with index " + index + " was already read from " + previous.getPdbFileName()); } long entriesCount = Long.parseLong(splittedPDBData[TopSpin.INDEX_OF_PDB_ENTRIES_COUNT]); int[] tokensArray = Utils.stringToIntegerArray(splittedPDBData[TopSpin.INDEX_OF_PDB_TOKENS_ARRAY]); String pdbFileName = splittedPDBData[TopSpin.INDEX_OF_PDB_FILENAME]; SinglePDB currentPDB = new SinglePDB(entriesCount, tokensArray, pdbFileName, true); this.pdbs.put(index, currentPDB); break; } default: { System.out.println("No such parameter: " + parameterName + " (value: " + value + ")"); throw new IllegalArgumentException(); } } }