function bnode = mk_logistic_node(bnet, self)
% MK_LOGISTIC_NODE Make a node whose cond. distrib. is a logistic function.
% BNODE = MK_LOGISTIC_NODE(BNET, NODE_NUM)
%
% Pr(Q = on| X = x) = p, where Q is this node, X are its parents, and p is defined by
%   logit p = log (p/(1-p)) = log odds = w'x + b
%  => p = 1/(1+exp(-w'x + b))
% The weights w and bias b params are stored in fields called glim.w1 and glim.b1 respectively.
% w1 is the normal vector to the decision boundary. If it has a small magnitude.
% the boundary will be soft; if large, it will be hard.
% b1 is the offset for the decision boundary.
% Class 2 corresponds to the side of the decision boundary into which w points.
% Class 1 is the other side.
% e.g., consider the case where the parent values are in R^2.
%  w1 = [1  , b1 = [0]  means class 2 are points with +ve x coord.
%        0]                   class 1 "     "     "   -ve x coord.
% 
%
% The following fields control the behavior of the M step (maximize_params_softmax).
% (Note that the M step calls glmtrain, so netlab must be installed.)
% bnode.max_iter is the maximum number of steps to take (default: 10)
% bnode.verbose controls whether to print (default: 0).
% bnode.wthresh is a measure of the precision required for the value of
%    the weights W at the solution. Default: 1e-2.
% bnode.llthresh is a measure of the precision required of the objective
%     function at the solution.  Both this and the previous condition must
%     be satisfied for termination. Default: 1e-2.
% bnode.approx_hess is set to 1 if an approximation to the Hessian (which
%     assumes that all outputs are independent) is used for softmax
%     outputs. With the default value of 0 the exact Hessian (which is more
%     expensive to compute) is used.
%


bnode.verbose = 0;
bnode.wthresh = 1e-2;
bnode.llthresh = 1e-2;
bnode.approx_hess = 0;
bnode.max_iter = 10;

ns = bnet.node_sizes;
bnode.self = self;
bnode.parents = parents(bnet.adj_mat, self);

if ~subset(bnode.parents, bnet.cts_nodes)
  error('logistic nodes must have continuous parents');
end
if ~ismember(self, bnet.discrete_nodes)
  error('logistic nodes must be discrete');
end
if ns(bnode.self) ~= 2
  error('logistic nodes must be binary');
end
if length(bnode.parents) ~= 1
  error('logistic nodes must have exactly 1 parent');
end

bnode.type = 'logistic';
bnode.adjustable = 1;
bnode.parents_size = sum(ns(bnode.parents));
bnode.self_size = sum(ns(self));
bnode.sizes = [ns(bnode.parents) ns(self)];

bnode = randomize_params_logistic(bnode);
bnode = reset_ess_logistic(bnode);



