<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">import java.util.ArrayList;
import java.util.List;

/* this program simulates learning in recurrent Hopfield networks.
	it will tell you what the stable states are and what their energy value is.
	For this task we don't need to know if the activation is synchronous or not
	(since when a neuron changes its value -then we call it an "active" neuron,
	the only information we store is "not a stable state")
	*/
class Hopfield {
	/* important: the n * n matrix with symmetric connection weights.
	   it suffices to fill the upper right half with values (a Hopfield net
	   requires symmetric weights -e.g. xy = yx-, and this program can read all
	   the values from only there, so there's no need to write every 
	   value twice). Just leave the other weights to zero or whatever.
	   Remember that there is no connection from a neuron to itself, so
	   every xy-connection has to be zero when x=y !
	*/
	private static float[][] connections = {{ 0, 3,-1, 0, 0},
				 							{ 0, 0,-2, 1, 2},
											{ 0, 0, 0, 2, 1},
											{ 0, 0, 0, 0,-2},
				 							{ 0, 0, 0, 0, 0}};
	//this vector must be n digits long - these are the thresholds
	private static float[] bias_weights = {0,0,0,0,0};
	
	private static List stable_states = new ArrayList();
	//(a)synchrounous updating?
	private static boolean synchronous = false;

	public static void main(String[] args) {
		int[][] states = permutateStates(bias_weights.length);
		
		//search stable states
		for(int x=0; x &lt; states.length; x++) {
			int[] state = computeState(states[x]);
			if (isStable(state)) addToStableStates(state);
		}
		
		System.out.println("The stable states are:");
		
		for(int x=0; x &lt; stable_states.size(); x++) {
			System.out.print("(");
			int[] a_state = (int[]) stable_states.get(x);
			printArray(a_state);
			System.out.println(") with energy " + energy(a_state));
		}
	}
	
	private static void addToStableStates(int[] state) {
		if (isAlreadyStable(state)) return;
		stable_states.add(state);
	}
	
	private static int[] computeState(int[] state) {
		int[] new_state = new int[state.length];
		for(int x=0; x &lt; new_state.length; x++) {
		 	float value = computeNeuron(state, x);
			
			int new_val = state[x];
			if (value &gt; 0) new_val = 1;
			else if (value &lt; 0) new_val = -1;
			new_state[x] = new_val;
			
			if (!synchronous) state[x] = new_val;
		 }
		 return new_state;
	}
	
	private static float computeNeuron(int[] state, int index) {
		float sum = 0;
		for(int x=0; x &lt; connections[index].length; x++) {
			if (x != index) {
				//this trick helps us not to write every connection weight twice
				if (index &lt; x) sum += state[x] * connections[index][x];
				else sum += state[x] * connections[x][index];
			}
		}
		sum += state[index] * bias_weights[index];
		return sum;
	}
	
	private static int[][] permutateStates(int num) {
		int poww=2; for(int i=2;i&lt;=num;i++) poww = poww * 2;	//my own power function
		int [][] states = new int[poww][num];
		for(int x=poww-1; x &gt;= 0; x--) {
			int tmp = x;
			for(int y = num-1; y &gt;= 0; y--) {
				int rest = tmp % 2;
				states[x][y] = (rest == 1) ? 1 : -1;
				tmp = tmp/2;
			}
		}
		return states;
	}
	
	private static boolean isStable(int[] state) {
		if (isAlreadyStable(inverse(state))) return true;
		else if (equal(state, computeState(state))) return true;
		else return false;
	}
	
	private static int[] inverse(int[] state) {
		int[] inv_state = new int[state.length];
		for(int x=0; x &lt; state.length; x++) {
			inv_state[x] = (state[x] == 1) ? -1 : 1;
		}
		return inv_state;
	}
	
	private static boolean isAlreadyStable(int[] state) {
		for(int x=0; x &lt; stable_states.size(); x++) {
			int[] a_state = (int[]) stable_states.get(x);
			if (equal(a_state, state)) return true;
		}
		return false;	
	}

	private static boolean equal(int[] state1, int[] state2) {
		if (state1.length != state2.length) return false;
		boolean isEqual = true;
		for(int x=0; x &lt; state1.length; x++) {
			if (state1[x] != state2[x]) isEqual = false;
		}
		return isEqual;	
	}
	
	private static void printArray(int[] arr) {
		for(int x = arr.length-1; x &gt;= 0; x--) {
			System.out.print(arr[x] + " ");
		}
	}
	
	private static float energy(int[] state) {
		float sum = 0;
		for(int x=0; x &lt; state.length; x++) {
			for(int y=0; y &lt; connections[x].length; y++) {
				//this trick helps us not to write every connection weight twice
				if (x &lt; y)  sum += state[x] * connections[x][y] * state[y];
				else sum += state[x] * connections[y][x] * state[y];
			}
			sum += state[x] * bias_weights[x];
		}
		sum = sum * -0.5f;
		return sum;
	}
}
</pre></body></html>