function [R_tau, tau_opt] = tau_opt_cal(k, lambda, gamma)
% This function calculates the optimal values of z and tau based on Proposition 4.1

u_min = 0; u_max = 1e1;
flag = 0;

% first find the optimal value of u and z based on known lambda and gamma
while flag == 0
    u = mean([u_min, u_max]);
    z_opt = zeros(1, k);
    
    for i = 1 : k
        syms x
        % find the value of z satisfying equation (18) in the paper
        z_opt(i) = solve(log(1+x) - x/1+x == u/lambda(i) * log(2), x);
    end
    
    % calculate the value of the left-hand side of (19)
    s_z = sum(lambda .* gamma ./ (1 + z_opt));
    if abs(s_z - u * log(2)) <= 1e-3 % if equation (19) holds
        flag = 1;
    elseif s_z < u * log(2)
        u_max = u;
    elseif s_z > u * log(2)
        u_min = u;
    end
end

% based on the obtained u and z, calculate the optimal tau based on Proposition 4.1
tau_opt = zeros(1, k+1);
tau_opt(1) = 1 / ( 1 + sum(gamma./z_opt) );
R_tau = zeros(1, k);
for i = 1 : k
    tau_opt(i+1) = gamma(i) / z_opt(i) / (1 + sum(gamma./z_opt) );
    if tau_opt(i+1) == 0
        R_tau(i)  = 0;
    else
        R_tau(i) = tau_opt(i+1) * log2(1 + gamma(i) * tau_opt(1) / tau_opt(i+1));
    end
end