function [V_predicted, lambda_predicted, J] = cpf_predict(Ybus, ref, pv, pq, V, lambda, sigma, type_predict, initQPratio, loadvarloc, flag_lambdaIncrease)
% function: do prediction in cpf 
% [INPUT PARAMETERS]
% type_predict: 1-predict voltage; 2-predict lambda
% loadvarloc: (in internal bus numbering)
% [OUTPUT PARAMETERS]
% J: jacobian matrix for the given voltage profile (before prediction)
% created by Rui Bo on 2007/11/12

%% set up indexing
npv = length(pv);
npq = length(pq);

pv_bus = ~isempty(find(pv == loadvarloc));

%% form current variable set from given voltage
x_current = [ angle(V([pv;pq]));
              abs(V(pq));
              lambda];

%% evaluate Jacobian
[dSbus_dVm, dSbus_dVa] = dSbus_dV(Ybus, V);

j11 = real(dSbus_dVa([pv; pq], [pv; pq]));
j12 = real(dSbus_dVm([pv; pq], pq));
j21 = imag(dSbus_dVa(pq, [pv; pq]));
j22 = imag(dSbus_dVm(pq, pq));

J = [   j11 j12;
        j21 j22;    ];

%% form K
K = zeros(npv+2*npq, 1);
if pv_bus % pv bus
    K(find(pv == loadvarloc)) = -1;                         % corresponding to deltaP
else % pq bus
    K(npv + find(pq == loadvarloc)) = -1;                   % corresponding to deltaP
    K(npv + npq + find(pq == loadvarloc)) = -initQPratio;   % corresponding to deltaQ
end

%% form e
e = zeros(1, npv+2*npq+1);
if type_predict == 1 % predict voltage
    if flag_lambdaIncrease == true
        e(npv+2*npq+1) = 1; % dLambda = 1
    else
        e(npv+2*npq+1) = -1; % dLambda = -1
    end
elseif type_predict == 2 % predict lambda
    e(npv+npq+find(pq == loadvarloc)) = -1; % dVm = -1
else
    fprintf('Error: unknow ''type_predict''.\n');
    pause
end

%% form b
b = zeros(npv+2*npq+1, 1);
b(npv+2*npq+1) = 1;

%% form augmented Jacobian
%NOTE: the use of '-J' instead of 'J' is due to that the definition of
%dP(,dQ) in the textbook is the negative of the definition in MATPOWER. In
%the textbook, dP=Pinj-Pbus; In MATPOWER, dP=Pbus-Pinj. Therefore, the
%Jacobians generated by the two definitions differ only in the sign.
augJ = [-J K;   
        e   ];

%% calculate predicted variable set
x_predicted = x_current + sigma*(augJ\b);

%% convert variable set to voltage form
V_predicted([ref], 1) = V([ref]);
V_predicted([pv], 1) = abs(V([pv])).* exp(sqrt(-1) * x_predicted([1:npv]) );
V_predicted([pq], 1) = x_predicted([npv+npq+1:npv+2*npq]).* exp(sqrt(-1) * x_predicted([npv+1:npv+npq]) );
lambda_predicted = x_predicted(npv+2*npq+1);
