nodes: 0, module; 1, function_definition; 2, function_name:_get_efron_values_single; 3, parameters; 4, block; 5, identifier:self; 6, identifier:X; 7, identifier:T; 8, identifier:E; 9, identifier:weights; 10, identifier:beta; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, expression_statement; 15, expression_statement; 16, comment:# Init risk and tie sums to zero; 17, expression_statement; 18, expression_statement; 19, expression_statement; 20, expression_statement; 21, comment:# Init number of ties and weights; 22, expression_statement; 23, expression_statement; 24, expression_statement; 25, comment:# Iterate backwards to utilize recursive relationship; 26, for_statement; 27, return_statement; 28, comment:"""
          Calculates the first and second order vector differentials, with respect to beta.
          Note that X, T, E are assumed to be sorted on T!
  
          A good explanation for Efron. Consider three of five subjects who fail at the time.
          As it is not known a priori that who is the first to fail, so one-third of
          (φ1 + φ2 + φ3) is adjusted from sum_j^{5} φj after one fails. Similarly two-third
          of (φ1 + φ2 + φ3) is adjusted after first two individuals fail, etc.
  
          From https://cran.r-project.org/web/packages/survival/survival.pdf:
  
          "Setting all weights to 2 for instance will give the same coefficient estimate but halve the variance. When
          the Efron approximation for ties (default) is employed replication of the data will not give exactly the same coefficients as the
          weights option, and in this case the weighted fit is arguably the correct one."
  
          Parameters
          ----------
          X: array
              (n,d) numpy array of observations.
          T: array
              (n) numpy array representing observed durations.
          E: array
              (n) numpy array representing death events.
          weights: array
              (n) an array representing weights per observation.
          beta: array
              (1, d) numpy array of coefficients.
  
          Returns
          -------
          hessian:
              (d, d) numpy array,
          gradient:
              (1, d) numpy array
          log_likelihood: float
          """; 29, assignment; 30, assignment; 31, assignment; 32, assignment; 33, assignment; 34, assignment; 35, assignment; 36, assignment; 37, assignment; 38, assignment; 39, assignment; 40, identifier:i; 41, call; 42, comment:# Doing it like this to preserve shape; 43, block; 44, expression_list; 45, pattern_list; 46, attribute; 47, identifier:hessian; 48, call; 49, identifier:gradient; 50, call; 51, identifier:log_lik; 52, integer:0; 53, identifier:x_death_sum; 54, call; 55, pattern_list; 56, expression_list; 57, pattern_list; 58, expression_list; 59, pattern_list; 60, expression_list; 61, identifier:weight_count; 62, float:0.0; 63, identifier:tied_death_counts; 64, integer:0; 65, identifier:scores; 66, binary_operator:weights * np.exp(np.dot(X, beta)); 67, identifier:range; 68, argument_list; 69, expression_statement; 70, expression_statement; 71, expression_statement; 72, expression_statement; 73, expression_statement; 74, comment:# Calculate phi values; 75, expression_statement; 76, expression_statement; 77, expression_statement; 78, comment:# Calculate sums of Risk set; 79, expression_statement; 80, expression_statement; 81, expression_statement; 82, comment:# Calculate sums of Ties, if this is an event; 83, if_statement; 84, if_statement; 85, comment:# There was atleast one event and no more ties remain. Time to sum.; 86, comment:#; 87, comment:# This code is near identical to the _batch algorithm below. In fact, see _batch for comments.; 88, comment:#; 89, expression_statement; 90, if_statement; 91, expression_statement; 92, expression_statement; 93, expression_statement; 94, expression_statement; 95, expression_statement; 96, comment:# reset tie values; 97, expression_statement; 98, expression_statement; 99, expression_statement; 100, expression_statement; 101, expression_statement; 102, expression_statement; 103, identifier:hessian; 104, identifier:gradient; 105, identifier:log_lik; 106, identifier:n; 107, identifier:d; 108, identifier:X; 109, identifier:shape; 110, attribute; 111, argument_list; 112, attribute; 113, argument_list; 114, attribute; 115, argument_list; 116, identifier:risk_phi; 117, identifier:tie_phi; 118, integer:0; 119, integer:0; 120, identifier:risk_phi_x; 121, identifier:tie_phi_x; 122, call; 123, call; 124, identifier:risk_phi_x_x; 125, identifier:tie_phi_x_x; 126, call; 127, call; 128, identifier:weights; 129, call; 130, binary_operator:n - 1; 131, unary_operator; 132, unary_operator; 133, assignment; 134, assignment; 135, assignment; 136, assignment; 137, assignment; 138, assignment; 139, assignment; 140, assignment; 141, assignment; 142, assignment; 143, assignment; 144, identifier:ei; 145, block; 146, boolean_operator; 147, comment:# There are more ties/members of the risk set; 148, block; 149, elif_clause; 150, assignment; 151, comparison_operator:tied_death_counts > 1; 152, block; 153, else_clause; 154, assignment; 155, assignment; 156, assignment; 157, assignment; 158, assignment; 159, assignment; 160, assignment; 161, assignment; 162, assignment; 163, assignment; 164, assignment; 165, identifier:np; 166, identifier:zeros; 167, tuple; 168, identifier:np; 169, identifier:zeros; 170, tuple; 171, identifier:np; 172, identifier:zeros; 173, tuple; 174, attribute; 175, argument_list; 176, attribute; 177, argument_list; 178, attribute; 179, argument_list; 180, attribute; 181, argument_list; 182, attribute; 183, argument_list; 184, identifier:n; 185, integer:1; 186, integer:1; 187, integer:1; 188, identifier:ti; 189, subscript; 190, identifier:ei; 191, subscript; 192, identifier:xi; 193, subscript; 194, identifier:score; 195, subscript; 196, identifier:w; 197, subscript; 198, identifier:phi_i; 199, identifier:score; 200, identifier:phi_x_i; 201, binary_operator:phi_i * xi; 202, identifier:phi_x_x_i; 203, call; 204, identifier:risk_phi; 205, binary_operator:risk_phi + phi_i; 206, identifier:risk_phi_x; 207, binary_operator:risk_phi_x + phi_x_i; 208, identifier:risk_phi_x_x; 209, binary_operator:risk_phi_x_x + phi_x_x_i; 210, expression_statement; 211, expression_statement; 212, expression_statement; 213, expression_statement; 214, comment:# Keep track of count; 215, expression_statement; 216, expression_statement; 217, comparison_operator:i > 0; 218, comparison_operator:T[i - 1] == ti; 219, continue_statement; 220, comparison_operator:tied_death_counts == 0; 221, comment:# Only censored with current time, move on; 222, block; 223, identifier:weighted_average; 224, binary_operator:weight_count / tied_death_counts; 225, identifier:tied_death_counts; 226, integer:1; 227, expression_statement; 228, expression_statement; 229, expression_statement; 230, expression_statement; 231, block; 232, identifier:summand; 233, binary_operator:numer * denom[:, None]; 234, identifier:a2; 235, call; 236, identifier:gradient; 237, binary_operator:gradient + x_death_sum - weighted_average * summand.sum(0); 238, identifier:log_lik; 239, binary_operator:log_lik + np.dot(x_death_sum, beta) + weighted_average * np.log(denom).sum(); 240, identifier:hessian; 241, binary_operator:hessian + weighted_average * (a2 - a1); 242, identifier:tied_death_counts; 243, integer:0; 244, identifier:weight_count; 245, float:0.0; 246, identifier:x_death_sum; 247, call; 248, identifier:tie_phi; 249, integer:0; 250, identifier:tie_phi_x; 251, call; 252, identifier:tie_phi_x_x; 253, call; 254, identifier:d; 255, identifier:d; 256, identifier:d; 257, identifier:d; 258, identifier:np; 259, identifier:zeros; 260, tuple; 261, identifier:np; 262, identifier:zeros; 263, tuple; 264, identifier:np; 265, identifier:zeros; 266, tuple; 267, identifier:np; 268, identifier:zeros; 269, tuple; 270, identifier:np; 271, identifier:exp; 272, call; 273, identifier:T; 274, identifier:i; 275, identifier:E; 276, identifier:i; 277, identifier:X; 278, identifier:i; 279, identifier:scores; 280, identifier:i; 281, identifier:weights; 282, identifier:i; 283, identifier:phi_i; 284, identifier:xi; 285, attribute; 286, argument_list; 287, identifier:risk_phi; 288, identifier:phi_i; 289, identifier:risk_phi_x; 290, identifier:phi_x_i; 291, identifier:risk_phi_x_x; 292, identifier:phi_x_x_i; 293, assignment; 294, assignment; 295, assignment; 296, assignment; 297, augmented_assignment; 298, augmented_assignment; 299, identifier:i; 300, integer:0; 301, subscript; 302, identifier:ti; 303, identifier:tied_death_counts; 304, integer:0; 305, continue_statement; 306, identifier:weight_count; 307, identifier:tied_death_counts; 308, assignment; 309, assignment; 310, assignment; 311, assignment; 312, expression_statement; 313, expression_statement; 314, expression_statement; 315, identifier:numer; 316, subscript; 317, attribute; 318, argument_list; 319, binary_operator:gradient + x_death_sum; 320, binary_operator:weighted_average * summand.sum(0); 321, binary_operator:log_lik + np.dot(x_death_sum, beta); 322, binary_operator:weighted_average * np.log(denom).sum(); 323, identifier:hessian; 324, binary_operator:weighted_average * (a2 - a1); 325, attribute; 326, argument_list; 327, attribute; 328, argument_list; 329, attribute; 330, argument_list; 331, identifier:d; 332, identifier:d; 333, identifier:d; 334, identifier:d; 335, identifier:d; 336, identifier:d; 337, attribute; 338, argument_list; 339, identifier:np; 340, identifier:outer; 341, identifier:xi; 342, identifier:phi_x_i; 343, identifier:x_death_sum; 344, binary_operator:x_death_sum + w * xi; 345, identifier:tie_phi; 346, binary_operator:tie_phi + phi_i; 347, identifier:tie_phi_x; 348, binary_operator:tie_phi_x + phi_x_i; 349, identifier:tie_phi_x_x; 350, binary_operator:tie_phi_x_x + phi_x_x_i; 351, identifier:tied_death_counts; 352, integer:1; 353, identifier:weight_count; 354, identifier:w; 355, identifier:T; 356, binary_operator:i - 1; 357, identifier:increasing_proportion; 358, binary_operator:np.arange(tied_death_counts) / tied_death_counts; 359, identifier:denom; 360, binary_operator:1.0 / (risk_phi - increasing_proportion * tie_phi); 361, identifier:numer; 362, binary_operator:risk_phi_x - np.outer(increasing_proportion, tie_phi_x); 363, identifier:a1; 364, binary_operator:np.einsum("ab,i->ab", risk_phi_x_x, denom) - np.einsum(
                      "ab,i->ab", tie_phi_x_x, increasing_proportion * denom
                  ); 365, assignment; 366, assignment; 367, assignment; 368, identifier:denom; 369, slice; 370, None; 371, attribute; 372, identifier:dot; 373, identifier:summand; 374, identifier:gradient; 375, identifier:x_death_sum; 376, identifier:weighted_average; 377, call; 378, identifier:log_lik; 379, call; 380, identifier:weighted_average; 381, call; 382, identifier:weighted_average; 383, parenthesized_expression; 384, identifier:np; 385, identifier:zeros; 386, tuple; 387, identifier:np; 388, identifier:zeros; 389, tuple; 390, identifier:np; 391, identifier:zeros; 392, tuple; 393, identifier:np; 394, identifier:dot; 395, identifier:X; 396, identifier:beta; 397, identifier:x_death_sum; 398, binary_operator:w * xi; 399, identifier:tie_phi; 400, identifier:phi_i; 401, identifier:tie_phi_x; 402, identifier:phi_x_i; 403, identifier:tie_phi_x_x; 404, identifier:phi_x_x_i; 405, identifier:i; 406, integer:1; 407, call; 408, identifier:tied_death_counts; 409, float:1.0; 410, parenthesized_expression; 411, identifier:risk_phi_x; 412, call; 413, call; 414, call; 415, identifier:denom; 416, binary_operator:1.0 / np.array([risk_phi]); 417, identifier:numer; 418, identifier:risk_phi_x; 419, identifier:a1; 420, binary_operator:risk_phi_x_x * denom; 421, identifier:summand; 422, identifier:T; 423, attribute; 424, argument_list; 425, attribute; 426, argument_list; 427, attribute; 428, argument_list; 429, binary_operator:a2 - a1; 430, identifier:d; 431, identifier:d; 432, identifier:d; 433, identifier:d; 434, identifier:w; 435, identifier:xi; 436, attribute; 437, argument_list; 438, binary_operator:risk_phi - increasing_proportion * tie_phi; 439, attribute; 440, argument_list; 441, attribute; 442, argument_list; 443, attribute; 444, argument_list; 445, float:1.0; 446, call; 447, identifier:risk_phi_x_x; 448, identifier:denom; 449, identifier:summand; 450, identifier:sum; 451, integer:0; 452, identifier:np; 453, identifier:dot; 454, identifier:x_death_sum; 455, identifier:beta; 456, call; 457, identifier:sum; 458, identifier:a2; 459, identifier:a1; 460, identifier:np; 461, identifier:arange; 462, identifier:tied_death_counts; 463, identifier:risk_phi; 464, binary_operator:increasing_proportion * tie_phi; 465, identifier:np; 466, identifier:outer; 467, identifier:increasing_proportion; 468, identifier:tie_phi_x; 469, identifier:np; 470, identifier:einsum; 471, string:"ab,i->ab"; 472, identifier:risk_phi_x_x; 473, identifier:denom; 474, identifier:np; 475, identifier:einsum; 476, string:"ab,i->ab"; 477, identifier:tie_phi_x_x; 478, binary_operator:increasing_proportion * denom; 479, attribute; 480, argument_list; 481, attribute; 482, argument_list; 483, identifier:increasing_proportion; 484, identifier:tie_phi; 485, identifier:increasing_proportion; 486, identifier:denom; 487, identifier:np; 488, identifier:array; 489, list; 490, identifier:np; 491, identifier:log; 492, identifier:denom; 493, identifier:risk_phi
code: def _get_efron_values_single(self, X, T, E, weights, beta):
          """
          Calculates the first and second order vector differentials, with respect to beta.
          Note that X, T, E are assumed to be sorted on T!
  
          A good explanation for Efron. Consider three of five subjects who fail at the time.
          As it is not known a priori that who is the first to fail, so one-third of
          (φ1 + φ2 + φ3) is adjusted from sum_j^{5} φj after one fails. Similarly two-third
          of (φ1 + φ2 + φ3) is adjusted after first two individuals fail, etc.
  
          From https://cran.r-project.org/web/packages/survival/survival.pdf:
  
          "Setting all weights to 2 for instance will give the same coefficient estimate but halve the variance. When
          the Efron approximation for ties (default) is employed replication of the data will not give exactly the same coefficients as the
          weights option, and in this case the weighted fit is arguably the correct one."
  
          Parameters
          ----------
          X: array
              (n,d) numpy array of observations.
          T: array
              (n) numpy array representing observed durations.
          E: array
              (n) numpy array representing death events.
          weights: array
              (n) an array representing weights per observation.
          beta: array
              (1, d) numpy array of coefficients.
  
          Returns
          -------
          hessian:
              (d, d) numpy array,
          gradient:
              (1, d) numpy array
          log_likelihood: float
          """
  
          n, d = X.shape
          hessian = np.zeros((d, d))
          gradient = np.zeros((d,))
          log_lik = 0
  
          # Init risk and tie sums to zero
          x_death_sum = np.zeros((d,))
          risk_phi, tie_phi = 0, 0
          risk_phi_x, tie_phi_x = np.zeros((d,)), np.zeros((d,))
          risk_phi_x_x, tie_phi_x_x = np.zeros((d, d)), np.zeros((d, d))
  
          # Init number of ties and weights
          weight_count = 0.0
          tied_death_counts = 0
          scores = weights * np.exp(np.dot(X, beta))
  
          # Iterate backwards to utilize recursive relationship
          for i in range(n - 1, -1, -1):
              # Doing it like this to preserve shape
              ti = T[i]
              ei = E[i]
              xi = X[i]
              score = scores[i]
              w = weights[i]
  
              # Calculate phi values
              phi_i = score
              phi_x_i = phi_i * xi
              phi_x_x_i = np.outer(xi, phi_x_i)
  
              # Calculate sums of Risk set
              risk_phi = risk_phi + phi_i
              risk_phi_x = risk_phi_x + phi_x_i
              risk_phi_x_x = risk_phi_x_x + phi_x_x_i
  
              # Calculate sums of Ties, if this is an event
              if ei:
                  x_death_sum = x_death_sum + w * xi
                  tie_phi = tie_phi + phi_i
                  tie_phi_x = tie_phi_x + phi_x_i
                  tie_phi_x_x = tie_phi_x_x + phi_x_x_i
  
                  # Keep track of count
                  tied_death_counts += 1
                  weight_count += w
  
              if i > 0 and T[i - 1] == ti:
                  # There are more ties/members of the risk set
                  continue
              elif tied_death_counts == 0:
                  # Only censored with current time, move on
                  continue
  
              # There was atleast one event and no more ties remain. Time to sum.
              #
              # This code is near identical to the _batch algorithm below. In fact, see _batch for comments.
              #
              weighted_average = weight_count / tied_death_counts
  
              if tied_death_counts > 1:
                  increasing_proportion = np.arange(tied_death_counts) / tied_death_counts
                  denom = 1.0 / (risk_phi - increasing_proportion * tie_phi)
                  numer = risk_phi_x - np.outer(increasing_proportion, tie_phi_x)
                  a1 = np.einsum("ab,i->ab", risk_phi_x_x, denom) - np.einsum(
                      "ab,i->ab", tie_phi_x_x, increasing_proportion * denom
                  )
              else:
                  denom = 1.0 / np.array([risk_phi])
                  numer = risk_phi_x
                  a1 = risk_phi_x_x * denom
  
              summand = numer * denom[:, None]
              a2 = summand.T.dot(summand)
  
              gradient = gradient + x_death_sum - weighted_average * summand.sum(0)
  
              log_lik = log_lik + np.dot(x_death_sum, beta) + weighted_average * np.log(denom).sum()
              hessian = hessian + weighted_average * (a2 - a1)
  
              # reset tie values
              tied_death_counts = 0
              weight_count = 0.0
              x_death_sum = np.zeros((d,))
              tie_phi = 0
              tie_phi_x = np.zeros((d,))
              tie_phi_x_x = np.zeros((d, d))
  
          return hessian, gradient, log_lik