/* * Encog(tm) Examples v2.4 * http://www.heatonresearch.com/encog/ * http://code.google.com/p/encog-java/ * * Copyright 2008-2010 by Heaton Research Inc. * * Released under the LGPL. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * * Encog and Heaton Research are Trademarks of Heaton Research, Inc. * For information on Heaton Research trademarks, visit: * * http://www.heatonresearch.com/copyright.html */ package org.encog.examples.neural.boltzmann; import org.encog.neural.data.bipolar.BiPolarNeuralData; import org.encog.neural.networks.BasicNetwork; import org.encog.neural.networks.logic.BoltzmannLogic; import org.encog.neural.pattern.BoltzmannPattern; public class BoltzTSP { public static final int NUM_CITIES = 10; public static final int NEURON_COUNT = NUM_CITIES * NUM_CITIES; private double gamma = 7; private double[][] distance; public double sqr(double x) { return x * x; } public void createCities() { double x1, x2, y1, y2; double alpha1, alpha2; this.distance = new double[NUM_CITIES][NUM_CITIES]; for (int n1 = 0; n1 < NUM_CITIES; n1++) { for (int n2 = 0; n2 < NUM_CITIES; n2++) { alpha1 = ((double) n1 / NUM_CITIES) * 2 * Math.PI; alpha2 = ((double) n2 / NUM_CITIES) * 2 * Math.PI; x1 = Math.cos(alpha1); y1 = Math.sin(alpha1); x2 = Math.cos(alpha2); y2 = Math.sin(alpha2); distance[n1][n2] = Math.sqrt(sqr(x1 - x2) + sqr(y1 - y2)); } } } public boolean isValidTour(BiPolarNeuralData data) { int cities, stops; for (int n1 = 0; n1 < NUM_CITIES; n1++) { cities = 0; stops = 0; for (int n2 = 0; n2 < NUM_CITIES; n2++) { if (data.getBoolean(n1 * NUM_CITIES + n2)) { if (++cities > 1) return false; } if (data.getBoolean(n2 * NUM_CITIES + n1)) { if (++stops > 1) return false; } } if ((cities != 1) || (stops != 1)) return false; } return true; } public double lengthOfTour(BiPolarNeuralData data) { double result; int n1, n2, n3; result = 0; for (n1 = 0; n1 < NUM_CITIES; n1++) { for (n2 = 0; n2 < NUM_CITIES; n2++) { if (data.getBoolean(((n1) % NUM_CITIES) * NUM_CITIES + n2)) break; } for (n3 = 0; n3 < NUM_CITIES; n3++) { if (data.getBoolean(((n1 + 1) % NUM_CITIES) * NUM_CITIES + n3)) break; } result += distance[n2][n3]; } return result; } String displayTour(BiPolarNeuralData data) { StringBuilder result = new StringBuilder(); int n1, n2; boolean first; for (n1 = 0; n1 < NUM_CITIES; n1++) { first = true; result.append("["); for (n2 = 0; n2 < NUM_CITIES; n2++) { if (data.getBoolean(n1 * NUM_CITIES + n2)) { if (first) { first = false; result.append(n2); } else { result.append(", " + n2); } } } result.append("]"); if (n1 != NUM_CITIES - 1) { result.append(" -> "); } } return result.toString(); } public void calculateWeights(BasicNetwork network) { BoltzmannLogic logic = (BoltzmannLogic)network.getLogic(); for (int sourceTour = 0; sourceTour < NUM_CITIES; sourceTour++) { for (int sourceCity = 0; sourceCity < NUM_CITIES; sourceCity++) { int sourceIndex = sourceTour * NUM_CITIES + sourceCity; for (int targetTour = 0; targetTour < NUM_CITIES; targetTour++) { for (int targetCity = 0; targetCity < NUM_CITIES; targetCity++) { int targetIndex = targetTour * NUM_CITIES + targetCity; double weight = 0; if (sourceIndex != targetIndex) { int predTargetTour = (targetTour == 0 ? NUM_CITIES - 1 : targetTour - 1); int succTargetTour = (targetTour == NUM_CITIES - 1 ? 0 : targetTour + 1); if ((sourceTour == targetTour) || (sourceCity == targetCity)) weight = -gamma; else if ((sourceTour == predTargetTour) || (sourceTour == succTargetTour)) weight = -distance[sourceCity][targetCity]; } logic.getThermalSynapse().getMatrix().set(sourceIndex, targetIndex, weight); } } logic.getThermalLayer().setBiasWeight(sourceIndex, -gamma / 2); } } } public void run() { BoltzmannPattern pattern = new BoltzmannPattern(); pattern.setInputNeurons(NEURON_COUNT); BasicNetwork network = pattern.generate(); BoltzmannLogic logic = (BoltzmannLogic)network.getLogic(); createCities(); calculateWeights(network); logic.setTemperature(100); do { logic.establishEquilibrium(); System.out.println(logic.getTemperature()+" : "+displayTour(logic.getCurrentState())); logic.decreaseTemperature(0.99); } while (!isValidTour(logic.getCurrentState())); System.out.println("Final Length: " + this.lengthOfTour(logic.getCurrentState()) ); } public static void main(String[] args) { BoltzTSP program = new BoltzTSP(); program.run(); } }