% hopdemo.m
%
%  Simulation of a Hopfield network.
%  kornel laskowski & dave touretzky (c) 2004
%  cmu 15-782 artificial neural networks

% --+----1----+----2----+----3----+----4----+----5----+----6----+----7----+

%%%
%%% Network architecture definition
%%%

%
%           [1]-------[2]
%            | \       |
%            |  -----  |
%            |       \ |
%           [3]-------[4]
%          /   \     /   \
%         /     \   /     \
%      [5]-------[6]-------[7]
%

global W;

s = [ 0 1 0 0 1 0 0 ]'; % N x 1, binary

W = [
		 0 -1 +1 -1  0  0  0;
		-1  0  0 +3  0  0  0;
		+1  0  0 -1 +2 +1  0;
		-1 +3 -1  0  0 -2 +3;
		 0  0 +2  0  0 +1  0;
		 0  0 +1 -2 +1  0 -1;
		 0  0  0 +3  0 -1  0;
	]; % N x N, symmetric

sX = [ 2 4 2 4 1 3 5 ];
sY = [ 5 5 3 3 1 1 1 ];

% --+----1----+----2----+----3----+----4----+----5----+----6----+----7----+

%%%
%%% Sanity
%%%

N = length(s);
[Nwrow,Nwcol] = size(W);

if N ~= Nwrow
	error('number of rows in W must be the same as the length of s'); 
elseif N ~= Nwcol
	error('number of cols in W must be the same as the length of s'); 
elseif sum(sum(abs(W - W'))) > 0
	error('W must be symmetric');
elseif sum(sum(W .* eye(N))) > 0
	error('W must be zero along its diagonal');
else
	clear Nwrow, Nwcol;
end

% --+----1----+----2----+----3----+----4----+----5----+----6----+----7----+

%%%
%%% Network display
%%%

global hTab;
global energyText;
global relax_step;
global unitsPopup;
global offUnitsLegend;
global boltzmannPopup;
global relaxButton;
global stepButton;
global thermometer;
global mercuryColumn;
global temperatureLabel;
global sigmoidAxes;
global mThermTick;
global Tmax;
global T;
global nT;

pts = 0 : pi/20 : 2*pi;
xp = 0.35 * cos(pts);
yp = 0.35 * sin(pts);

clf;
whitebg(gcf,[0 0 0])
set(gcf,'Color',[0 0 0])

N = length(s);
for i=1:N

	% 1. draw the unit's connections

	for j=i+1:N
		if W(i,j) ~= 0
			line( [sX(i) sX(j)], [sY(i) sY(j)], [-1 -1], ...
				'Color', [1.0 1.0 0.0], 'LineWidth', 3 );
			text( 'Position', [(sX(i) + sX(j))/2 (sY(i) + sY(j))/2 0], ...
				'HorizontalAlignment','center', ...
				'VerticalAlignment','middle', ...
				'String', sprintf('%+d',W(i,j) ), ...
				'FontSize',12,'FontWeight','bold', ...
				'BackgroundColor', [1.0 1.0 0.0], 'Color', [0 0 0] );
		end
	end

	% 2. draw the unit

	if s(i) == 0
		h = patch( xp + sX(i), yp + sY(i), [0 0 0.5] );
		set( h, 'UserData', 0 );
	else
		h = patch( xp + sX(i), yp + sY(i), [1 0.5 0.5] );
		set( h, 'UserData', 1 );
	end
	set( h, 'buttondown', 'hopToggleUnitVal_callback' );
	hTab(i) = h;

end

axis equal
axis off

E = -0.5 * s' * W * s;

% --+----1----+----2----+----3----+----4----+----5----+----6----+----7----+

%%%
%%% Button/Textbox display
%%%

uicontrol('Style','Text', ...
	'Position', [10 390 150 18], ...
	'BackgroundColor', [1 .5 .5], 'String','On (+1)');

offUnitsLegend = uicontrol('Style','Text', ...
	'Position', [10 370 150 18], ...
	'BackgroundColor', [0 0 .5], 'String','Off (-1)', ...
	'ForegroundColor', [1 1 1]);

unitsPopup = uicontrol('Style','PopUpMenu', ...
	'Position', [10 350 150 18], ...
	'String',{'-1/+1 Units','0/1 Units'}, ...
	'Callback', 'hopToggleUnitType_callback');

boltzmannPopup = uicontrol('Style','PopUpMenu', ...
	'Position', [10 330 150 18], ...
	'String',{'Hopfield Net', 'Boltzmann Machine', 'Mean Field Approx'}, ...
	'Callback', 'hopToggleNetType_callback');

uicontrol('Style','PushButton','Position',[10 10 100 18], ...
    'BackgroundColor',[1 .5 .5],'String','Randomize', ...
    'CallBack','hopRandNet_callback');

stepButton = uicontrol('Style','PushButton','Position',[10 30 100 18], ...
    'BackgroundColor',[.5 .5 1],'String','Relax Step', ...
    'CallBack','relax_step = 0; hopRelaxNet_callback');

relaxButton = uicontrol('Style','PushButton','Position',[10 50 100 18], ...
    'BackgroundColor',[.2 .8 .2],'String','Relax', ...
    'CallBack','relax_step = 1; hopRelaxNet_callback');

energyText = uicontrol('Style','Text', ...
	'Position', [165 28 250 20], ... 
	'BackgroundColor',[.9 .5 .9], ...
	'String',sprintf('Energy  =  %g',E), ...
	'FontSize',14);

Tmax = 4;
[thermometer,mercuryColumn,temperatureLabel,mThermTick,sigmoidAxes] = ...
	hopThermometer( Tmax );
T = Tmax;
nT = 0;

% --+----1----+----2----+----3----+----4----+----5----+----6----+----7----+

