/** * To reduce the search space we will only consider routes that start and end at one city * (whichever is first in the collection). All other possible routes are equivalent to one of * these routes since start city is irrelevant in determining the shortest cycle. * * @param cities The list of destinations, each of which must be visited once. * @param progressListener Call-back for receiving the status of the algorithm as it progresses. * May be null. * @return The shortest route that visits each of the specified cities once. */ public List<String> calculateShortestRoute( Collection<String> cities, ProgressListener progressListener) { Iterator<String> iterator = cities.iterator(); String startCity = iterator.next(); Collection<String> destinations = new ArrayList<String>(cities.size() - 1); while (iterator.hasNext()) { destinations.add(iterator.next()); } FitnessEvaluator<List<String>> evaluator = new RouteEvaluator(distances); PermutationGenerator<String> generator = new PermutationGenerator<String>(destinations); long totalPermutations = generator.getTotalPermutations(); long count = 0; List<String> shortestRoute = null; double shortestDistance = Double.POSITIVE_INFINITY; List<String> currentRoute = new ArrayList<String>(cities.size()); while (generator.hasMore()) { List<String> route = generator.nextPermutationAsList(currentRoute); route.add(0, startCity); double distance = evaluator.getFitness(route, null); if (distance < shortestDistance) { shortestDistance = distance; shortestRoute = new ArrayList<String>(route); } ++count; if (count % 1000 == 0 && progressListener != null) { progressListener.updateProgress(((double) count) / totalPermutations * 100); } } if (progressListener != null) { progressListener.updateProgress(100); // Finished. } return shortestRoute; }
public void analyzeInnerClasses(ProgressListener pl, double done, double scale) { double subScale = scale / innerComplexity; // If output should be immediate, we delay analyzation to output. // Note that this may break anonymous classes, but the user // has been warned. if ((Options.options & Options.OPTION_IMMEDIATE) != 0) return; // Now analyze the inner classes. for (int j = 0; j < inners.length; j++) { if (pl != null) { double innerCompl = inners[j].getComplexity() * subScale; if (innerCompl > STEP_COMPLEXITY) { double innerscale = subScale * inners[j].methodComplexity; inners[j].analyze(pl, done, innerscale); inners[j].analyzeInnerClasses(null, done + innerscale, innerCompl - innerscale); } else { pl.updateProgress(done, inners[j].name); inners[j].analyze(null, 0.0, 0.0); inners[j].analyzeInnerClasses(null, 0.0, 0.0); } done += innerCompl; } else { inners[j].analyze(null, 0.0, 0.0); inners[j].analyzeInnerClasses(null, 0.0, 0.0); } } // Now analyze the method scoped classes. for (int j = 0; j < methods.length; j++) methods[j].analyzeInnerClasses(); }
public void dumpJavaFile(TabbedPrintWriter writer, ProgressListener pl) throws IOException { imports.init(clazz.getName()); LocalInfo.init(); initialize(); double done = 0.05; double scale = (0.75) * methodComplexity / (methodComplexity + innerComplexity); analyze(pl, INITIALIZE_COMPLEXITY, scale); done += scale; analyzeInnerClasses(pl, done, 0.8 - done); makeDeclaration(new SimpleSet()); imports.dumpHeader(writer); dumpSource(writer, pl, 0.8, 0.2); if (pl != null) pl.updateProgress(1.0, name); }
public void dumpBlock(TabbedPrintWriter writer, ProgressListener pl, double done, double scale) throws IOException { double subScale = scale / getComplexity(); writer.pushScope(this); boolean needFieldNewLine = false; boolean needNewLine = false; Set declared = null; if ((Options.options & Options.OPTION_IMMEDIATE) != 0) declared = new SimpleSet(); for (int i = 0; i < fields.length; i++) { if (blockInitializers[i] != null) { if (needNewLine) writer.println(); writer.openBrace(); writer.tab(); blockInitializers[i].dumpSource(writer); writer.untab(); writer.closeBrace(); needFieldNewLine = needNewLine = true; } if ((Options.options & Options.OPTION_IMMEDIATE) != 0) { // We now do the analyzation we skipped before. fields[i].analyze(); fields[i].makeDeclaration(declared); } if (fields[i].skipWriting()) continue; if (needFieldNewLine) writer.println(); fields[i].dumpSource(writer); needNewLine = true; } if (blockInitializers[fields.length] != null) { if (needNewLine) writer.println(); writer.openBrace(); writer.tab(); blockInitializers[fields.length].dumpSource(writer); writer.untab(); writer.closeBrace(); needNewLine = true; } for (int i = 0; i < inners.length; i++) { if (needNewLine) writer.println(); if ((Options.options & Options.OPTION_IMMEDIATE) != 0) { // We now do the analyzation we skipped before. inners[i].analyze(null, 0.0, 0.0); inners[i].analyzeInnerClasses(null, 0.0, 0.0); inners[i].makeDeclaration(declared); } if (pl != null) { double innerCompl = inners[i].getComplexity() * subScale; if (innerCompl > STEP_COMPLEXITY) inners[i].dumpSource(writer, pl, done, innerCompl); else { pl.updateProgress(done, name); inners[i].dumpSource(writer); } done += innerCompl; } else inners[i].dumpSource(writer); needNewLine = true; } for (int i = 0; i < methods.length; i++) { if ((Options.options & Options.OPTION_IMMEDIATE) != 0) { // We now do the analyzation we skipped before. if (!methods[i].isConstructor()) methods[i].analyze(null, 0.0, 0.0); methods[i].analyzeInnerClasses(); methods[i].makeDeclaration(declared); } if (methods[i].skipWriting()) continue; if (needNewLine) writer.println(); if (pl != null) { double methodCompl = methods[i].getComplexity() * subScale; pl.updateProgress(done, methods[i].getName()); methods[i].dumpSource(writer); done += methodCompl; } else methods[i].dumpSource(writer); needNewLine = true; } writer.popScope(); clazz.dropInfo(clazz.KNOWNATTRIBS | clazz.UNKNOWNATTRIBS); }
public void analyze(ProgressListener pl, double done, double scale) { if (GlobalOptions.verboseLevel > 0) GlobalOptions.err.println("Class " + name); double subScale = scale / methodComplexity; if (pl != null) pl.updateProgress(done, name); imports.useClass(clazz); if (clazz.getSuperclass() != null) imports.useClass(clazz.getSuperclass()); ClassInfo[] interfaces = clazz.getInterfaces(); for (int j = 0; j < interfaces.length; j++) imports.useClass(interfaces[j]); if (fields == null) { /* This means that the class could not be loaded. * give up. */ return; } // First analyze constructors and synthetic fields: constrAna = null; if (constructors.length > 0) { for (int j = 0; j < constructors.length; j++) { if (pl != null) { double constrCompl = constructors[j].getComplexity() * subScale; if (constrCompl > STEP_COMPLEXITY) constructors[j].analyze(pl, done, constrCompl); else { pl.updateProgress(done, name); constructors[j].analyze(null, 0.0, 0.0); } done += constrCompl; } else constructors[j].analyze(null, 0.0, 0.0); } constrAna = new TransformConstructors(this, false, constructors); constrAna.removeSynthInitializers(); } if (staticConstructor != null) { if (pl != null) { double constrCompl = staticConstructor.getComplexity() * subScale; if (constrCompl > STEP_COMPLEXITY) staticConstructor.analyze(pl, done, constrCompl); else { pl.updateProgress(done, name); staticConstructor.analyze(null, 0.0, 0.0); } done += constrCompl; } else staticConstructor.analyze(null, 0.0, 0.0); } // If output should be immediate, we delay analyzation to output. // Note that this may break anonymous classes, but the user // has been warned. if ((Options.options & Options.OPTION_IMMEDIATE) != 0) return; // Analyze fields for (int j = 0; j < fields.length; j++) fields[j].analyze(); // Now analyze remaining methods. for (int j = 0; j < methods.length; j++) { if (!methods[j].isConstructor()) if (pl != null) { double methodCompl = methods[j].getComplexity() * subScale; if (methodCompl > STEP_COMPLEXITY) methods[j].analyze(pl, done, methodCompl); else { pl.updateProgress(done, methods[j].getName()); methods[j].analyze(null, 0.0, 0.0); } done += methodCompl; } else methods[j].analyze(null, 0.0, 0.0); } }
/** * Construct the singular value decomposition * * @param Arg Rectangular matrix * @return Structure to access U, S and V. */ public SingularValueDecomposition( double[][] A, ProgressListener progressListener, ThreadMaster threadMaster) { // Derived from LINPACK code. // Initialize. m = A.length; n = A[0].length; int nu = Math.min(m, n); s = new double[Math.min(m + 1, n)]; U = new double[m][nu]; V = new double[n][n]; double[] e = new double[n]; double[] work = new double[m]; boolean wantu = true; boolean wantv = true; // Reduce A to bidiagonal form, storing the diagonal elements // in s and the super-diagonal elements in e. int nct = Math.min(m - 1, n); int nrt = Math.max(0, Math.min(n - 2, m)); if (progressListener != null) progressListener.startProgress("Initializing SVD...", 0, Math.max(nct, nrt)); for (int k = 0; k < Math.max(nct, nrt); k++) { if (progressListener != null) progressListener.updateProgress(k); if (threadMaster != null && threadMaster.threadMustDie()) return; if (k < nct) { // Compute the transformation for the k-th column and // place the k-th diagonal in s[k]. // Compute 2-norm of k-th column without under/overflow. s[k] = 0; for (int i = k; i < m; i++) { s[k] = hypot(s[k], A[i][k]); } if (s[k] != 0.0) { if (A[k][k] < 0.0) { s[k] = -s[k]; } for (int i = k; i < m; i++) { A[i][k] /= s[k]; } A[k][k] += 1.0; } s[k] = -s[k]; } for (int j = k + 1; j < n; j++) { if ((k < nct) & (s[k] != 0.0)) { // Apply the transformation. double t = 0; for (int i = k; i < m; i++) { t += A[i][k] * A[i][j]; } t = -t / A[k][k]; for (int i = k; i < m; i++) { A[i][j] += t * A[i][k]; } } // Place the k-th row of A into e for the // subsequent calculation of the row transformation. e[j] = A[k][j]; } if (wantu & (k < nct)) { // Place the transformation in U for subsequent back // multiplication. for (int i = k; i < m; i++) { U[i][k] = A[i][k]; } } if (k < nrt) { // Compute the k-th row transformation and place the // k-th super-diagonal in e[k]. // Compute 2-norm without under/overflow. e[k] = 0; for (int i = k + 1; i < n; i++) { e[k] = hypot(e[k], e[i]); } if (e[k] != 0.0) { if (e[k + 1] < 0.0) { e[k] = -e[k]; } for (int i = k + 1; i < n; i++) { e[i] /= e[k]; } e[k + 1] += 1.0; } e[k] = -e[k]; if ((k + 1 < m) & (e[k] != 0.0)) { // Apply the transformation. for (int i = k + 1; i < m; i++) { work[i] = 0.0; } for (int j = k + 1; j < n; j++) { for (int i = k + 1; i < m; i++) { work[i] += e[j] * A[i][j]; } } for (int j = k + 1; j < n; j++) { double t = -e[j] / e[k + 1]; for (int i = k + 1; i < m; i++) { A[i][j] += t * work[i]; } } } if (wantv) { // Place the transformation in V for subsequent // back multiplication. for (int i = k + 1; i < n; i++) { V[i][k] = e[i]; } } } } // Set up the final bidiagonal matrix or order p. int p = Math.min(n, m + 1); if (nct < n) { s[nct] = A[nct][nct]; } if (m < p) { s[p - 1] = 0.0; } if (nrt + 1 < p) { e[nrt] = A[nrt][p - 1]; } e[p - 1] = 0.0; // If required, generate U. if (wantu) { if (progressListener != null) progressListener.startProgress("generating eigenvalues...", 0, nct); for (int j = nct; j < nu; j++) { for (int i = 0; i < m; i++) { U[i][j] = 0.0; } U[j][j] = 1.0; } for (int k = nct - 1; k >= 0; k--) { if (progressListener != null) progressListener.updateProgress(nct - k); if (threadMaster != null && threadMaster.threadMustDie()) return; if (s[k] != 0.0) { for (int j = k + 1; j < nu; j++) { double t = 0; for (int i = k; i < m; i++) { t += U[i][k] * U[i][j]; } t = -t / U[k][k]; for (int i = k; i < m; i++) { U[i][j] += t * U[i][k]; } } for (int i = k; i < m; i++) { U[i][k] = -U[i][k]; } U[k][k] = 1.0 + U[k][k]; for (int i = 0; i < k - 1; i++) { U[i][k] = 0.0; } } else { for (int i = 0; i < m; i++) { U[i][k] = 0.0; } U[k][k] = 1.0; } } } // If required, generate V. if (wantv) { if (progressListener != null) progressListener.startProgress("generating eigenvectors...", 0, n); for (int k = n - 1; k >= 0; k--) { if (progressListener != null) progressListener.updateProgress(n - k); if (threadMaster != null && threadMaster.threadMustDie()) return; if ((k < nrt) & (e[k] != 0.0)) { for (int j = k + 1; j < nu; j++) { double t = 0; for (int i = k + 1; i < n; i++) { t += V[i][k] * V[i][j]; } t = -t / V[k + 1][k]; for (int i = k + 1; i < n; i++) { V[i][j] += t * V[i][k]; } } } for (int i = 0; i < n; i++) { V[i][k] = 0.0; } V[k][k] = 1.0; } } // Main iteration loop for the singular values. int pp = p - 1; int iter = 0; double eps = Math.pow(2.0, -52.0); if (progressListener != null) progressListener.startProgress("locating negligible elements...", 0, pp + 1); while (p > 0) { if (progressListener != null) progressListener.updateProgress(pp - p); if (threadMaster != null && threadMaster.threadMustDie()) return; int k, kase; // Here is where a test for too many iterations would go. // This section of the program inspects for // negligible elements in the s and e arrays. On // completion the variables kase and k are set as follows. // kase = 1 if s(p) and e[k-1] are negligible and k<p // kase = 2 if s(k) is negligible and k<p // kase = 3 if e[k-1] is negligible, k<p, and // s(k), ..., s(p) are not negligible (qr step). // kase = 4 if e(p-1) is negligible (convergence). for (k = p - 2; k >= -1; k--) { if (k == -1) { break; } if (Math.abs(e[k]) <= eps * (Math.abs(s[k]) + Math.abs(s[k + 1]))) { e[k] = 0.0; break; } } if (k == p - 2) { kase = 4; } else { int ks; for (ks = p - 1; ks >= k; ks--) { if (ks == k) { break; } double t = (ks != p ? Math.abs(e[ks]) : 0.) + (ks != k + 1 ? Math.abs(e[ks - 1]) : 0.); if (Math.abs(s[ks]) <= eps * t) { s[ks] = 0.0; break; } } if (ks == k) { kase = 3; } else if (ks == p - 1) { kase = 1; } else { kase = 2; k = ks; } } k++; // Perform the task indicated by kase. switch (kase) { // Deflate negligible s(p). case 1: { double f = e[p - 2]; e[p - 2] = 0.0; for (int j = p - 2; j >= k; j--) { double t = hypot(s[j], f); double cs = s[j] / t; double sn = f / t; s[j] = t; if (j != k) { f = -sn * e[j - 1]; e[j - 1] = cs * e[j - 1]; } if (wantv) { for (int i = 0; i < n; i++) { t = cs * V[i][j] + sn * V[i][p - 1]; V[i][p - 1] = -sn * V[i][j] + cs * V[i][p - 1]; V[i][j] = t; } } } } break; // Split at negligible s(k). case 2: { double f = e[k - 1]; e[k - 1] = 0.0; for (int j = k; j < p; j++) { double t = hypot(s[j], f); double cs = s[j] / t; double sn = f / t; s[j] = t; f = -sn * e[j]; e[j] = cs * e[j]; if (wantu) { for (int i = 0; i < m; i++) { t = cs * U[i][j] + sn * U[i][k - 1]; U[i][k - 1] = -sn * U[i][j] + cs * U[i][k - 1]; U[i][j] = t; } } } } break; // Perform one qr step. case 3: { // Calculate the shift. double scale = Math.max( Math.max( Math.max( Math.max(Math.abs(s[p - 1]), Math.abs(s[p - 2])), Math.abs(e[p - 2])), Math.abs(s[k])), Math.abs(e[k])); double sp = s[p - 1] / scale; double spm1 = s[p - 2] / scale; double epm1 = e[p - 2] / scale; double sk = s[k] / scale; double ek = e[k] / scale; double b = ((spm1 + sp) * (spm1 - sp) + epm1 * epm1) / 2.0; double c = (sp * epm1) * (sp * epm1); double shift = 0.0; if ((b != 0.0) | (c != 0.0)) { shift = Math.sqrt(b * b + c); if (b < 0.0) { shift = -shift; } shift = c / (b + shift); } double f = (sk + sp) * (sk - sp) + shift; double g = sk * ek; // Chase zeros. for (int j = k; j < p - 1; j++) { double t = hypot(f, g); double cs = f / t; double sn = g / t; if (j != k) { e[j - 1] = t; } f = cs * s[j] + sn * e[j]; e[j] = cs * e[j] - sn * s[j]; g = sn * s[j + 1]; s[j + 1] = cs * s[j + 1]; if (wantv) { for (int i = 0; i < n; i++) { t = cs * V[i][j] + sn * V[i][j + 1]; V[i][j + 1] = -sn * V[i][j] + cs * V[i][j + 1]; V[i][j] = t; } } t = hypot(f, g); cs = f / t; sn = g / t; s[j] = t; f = cs * e[j] + sn * s[j + 1]; s[j + 1] = -sn * e[j] + cs * s[j + 1]; g = sn * e[j + 1]; e[j + 1] = cs * e[j + 1]; if (wantu && (j < m - 1)) { for (int i = 0; i < m; i++) { t = cs * U[i][j] + sn * U[i][j + 1]; U[i][j + 1] = -sn * U[i][j] + cs * U[i][j + 1]; U[i][j] = t; } } } e[p - 2] = f; iter = iter + 1; } break; // Convergence. case 4: { // Make the singular values positive. if (s[k] <= 0.0) { s[k] = (s[k] < 0.0 ? -s[k] : 0.0); if (wantv) { for (int i = 0; i <= pp; i++) { V[i][k] = -V[i][k]; } } } // Order the singular values. while (k < pp) { if (s[k] >= s[k + 1]) { break; } double t = s[k]; s[k] = s[k + 1]; s[k + 1] = t; if (wantv && (k < n - 1)) { for (int i = 0; i < n; i++) { t = V[i][k + 1]; V[i][k + 1] = V[i][k]; V[i][k] = t; } } if (wantu && (k < m - 1)) { for (int i = 0; i < m; i++) { t = U[i][k + 1]; U[i][k + 1] = U[i][k]; U[i][k] = t; } } k++; } iter = 0; p--; } break; } } }
/** * Downloads to a directory represented by a {@link File} object, determining the file name from * the Content-Disposition header. * * @param url URL of file * @param base base directory in which the download is saved * @return the absolute file path of the downloaded file, or an empty string if the file could not * be downloaded */ public String download(String url, File base) { if (mHTTPClient == null) { mHTTPClient = createHTTPClient(mPrivateKey, mCertificate, mValidateCertificate); if (mHTTPClient == null) return ""; } LOGGER.info("downloading file from URL=" + url + "..."); mCurrentRequest = new HttpGet(url); // execute request CloseableHttpResponse response; try { response = mHTTPClient.execute(mCurrentRequest); } catch (IOException ex) { LOGGER.log(Level.WARNING, "can't execute request", ex); return ""; } try { int code = response.getStatusLine().getStatusCode(); // HTTP/1.1 200 OK -- other codes should throw Exceptions if (code != 200) { LOGGER.warning("invalid response code: " + code); return ""; } // get filename Header dispHeader = response.getFirstHeader("Content-Disposition"); if (dispHeader == null) { LOGGER.warning("no content header"); return ""; } String filename = parseContentDisposition(dispHeader.getValue()); // never trust incoming data filename = filename != null ? new File(filename).getName() : ""; if (filename.isEmpty()) { LOGGER.warning("no filename in content: " + dispHeader.getValue()); return ""; } // get file size long s = -1; Header lengthHeader = response.getFirstHeader("Content-Length"); if (lengthHeader == null) { LOGGER.warning("no length header"); } else { try { s = Long.parseLong(lengthHeader.getValue()); } catch (NumberFormatException ex) { LOGGER.log(Level.WARNING, "can' parse file size", ex); } } final long fileSize = s; mListener.updateProgress(s < 0 ? -2 : 0); // TODO should check for content-disposition parsing here // and choose another filename if necessary HttpEntity entity = response.getEntity(); if (entity == null) { LOGGER.warning("no entity in response"); return ""; } File destination = new File(base, filename); if (destination.exists()) { LOGGER.warning("file already exists: " + destination.getAbsolutePath()); return ""; } try (FileOutputStream out = new FileOutputStream(destination)) { CountingOutputStream cOut = new CountingOutputStream(out) { @Override protected synchronized void afterWrite(int n) { if (fileSize <= 0) return; // inform listener mListener.updateProgress((int) (this.getByteCount() / (fileSize * 1.0) * 100)); } }; entity.writeTo(cOut); } catch (IOException ex) { LOGGER.log(Level.WARNING, "can't download file", ex); return ""; } LOGGER.info("... download successful!"); return destination.getAbsolutePath(); } finally { try { response.close(); } catch (IOException ex) { LOGGER.log(Level.WARNING, "can't close response", ex); } } }
// TODO unused public void abort() { if (mCurrentRequest != null) mCurrentRequest.abort(); mListener.updateProgress(-3); }