diff --git a/scripts/algorithms/StepGLM.dml b/scripts/algorithms/StepGLM.dml
deleted file mode 100644
index 213f373b1b9..00000000000
--- a/scripts/algorithms/StepGLM.dml
+++ /dev/null
@@ -1,1196 +0,0 @@
-#-------------------------------------------------------------
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-#-------------------------------------------------------------
-
-#
-# THIS SCRIPT CHOOSES A GLM REGRESSION MODEL IN A STEPWISE ALGIRITHM USING AIC
-# EACH GLM REGRESSION IS SOLVED USING NEWTON/FISHER SCORING WITH TRUST REGIONS
-#
-# INPUT PARAMETERS:
-# ---------------------------------------------------------------------------------------------
-# NAME TYPE DEFAULT MEANING
-# ---------------------------------------------------------------------------------------------
-# X String --- Location to read the matrix X of feature vectors
-# Y String --- Location to read response matrix Y with 1 column
-# B String --- Location to store estimated regression parameters (the betas)
-# S String --- Location to write the selected features ordered as computed by the algorithm
-# O String " " Location to write the printed statistics; by default is standard output
-# link Int 2 Link function code: 1 = log, 2 = Logit, 3 = Probit, 4 = Cloglog
-# yneg Double 0.0 Response value for Bernoulli "No" label, usually 0.0 or -1.0
-# icpt Int 0 Intercept presence, X columns shifting and rescaling:
-# 0 = no intercept, no shifting, no rescaling;
-# 1 = add intercept, but neither shift nor rescale X;
-# 2 = add intercept, shift & rescale X columns to mean = 0, variance = 1
-# tol Double 0.000001 Tolerance (epsilon)
-# disp Double 0.0 (Over-)dispersion value, or 0.0 to estimate it from data
-# moi Int 200 Maximum number of outer (Newton / Fisher Scoring) iterations
-# mii Int 0 Maximum number of inner (Conjugate Gradient) iterations, 0 = no maximum
-# thr Double 0.01 Threshold to stop the algorithm: if the decrease in the value of AIC falls below thr
-# no further features are being checked and the algorithm stops
-# fmt String "text" The betas matrix output format, such as "text" or "csv"
-# ---------------------------------------------------------------------------------------------
-# OUTPUT: Matrix beta, whose size depends on icpt:
-# icpt=0: ncol(X) x 1; icpt=1: (ncol(X) + 1) x 1; icpt=2: (ncol(X) + 1) x 2
-#
-# In addition, in the last run of GLM some statistics are provided in CSV format, one comma-separated name-value
-# pair per each line, as follows:
-#
-# NAME MEANING
-# -------------------------------------------------------------------------------------------
-# TERMINATION_CODE A positive integer indicating success/failure as follows:
-# 1 = Converged successfully; 2 = Maximum number of iterations reached;
-# 3 = Input (X, Y) out of range; 4 = Distribution/link is not supported
-# BETA_MIN Smallest beta value (regression coefficient), excluding the intercept
-# BETA_MIN_INDEX Column index for the smallest beta value
-# BETA_MAX Largest beta value (regression coefficient), excluding the intercept
-# BETA_MAX_INDEX Column index for the largest beta value
-# INTERCEPT Intercept value, or NaN if there is no intercept (if icpt=0)
-# DISPERSION Dispersion used to scale deviance, provided as "disp" input parameter
-# or estimated (same as DISPERSION_EST) if the "disp" parameter is <= 0
-# DISPERSION_EST Dispersion estimated from the dataset
-# DEVIANCE_UNSCALED Deviance from the saturated model, assuming dispersion == 1.0
-# DEVIANCE_SCALED Deviance from the saturated model, scaled by the DISPERSION value
-# -------------------------------------------------------------------------------------------
-#
-# HOW TO INVOKE THIS SCRIPT - EXAMPLE:
-# hadoop jar SystemDS.jar -f StepGLM.dml -nvargs X=INPUT_DIR/X Y=INPUT_DIR/Y B=OUTPUT_DIR/betas
-# S=OUTPUT_DIR_S/selected O=OUTPUT_DIR/stats link=2 yneg=-1.0 icpt=2 tol=0.00000001
-# disp=1.0 moi=100 mii=10 thr=0.01 fmt=csv
-#
-# THE StepGLM SCRIPT CURRENTLY SUPPORTS BERNOULLI DISTRIBUTION FAMILY AND THE FOLLOWING LINK FUNCTIONS ONLY!
-# - LOG
-# - LOGIT
-# - PROBIT
-# - CLOGLOG
-
-fileX = $X;
-fileY = $Y;
-fileB = $B;
-intercept_status = ifdef ($icpt, 0);
-thr = ifdef ($thr, 0.01);
-bernoulli_No_label = ifdef ($yneg, 0.0); # $yneg = 0.0;
-distribution_type = 2;
-
-bernoulli_No_label = as.double (bernoulli_No_label);
-
-# currently only the forward selection strategy in supported: start from one feature and iteratively add
-# features until AIC improves
-dir = "forward";
-
-print("BEGIN STEPWISE GLM SCRIPT");
-print ("Reading X and Y...");
-X_orig = read (fileX);
-Y = read (fileY);
-
-if (distribution_type == 2 & ncol(Y) == 1) {
- is_Y_negative = (Y == bernoulli_No_label);
- Y = cbind (1 - is_Y_negative, is_Y_negative);
- count_Y_negative = sum (is_Y_negative);
- if (count_Y_negative == 0) {
- stop ("StepGLM Input Error: all Y-values encode Bernoulli YES-label, none encode NO-label");
- }
- if (count_Y_negative == nrow(Y)) {
- stop ("StepGLM Input Error: all Y-values encode Bernoulli NO-label, none encode YES-label");
- }
-}
-
-num_records = nrow (X_orig);
-num_features = ncol (X_orig);
-
-# BEGIN STEPWISE GENERALIZED LINEAR MODELS
-
-if (dir == "forward") {
-
- continue = TRUE;
- columns_fixed = matrix (0, rows = 1, cols = num_features);
- columns_fixed_ordered = matrix (0, rows = 1, cols = 1);
-
- # X_global stores the best model found at each step
- X_global = matrix (0, rows = num_records, cols = 1);
-
- if (intercept_status == 0) {
- # Compute AIC of an empty model with no features and no intercept (all Ys are zero)
- [AIC_best] = glm_fit (X_global, Y, 0, num_features, columns_fixed_ordered, " ");
- } else {
- # compute AIC of an empty model with only intercept (all Ys are constant)
- all_ones = matrix (1, rows = num_records, cols = 1);
- [AIC_best] = glm_fit (all_ones, Y, 0, num_features, columns_fixed_ordered, " ");
- }
- print ("Best AIC without any features: " + AIC_best);
-
- # First pass to examine single features
- AICs = matrix (AIC_best, rows = 1, cols = num_features);
- parfor (i in 1:num_features) {
- [AIC_1] = glm_fit (X_orig[,i], Y, intercept_status, num_features, columns_fixed_ordered, " ");
- AICs[1,i] = AIC_1;
- }
-
- # Determine the best AIC
- column_best = 0;
- for (k in 1:num_features) {
- AIC_cur = as.scalar (AICs[1,k]);
- if ( (AIC_cur < AIC_best) & ((AIC_best - AIC_cur) > abs (thr * AIC_best)) ) {
- column_best = k;
- AIC_best = as.scalar(AICs[1,k]);
- }
- }
-
- if (column_best == 0) {
- print ("AIC of an empty model is " + AIC_best + " and adding no feature achieves more than " + (thr * 100) + "% decrease in AIC!");
- if (intercept_status == 0) {
- # Compute AIC of an empty model with no features and no intercept (all Ys are zero)
- [AIC_best] = glm_fit (X_global, Y, 0, num_features, columns_fixed_ordered, fileB);
- } else {
- # compute AIC of an empty model with only intercept (all Ys are constant)
- ###all_ones = matrix (1, rows = num_records, cols = 1);
- [AIC_best] = glm_fit (all_ones, Y, 0, num_features, columns_fixed_ordered, fileB);
- }
- };
-
- print ("Best AIC " + AIC_best + " achieved with feature: " + column_best);
- columns_fixed[1,column_best] = 1;
- columns_fixed_ordered[1,1] = column_best;
- X_global = X_orig[,column_best];
-
- while (continue) {
- # Subsequent passes over the features
- parfor (i in 1:num_features) {
- if (as.scalar(columns_fixed[1,i]) == 0) {
-
- # Construct the feature matrix
- X = cbind (X_global, X_orig[,i]);
-
- [AIC_2] = glm_fit (X, Y, intercept_status, num_features, columns_fixed_ordered, " ");
- AICs[1,i] = AIC_2;
- }
- }
-
- # Determine the best AIC
- for (k in 1:num_features) {
- AIC_cur = as.scalar (AICs[1,k]);
- if ( (AIC_cur < AIC_best) & ((AIC_best - AIC_cur) > abs (thr * AIC_best)) & (as.scalar(columns_fixed[1,k]) == 0) ) {
- column_best = k;
- AIC_best = as.scalar(AICs[1,k]);
- }
- }
-
- # cbind best found features (i.e., columns) to X_global
- if (as.scalar(columns_fixed[1,column_best]) == 0) { # new best feature found
- print ("Best AIC " + AIC_best + " achieved with feature: " + column_best);
- columns_fixed[1,column_best] = 1;
- columns_fixed_ordered = cbind (columns_fixed_ordered, as.matrix(column_best));
- if (ncol(columns_fixed_ordered) == num_features) { # all features examined
- X_global = cbind (X_global, X_orig[,column_best]);
- continue = FALSE;
- } else {
- X_global = cbind (X_global, X_orig[,column_best]);
- }
- } else {
- continue = FALSE;
- }
- }
-
- # run GLM with selected set of features
- print ("Running GLM with selected features...");
- [AIC] = glm_fit (X_global, Y, intercept_status, num_features, columns_fixed_ordered, fileB);
-
-} else {
- stop ("Currently only forward selection strategy is supported!");
-}
-
-
-################### UDFS USED IN THIS SCRIPT ##################
-
-glm_fit = function (Matrix[Double] X, Matrix[Double] Y, Int intercept_status, Double num_features_orig, Matrix[Double] Selected, String fileB) return (Double AIC) {
-
- # distribution family code: 1 = Power, 2 = Bernoulli/Binomial; currently only Bernouli distribution family is supported!
- distribution_type = 2; # $dfam = 2;
- variance_as_power_of_the_mean = 0.0; # $vpow = 0.0;
- # link function code: 0 = canonical (depends on distribution), 1 = Power, 2 = Logit, 3 = Probit, 4 = Cloglog, 5 = Cauchit;
- # currently only log (link = 1), logit (link = 2), probit (link = 3), and cloglog (link = 4) are supported!
- link_type = ifdef ($link, 2); # $link = 2;
- link_as_power_of_the_mean = 0.0; # $lpow = 0.0;
-
- dispersion = ifdef ($disp, 0.0); # $disp = 0.0;
- eps = ifdef ($tol, 0.000001); # $tol = 0.000001;
- max_iteration_IRLS = ifdef ($moi, 200); # $moi = 200;
- max_iteration_CG = ifdef ($mii, 0); # $mii = 0;
-
- variance_as_power_of_the_mean = as.double (variance_as_power_of_the_mean);
- link_as_power_of_the_mean = as.double (link_as_power_of_the_mean);
-
- dispersion = as.double (dispersion);
- eps = as.double (eps);
-
- # Default values for output statistics:
- regularization = 0.0;
- termination_code = 0.0;
- min_beta = NaN;
- i_min_beta = NaN;
- max_beta = NaN;
- i_max_beta = NaN;
- intercept_value = NaN;
- dispersion = NaN;
- estimated_dispersion = NaN;
- deviance_nodisp = NaN;
- deviance = NaN;
-
- ##### INITIALIZE THE PARAMETERS #####
-
- num_records = nrow (X);
- num_features = ncol (X);
- zeros_r = matrix (0, rows = num_records, cols = 1);
- ones_r = 1 + zeros_r;
-
- # Introduce the intercept, shift and rescale the columns of X if needed
-
- if (intercept_status == 1 | intercept_status == 2) { # add the intercept column
- X = cbind (X, ones_r);
- num_features = ncol (X);
- }
-
- scale_lambda = matrix (1, rows = num_features, cols = 1);
- if (intercept_status == 1 | intercept_status == 2) {
- scale_lambda [num_features, 1] = 0;
- }
-
- if (intercept_status == 2) { # scale-&-shift X columns to mean 0, variance 1
- # Important assumption: X [, num_features] = ones_r
- avg_X_cols = t(colSums(X)) / num_records;
- var_X_cols = (t(colSums (X ^ 2)) - num_records * (avg_X_cols ^ 2)) / (num_records - 1);
- is_unsafe = (var_X_cols <= 0);
- scale_X = 1.0 / sqrt (var_X_cols * (1 - is_unsafe) + is_unsafe);
- scale_X [num_features, 1] = 1;
- shift_X = - avg_X_cols * scale_X;
- shift_X [num_features, 1] = 0;
- rowSums_X_sq = (X ^ 2) %*% (scale_X ^ 2) + X %*% (2 * scale_X * shift_X) + sum (shift_X ^ 2);
- } else {
- scale_X = matrix (1, rows = num_features, cols = 1);
- shift_X = matrix (0, rows = num_features, cols = 1);
- rowSums_X_sq = rowSums (X ^ 2);
- }
-
- # Henceforth we replace "X" with "X %*% (SHIFT/SCALE TRANSFORM)" and rowSums(X ^ 2)
- # with "rowSums_X_sq" in order to preserve the sparsity of X under shift and scale.
- # The transform is then associatively applied to the other side of the expression,
- # and is rewritten via "scale_X" and "shift_X" as follows:
- #
- # ssX_A = (SHIFT/SCALE TRANSFORM) %*% A --- is rewritten as:
- # ssX_A = diag (scale_X) %*% A;
- # ssX_A [num_features, ] = ssX_A [num_features, ] + t(shift_X) %*% A;
- #
- # tssX_A = t(SHIFT/SCALE TRANSFORM) %*% A --- is rewritten as:
- # tssX_A = diag (scale_X) %*% A + shift_X %*% A [num_features, ];
-
- # Initialize other input-dependent parameters
-
- lambda = scale_lambda * regularization;
- if (max_iteration_CG == 0) {
- max_iteration_CG = num_features;
- }
-
- # Set up the canonical link, if requested [Then we have: Var(mu) * (d link / d mu) = const]
-
- if (link_type == 0) {
- if (distribution_type == 1) {
- link_type = 1;
- link_as_power_of_the_mean = 1.0 - variance_as_power_of_the_mean;
- } else {
- if (distribution_type == 2) {
- link_type = 2;
- }
- }
- }
-
- # For power distributions and/or links, we use two constants,
- # "variance as power of the mean" and "link_as_power_of_the_mean",
- # to specify the variance and the link as arbitrary powers of the
- # mean. However, the variance-powers of 1.0 (Poisson family) and
- # 2.0 (Gamma family) have to be treated as special cases, because
- # these values integrate into logarithms. The link-power of 0.0
- # is also special as it represents the logarithm link.
-
- num_response_columns = ncol (Y);
- is_supported = 0;
- if (num_response_columns == 2 & distribution_type == 2 & link_type >= 1 & link_type <= 4) { # BERNOULLI DISTRIBUTION
- is_supported = 1;
- }
- if (num_response_columns == 1 & distribution_type == 2) {
- print ("Error: Bernoulli response matrix has not been converted into two-column format.");
- }
-
- if (is_supported == 1) {
-
- ##### INITIALIZE THE BETAS #####
-
- [beta, saturated_log_l, isNaN] =
- glm_initialize (X, Y, distribution_type, variance_as_power_of_the_mean, link_type, link_as_power_of_the_mean, intercept_status, max_iteration_CG);
-
- # print(" --- saturated logLik " + saturated_log_l);
-
- if (isNaN == 0) {
-
- ##### START OF THE MAIN PART #####
-
- sum_X_sq = sum (rowSums_X_sq);
- trust_delta = 0.5 * sqrt (num_features) / max (sqrt (rowSums_X_sq));
- ### max_trust_delta = trust_delta * 10000.0;
- log_l = 0.0;
- deviance_nodisp = 0.0;
- new_deviance_nodisp = 0.0;
- isNaN_log_l = 2;
- newbeta = beta;
- g = matrix (0.0, rows = num_features, cols = 1);
- g_norm = sqrt (sum ((g + lambda * beta) ^ 2));
- accept_new_beta = 1;
- reached_trust_boundary = 0;
- neg_log_l_change_predicted = 0.0;
- i_IRLS = 0;
-
- # print ("BEGIN IRLS ITERATIONS...");
-
- ssX_newbeta = diag (scale_X) %*% newbeta;
- ssX_newbeta [num_features, ] = ssX_newbeta [num_features, ] + t(shift_X) %*% newbeta;
- all_linear_terms = X %*% ssX_newbeta;
-
- [new_log_l, isNaN_new_log_l] = glm_log_likelihood_part
- (all_linear_terms, Y, distribution_type, variance_as_power_of_the_mean, link_type, link_as_power_of_the_mean);
-
- if (isNaN_new_log_l == 0) {
- new_deviance_nodisp = 2.0 * (saturated_log_l - new_log_l);
- new_log_l = new_log_l - 0.5 * sum (lambda * newbeta ^ 2);
- }
-
- while (termination_code == 0) {
- accept_new_beta = 1;
-
- if (i_IRLS > 0) {
- if (isNaN_log_l == 0) {
- accept_new_beta = 0;
- }
-
- # Decide whether to accept a new iteration point and update the trust region
- # See Alg. 4.1 on p. 69 of "Numerical Optimization" 2nd ed. by Nocedal and Wright
-
- rho = (- new_log_l + log_l) / neg_log_l_change_predicted;
- if (rho < 0.25 | isNaN_new_log_l == 1) {
- trust_delta = 0.25 * trust_delta;
- }
- if (rho > 0.75 & isNaN_new_log_l == 0 & reached_trust_boundary == 1) {
- trust_delta = 2 * trust_delta;
-
- ### if (trust_delta > max_trust_delta) {
- ### trust_delta = max_trust_delta;
- ### }
- }
- if (rho > 0.1 & isNaN_new_log_l == 0) {
- accept_new_beta = 1;
- }
- }
-
- if (accept_new_beta == 1) {
- beta = newbeta; log_l = new_log_l; deviance_nodisp = new_deviance_nodisp; isNaN_log_l = isNaN_new_log_l;
-
- [g_Y, w] = glm_dist (all_linear_terms, Y, distribution_type, variance_as_power_of_the_mean, link_type, link_as_power_of_the_mean);
-
- # We introduced these variables to avoid roundoff errors:
- # g_Y = y_residual / (y_var * link_grad);
- # w = 1.0 / (y_var * link_grad * link_grad);
-
- gXY = - t(X) %*% g_Y;
- g = diag (scale_X) %*% gXY + shift_X %*% gXY [num_features, ];
- g_norm = sqrt (sum ((g + lambda * beta) ^ 2));
- }
-
- [z, neg_log_l_change_predicted, num_CG_iters, reached_trust_boundary] =
- get_CG_Steihaug_point (X, scale_X, shift_X, w, g, beta, lambda, trust_delta, max_iteration_CG);
-
- newbeta = beta + z;
-
- ssX_newbeta = diag (scale_X) %*% newbeta;
- ssX_newbeta [num_features, ] = ssX_newbeta [num_features, ] + t(shift_X) %*% newbeta;
- all_linear_terms = X %*% ssX_newbeta;
-
- [new_log_l, isNaN_new_log_l] = glm_log_likelihood_part
- (all_linear_terms, Y, distribution_type, variance_as_power_of_the_mean, link_type, link_as_power_of_the_mean);
-
- if (isNaN_new_log_l == 0) {
- new_deviance_nodisp = 2.0 * (saturated_log_l - new_log_l);
- new_log_l = new_log_l - 0.5 * sum (lambda * newbeta ^ 2);
- }
-
- log_l_change = new_log_l - log_l; # R's criterion for termination: |dev - devold|/(|dev| + 0.1) < eps
-
- if (reached_trust_boundary == 0 & isNaN_new_log_l == 0 &
- (2.0 * abs (log_l_change) < eps * (deviance_nodisp + 0.1) | abs (log_l_change) < (abs (log_l) + abs (new_log_l)) * 0.00000000000001) ) {
- termination_code = 1;
- }
- rho = - log_l_change / neg_log_l_change_predicted;
- z_norm = sqrt (sum (z * z));
-
- i_IRLS = i_IRLS + 1;
-
- if (i_IRLS == max_iteration_IRLS) {
- termination_code = 2;
- }
- }
-
- beta = newbeta;
- log_l = new_log_l;
- deviance_nodisp = new_deviance_nodisp;
-
- #---------------------------- last part
-
- if (termination_code != 1) {
- print ("One of the runs of GLM did not converged in " + i_IRLS + " steps!");
- }
-
- ##### COMPUTE AIC #####
-
- if (distribution_type == 2 & link_type >= 1 & link_type <= 4) {
- AIC = -2 * log_l;
- if (sum (X) != 0) {
- AIC = AIC + 2 * num_features;
- }
- } else {
- stop ("Currently only the Bernoulli distribution family the following link functions are supported: log, logit, probit, and cloglog!");
- }
-
- if (fileB != " ") {
- fileO = ifdef ($O, " ");
- fileS = $S;
- fmt = ifdef ($fmt, "text");
-
- # Output which features give the best AIC and are being used for linear regression
- write (Selected, fileS, format=fmt);
-
- ssX_beta = diag (scale_X) %*% beta;
- ssX_beta [num_features, ] = ssX_beta [num_features, ] + t(shift_X) %*% beta;
- if (intercept_status == 2) {
- beta_out = cbind (ssX_beta, beta);
- } else {
- beta_out = ssX_beta;
- }
-
- if (intercept_status == 0 & num_features == 1) {
- p = sum (X == 1);
- if (p == num_records) {
- beta_out = beta_out[1,];
- }
- }
-
-
- if (intercept_status == 1 | intercept_status == 2) {
- intercept_value = as.scalar (beta_out [num_features, 1]);
- beta_noicept = beta_out [1 : (num_features - 1), 1];
- } else {
- beta_noicept = beta_out [1 : num_features, 1];
- }
- min_beta = min (beta_noicept);
- max_beta = max (beta_noicept);
- tmp_i_min_beta = rowIndexMin (t(beta_noicept))
- i_min_beta = as.scalar (tmp_i_min_beta [1, 1]);
- tmp_i_max_beta = rowIndexMax (t(beta_noicept))
- i_max_beta = as.scalar (tmp_i_max_beta [1, 1]);
-
- ##### OVER-DISPERSION PART #####
-
- all_linear_terms = X %*% ssX_beta;
- [g_Y, w] = glm_dist (all_linear_terms, Y, distribution_type, variance_as_power_of_the_mean, link_type, link_as_power_of_the_mean);
-
- pearson_residual_sq = g_Y ^ 2 / w;
- pearson_residual_sq = replace (target = pearson_residual_sq, pattern = NaN, replacement = 0);
- # pearson_residual_sq = (y_residual ^ 2) / y_var;
-
- if (num_records > num_features) {
- estimated_dispersion = sum (pearson_residual_sq) / (num_records - num_features);
- }
- if (dispersion <= 0) {
- dispersion = estimated_dispersion;
- }
- deviance = deviance_nodisp / dispersion;
-
- ##### END OF THE MAIN PART #####
-
- str = "BETA_MIN," + min_beta;
- str = append (str, "BETA_MIN_INDEX," + i_min_beta);
- str = append (str, "BETA_MAX," + max_beta);
- str = append (str, "BETA_MAX_INDEX," + i_max_beta);
- str = append (str, "INTERCEPT," + intercept_value);
- str = append (str, "DISPERSION," + dispersion);
- str = append (str, "DISPERSION_EST," + estimated_dispersion);
- str = append (str, "DEVIANCE_UNSCALED," + deviance_nodisp);
- str = append (str, "DEVIANCE_SCALED," + deviance);
-
- if (fileO != " ") {
- write (str, fileO);
- }
- else {
- print (str);
- }
-
- # Prepare the output matrix
- print ("Writing the output matrix...");
- if (intercept_status == 0 & num_features == 1) {
- if (p == num_records) {
- beta_out_tmp = matrix (0, rows = num_features_orig + 1, cols = 1);
- beta_out_tmp[num_features_orig + 1,] = beta_out;
- beta_out = beta_out_tmp;
- write (beta_out, fileB, format=fmt);
- stop ("");
- } else if (sum (X) == 0){
- beta_out = matrix (0, rows = num_features_orig, cols = 1);
- write (beta_out, fileB, format=fmt);
- stop ("");
- }
- }
-
- no_selected = ncol (Selected);
- max_selected = max (Selected);
- last = max_selected + 1;
-
- if (intercept_status != 0) {
-
- Selected_ext = cbind (Selected, as.matrix (last));
- P1 = table (seq (1, ncol (Selected_ext)), t(Selected_ext));
-
- if (intercept_status == 2) {
-
- P1_ssX_beta = P1 * ssX_beta;
- P2_ssX_beta = colSums (P1_ssX_beta);
- P1_beta = P1 * beta;
- P2_beta = colSums (P1_beta);
-
- if (max_selected < num_features_orig) {
-
- P2_ssX_beta = cbind (P2_ssX_beta, matrix (0, rows=1, cols=(num_features_orig - max_selected)));
- P2_beta = cbind (P2_beta, matrix (0, rows=1, cols=(num_features_orig - max_selected)));
-
- P2_ssX_beta[1, num_features_orig+1] = P2_ssX_beta[1, max_selected + 1];
- P2_ssX_beta[1, max_selected + 1] = 0;
-
- P2_beta[1, num_features_orig+1] = P2_beta[1, max_selected + 1];
- P2_beta[1, max_selected + 1] = 0;
-
- }
- beta_out = cbind (t(P2_ssX_beta), t(P2_beta));
-
- } else {
-
- P1_beta = P1 * beta;
- P2_beta = colSums (P1_beta);
-
- if (max_selected < num_features_orig) {
- P2_beta = cbind (P2_beta, matrix (0, rows=1, cols=(num_features_orig - max_selected)));
- P2_beta[1, num_features_orig+1] = P2_beta[1, max_selected + 1] ;
- P2_beta[1, max_selected + 1] = 0;
- }
- beta_out = t(P2_beta);
-
- }
- } else {
-
- P1 = table (seq (1, no_selected), t(Selected));
- P1_beta = P1 * beta;
- P2_beta = colSums (P1_beta);
-
- if (max_selected < num_features_orig) {
- P2_beta = cbind (P2_beta, matrix (0, rows=1, cols=(num_features_orig - max_selected)));
- }
-
- beta_out = t(P2_beta);
- }
-
- write ( beta_out, fileB, format=fmt );
-
- }
-
- } else {
- stop ("Input matrices X and/or Y are out of range!");
- }
- } else {
- stop ("Response matrix with " + num_response_columns + " columns, distribution family (" + distribution_type + ", " + variance_as_power_of_the_mean
- + ") and link family (" + link_type + ", " + link_as_power_of_the_mean + ") are NOT supported together.");
- }
-}
-
-glm_initialize = function (Matrix[double] X, Matrix[double] Y, int dist_type, double var_power, int link_type, double link_power, int icept_status, int max_iter_CG)
- return (Matrix[double] beta, double saturated_log_l, int isNaN)
-{
- saturated_log_l = 0.0;
- isNaN = 0;
- y_corr = Y [, 1];
- if (dist_type == 2) {
- n_corr = rowSums (Y);
- is_n_zero = (n_corr == 0);
- y_corr = Y [, 1] / (n_corr + is_n_zero) + (0.5 - Y [, 1]) * is_n_zero;
- }
- linear_terms = y_corr;
- if (dist_type == 1 & link_type == 1) { # POWER DISTRIBUTION
- if (link_power == 0) {
- if (sum (y_corr < 0) == 0) {
- is_zero_y_corr = (y_corr == 0);
- linear_terms = log (y_corr + is_zero_y_corr) - is_zero_y_corr / (1.0 - is_zero_y_corr);
- } else { isNaN = 1; }
- } else { if (link_power == 1.0) {
- linear_terms = y_corr;
- } else { if (link_power == -1.0) {
- linear_terms = 1.0 / y_corr;
- } else { if (link_power == 0.5) {
- if (sum (y_corr < 0) == 0) {
- linear_terms = sqrt (y_corr);
- } else { isNaN = 1; }
- } else { if (link_power > 0) {
- if (sum (y_corr < 0) == 0) {
- is_zero_y_corr = (y_corr == 0);
- linear_terms = (y_corr + is_zero_y_corr) ^ link_power - is_zero_y_corr;
- } else { isNaN = 1; }
- } else {
- if (sum (y_corr <= 0) == 0) {
- linear_terms = y_corr ^ link_power;
- } else { isNaN = 1; }
- }}}}}
- }
- if (dist_type == 2 & link_type >= 1 & link_type <= 5)
- { # BINOMIAL/BERNOULLI DISTRIBUTION
- if (link_type == 1 & link_power == 0) { # Binomial.log
- if (sum (y_corr < 0) == 0) {
- is_zero_y_corr = (y_corr == 0);
- linear_terms = log (y_corr + is_zero_y_corr) - is_zero_y_corr / (1.0 - is_zero_y_corr);
- } else { isNaN = 1; }
- } else { if (link_type == 1 & link_power > 0) { # Binomial.power_nonlog pos
- if (sum (y_corr < 0) == 0) {
- is_zero_y_corr = (y_corr == 0);
- linear_terms = (y_corr + is_zero_y_corr) ^ link_power - is_zero_y_corr;
- } else { isNaN = 1; }
- } else { if (link_type == 1) { # Binomial.power_nonlog neg
- if (sum (y_corr <= 0) == 0) {
- linear_terms = y_corr ^ link_power;
- } else { isNaN = 1; }
- } else {
- is_zero_y_corr = (y_corr <= 0);
- is_one_y_corr = (y_corr >= 1.0);
- y_corr = y_corr * (1.0 - is_zero_y_corr) * (1.0 - is_one_y_corr) + 0.5 * (is_zero_y_corr + is_one_y_corr);
- if (link_type == 2) { # Binomial.logit
- linear_terms = log (y_corr / (1.0 - y_corr))
- + is_one_y_corr / (1.0 - is_one_y_corr) - is_zero_y_corr / (1.0 - is_zero_y_corr);
- } else { if (link_type == 3) { # Binomial.probit
- y_below_half = y_corr + (1.0 - 2.0 * y_corr) * (y_corr > 0.5);
- t = sqrt (- 2.0 * log (y_below_half));
- approx_inv_Gauss_CDF = - t + (2.515517 + t * (0.802853 + t * 0.010328)) / (1.0 + t * (1.432788 + t * (0.189269 + t * 0.001308)));
- linear_terms = approx_inv_Gauss_CDF * (1.0 - 2.0 * (y_corr > 0.5))
- + is_one_y_corr / (1.0 - is_one_y_corr) - is_zero_y_corr / (1.0 - is_zero_y_corr);
- } else { if (link_type == 4) { # Binomial.cloglog
- linear_terms = log (- log (1.0 - y_corr))
- - log (- log (0.5)) * (is_zero_y_corr + is_one_y_corr)
- + is_one_y_corr / (1.0 - is_one_y_corr) - is_zero_y_corr / (1.0 - is_zero_y_corr);
- } else { if (link_type == 5) { # Binomial.cauchit
- linear_terms = tan ((y_corr - 0.5) * pi)
- + is_one_y_corr / (1.0 - is_one_y_corr) - is_zero_y_corr / (1.0 - is_zero_y_corr);
- }} }}}}}
- }
-
- if (isNaN == 0) {
- [saturated_log_l, isNaN] =
- glm_log_likelihood_part (linear_terms, Y, dist_type, var_power, link_type, link_power);
- }
-
- if ((dist_type == 1 & link_type == 1 & link_power == 0) |
- (dist_type == 2 & link_type >= 2))
- {
- desired_eta = 0.0;
- } else { if (link_type == 1 & link_power == 0) {
- desired_eta = log (0.5);
- } else { if (link_type == 1) {
- desired_eta = 0.5 ^ link_power;
- } else {
- desired_eta = 0.5;
- }}}
-
- beta = matrix (0.0, rows = ncol(X), cols = 1);
-
- if (desired_eta != 0) {
- if (icept_status == 1 | icept_status == 2) {
- beta [nrow(beta), 1] = desired_eta;
- } else {
- # We want: avg (X %*% ssX_transform %*% beta) = desired_eta
- # Note that "ssX_transform" is trivial here, hence ignored
-
- beta = straightenX (X, 0.000001, max_iter_CG);
- beta = beta * desired_eta;
- } } }
-
-
-glm_dist = function (Matrix[double] linear_terms, Matrix[double] Y,
- int dist_type, double var_power, int link_type, double link_power)
- return (Matrix[double] g_Y, Matrix[double] w)
-# ORIGINALLY we returned more meaningful vectors, namely:
-# Matrix[double] y_residual : y - y_mean, i.e. y observed - y predicted
-# Matrix[double] link_gradient : derivative of the link function
-# Matrix[double] var_function : variance without dispersion, i.e. the V(mu) function
-# BUT, this caused roundoff errors, so we had to compute "directly useful" vectors
-# and skip over the "meaningful intermediaries". Now we output these two variables:
-# g_Y = y_residual / (var_function * link_gradient);
-# w = 1.0 / (var_function * link_gradient ^ 2);
-{
- num_records = nrow (linear_terms);
- zeros_r = matrix (0.0, rows = num_records, cols = 1);
- ones_r = 1 + zeros_r;
- g_Y = zeros_r;
- w = zeros_r;
-
- # Some constants
-
- one_over_sqrt_two_pi = 0.39894228040143267793994605993438;
- ones_2 = matrix (1.0, rows = 1, cols = 2);
- p_one_m_one = ones_2;
- p_one_m_one [1, 2] = -1.0;
- m_one_p_one = ones_2;
- m_one_p_one [1, 1] = -1.0;
- zero_one = ones_2;
- zero_one [1, 1] = 0.0;
- one_zero = ones_2;
- one_zero [1, 2] = 0.0;
- flip_pos = matrix (0, rows = 2, cols = 2);
- flip_neg = flip_pos;
- flip_pos [1, 2] = 1;
- flip_pos [2, 1] = 1;
- flip_neg [1, 2] = -1;
- flip_neg [2, 1] = 1;
-
- if (dist_type == 1 & link_type == 1) { # POWER DISTRIBUTION
- y_mean = zeros_r;
- if (link_power == 0) {
- y_mean = exp (linear_terms);
- y_mean_pow = y_mean ^ (1 - var_power);
- w = y_mean_pow * y_mean;
- g_Y = y_mean_pow * (Y - y_mean);
- } else { if (link_power == 1.0) {
- y_mean = linear_terms;
- w = y_mean ^ (- var_power);
- g_Y = w * (Y - y_mean);
- } else {
- y_mean = linear_terms ^ (1.0 / link_power);
- c1 = (1 - var_power) / link_power - 1;
- c2 = (2 - var_power) / link_power - 2;
- g_Y = (linear_terms ^ c1) * (Y - y_mean) / link_power;
- w = (linear_terms ^ c2) / (link_power ^ 2);
- } }}
- if (dist_type == 2 & link_type >= 1 & link_type <= 5)
- { # BINOMIAL/BERNOULLI DISTRIBUTION
- if (link_type == 1) { # BINOMIAL.POWER LINKS
- if (link_power == 0) { # Binomial.log
- vec1 = 1 / (exp (- linear_terms) - 1);
- g_Y = Y [, 1] - Y [, 2] * vec1;
- w = rowSums (Y) * vec1;
- } else { # Binomial.nonlog
- vec1 = zeros_r;
- if (link_power == 0.5) {
- vec1 = 1 / (1 - linear_terms ^ 2);
- } else { if (sum (linear_terms < 0) == 0) {
- vec1 = linear_terms ^ (- 2 + 1 / link_power) / (1 - linear_terms ^ (1 / link_power));
- } else {isNaN = 1;}}
- # We want a "zero-protected" version of
- # vec2 = Y [, 1] / linear_terms;
- is_y_0 = (Y [, 1] == 0);
- vec2 = (Y [, 1] + is_y_0) / (linear_terms * (1 - is_y_0) + is_y_0) - is_y_0;
- g_Y = (vec2 - Y [, 2] * vec1 * linear_terms) / link_power;
- w = rowSums (Y) * vec1 / link_power ^ 2;
- }
- } else {
- is_LT_pos_infinite = (linear_terms == Inf);
- is_LT_neg_infinite = (linear_terms == -Inf);
- is_LT_infinite = is_LT_pos_infinite %*% one_zero + is_LT_neg_infinite %*% zero_one;
- finite_linear_terms = replace (target = linear_terms, pattern = Inf, replacement = 0);
- finite_linear_terms = replace (target = finite_linear_terms, pattern = -Inf, replacement = 0);
- if (link_type == 2) { # Binomial.logit
- Y_prob = exp (finite_linear_terms) %*% one_zero + ones_r %*% zero_one;
- Y_prob = Y_prob / (rowSums (Y_prob) %*% ones_2);
- Y_prob = Y_prob * ((1.0 - rowSums (is_LT_infinite)) %*% ones_2) + is_LT_infinite;
- g_Y = rowSums (Y * (Y_prob %*% flip_neg)); ### = y_residual;
- w = rowSums (Y * (Y_prob %*% flip_pos) * Y_prob); ### = y_variance;
- } else { if (link_type == 3) { # Binomial.probit
- is_lt_pos = (linear_terms >= 0);
- t_gp = 1.0 / (1.0 + abs (finite_linear_terms) * 0.231641888); # 0.231641888 = 0.3275911 / sqrt (2.0)
- pt_gp = t_gp * ( 0.254829592
- + t_gp * (-0.284496736 # "Handbook of Mathematical Functions", ed. by M. Abramowitz and I.A. Stegun,
- + t_gp * ( 1.421413741 # U.S. Nat-l Bureau of Standards, 10th print (Dec 1972), Sec. 7.1.26, p. 299
- + t_gp * (-1.453152027
- + t_gp * 1.061405429))));
- the_gauss_exp = exp (- (linear_terms ^ 2) / 2.0);
- vec1 = 0.25 * pt_gp * (2 - the_gauss_exp * pt_gp);
- vec2 = Y [, 1] - rowSums (Y) * is_lt_pos + the_gauss_exp * pt_gp * rowSums (Y) * (is_lt_pos - 0.5);
- w = the_gauss_exp * (one_over_sqrt_two_pi ^ 2) * rowSums (Y) / vec1;
- g_Y = one_over_sqrt_two_pi * vec2 / vec1;
- } else { if (link_type == 4) { # Binomial.cloglog
- the_exp = exp (linear_terms)
- the_exp_exp = exp (- the_exp);
- is_too_small = ((10000000 + the_exp) == 10000000);
- the_exp_ratio = (1 - is_too_small) * (1 - the_exp_exp) / (the_exp + is_too_small) + is_too_small * (1 - the_exp / 2);
- g_Y = (rowSums (Y) * the_exp_exp - Y [, 2]) / the_exp_ratio;
- w = the_exp_exp * the_exp * rowSums (Y) / the_exp_ratio;
- } else { if (link_type == 5) { # Binomial.cauchit
- Y_prob = 0.5 + (atan (finite_linear_terms) %*% p_one_m_one) / pi;
- Y_prob = Y_prob * ((1.0 - rowSums (is_LT_infinite)) %*% ones_2) + is_LT_infinite;
- y_residual = Y [, 1] * Y_prob [, 2] - Y [, 2] * Y_prob [, 1];
- var_function = rowSums (Y) * Y_prob [, 1] * Y_prob [, 2];
- link_gradient_normalized = (1 + linear_terms ^ 2) * pi;
- g_Y = rowSums (Y) * y_residual / (var_function * link_gradient_normalized);
- w = (rowSums (Y) ^ 2) / (var_function * link_gradient_normalized ^ 2);
- }}}}
- }
- }
- }
-
-
-glm_log_likelihood_part = function (Matrix[double] linear_terms, Matrix[double] Y,
- int dist_type, double var_power, int link_type, double link_power)
- return (double log_l, int isNaN)
-{
- isNaN = 0;
- log_l = 0.0;
- num_records = nrow (Y);
- zeros_r = matrix (0.0, rows = num_records, cols = 1);
-
- if (dist_type == 1 & link_type == 1)
- { # POWER DISTRIBUTION
- b_cumulant = zeros_r;
- natural_parameters = zeros_r;
- is_natural_parameter_log_zero = zeros_r;
- if (var_power == 1.0 & link_power == 0) { # Poisson.log
- b_cumulant = exp (linear_terms);
- is_natural_parameter_log_zero = (linear_terms == -Inf);
- natural_parameters = replace (target = linear_terms, pattern = -Inf, replacement = 0);
- } else { if (var_power == 1.0 & link_power == 1.0) { # Poisson.id
- if (sum (linear_terms < 0) == 0) {
- b_cumulant = linear_terms;
- is_natural_parameter_log_zero = (linear_terms == 0);
- natural_parameters = log (linear_terms + is_natural_parameter_log_zero);
- } else {isNaN = 1;}
- } else { if (var_power == 1.0 & link_power == 0.5) { # Poisson.sqrt
- if (sum (linear_terms < 0) == 0) {
- b_cumulant = linear_terms ^ 2;
- is_natural_parameter_log_zero = (linear_terms == 0);
- natural_parameters = 2.0 * log (linear_terms + is_natural_parameter_log_zero);
- } else {isNaN = 1;}
- } else { if (var_power == 1.0 & link_power > 0) { # Poisson.power_nonlog, pos
- if (sum (linear_terms < 0) == 0) {
- is_natural_parameter_log_zero = (linear_terms == 0);
- b_cumulant = (linear_terms + is_natural_parameter_log_zero) ^ (1.0 / link_power) - is_natural_parameter_log_zero;
- natural_parameters = log (linear_terms + is_natural_parameter_log_zero) / link_power;
- } else {isNaN = 1;}
- } else { if (var_power == 1.0) { # Poisson.power_nonlog, neg
- if (sum (linear_terms <= 0) == 0) {
- b_cumulant = linear_terms ^ (1.0 / link_power);
- natural_parameters = log (linear_terms) / link_power;
- } else {isNaN = 1;}
- } else { if (var_power == 2.0 & link_power == -1.0) { # Gamma.inverse
- if (sum (linear_terms <= 0) == 0) {
- b_cumulant = - log (linear_terms);
- natural_parameters = - linear_terms;
- } else {isNaN = 1;}
- } else { if (var_power == 2.0 & link_power == 1.0) { # Gamma.id
- if (sum (linear_terms <= 0) == 0) {
- b_cumulant = log (linear_terms);
- natural_parameters = - 1.0 / linear_terms;
- } else {isNaN = 1;}
- } else { if (var_power == 2.0 & link_power == 0) { # Gamma.log
- b_cumulant = linear_terms;
- natural_parameters = - exp (- linear_terms);
- } else { if (var_power == 2.0) { # Gamma.power_nonlog
- if (sum (linear_terms <= 0) == 0) {
- b_cumulant = log (linear_terms) / link_power;
- natural_parameters = - linear_terms ^ (- 1.0 / link_power);
- } else {isNaN = 1;}
- } else { if (link_power == 0) { # PowerDist.log
- natural_parameters = exp (linear_terms * (1.0 - var_power)) / (1.0 - var_power);
- b_cumulant = exp (linear_terms * (2.0 - var_power)) / (2.0 - var_power);
- } else { # PowerDist.power_nonlog
- if (-2 * link_power == 1.0 - var_power) {
- natural_parameters = 1.0 / (linear_terms ^ 2) / (1.0 - var_power);
- } else { if (-1 * link_power == 1.0 - var_power) {
- natural_parameters = 1.0 / linear_terms / (1.0 - var_power);
- } else { if ( link_power == 1.0 - var_power) {
- natural_parameters = linear_terms / (1.0 - var_power);
- } else { if ( 2 * link_power == 1.0 - var_power) {
- natural_parameters = linear_terms ^ 2 / (1.0 - var_power);
- } else {
- if (sum (linear_terms <= 0) == 0) {
- power = (1.0 - var_power) / link_power;
- natural_parameters = (linear_terms ^ power) / (1.0 - var_power);
- } else {isNaN = 1;}
- }}}}
- if (-2 * link_power == 2.0 - var_power) {
- b_cumulant = 1.0 / (linear_terms ^ 2) / (2.0 - var_power);
- } else { if (-1 * link_power == 2.0 - var_power) {
- b_cumulant = 1.0 / linear_terms / (2.0 - var_power);
- } else { if ( link_power == 2.0 - var_power) {
- b_cumulant = linear_terms / (2.0 - var_power);
- } else { if ( 2 * link_power == 2.0 - var_power) {
- b_cumulant = linear_terms ^ 2 / (2.0 - var_power);
- } else {
- if (sum (linear_terms <= 0) == 0) {
- power = (2.0 - var_power) / link_power;
- b_cumulant = (linear_terms ^ power) / (2.0 - var_power);
- } else {isNaN = 1;}
- }}}}
- }}}}} }}}}}
- if (sum (is_natural_parameter_log_zero * abs (Y)) > 0) {
- log_l = -Inf;
- isNaN = 1;
- }
- if (isNaN == 0)
- {
- log_l = sum (Y * natural_parameters - b_cumulant);
- if (log_l != log_l | (log_l == log_l + 1.0 & log_l == log_l * 2.0)) {
- log_l = -Inf;
- isNaN = 1;
- } } }
-
- if (dist_type == 2 & link_type >= 1 & link_type <= 5)
- { # BINOMIAL/BERNOULLI DISTRIBUTION
-
- [Y_prob, isNaN] = binomial_probability_two_column (linear_terms, link_type, link_power);
-
- if (isNaN == 0) {
- does_prob_contradict = (Y_prob <= 0);
- if (sum (does_prob_contradict * abs (Y)) == 0) {
- log_l = sum (Y * log (Y_prob * (1 - does_prob_contradict) + does_prob_contradict));
- if (log_l != log_l | (log_l == log_l + 1.0 & log_l == log_l * 2.0)) {
- isNaN = 1;
- }
- } else {
- log_l = -Inf;
- isNaN = 1;
- } } }
-
- if (isNaN == 1) {
- log_l = - Inf;
- }
- }
-
-
-
-binomial_probability_two_column =
- function (Matrix[double] linear_terms, int link_type, double link_power)
- return (Matrix[double] Y_prob, int isNaN)
-{
- isNaN = 0;
- num_records = nrow (linear_terms);
-
- # Define some auxiliary matrices
-
- ones_2 = matrix (1.0, rows = 1, cols = 2);
- p_one_m_one = ones_2;
- p_one_m_one [1, 2] = -1.0;
- m_one_p_one = ones_2;
- m_one_p_one [1, 1] = -1.0;
- zero_one = ones_2;
- zero_one [1, 1] = 0.0;
- one_zero = ones_2;
- one_zero [1, 2] = 0.0;
-
- zeros_r = matrix (0.0, rows = num_records, cols = 1);
- ones_r = 1.0 + zeros_r;
-
- # Begin the function body
-
- Y_prob = zeros_r %*% ones_2;
- if (link_type == 1) { # Binomial.power
- if (link_power == 0) { # Binomial.log
- Y_prob = exp (linear_terms) %*% p_one_m_one + ones_r %*% zero_one;
- } else { if (link_power == 0.5) { # Binomial.sqrt
- Y_prob = (linear_terms ^ 2) %*% p_one_m_one + ones_r %*% zero_one;
- } else { # Binomial.power_nonlog
- if (sum (linear_terms < 0) == 0) {
- Y_prob = (linear_terms ^ (1.0 / link_power)) %*% p_one_m_one + ones_r %*% zero_one;
- } else {isNaN = 1;}
- }}
- } else { # Binomial.non_power
- is_LT_pos_infinite = (linear_terms == Inf);
- is_LT_neg_infinite = (linear_terms == -Inf);
- is_LT_infinite = is_LT_pos_infinite %*% one_zero + is_LT_neg_infinite %*% zero_one;
- finite_linear_terms = replace (target = linear_terms, pattern = Inf, replacement = 0);
- finite_linear_terms = replace (target = finite_linear_terms, pattern = -Inf, replacement = 0);
- if (link_type == 2) { # Binomial.logit
- Y_prob = exp (finite_linear_terms) %*% one_zero + ones_r %*% zero_one;
- Y_prob = Y_prob / (rowSums (Y_prob) %*% ones_2);
- } else { if (link_type == 3) { # Binomial.probit
- lt_pos_neg = (finite_linear_terms >= 0) %*% p_one_m_one + ones_r %*% zero_one;
- t_gp = 1.0 / (1.0 + abs (finite_linear_terms) * 0.231641888); # 0.231641888 = 0.3275911 / sqrt (2.0)
- pt_gp = t_gp * ( 0.254829592
- + t_gp * (-0.284496736 # "Handbook of Mathematical Functions", ed. by M. Abramowitz and I.A. Stegun,
- + t_gp * ( 1.421413741 # U.S. Nat-l Bureau of Standards, 10th print (Dec 1972), Sec. 7.1.26, p. 299
- + t_gp * (-1.453152027
- + t_gp * 1.061405429))));
- the_gauss_exp = exp (- (finite_linear_terms ^ 2) / 2.0);
- Y_prob = lt_pos_neg + ((the_gauss_exp * pt_gp) %*% ones_2) * (0.5 - lt_pos_neg);
- } else { if (link_type == 4) { # Binomial.cloglog
- the_exp = exp (finite_linear_terms);
- the_exp_exp = exp (- the_exp);
- is_too_small = ((10000000 + the_exp) == 10000000);
- Y_prob [, 1] = (1 - is_too_small) * (1 - the_exp_exp) + is_too_small * the_exp * (1 - the_exp / 2);
- Y_prob [, 2] = the_exp_exp;
- } else { if (link_type == 5) { # Binomial.cauchit
- Y_prob = 0.5 + (atan (finite_linear_terms) %*% p_one_m_one) / pi;
- } else {
- isNaN = 1;
- }}}}
- Y_prob = Y_prob * ((1.0 - rowSums (is_LT_infinite)) %*% ones_2) + is_LT_infinite;
- } }
-
-
-# THE CG-STEIHAUG PROCEDURE SCRIPT
-
-# Apply Conjugate Gradient - Steihaug algorithm in order to approximately minimize
-# 0.5 z^T (X^T diag(w) X + diag (lambda)) z + (g + lambda * beta)^T z
-# under constraint: ||z|| <= trust_delta.
-# See Alg. 7.2 on p. 171 of "Numerical Optimization" 2nd ed. by Nocedal and Wright
-# IN THE ABOVE, "X" IS UNDERSTOOD TO BE "X %*% (SHIFT/SCALE TRANSFORM)"; this transform
-# is given separately because sparse "X" may become dense after applying the transform.
-#
-get_CG_Steihaug_point =
- function (Matrix[double] X, Matrix[double] scale_X, Matrix[double] shift_X, Matrix[double] w,
- Matrix[double] g, Matrix[double] beta, Matrix[double] lambda, double trust_delta, int max_iter_CG)
- return (Matrix[double] z, double neg_log_l_change, int i_CG, int reached_trust_boundary)
-{
- trust_delta_sq = trust_delta ^ 2;
- size_CG = nrow (g);
- z = matrix (0.0, rows = size_CG, cols = 1);
- neg_log_l_change = 0.0;
- reached_trust_boundary = 0;
- g_reg = g + lambda * beta;
- r_CG = g_reg;
- p_CG = -r_CG;
- rr_CG = sum(r_CG * r_CG);
- eps_CG = rr_CG * min (0.25, sqrt (rr_CG));
- converged_CG = 0;
- if (rr_CG < eps_CG) {
- converged_CG = 1;
- }
-
- max_iteration_CG = max_iter_CG;
- if (max_iteration_CG <= 0) {
- max_iteration_CG = size_CG;
- }
- i_CG = 0;
- while (converged_CG == 0)
- {
- i_CG = i_CG + 1;
- ssX_p_CG = diag (scale_X) %*% p_CG;
- ssX_p_CG [size_CG, ] = ssX_p_CG [size_CG, ] + t(shift_X) %*% p_CG;
- temp_CG = t(X) %*% (w * (X %*% ssX_p_CG));
- q_CG = (lambda * p_CG) + diag (scale_X) %*% temp_CG + shift_X %*% temp_CG [size_CG, ];
- pq_CG = sum (p_CG * q_CG);
- if (pq_CG <= 0) {
- pp_CG = sum (p_CG * p_CG);
- if (pp_CG > 0) {
- [z, neg_log_l_change] =
- get_trust_boundary_point (g_reg, z, p_CG, q_CG, r_CG, pp_CG, pq_CG, trust_delta_sq);
- reached_trust_boundary = 1;
- } else {
- neg_log_l_change = 0.5 * sum (z * (r_CG + g_reg));
- }
- converged_CG = 1;
- }
- if (converged_CG == 0) {
- alpha_CG = rr_CG / pq_CG;
- new_z = z + alpha_CG * p_CG;
- if (sum(new_z * new_z) >= trust_delta_sq) {
- pp_CG = sum (p_CG * p_CG);
- [z, neg_log_l_change] =
- get_trust_boundary_point (g_reg, z, p_CG, q_CG, r_CG, pp_CG, pq_CG, trust_delta_sq);
- reached_trust_boundary = 1;
- converged_CG = 1;
- }
- if (converged_CG == 0) {
- z = new_z;
- old_rr_CG = rr_CG;
- r_CG = r_CG + alpha_CG * q_CG;
- rr_CG = sum(r_CG * r_CG);
- if (i_CG == max_iteration_CG | rr_CG < eps_CG) {
- neg_log_l_change = 0.5 * sum (z * (r_CG + g_reg));
- reached_trust_boundary = 0;
- converged_CG = 1;
- }
- if (converged_CG == 0) {
- p_CG = -r_CG + (rr_CG / old_rr_CG) * p_CG;
- } } } } }
-
-
-# An auxiliary function used twice inside the CG-STEIHAUG loop:
-get_trust_boundary_point =
- function (Matrix[double] g, Matrix[double] z, Matrix[double] p,
- Matrix[double] q, Matrix[double] r, double pp, double pq,
- double trust_delta_sq)
- return (Matrix[double] new_z, double f_change)
-{
- zz = sum (z * z); pz = sum (p * z);
- sq_root_d = sqrt (pz * pz - pp * (zz - trust_delta_sq));
- tau_1 = (- pz + sq_root_d) / pp;
- tau_2 = (- pz - sq_root_d) / pp;
- zq = sum (z * q); gp = sum (g * p);
- f_extra = 0.5 * sum (z * (r + g));
- f_change_1 = f_extra + (0.5 * tau_1 * pq + zq + gp) * tau_1;
- f_change_2 = f_extra + (0.5 * tau_2 * pq + zq + gp) * tau_2;
- ind1 = as.integer(f_change_1 < f_change_2);
- ind2 = as.integer(f_change_1 >= f_change_2);
- new_z = z + ((ind1 * tau_1 + ind2 * tau_2) * p);
- f_change = ind1 * f_change_1 + ind2 * f_change_2;
-}
-
-
-# Computes vector w such that ||X %*% w - 1|| -> MIN given avg(X %*% w) = 1
-# We find z_LS such that ||X %*% z_LS - 1|| -> MIN unconditionally, then scale
-# it to compute w = c * z_LS such that sum(X %*% w) = nrow(X).
-straightenX =
- function (Matrix[double] X, double eps, int max_iter_CG)
- return (Matrix[double] w)
-{
- w_X = t(colSums(X));
- lambda_LS = 0.000001 * sum(X ^ 2) / ncol(X);
- eps_LS = eps * nrow(X);
-
- # BEGIN LEAST SQUARES
-
- r_LS = - w_X;
- z_LS = matrix (0.0, rows = ncol(X), cols = 1);
- p_LS = - r_LS;
- norm_r2_LS = sum (r_LS ^ 2);
- i_LS = 0;
- while (i_LS < max_iter_CG & i_LS < ncol(X) & norm_r2_LS >= eps_LS)
- {
- q_LS = t(X) %*% X %*% p_LS;
- q_LS = q_LS + lambda_LS * p_LS;
- alpha_LS = norm_r2_LS / sum (p_LS * q_LS);
- z_LS = z_LS + alpha_LS * p_LS;
- old_norm_r2_LS = norm_r2_LS;
- r_LS = r_LS + alpha_LS * q_LS;
- norm_r2_LS = sum (r_LS ^ 2);
- p_LS = -r_LS + (norm_r2_LS / old_norm_r2_LS) * p_LS;
- i_LS = i_LS + 1;
- }
-
- # END LEAST SQUARES
-
- w = (nrow(X) / sum (w_X * z_LS)) * z_LS;
- }
-
-
\ No newline at end of file
diff --git a/scripts/builtin/stepGLM.dml b/scripts/builtin/stepGLM.dml
new file mode 100644
index 00000000000..42492c9b276
--- /dev/null
+++ b/scripts/builtin/stepGLM.dml
@@ -0,0 +1,266 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+#
+# THIS SCRIPT CHOOSES A GLM REGRESSION MODEL IN A STEPWISE ALGIRITHM USING AIC
+# EACH GLM REGRESSION IS SOLVED USING NEWTON/FISHER SCORING WITH TRUST REGIONS
+#
+# INPUT PARAMETERS:
+# ---------------------------------------------------------------------------------------------
+# NAME TYPE DEFAULT MEANING
+# ---------------------------------------------------------------------------------------------
+# X Matrix --- Matrix X of feature vectors
+# Y Matrix --- Response Matrix Y with 1 column
+# link Int 2 Link function code: 1 = log, 2 = Logit, 3 = Probit, 4 = Cloglog
+# yneg Double 0.0 Response value for Bernoulli "No" label, usually 0.0 or -1.0
+# icpt Int 0 Intercept presence, X columns shifting and rescaling:
+# 0 = no intercept, no shifting, no rescaling;
+# 1 = add intercept, but neither shift nor rescale X;
+# 2 = add intercept, shift & rescale X columns to mean = 0, variance = 1
+# tol Double 0.000001 Tolerance (epsilon)
+# disp Double 0.0 (Over-)dispersion value, or 0.0 to estimate it from data
+# moi Int 200 Maximum number of outer (Newton / Fisher Scoring) iterations
+# mii Int 0 Maximum number of inner (Conjugate Gradient) iterations, 0 = no maximum
+# thr Double 0.01 Threshold to stop the algorithm: if the decrease in the value of AIC falls below thr
+# no further features are being checked and the algorithm stops
+# ---------------------------------------------------------------------------------------------
+# OUTPUT: Matrix beta, whose size depends on icpt:
+# icpt=0: ncol(X) x 1; icpt=1: (ncol(X) + 1) x 1; icpt=2: (ncol(X) + 1) x 2
+#
+# AIC Double --- AIC value
+# B Matrix --- Estimated regression parameters (betas)
+# S Matrix --- The selected features ordered as computed by the algorithm
+# ---------------------------------------------------------------------------------------------
+
+# THE StepGLM SCRIPT CURRENTLY SUPPORTS BERNOULLI DISTRIBUTION FAMILY AND THE FOLLOWING LINK FUNCTIONS ONLY!
+# - LOG
+# - LOGIT
+# - PROBIT
+# - CLOGLOG
+
+source("./scripts/builtin/glm.dml") as glm;
+
+m_stepGLM = function (
+ Matrix[Double] X,
+ Matrix[Double] Y,
+ Int link = 2,
+ Double yneg = 0.0,
+ Int icpt = 0,
+ Double tol = 0.000001,
+ Double disp = 0.0,
+ Int moi = 200,
+ Int mii = 0,
+ Double thr = 0.01
+) return (
+ Double AIC,
+ Matrix[Double] B,
+ Matrix[Double] S
+ )
+ {
+ intercept_status = icpt;
+ bernoulli_No_label = yneg;
+ distribution_type = 2;
+
+
+ if (distribution_type == 2 & ncol(Y) == 1) {
+ is_Y_negative = (Y == bernoulli_No_label);
+ Y = cbind (1 - is_Y_negative, is_Y_negative);
+ count_Y_negative = sum (is_Y_negative);
+ if (count_Y_negative == 0) {
+ stop ("StepGLM Input Error: all Y-values encode Bernoulli YES-label, none encode NO-label");
+ }
+ if (count_Y_negative == nrow(Y)) {
+ stop ("StepGLM Input Error: all Y-values encode Bernoulli NO-label, none encode YES-label");
+ }
+ }
+
+ X_orig = X;
+ num_records = nrow (X_orig);
+ num_features = ncol (X_orig);
+
+ # BEGIN STEPWISE GENERALIZED LINEAR MODELS
+
+ continue = TRUE;
+ columns_fixed = matrix (0, rows = 1, cols = num_features);
+ columns_fixed_ordered = matrix (0, rows = 1, cols = 1);
+
+ # X_global stores the best model found at each step
+ X_global = matrix (0, rows = num_records, cols = 1);
+
+ if (intercept_status == 0) {
+ # Compute AIC of an empty model with no features and no intercept (all Ys are zero)
+ [AIC_best, ignore_B1, ignore_S1] = internal_glm(X=X_global, Y=Y, intercept_status=0, num_features_orig=num_features, Selected=columns_fixed_ordered, link=link, disp=disp, tol=tol, moi=moi, mii=mii);
+ } else {
+ # compute AIC of an empty model with only intercept (all Ys are constant)
+ all_ones = matrix (1, rows = num_records, cols = 1);
+ [AIC_best, ignore_beta2, ignore_S2] = internal_glm(X=all_ones, Y=Y, intercept_status=0, num_features_orig=num_features, Selected=columns_fixed_ordered, link=link, disp=disp, tol=tol, moi=moi, mii=mii);
+ }
+
+ # First pass to examine single features
+ AICs = matrix (AIC_best, rows = 1, cols = num_features);
+ parfor (i in 1:num_features) {
+ [AIC_1, ignore_beta3, ignore_S3] = internal_glm(X=X_orig[,i], Y=Y, intercept_status=intercept_status, num_features_orig=num_features, Selected=columns_fixed_ordered, link=link, disp=disp, tol=tol, moi=moi, mii=mii);
+ AICs[1,i] = AIC_1;
+ }
+
+ # Determine the best AIC
+ column_best = 0;
+ for (k in 1:num_features) {
+ AIC_cur = as.scalar (AICs[1,k]);
+ if ( (AIC_cur < AIC_best) & ((AIC_best - AIC_cur) > abs (thr * AIC_best)) ) {
+ column_best = k;
+ AIC_best = as.scalar(AICs[1,k]);
+ }
+ }
+
+ if (column_best == 0) {
+ if (intercept_status == 0) {
+ # Compute AIC of an empty model with no features and no intercept (all Ys are zero)
+ [AIC_best, ignore_beta4, ignore_S4] = internal_glm(X=X_global, Y=Y, intercept_status=0, num_features_orig=num_features, Selected=columns_fixed_ordered, link=link, disp=disp, tol=tol, moi=moi, mii=mii);
+ } else {
+ # compute AIC of an empty model with only intercept (all Ys are constant)
+ [AIC_best, ignore_beta5, ignore_S5] = internal_glm(X=all_ones, Y=Y, intercept_status=0, num_features_orig=num_features, Selected=columns_fixed_ordered, link=link, disp=disp, tol=tol, moi=moi, mii=mii);
+ }
+ };
+
+ columns_fixed[1,column_best] = 1;
+ columns_fixed_ordered[1,1] = column_best;
+ X_global = X_orig[,column_best];
+
+ while (continue) {
+ # Subsequent passes over the features
+ parfor (i in 1:num_features) {
+ if (as.scalar(columns_fixed[1,i]) == 0) {
+
+ # Construct the feature matrix
+ X_loop = cbind (X_global, X_orig[,i]);
+
+ [AIC_2, ignore_beta6, ignore_S6] = internal_glm(X=X_loop, Y=Y, intercept_status=intercept_status, num_features_orig=num_features, Selected=columns_fixed_ordered, link=link, disp=disp, tol=tol, moi=moi, mii=mii);
+ AICs[1,i] = AIC_2;
+ }
+ }
+
+ # Determine the best AIC
+ for (k in 1:num_features) {
+ AIC_cur = as.scalar (AICs[1,k]);
+ if ( (AIC_cur < AIC_best) & ((AIC_best - AIC_cur) > abs (thr * AIC_best)) & (as.scalar(columns_fixed[1,k]) == 0) ) {
+ column_best = k;
+ AIC_best = as.scalar(AICs[1,k]);
+ }
+ }
+
+ # cbind best found features (i.e., columns) to X_global
+ if (as.scalar(columns_fixed[1,column_best]) == 0) { # new best feature found
+ columns_fixed[1,column_best] = 1;
+ columns_fixed_ordered = cbind (columns_fixed_ordered, as.matrix(column_best));
+ if (ncol(columns_fixed_ordered) == num_features) { # all features examined
+ X_global = cbind (X_global, X_orig[,column_best]);
+ continue = FALSE;
+ } else {
+ X_global = cbind (X_global, X_orig[,column_best]);
+ }
+ } else {
+ continue = FALSE;
+ }
+ }
+
+ # run GLM with selected set of features
+ [AIC, B, S] = internal_glm(X=X_global, Y=Y, intercept_status=intercept_status, num_features_orig=num_features, Selected=columns_fixed_ordered, link=link, disp=disp, tol=tol, moi=moi, mii=mii);
+ }
+
+compute_AIC = function(Matrix[Double] X, Matrix[Double] Y, Matrix[Double] B, Int link, Int icpt)
+ return (Double aic)
+{
+ # Isolate unscaled parameters; accounts for m_glm returning 2 columns when icpt=2
+ beta = B[, 1];
+
+ if (icpt > 0) {
+ ones = matrix(1, rows=nrow(X), cols=1);
+ X_design = cbind(X, ones);
+ } else {
+ X_design = X;
+ }
+
+ eta = X_design %*% beta;
+
+ # Map inverse link functions
+ if (link == 1) {
+ # log, see https://en.wikipedia.org/wiki/Generalized_linear_model#Link_function
+ mu = exp(eta);
+ } else if (link == 2) {
+ # logit, see https://en.wikipedia.org/wiki/Generalized_linear_model#Link_function
+ mu = 1 / (1 + exp(-eta));
+ } else if (link == 3) {
+ # probit approximation, page 1487 in "Qualitative Response Models: A Survey (1981)" by Takeshi Amemiya
+ mu = 1 / (1 + exp(-1.6 * eta));
+ } else if (link == 4) {
+ # cloglog, see https://search.r-project.org/CRAN/refmans/VGAM/html/clogloglink.html
+ mu = 1 - exp(-exp(eta));
+ } else {
+ stop("Unsupported link function code: " + link);
+ mu = eta;
+ }
+
+ # Constrain to prevent numerical discontinuity in log(0)
+ mu = max(mu, 1e-15);
+ mu = min(mu, 1 - 1e-15);
+
+ Y_yes = Y[, 1];
+ Y_neg = Y[, 2];
+
+ LL = sum(Y_yes * log(mu) + Y_neg * log(1 - mu));
+ k = nrow(beta);
+
+ aic = 2 * k - 2 * LL;
+}
+
+internal_glm = function (
+ Matrix[Double] X,
+ Matrix[Double] Y,
+ Int intercept_status,
+ Double num_features_orig,
+ Matrix[Double] Selected,
+ Int link,
+ Double disp,
+ Double tol,
+ Int moi,
+ Int mii
+) return (
+ Double AIC,
+ Matrix[Double] B,
+ Matrix[Double] S
+) {
+ # bernoulli family parameters, see table in ./scripts/builtin/m_glm.dml for details.
+ new_link = link;
+ new_lpow = 1.0;
+
+ if (link == 1) {
+ new_link = 1;
+ new_lpow = 0.0;
+ }
+ B = glm::m_glm(X=X, Y=Y, dfam=2, vpow=0.0, link=new_link, lpow=new_lpow, yneg=0.0,
+ icpt=intercept_status, disp=disp, reg=0.0, tol=tol,
+ moi=moi, mii=mii, verbose=FALSE);
+
+ AIC = compute_AIC(X, Y, B, link, intercept_status);
+
+ S = Selected;
+}
diff --git a/src/main/java/org/apache/sysds/api/DMLScript.java b/src/main/java/org/apache/sysds/api/DMLScript.java
index a7a175bb7b6..0bb1e9b462d 100644
--- a/src/main/java/org/apache/sysds/api/DMLScript.java
+++ b/src/main/java/org/apache/sysds/api/DMLScript.java
@@ -508,9 +508,9 @@ private static void execute(String dmlScriptStr, String fnameOptConfig, Map inHops1 = new ArrayList<>();
- inHops1.add(expr);
- inHops1.add(expr2);
- currBuiltinOp = new DnnOp(target.getName(), DataType.MATRIX, target.getValueType(),
- OpOpDnn.valueOf(source.getOpCode().name()), inHops1);
- setBlockSizeAndRefreshSizeInfo(expr, currBuiltinOp);
- break;
- }
- case AVG_POOL:
- case MAX_POOL: {
- currBuiltinOp = new DnnOp(target.getName(), DataType.MATRIX, target.getValueType(),
- OpOpDnn.valueOf(source.getOpCode().name()), getALHopsForPoolingForwardIM2COL(expr, source, 1, hops));
- setBlockSizeAndRefreshSizeInfo(expr, currBuiltinOp);
- break;
- }
- case AVG_POOL_BACKWARD:
- case MAX_POOL_BACKWARD: {
- currBuiltinOp = new DnnOp(target.getName(), DataType.MATRIX, target.getValueType(),
- OpOpDnn.valueOf(source.getOpCode().name()), getALHopsForConvOpPoolingCOL2IM(expr, source, 1, hops));
- setBlockSizeAndRefreshSizeInfo(expr, currBuiltinOp);
- break;
- }
- case CONV2D:
- case CONV2D_BACKWARD_FILTER:
- case CONV2D_BACKWARD_DATA: {
- currBuiltinOp = new DnnOp(target.getName(), DataType.MATRIX, target.getValueType(),
- OpOpDnn.valueOf(source.getOpCode().name()), getALHopsForConvOp(expr, source, 1, hops));
- setBlockSizeAndRefreshSizeInfo(expr, currBuiltinOp);
- break;
- }
-
- case ROW_COUNT_DISTINCT:
- currBuiltinOp = new AggUnaryOp(target.getName(),
- DataType.MATRIX, target.getValueType(), AggOp.COUNT_DISTINCT, Direction.Row, expr);
- break;
-
- case COL_COUNT_DISTINCT:
- currBuiltinOp = new AggUnaryOp(target.getName(),
- DataType.MATRIX, target.getValueType(), AggOp.COUNT_DISTINCT, Direction.Col, expr);
- break;
-
- case GET_CATEGORICAL_MASK:
- currBuiltinOp = new BinaryOp(target.getName(), DataType.MATRIX, ValueType.FP64, OpOp2.GET_CATEGORICAL_MASK, expr, expr2);
- break;
- default:
- throw new ParseException("Unsupported builtin function type: "+source.getOpCode());
- }
-
- boolean isConvolution = source.getOpCode() == Builtins.CONV2D || source.getOpCode() == Builtins.CONV2D_BACKWARD_DATA ||
- source.getOpCode() == Builtins.CONV2D_BACKWARD_FILTER ||
- source.getOpCode() == Builtins.MAX_POOL || source.getOpCode() == Builtins.MAX_POOL_BACKWARD ||
- source.getOpCode() == Builtins.AVG_POOL || source.getOpCode() == Builtins.AVG_POOL_BACKWARD;
- if( !isConvolution) {
+ boolean isConvolution = source.getOpCode() == Builtins.CONV2D ||
+ source.getOpCode() == Builtins.CONV2D_BACKWARD_DATA ||
+ source.getOpCode() == Builtins.CONV2D_BACKWARD_FILTER || source.getOpCode() == Builtins.MAX_POOL ||
+ source.getOpCode() == Builtins.MAX_POOL_BACKWARD || source.getOpCode() == Builtins.AVG_POOL ||
+ source.getOpCode() == Builtins.AVG_POOL_BACKWARD;
+ if(!isConvolution) {
// Since the dimension of output doesnot match that of input variable for these operations
setIdentifierParams(currBuiltinOp, source.getOutput());
}
diff --git a/src/main/java/org/apache/sysds/parser/DataExpression.java b/src/main/java/org/apache/sysds/parser/DataExpression.java
index 68a3d1b7ffe..3d3a90b4f6f 100644
--- a/src/main/java/org/apache/sysds/parser/DataExpression.java
+++ b/src/main/java/org/apache/sysds/parser/DataExpression.java
@@ -1176,52 +1176,72 @@ else if( getVarParam(READNNZPARAM) != null ) {
boolean isHDF5 = (formatTypeString != null && formatTypeString.equalsIgnoreCase(FileFormat.HDF5.toString()));
- boolean isCOG = (formatTypeString != null && formatTypeString.equalsIgnoreCase(FileFormat.COG.toString()));
+ // handle all csv default parameters
+ handleCSVDefaultParam(DELIM_DELIMITER, ValueType.STRING, conditional);
+ handleCSVDefaultParam(DELIM_FILL_VALUE, ValueType.FP64, conditional);
+ handleCSVDefaultParam(DELIM_HAS_HEADER_ROW, ValueType.BOOLEAN, conditional);
+ handleCSVDefaultParam(DELIM_FILL, ValueType.BOOLEAN, conditional);
+ handleCSVDefaultParam(DELIM_NA_STRINGS, ValueType.STRING, conditional);
+ }
- // Delta tables are self-describing (schema + dimensions discovered from the
- // transaction log at read time), so dimensions are optional like CSV.
- boolean isDelta = (formatTypeString != null && formatTypeString.equalsIgnoreCase(FileFormat.DELTA.toString()));
+ boolean isLIBSVM = false;
+ isLIBSVM = (formatTypeString != null &&
+ formatTypeString.equalsIgnoreCase(FileFormat.LIBSVM.toString()));
+ if(isLIBSVM) {
+ // Handle libsvm file format
+ shouldReadMTD = true;
+
+ // only allow IO_FILENAME, READROWPARAM, READCOLPARAM
+ // as valid parameters
+ if(!inferredFormatType) {
+ for(String key : _varParams.keySet()) {
+ if(!(key.equals(IO_FILENAME) || key.equals(FORMAT_TYPE) || key.equals(READROWPARAM) ||
+ key.equals(READCOLPARAM) || key.equals(READNNZPARAM) || key.equals(DATATYPEPARAM) ||
+ key.equals(VALUETYPEPARAM) || key.equals(DELIM_DELIMITER) ||
+ key.equals(LIBSVM_INDEX_DELIM))) {
+ String msg = "Only parameters allowed are: " + IO_FILENAME + "," + READROWPARAM + ","
+ + READCOLPARAM + DELIM_DELIMITER + "," + LIBSVM_INDEX_DELIM;
+
+ raiseValidateError(
+ "Invalid parameter " + key + " in read statement: " + toString() + ". " + msg,
+ conditional, LanguageErrorCodes.INVALID_PARAMETERS);
+ }
+ }
+ }
+ // handle all default parameters
+ handleCSVDefaultParam(DELIM_DELIMITER, ValueType.STRING, conditional);
+ handleCSVDefaultParam(LIBSVM_INDEX_DELIM, ValueType.STRING, conditional);
+ }
- dataTypeString = (getVarParam(DATATYPEPARAM) == null) ? null : getVarParam(DATATYPEPARAM).toString();
-
- if ( dataTypeString == null || dataTypeString.equalsIgnoreCase(Statement.MATRIX_DATA_TYPE)
- || dataTypeString.equalsIgnoreCase(Statement.FRAME_DATA_TYPE)) {
-
- boolean isMatrix = false;
- if ( dataTypeString == null || dataTypeString.equalsIgnoreCase(Statement.MATRIX_DATA_TYPE))
+ boolean isHDF5 = (formatTypeString != null &&
+ formatTypeString.equalsIgnoreCase(FileFormat.HDF5.toString()));
+
+ boolean isCOG = (formatTypeString != null &&
+ formatTypeString.equalsIgnoreCase(FileFormat.COG.toString()));
+
+ // Delta tables are self-describing (schema + dimensions discovered from the
+ // transaction log at read time), so dimensions are optional like CSV.
+ boolean isDelta = (formatTypeString != null &&
+ formatTypeString.equalsIgnoreCase(FileFormat.DELTA.toString()));
+
+ dataTypeString = (getVarParam(DATATYPEPARAM) == null) ? null : getVarParam(DATATYPEPARAM).toString();
+
+ if(dataTypeString == null || dataTypeString.equalsIgnoreCase(Statement.MATRIX_DATA_TYPE) ||
+ dataTypeString.equalsIgnoreCase(Statement.FRAME_DATA_TYPE)) {
+
+ boolean isMatrix = false;
+ if(dataTypeString == null || dataTypeString.equalsIgnoreCase(Statement.MATRIX_DATA_TYPE))
isMatrix = true;
-
- // set data type
- getOutput().setDataType(isMatrix ? DataType.MATRIX : DataType.FRAME);
-
- // set number non-zeros
- Expression ennz = getVarParam("nnz");
- long nnz = -1;
- if( ennz != null ) {
- nnz = Long.valueOf(ennz.toString());
- getOutput().setNnz(nnz);
- }
- // Following dimension checks must be done when data type = MATRIX_DATA_TYPE
- // initialize size of target data identifier to UNKNOWN
- getOutput().setDimensions(-1, -1);
-
- if (!isCSV && !isLIBSVM && !isHDF5 && !isCOG && !isDelta && ConfigurationManager.getCompilerConfig()
- .getBool(ConfigType.REJECT_READ_WRITE_UNKNOWNS) //skip check for csv/libsvm/delta format / jmlc api
- && (getVarParam(READROWPARAM) == null || getVarParam(READCOLPARAM) == null) ) {
- raiseValidateError("Missing or incomplete dimension information in read statement: "
- + mtdFileName, conditional, LanguageErrorCodes.INVALID_PARAMETERS);
- }
-
- if (getVarParam(READROWPARAM) instanceof ConstIdentifier
- && getVarParam(READCOLPARAM) instanceof ConstIdentifier)
- {
- // these are strings that are long values
- Long dim1 = (getVarParam(READROWPARAM) == null) ? null : Long.valueOf( getVarParam(READROWPARAM).toString());
- Long dim2 = (getVarParam(READCOLPARAM) == null) ? null : Long.valueOf( getVarParam(READCOLPARAM).toString());
- if ( !isCSV && !isDelta && (dim1 < 0 || dim2 < 0) && ConfigurationManager
- .getCompilerConfig().getBool(ConfigType.REJECT_READ_WRITE_UNKNOWNS) ) {
- raiseValidateError("Invalid dimension information in read statement", conditional, LanguageErrorCodes.INVALID_PARAMETERS);
+ // set data type
+ getOutput().setDataType(isMatrix ? DataType.MATRIX : DataType.FRAME);
+
+ // set number non-zeros
+ Expression ennz = getVarParam("nnz");
+ long nnz = -1;
+ if(ennz != null) {
+ nnz = Long.valueOf(ennz.toString());
+ getOutput().setNnz(nnz);
}
// set dim1 and dim2 values
@@ -1252,104 +1272,10 @@ && getVarParam(READCOLPARAM) instanceof ConstIdentifier)
catch(Exception ex) {
raiseValidateError("Invalid format '" + fmt+ "' in statement: " + toString(), conditional);
}
-
- if (getVarParam(ROWBLOCKCOUNTPARAM) instanceof ConstIdentifier && getVarParam(COLUMNBLOCKCOUNTPARAM) instanceof ConstIdentifier) {
- Integer rowBlockCount = (getVarParam(ROWBLOCKCOUNTPARAM) == null) ?
- null : Integer.valueOf(getVarParam(ROWBLOCKCOUNTPARAM).toString());
- getOutput().setBlocksize(rowBlockCount != null ? rowBlockCount : -1);
- }
-
- // block dimensions must be -1x-1 when format="text"
- // NOTE MB: disabled validate of default blocksize for inputs w/ format="binary"
- // because we automatically introduce reblocks if blocksizes don't match
- if ( (getOutput().getFileFormat().isTextFormat() || !isMatrix) && getOutput().getBlocksize() != -1 ){
- raiseValidateError("Invalid block dimensions (" + getOutput().getBlocksize() + ") when format=" + getVarParam(FORMAT_TYPE) + " in \"" + this.toString() + "\".", conditional);
- }
-
- }
- else if ( dataTypeString.equalsIgnoreCase(Statement.SCALAR_DATA_TYPE)) {
- getOutput().setDataType(DataType.SCALAR);
- getOutput().setNnz(-1L);
- }
- else if ( dataTypeString.equalsIgnoreCase(DataType.LIST.name())) {
- getOutput().setDataType(DataType.LIST);
- }
- else{
- raiseValidateError("Unknown Data Type " + dataTypeString + ". Valid values: "
- + Statement.SCALAR_DATA_TYPE +", " + Statement.MATRIX_DATA_TYPE+", " + Statement.FRAME_DATA_TYPE
- +", " + DataType.LIST.name().toLowerCase(), conditional, LanguageErrorCodes.INVALID_PARAMETERS);
- }
-
- // handle value type parameter
- if (getVarParam(VALUETYPEPARAM) != null && !(getVarParam(VALUETYPEPARAM) instanceof StringIdentifier)){
- raiseValidateError("for read method, parameter " + VALUETYPEPARAM + " can only be a string. " +
- "Valid values are: " + Statement.DOUBLE_VALUE_TYPE +", " + Statement.INT_VALUE_TYPE + ", " + Statement.BOOLEAN_VALUE_TYPE + ", " + Statement.STRING_VALUE_TYPE, conditional);
- }
- // Identify the value type (used only for read method)
- String valueTypeString = getVarParam(VALUETYPEPARAM) == null ? null : getVarParam(VALUETYPEPARAM).toString();
- if (valueTypeString != null) {
- if (valueTypeString.equalsIgnoreCase(Statement.DOUBLE_VALUE_TYPE))
- getOutput().setValueType(ValueType.FP64);
- else if (valueTypeString.equalsIgnoreCase(Statement.STRING_VALUE_TYPE))
- getOutput().setValueType(ValueType.STRING);
- else if (valueTypeString.equalsIgnoreCase(Statement.INT_VALUE_TYPE))
- getOutput().setValueType(ValueType.INT64);
- else if (valueTypeString.equalsIgnoreCase(Statement.BOOLEAN_VALUE_TYPE))
- getOutput().setValueType(ValueType.BOOLEAN);
- else if (valueTypeString.equalsIgnoreCase(ValueType.UNKNOWN.name()))
- getOutput().setValueType(ValueType.UNKNOWN);
- else {
- raiseValidateError("Unknown Value Type " + valueTypeString
- + ". Valid values are: " + Statement.DOUBLE_VALUE_TYPE +", " + Statement.INT_VALUE_TYPE + ", " + Statement.BOOLEAN_VALUE_TYPE + ", " + Statement.STRING_VALUE_TYPE, conditional);
- }
- } else {
- getOutput().setValueType(ValueType.FP64);
- }
-
- break;
-
- case WRITE:
-
- // for CSV format, if no delimiter specified THEN set default ","
- if (getVarParam(FORMAT_TYPE) == null || checkFormatType(FileFormat.CSV) ){
- if (getVarParam(DELIM_DELIMITER) == null) {
- addVarParam(DELIM_DELIMITER, new StringIdentifier(DEFAULT_DELIM_DELIMITER, this));
- }
- if (getVarParam(DELIM_HAS_HEADER_ROW) == null) {
- addVarParam(DELIM_HAS_HEADER_ROW, new BooleanIdentifier(DEFAULT_DELIM_HAS_HEADER_ROW, this));
- }
- if (getVarParam(DELIM_SPARSE) == null) {
- addVarParam(DELIM_SPARSE, new BooleanIdentifier(DEFAULT_DELIM_SPARSE, this));
- }
- }
-
- // for LIBSVM format, add the default separators if not specified
- if (getVarParam(FORMAT_TYPE) == null || checkFormatType(FileFormat.LIBSVM)) {
- if(getVarParam(DELIM_DELIMITER) == null) {
- addVarParam(DELIM_DELIMITER, new StringIdentifier(DEFAULT_DELIM_DELIMITER, this));
- }
- if(getVarParam(LIBSVM_INDEX_DELIM) == null) {
- addVarParam(LIBSVM_INDEX_DELIM, new StringIdentifier(DEFAULT_LIBSVM_INDEX_DELIM, this));
- }
- if(getVarParam(DELIM_SPARSE) == null) {
- addVarParam(DELIM_SPARSE, new BooleanIdentifier(DEFAULT_DELIM_SPARSE, this));
- }
- }
-
- //validate read filename
- if (getVarParam(FORMAT_TYPE) == null || FileFormat.isTextFormat(getVarParam(FORMAT_TYPE).toString())
- || checkFormatType(FileFormat.DELTA)) //delta: columnar, no block layout
- getOutput().setBlocksize(-1);
- else if (checkFormatType(FileFormat.BINARY, FileFormat.COMPRESSED, FileFormat.UNKNOWN)) {
- if( getVarParam(ROWBLOCKCOUNTPARAM)!=null )
- getOutput().setBlocksize(Integer.parseInt(getVarParam(ROWBLOCKCOUNTPARAM).toString()));
- else
- getOutput().setBlocksize(ConfigurationManager.getBlocksize());
- }
- else if( getVarParam(FORMAT_TYPE) instanceof StringIdentifier ) //literal format
- raiseValidateError("Invalid format " + getVarParam(FORMAT_TYPE)
- + " in statement: " + toString(), conditional);
- break;
+ else if(getVarParam(FORMAT_TYPE) instanceof StringIdentifier) // literal format
+ raiseValidateError("Invalid format " + getVarParam(FORMAT_TYPE) + " in statement: " + toString(),
+ conditional);
+ break;
case RAND:
diff --git a/src/main/java/org/apache/sysds/runtime/compress/CompressedMatrixBlock.java b/src/main/java/org/apache/sysds/runtime/compress/CompressedMatrixBlock.java
index d0ba5363939..042e0dc0328 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/CompressedMatrixBlock.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/CompressedMatrixBlock.java
@@ -484,7 +484,7 @@ public static CompressedMatrixBlock read(DataInput in) throws IOException {
long nonZeros = in.readLong();
boolean overlappingColGroups = in.readBoolean();
List groups = ColGroupIO.readGroups(in, rlen);
- CompressedMatrixBlock ret = new CompressedMatrixBlock(rlen, clen, nonZeros, overlappingColGroups, groups);
+ CompressedMatrixBlock ret = new CompressedMatrixBlock(rlen, clen, nonZeros, overlappingColGroups, groups);
LOG.debug("Compressed read serialization time: " + t.stop());
return ret;
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/AColGroup.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/AColGroup.java
index 354325e293b..66d4e78cb0f 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/AColGroup.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/AColGroup.java
@@ -402,7 +402,8 @@ public final AColGroup rightMultByMatrix(MatrixBlock right) {
* @param cru The right hand side column upper
* @param nRows The number of rows in this column group
*/
- public void rightDecompressingMult(MatrixBlock right, MatrixBlock ret, int rl, int ru, int nRows, int crl, int cru) {
+ public void rightDecompressingMult(MatrixBlock right, MatrixBlock ret, int rl, int ru, int nRows, int crl,
+ int cru) {
throw new NotImplementedException(
"not supporting right Decompressing Multiply on class: " + this.getClass().getSimpleName());
}
@@ -977,9 +978,9 @@ public AColGroup[] splitReshapePushDown(final int multiplier, final int nRow, fi
/**
* Sort the values of the column group according to double comparison operations and return as another compressed
* group.
- *
+ *
* This sorting assumes that the column group is sorted independently of everything else.
- *
+ *
* @return The sorted group
*/
public abstract AColGroup sort();
@@ -996,9 +997,9 @@ public String toString() {
/**
* Return a new column group containing only the selected rows in the given boolean vector.
- *
+ *
* Whenever possible only modify the index structure, not the dictionary of the column groups.
- *
+ *
* @param selectV The selection vector
* @param rOut The number of rows in the output
* @return The new column group
@@ -1007,9 +1008,9 @@ public String toString() {
/**
* Return a new column group containing only the selected columns in the given boolean vector.
- *
+ *
* Whenever possible only modify the column index, and reduce the dictionaries of the column groups.
- *
+ *
* @param selectV The selection vector
* @return The new column group, or {@code null} if no column of this group is selected
*/
@@ -1045,7 +1046,7 @@ public AColGroup removeEmptyCols(boolean[] selectV) {
/**
* Using the selection of columns, slice out those and return in a new column group with the given column indexes.
* Ideally this method should only modify the dictionaries.
- *
+ *
* @param newColumnIDs the new column indexes
* @param selectedColumns The selected columns of this column group (guaranteed < current number of columns)
* @return A new Column group
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/AColGroupValue.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/AColGroupValue.java
index d825b91f089..d610c1b586c 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/AColGroupValue.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/AColGroupValue.java
@@ -210,7 +210,6 @@ public void clear() {
counts = null;
}
-
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ASDCZero.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ASDCZero.java
index 30de5e120c5..794d90c0d11 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ASDCZero.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ASDCZero.java
@@ -212,8 +212,8 @@ public void decompressToSparseBlock(SparseBlock sb, int rl, int ru, int offR, in
// TODO make sparse decompression where the iterator is known in argument
decompressToSparseBlockSparseDictionary(sb, rl, ru, offR, offC, mb.getSparseBlock());
else
- decompressToSparseBlockDenseDictionaryWithProvidedIterator(sb, rl, ru, offR, offC, mb.getDenseBlockValues(),
- it);
+ decompressToSparseBlockDenseDictionaryWithProvidedIterator(sb, rl, ru, offR, offC,
+ mb.getDenseBlockValues(), it);
}
else
decompressToSparseBlockDenseDictionaryWithProvidedIterator(sb, rl, ru, offR, offC, _dict.getValues(), it);
@@ -240,7 +240,7 @@ public void decompressToDenseBlockDenseDictionary(DenseBlock db, int rl, int ru,
}
public abstract void decompressToSparseBlockDenseDictionaryWithProvidedIterator(SparseBlock db, int rl, int ru,
- int offR, int offC, double[] values, AIterator it);
+ int offR, int offC, double[] values, AIterator it);
public abstract void decompressToDenseBlockDenseDictionaryWithProvidedIterator(DenseBlock db, int rl, int ru,
int offR, int offC, double[] values, AIterator it);
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupDDC.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupDDC.java
index b316e48474a..d643cae440c 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupDDC.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupDDC.java
@@ -674,8 +674,8 @@ private void defaultRightDecompressingMult(MatrixBlock right, MatrixBlock ret, i
}
}
- final void vectMM(double aa, double[] b, double[] c, int endT, int jd, int crl, int cru, int offOut, int k, int vLen,
- DoubleVector vVec) {
+ final void vectMM(double aa, double[] b, double[] c, int endT, int jd, int crl, int cru, int offOut, int k,
+ int vLen, DoubleVector vVec) {
vVec = vVec.broadcast(aa);
final int offj = k * jd;
final int end = endT + offj;
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupEmpty.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupEmpty.java
index 64114a054ab..d5ad55772c7 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupEmpty.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupEmpty.java
@@ -478,14 +478,13 @@ public AColGroup combineWithSameIndex(int nRow, int nCol, List right)
return new ColGroupEmpty(combinedIndex);
}
- @Override
- public AColGroup removeEmptyRows(boolean[] selectV, int rOut){
+ @Override
+ public AColGroup removeEmptyRows(boolean[] selectV, int rOut) {
return this;
}
-
@Override
- protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns){
+ protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns) {
return new ColGroupEmpty(newColumnIDs);
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupLinearFunctional.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupLinearFunctional.java
index fa8aa104ffb..e0bea3c3696 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupLinearFunctional.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupLinearFunctional.java
@@ -747,7 +747,7 @@ public AColGroup removeEmptyRows(boolean[] selectV, int rOut) {
}
@Override
- protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns){
+ protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns) {
throw new NotImplementedException("Unimplemented method 'removeEmptyColumns'");
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupOLE.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupOLE.java
index a251d828b5f..b4f0c144a73 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupOLE.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupOLE.java
@@ -738,7 +738,7 @@ public AColGroup removeEmptyRows(boolean[] selectV, int rOut) {
}
@Override
- protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns){
+ protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns) {
throw new NotImplementedException("Unimplemented method 'removeEmptyColumns'");
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupRLE.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupRLE.java
index 347cea9c0da..43df7fa3b94 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupRLE.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupRLE.java
@@ -1195,9 +1195,9 @@ public AColGroup[] splitReshape(int multiplier, int nRow, int nColOrg) {
public AColGroup removeEmptyRows(boolean[] selectV, int rOut) {
throw new NotImplementedException("Unimplemented method 'removeEmptyRows'");
}
-
+
@Override
- protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns){
+ protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns) {
throw new NotImplementedException("Unimplemented method 'removeEmptyColumns'");
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCFOR.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCFOR.java
index 815ecacf378..4566106a3e2 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCFOR.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupSDCFOR.java
@@ -634,8 +634,8 @@ protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList s
for(int i = 0; i < selectedColumns.size(); i++) {
ref[i] = _reference[selectedColumns.get(i)];
}
- return ColGroupSDCFOR.create(newColumnIDs, _numRows, _dict.sliceColumns(selectedColumns, getNumCols()), _indexes, _data, null,
- ref);
+ return ColGroupSDCFOR.create(newColumnIDs, _numRows, _dict.sliceColumns(selectedColumns, getNumCols()),
+ _indexes, _data, null, ref);
}
@Override
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupUncompressed.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupUncompressed.java
index 611add6480f..9797087f8c3 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupUncompressed.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupUncompressed.java
@@ -85,7 +85,7 @@ public class ColGroupUncompressed extends AColGroup {
/**
* Do not use this constructor of column group uncompressed, instead use the create constructor.
- *
+ *
* @param mb The contained data.
* @param colIndexes Column indexes for this Columngroup
*/
@@ -96,9 +96,10 @@ protected ColGroupUncompressed(MatrixBlock mb, IColIndex colIndexes) {
/**
* Do not use this constructor of column group quantization-fused uncompressed, instead use the create constructor.
- *
+ *
* @param mb The contained data.
- * @param scaleFactors For quantization-fused compression, scale factors per row, or a single value for entire matrix
+ * @param scaleFactors For quantization-fused compression, scale factors per row, or a single value for entire
+ * matrix
* @param colIndexes Column indexes for this Columngroup
*/
protected ColGroupUncompressed(MatrixBlock mb, IColIndex colIndexes, double[] scaleFactors) {
@@ -138,7 +139,8 @@ public static AColGroup create(MatrixBlock mb, IColIndex colIndexes) {
*
* @param mb The MB / data to contain in the uncompressed column
* @param colIndexes The column indexes for the group
- * @param scaleFactors For quantization-fused compression, scale factors per row, or a single value for entire matrix
+ * @param scaleFactors For quantization-fused compression, scale factors per row, or a single value for entire
+ * matrix
* @return An Uncompressed Column group
*/
public static AColGroup createQuantized(MatrixBlock mb, IColIndex colIndexes, double[] scaleFactors) {
@@ -157,7 +159,8 @@ public static AColGroup createQuantized(MatrixBlock mb, IColIndex colIndexes, do
* @param rawBlock The uncompressed block; uncompressed data must be present at the time that the constructor is
* called
* @param transposed Says if the input matrix raw block have been transposed.
- * @param scaleFactors For quantization-fused compression, scale factors per row, or a single value for entire matrix
+ * @param scaleFactors For quantization-fused compression, scale factors per row, or a single value for entire
+ * matrix
* @return AColGroup.
*/
public static AColGroup createQuantized(IColIndex colIndexes, MatrixBlock rawBlock, boolean transposed,
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupUncompressedArray.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupUncompressedArray.java
index 51e26a3f9d2..de8a740ceb2 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupUncompressedArray.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/ColGroupUncompressedArray.java
@@ -290,7 +290,7 @@ public AColGroup removeEmptyRows(boolean[] selectV, int rOut) {
}
@Override
- protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns){
+ protected AColGroup removeEmptyColsSubset(IColIndex newColumnIDs, IntArrayList selectedColumns) {
throw new NotImplementedException("Unimplemented method 'removeEmptyColumns'");
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/AIdentityDictionary.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/AIdentityDictionary.java
index a7e715b59b8..6e66ef6ef9b 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/AIdentityDictionary.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/AIdentityDictionary.java
@@ -76,8 +76,8 @@ public double[] productAllRowsToDoubleWithDefault(double[] defaultTuple) {
return ret;
}
- @Override
- public int[] sort(){
+ @Override
+ public int[] sort() {
throw new NotImplementedException();
}
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/DeltaDictionary.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/DeltaDictionary.java
index 9a0412145f0..7ebba2f1a76 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/DeltaDictionary.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/DeltaDictionary.java
@@ -138,8 +138,8 @@ public IDictionary clone() {
throw new NotImplementedException();
}
- @Override
- public IDictionary sliceColumns(IntArrayList selectedColumns, int nCol){
+ @Override
+ public IDictionary sliceColumns(IntArrayList selectedColumns, int nCol) {
throw new NotImplementedException();
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IDictionary.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IDictionary.java
index c8ddfc4883a..b5e1a99355b 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IDictionary.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IDictionary.java
@@ -1055,7 +1055,7 @@ public IDictionary rightMMPreAggSparse(int numVals, SparseBlock b, IColIndex thi
/**
* Slice out the selected columns given of this encoded group.
- *
+ *
* @param selectedColumns The columns to slice out and return as a new matrix.
* @param nCol The number of columns in this dictionary.
* @return The returned matrix
@@ -1064,9 +1064,9 @@ public IDictionary rightMMPreAggSparse(int numVals, SparseBlock b, IColIndex thi
/**
* Sort the values of this dictionary via an index of how the values mapped previously.
- *
+ *
* In practice this design means we can reuse the previous dictionary for the resulting column group
- *
+ *
* @return The sorted index.
*/
public int[] sort();
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IdentityDictionary.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IdentityDictionary.java
index c2540de959a..4337da7307f 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IdentityDictionary.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IdentityDictionary.java
@@ -541,8 +541,8 @@ public String getString(int colIndexes) {
return "IdentityMatrix of size: " + nRowCol + " with empty: " + withEmpty;
}
- @Override
- public IDictionary sliceColumns(IntArrayList selectedColumns, int nCol){
+ @Override
+ public IDictionary sliceColumns(IntArrayList selectedColumns, int nCol) {
return getMBDict().sliceColumns(selectedColumns, nCol);
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IdentityDictionarySlice.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IdentityDictionarySlice.java
index c7f642edfd0..47628b43d2a 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IdentityDictionarySlice.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/dictionary/IdentityDictionarySlice.java
@@ -311,8 +311,8 @@ public String getString(int colIndexes) {
return toString();
}
- @Override
- public IDictionary sliceColumns(IntArrayList selectedColumns, int nCol){
+ @Override
+ public IDictionary sliceColumns(IntArrayList selectedColumns, int nCol) {
return getMBDict().sliceColumns(selectedColumns, nCol);
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/AMapToData.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/AMapToData.java
index 83a74972db7..6d516713689 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/AMapToData.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/mapping/AMapToData.java
@@ -1064,7 +1064,7 @@ public AMapToData removeEmpty(final boolean[] selectV, final int rOut) {
/**
* Use the offsets of the select vector to choose which values to keep.
- *
+ *
* @param select The row indexes to keep
* @return A New MapToData
*/
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/AOffset.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/AOffset.java
index f65876b7f37..bf8ee7f9ee1 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/AOffset.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/AOffset.java
@@ -56,11 +56,11 @@ public abstract class AOffset implements Serializable {
protected static final Log LOG = LogFactory.getLog(AOffset.class.getName());
/**
- * Lazy holder for the cached empty slice. The empty slice is built on first use rather than in AOffset's
- * static initializer: instantiating the OffsetEmpty subclass from AOffset's {@code } forms a
- * superclass/subclass class-initialization cycle that deadlocks when several threads first touch the offset
- * classes concurrently (e.g. parallel tests). Deferring it to first use guarantees AOffset is already
- * initialized by the time OffsetEmpty is loaded, so no cycle exists.
+ * Lazy holder for the cached empty slice. The empty slice is built on first use rather than in AOffset's static
+ * initializer: instantiating the OffsetEmpty subclass from AOffset's {@code } forms a superclass/subclass
+ * class-initialization cycle that deadlocks when several threads first touch the offset classes concurrently (e.g.
+ * parallel tests). Deferring it to first use guarantees AOffset is already initialized by the time OffsetEmpty is
+ * loaded, so no cycle exists.
*/
private static final class EmptySliceHolder {
static final OffsetSliceInfo EMPTY_SLICE = new OffsetSliceInfo(-1, -1, new OffsetEmpty());
diff --git a/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/OffsetEmpty.java b/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/OffsetEmpty.java
index 866168ded2f..37ff41cf817 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/OffsetEmpty.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/colgroup/offset/OffsetEmpty.java
@@ -76,6 +76,7 @@ public int getOffsetToLast() {
public long getInMemorySize() {
return estimateInMemorySize();
}
+
@Override
public boolean equals(AOffset b) {
return b instanceof OffsetEmpty;
diff --git a/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibBinaryCellOp.java b/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibBinaryCellOp.java
index d981ab87838..7953322350e 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibBinaryCellOp.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibBinaryCellOp.java
@@ -139,7 +139,8 @@ private static boolean isDoubleCompressedOpApplicable(CompressedMatrixBlock m1,
m1.getColGroups().get(0) instanceof ColGroupDDC && !((CompressedMatrixBlock) that).isOverlapping() &&
((CompressedMatrixBlock) that).getColGroups().get(0) instanceof ColGroupDDC &&
((IMapToDataGroup) m1.getColGroups().get(0))
- .getMapToData() == ((IMapToDataGroup) ((CompressedMatrixBlock) that).getColGroups().get(0)).getMapToData();
+ .getMapToData() == ((IMapToDataGroup) ((CompressedMatrixBlock) that).getColGroups().get(0))
+ .getMapToData();
}
private static CompressedMatrixBlock doubleCompressedBinaryOp(BinaryOperator op, CompressedMatrixBlock m1,
@@ -1062,7 +1063,8 @@ public Long call() {
return _ret.recomputeNonZeros(_rl, _ru - 1);
}
- private final void processBlock(final int rl, final int ru, final List groups, final AIterator[] its) {
+ private final void processBlock(final int rl, final int ru, final List groups,
+ final AIterator[] its) {
decompressToTmpBlock(rl, ru, tmp.getSparseBlock(), groups, its);
// decompressing multiple column groups can leave the temp rows with unsorted column indices, so sort
// before reading them in stored order into the (column-sorted) output sparse block.
diff --git a/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibMMChain.java b/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibMMChain.java
index cc7953f8c5d..a91b75ae73c 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibMMChain.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibMMChain.java
@@ -96,7 +96,7 @@ public static MatrixBlock mmChain(CompressedMatrixBlock x, MatrixBlock v, Matrix
if(x.isEmpty())
return returnEmpty(x, out);
- if(ctype == ChainType.XtXv && x.getColGroups().size() < 5 && x.getNumColumns()> 30){
+ if(ctype == ChainType.XtXv && x.getColGroups().size() < 5 && x.getNumColumns() > 30) {
MatrixBlock tmp = CLALibTSMM.leftMultByTransposeSelf(x, k);
return tmp.aggregateBinaryOperations(tmp, v, out, InstructionUtils.getMatMultOperator(k));
}
diff --git a/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibRemoveEmpty.java b/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibRemoveEmpty.java
index 3755e4040e7..802eddffcb8 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibRemoveEmpty.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibRemoveEmpty.java
@@ -36,7 +36,7 @@ public class CLALibRemoveEmpty {
/**
* CP rmempty operation (single input, single output matrix)
- *
+ *
* @param in The input matrix
* @param ret The output matrix
* @param rows If we are removing based on rows, or columns.
@@ -66,13 +66,13 @@ private static MatrixBlock rmEmptyCols(CompressedMatrixBlock in, MatrixBlock ret
int cOut = (int) select.getNonZeros();
if(cOut == -1)
cOut = (int) select.recomputeNonZeros();
- if(cOut == 0){
+ if(cOut == 0) {
ret.reset(in.getNumRows(), !emptyReturn ? 0 : 1);
return ret;
}
- final boolean[] selectV = DataConverter
- .convertToBooleanVector(CompressedMatrixBlock.getUncompressed(select, "decompressing selection in rmempty"));
+ final boolean[] selectV = DataConverter.convertToBooleanVector(
+ CompressedMatrixBlock.getUncompressed(select, "decompressing selection in rmempty"));
final List inG = in.getColGroups();
final List retG = new ArrayList<>(inG.size());
@@ -102,18 +102,17 @@ private static MatrixBlock rmEmptyRows(CompressedMatrixBlock in, MatrixBlock ret
int rOut = (int) select.getNonZeros();
if(rOut == -1)
rOut = (int) select.recomputeNonZeros();
- if(rOut == 0){
+ if(rOut == 0) {
ret.reset(!emptyReturn ? 0 : 1, in.getNumColumns());
return ret;
}
- // TODO: add optimization to avoid linear scan and make selectV indexes, if selection is small relative to number
+ // TODO: add optimization to avoid linear scan and make selectV indexes, if selection is small relative to
+ // number
// of rows
// TODO: add decompress to boolean vector.
final boolean[] selectV = DataConverter.convertToBooleanVector(select);
-
-
final List inG = in.getColGroups();
final List retG = new ArrayList<>(inG.size());
try {
diff --git a/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibSort.java b/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibSort.java
index b94f11ae723..5ae7bd5103b 100644
--- a/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibSort.java
+++ b/src/main/java/org/apache/sysds/runtime/compress/lib/CLALibSort.java
@@ -40,10 +40,10 @@ private CLALibSort() {
/**
* Sort (order) a compressed matrix in place of the {@code order} built-in, while keeping the result compressed.
*
- * The compressed fast-path only supports the case the user can benefit from: a single column held in a single column
- * group, sorted ascending and returning the sorted values (not the index permutation). For everything else (multiple
- * columns, multiple column groups, descending order, index return, or a column-group encoding without a sort
- * implementation) this returns {@code null} so the caller can fall back to a decompressed reorg.
+ * The compressed fast-path only supports the case the user can benefit from: a single column held in a single
+ * column group, sorted ascending and returning the sorted values (not the index permutation). For everything else
+ * (multiple columns, multiple column groups, descending order, index return, or a column-group encoding without a
+ * sort implementation) this returns {@code null} so the caller can fall back to a decompressed reorg.
*
* @param mb the compressed matrix to sort
* @param fn the sort specification carried by the reorg operator
diff --git a/src/main/java/org/apache/sysds/runtime/controlprogram/caching/FrameObject.java b/src/main/java/org/apache/sysds/runtime/controlprogram/caching/FrameObject.java
index 87d14dbf87e..9ccaa474f39 100644
--- a/src/main/java/org/apache/sysds/runtime/controlprogram/caching/FrameObject.java
+++ b/src/main/java/org/apache/sysds/runtime/controlprogram/caching/FrameObject.java
@@ -208,8 +208,8 @@ protected FrameBlock readBlobFromHDFS(String fname, long[] dims) throws IOExcept
if(data == null)
throw new IOException("Unable to load frame from file: " + fname);
- //Delta and CSV discover dimensions (and Delta also schema) at read time, so
- //refresh the cached metadata to reflect the materialized frame block.
+ // Delta and CSV discover dimensions (and Delta also schema) at read time, so
+ // refresh the cached metadata to reflect the materialized frame block.
if(iimd.getFileFormat() == FileFormat.CSV || iimd.getFileFormat() == FileFormat.DELTA) {
_metaData = _metaData instanceof MetaDataFormat ? new MetaDataFormat(data.getDataCharacteristics(),
iimd.getFileFormat()) : new MetaData(data.getDataCharacteristics());
diff --git a/src/main/java/org/apache/sysds/runtime/controlprogram/caching/MatrixObject.java b/src/main/java/org/apache/sysds/runtime/controlprogram/caching/MatrixObject.java
index 28fa70f7741..4331da2b426 100644
--- a/src/main/java/org/apache/sysds/runtime/controlprogram/caching/MatrixObject.java
+++ b/src/main/java/org/apache/sysds/runtime/controlprogram/caching/MatrixObject.java
@@ -454,7 +454,7 @@ protected MatrixBlock readBlobFromHDFS(String fname, long[] dims) throws IOExcep
rlen, clen, blen, mc.getNonZeros(), getFileFormatProperties());
if(iimd.getFileFormat() == FileFormat.CSV || iimd.getFileFormat() == FileFormat.DELTA) {
- //dimensions/nnz are discovered at read time for these self-describing formats
+ // dimensions/nnz are discovered at read time for these self-describing formats
_metaData = _metaData instanceof MetaDataFormat ? new MetaDataFormat(newData.getDataCharacteristics(),
iimd.getFileFormat()) : new MetaData(newData.getDataCharacteristics());
}
diff --git a/src/main/java/org/apache/sysds/runtime/controlprogram/context/SparkExecutionContext.java b/src/main/java/org/apache/sysds/runtime/controlprogram/context/SparkExecutionContext.java
index b52f3777e1f..fbae4925c66 100644
--- a/src/main/java/org/apache/sysds/runtime/controlprogram/context/SparkExecutionContext.java
+++ b/src/main/java/org/apache/sysds/runtime/controlprogram/context/SparkExecutionContext.java
@@ -122,9 +122,9 @@ public class SparkExecutionContext extends ExecutionContext
//singleton spark context (as there can be only one spark context per JVM)
private static JavaSparkContext _spctx = null;
- //registered users of the singleton context (guarded by the
- //SparkExecutionContext.class monitor); maintained by enterSparkExecution()/
- //exitSparkExecution(), and close() only stops the context once it hits zero
+ // registered users of the singleton context (guarded by the
+ // SparkExecutionContext.class monitor); maintained by enterSparkExecution()/
+ // exitSparkExecution(), and close() only stops the context once it hits zero
private static int _activeExecutions = 0;
//registry of parallelized RDDs to enforce that at any time, we spent at most
@@ -175,8 +175,8 @@ public synchronized static JavaSparkContext getSparkContextStatic() {
initSparkContext();
if(_spctx.sc().isStopped()){
_spctx = null;
- //the previous context was stopped; reset the active-execution count so a
- //stale registration cannot skip a future legitimate stop of the new one
+ // the previous context was stopped; reset the active-execution count so a
+ // stale registration cannot skip a future legitimate stop of the new one
_activeExecutions = 0;
initSparkContext();
}
@@ -196,16 +196,15 @@ public synchronized static boolean isSparkContextCreated() {
public static void resetSparkContextStatic() {
synchronized(SparkExecutionContext.class) {
_spctx = null;
- //force-discarding the shared context: drop the active-execution count so
- //a stale registration cannot skip a future legitimate stop
+ // force-discarding the shared context: drop the active-execution count so
+ // a stale registration cannot skip a future legitimate stop
_activeExecutions = 0;
}
}
/**
- * Registers an active user of the shared spark context. Must be balanced by a
- * later {@link #exitSparkExecution()} so a concurrent execution cannot stop the
- * context while this one still has in-flight jobs.
+ * Registers an active user of the shared spark context. Must be balanced by a later {@link #exitSparkExecution()}
+ * so a concurrent execution cannot stop the context while this one still has in-flight jobs.
*/
public static void enterSparkExecution() {
synchronized(SparkExecutionContext.class) {
@@ -214,9 +213,8 @@ public static void enterSparkExecution() {
}
/**
- * Releases an active user previously registered via {@link #enterSparkExecution()}.
- * Only adjusts the count; the actual teardown is left to {@link #close()}, which
- * stops the context once no registered execution remains.
+ * Releases an active user previously registered via {@link #enterSparkExecution()}. Only adjusts the count; the
+ * actual teardown is left to {@link #close()}, which stops the context once no registered execution remains.
*/
public static void exitSparkExecution() {
synchronized(SparkExecutionContext.class) {
@@ -227,13 +225,13 @@ public static void exitSparkExecution() {
public void close() {
synchronized(SparkExecutionContext.class) {
- //keep the shared context alive while a registered execution still uses
- //it; close() never changes the count, so an unpaired close() (a caller
- //that never entered) cannot stop a context another execution is using
+ // keep the shared context alive while a registered execution still uses
+ // it; close() never changes the count, so an unpaired close() (a caller
+ // that never entered) cannot stop a context another execution is using
if(_activeExecutions > 0) {
if(LOG.isDebugEnabled())
- LOG.debug("Keeping shared spark context alive; " + _activeExecutions
- + " execution(s) still active");
+ LOG.debug(
+ "Keeping shared spark context alive; " + _activeExecutions + " execution(s) still active");
return;
}
if(_spctx != null) {
diff --git a/src/main/java/org/apache/sysds/runtime/controlprogram/federated/FederatedWorker.java b/src/main/java/org/apache/sysds/runtime/controlprogram/federated/FederatedWorker.java
index 682cc8e3fff..c502817e026 100644
--- a/src/main/java/org/apache/sysds/runtime/controlprogram/federated/FederatedWorker.java
+++ b/src/main/java/org/apache/sysds/runtime/controlprogram/federated/FederatedWorker.java
@@ -95,8 +95,7 @@ private void run() {
int par_conn = ConfigurationManager.getDMLConfig().getIntValue(DMLConfig.FEDERATED_PAR_CONN);
final int EVENT_LOOP_THREADS = (par_conn > 0) ? par_conn : InfrastructureAnalyzer.getLocalParallelism();
// Daemon event loops so a leaked in-JVM (test) worker cannot block JVM exit.
- NioEventLoopGroup bossGroup = new NioEventLoopGroup(1,
- new DefaultThreadFactory("fed-worker-boss", true));
+ NioEventLoopGroup bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("fed-worker-boss", true));
ThreadPoolExecutor workerTPE = new ThreadPoolExecutor(1, Integer.MAX_VALUE, 10, TimeUnit.SECONDS,
new SynchronousQueue(true), new DefaultThreadFactory("fed-worker-pool", true));
NioEventLoopGroup workerGroup = new NioEventLoopGroup(EVENT_LOOP_THREADS, workerTPE);
diff --git a/src/main/java/org/apache/sysds/runtime/frame/data/columns/ArrayFactory.java b/src/main/java/org/apache/sysds/runtime/frame/data/columns/ArrayFactory.java
index 80a5d699dfa..ebf05972b87 100644
--- a/src/main/java/org/apache/sysds/runtime/frame/data/columns/ArrayFactory.java
+++ b/src/main/java/org/apache/sysds/runtime/frame/data/columns/ArrayFactory.java
@@ -125,13 +125,15 @@ public static RaggedArray create(T[] col, int m) {
/**
* Wrap a fully populated raw typed column array into an {@link Array} of the given value type. The runtime type of
- * {@code col} must match the primitive backing type of {@code vt} (e.g. {@code double[]} for {@link ValueType#FP64},
- * {@code String[]} for {@link ValueType#STRING}).
+ * {@code col} must match the primitive backing type of {@code vt} (e.g. {@code double[]} for
+ * {@link ValueType#FP64}, {@code String[]} for {@link ValueType#STRING}).
*
- *
For {@link ValueType#BOOLEAN} this mirrors {@link #allocateBoolean(int)}: a {@code boolean[]} longer than
- * {@link #bitSetSwitchPoint} is bit-packed into a compact {@link BitSetArray} (so a bulk decoder that fills a
- * plain {@code boolean[]} still ends up with the same representation as every other frame allocation path),
- * while shorter columns stay a plain {@link BooleanArray}.
+ *
+ * For {@link ValueType#BOOLEAN} this mirrors {@link #allocateBoolean(int)}: a {@code boolean[]} longer than
+ * {@link #bitSetSwitchPoint} is bit-packed into a compact {@link BitSetArray} (so a bulk decoder that fills a plain
+ * {@code boolean[]} still ends up with the same representation as every other frame allocation path), while shorter
+ * columns stay a plain {@link BooleanArray}.
+ *
*
* @param vt the value type of the column
* @param col the backing array to wrap
@@ -168,10 +170,10 @@ public static Array> create(ValueType vt, Object col) {
/**
* Allocate the raw backing array for a column of the given value type: the inverse of
- * {@link #create(ValueType, Object)}. Returns {@code double[]} for {@link ValueType#FP64},
- * {@code int[]} for INT32/UINT/HASH32, {@code long[]} for INT64/HASH64, {@code String[]} for STRING, etc. The
- * runtime array type matches what {@link #create(ValueType, Object)} expects, so a bulk decoder can fill this
- * primitive array directly and then wrap it via {@code create(vt, backing)}.
+ * {@link #create(ValueType, Object)}. Returns {@code double[]} for {@link ValueType#FP64}, {@code int[]} for
+ * INT32/UINT/HASH32, {@code long[]} for INT64/HASH64, {@code String[]} for STRING, etc. The runtime array type
+ * matches what {@link #create(ValueType, Object)} expects, so a bulk decoder can fill this primitive array directly
+ * and then wrap it via {@code create(vt, backing)}.
*
* @param vt the value type of the column
* @param nRow the number of rows to allocate
diff --git a/src/main/java/org/apache/sysds/runtime/frame/data/lib/MatrixBlockFromFrame.java b/src/main/java/org/apache/sysds/runtime/frame/data/lib/MatrixBlockFromFrame.java
index 9ff58065d97..95be95117e2 100644
--- a/src/main/java/org/apache/sysds/runtime/frame/data/lib/MatrixBlockFromFrame.java
+++ b/src/main/java/org/apache/sysds/runtime/frame/data/lib/MatrixBlockFromFrame.java
@@ -41,7 +41,7 @@ public class MatrixBlockFromFrame {
public static Boolean WARNED_FOR_FAILED_CAST = false;
- private MatrixBlockFromFrame(){
+ private MatrixBlockFromFrame() {
// private constructor for code coverage.
}
@@ -115,7 +115,7 @@ private static long convert(FrameBlock frame, MatrixBlock mb, int n, int rl, int
return convertStrict(frame, mb, n, rl, ru);
}
catch(NumberFormatException | DMLRuntimeException e) {
- synchronized(WARNED_FOR_FAILED_CAST){
+ synchronized(WARNED_FOR_FAILED_CAST) {
if(!WARNED_FOR_FAILED_CAST) {
LOG.error(
"Failed to convert to Matrix because of number format errors, falling back to NaN on incompatible cells",
diff --git a/src/main/java/org/apache/sysds/runtime/functionobjects/Builtin.java b/src/main/java/org/apache/sysds/runtime/functionobjects/Builtin.java
index eed2c58f78c..c12a187cf17 100644
--- a/src/main/java/org/apache/sysds/runtime/functionobjects/Builtin.java
+++ b/src/main/java/org/apache/sysds/runtime/functionobjects/Builtin.java
@@ -30,32 +30,13 @@
import jdk.incubator.vector.VectorSpecies;
-/**
- * Class with pre-defined set of objects. This class can not be instantiated elsewhere.
- *
- * Notes on commons.math FastMath:
- * * FastMath uses lookup tables and interpolation instead of native calls.
- * * The memory overhead for those tables is roughly 48KB in total (acceptable)
- * * Micro and application benchmarks showed significantly (30%-3x) performance improvements
- * for most operations; without loss of accuracy.
- * * atan / sqrt were 20% slower in FastMath and hence, we use Math there
- * * round / abs were equivalent in FastMath and hence, we use Math there
- * * Finally, there is just one argument against FastMath - The comparison heavily depends
- * on the JVM. For example, currently the IBM JDK JIT compiles to HW instructions for sqrt
- * which makes this operation very efficient; as soon as other operations like log/exp are
- * similarly compiled, we should rerun the micro benchmarks, and switch back if necessary.
- *
- */
-public class Builtin extends ValueFunction
-{
- private static final long serialVersionUID = 3836744687789840574L;
-
- public enum BuiltinCode { AUTODIFF, SIN, COS, TAN, SINH, COSH, TANH, ASIN, ACOS, ATAN, LOG, LOG_NZ, MIN,
- MAX, ABS, SIGN, SQRT, EXP, PLOGP, PRINT, PRINTF, NROW, NCOL, LENGTH, LINEAGE, ROUND, MAXINDEX, MININDEX,
- STOP, CEIL, FLOOR, CUMSUM, ROWCUMSUM, CUMPROD, CUMMIN, CUMMAX, CUMSUMPROD, INVERSE, SPROP, SIGMOID, EVAL, LIST,
- TYPEOF, APPLY_SCHEMA, DETECTSCHEMA, ISNA, ISNAN, ISINF, DROP_INVALID_TYPE,
- DROP_INVALID_LENGTH, VALUE_SWAP, FRAME_ROW_REPLICATE, GET_CATEGORICAL_MASK,
- MAP, COUNT_DISTINCT, COUNT_DISTINCT_APPROX, UNIQUE}
+ public enum BuiltinCode {
+ AUTODIFF, SIN, COS, TAN, SINH, COSH, TANH, ASIN, ACOS, ATAN, LOG, LOG_NZ, MIN, MAX, ABS, SIGN, SQRT, EXP, PLOGP,
+ PRINT, PRINTF, NROW, NCOL, LENGTH, LINEAGE, ROUND, MAXINDEX, MININDEX, STOP, CEIL, FLOOR, CUMSUM, ROWCUMSUM,
+ CUMPROD, CUMMIN, CUMMAX, CUMSUMPROD, INVERSE, SPROP, SIGMOID, EVAL, LIST, TYPEOF, APPLY_SCHEMA, DETECTSCHEMA,
+ ISNA, ISNAN, ISINF, DROP_INVALID_TYPE, DROP_INVALID_LENGTH, VALUE_SWAP, FRAME_ROW_REPLICATE,
+ GET_CATEGORICAL_MASK, MAP, COUNT_DISTINCT, COUNT_DISTINCT_APPROX, UNIQUE
+ }
private static final VectorSpecies SPECIES = DoubleVector.SPECIES_PREFERRED;
private static final int vLen = SPECIES.length();
@@ -68,59 +49,59 @@ public enum BuiltinCode { AUTODIFF, SIN, COS, TAN, SINH, COSH, TANH, ASIN, ACOS,
static public HashMap String2BuiltinCode;
static {
String2BuiltinCode = new HashMap<>();
- String2BuiltinCode.put( "autoDiff" , BuiltinCode.AUTODIFF);
- String2BuiltinCode.put( "sin" , BuiltinCode.SIN);
- String2BuiltinCode.put( "cos" , BuiltinCode.COS);
- String2BuiltinCode.put( "tan" , BuiltinCode.TAN);
- String2BuiltinCode.put( "sinh" , BuiltinCode.SINH);
- String2BuiltinCode.put( "cosh" , BuiltinCode.COSH);
- String2BuiltinCode.put( "tanh" , BuiltinCode.TANH);
- String2BuiltinCode.put( "asin" , BuiltinCode.ASIN);
- String2BuiltinCode.put( "acos" , BuiltinCode.ACOS);
- String2BuiltinCode.put( "atan" , BuiltinCode.ATAN);
- String2BuiltinCode.put( "log" , BuiltinCode.LOG);
- String2BuiltinCode.put( "log_nz" , BuiltinCode.LOG_NZ);
- String2BuiltinCode.put( "min" , BuiltinCode.MIN);
- String2BuiltinCode.put( "max" , BuiltinCode.MAX);
- String2BuiltinCode.put( "maxindex", BuiltinCode.MAXINDEX);
- String2BuiltinCode.put( "minindex", BuiltinCode.MININDEX);
- String2BuiltinCode.put( "abs" , BuiltinCode.ABS);
- String2BuiltinCode.put( "sign" , BuiltinCode.SIGN);
- String2BuiltinCode.put( "sqrt" , BuiltinCode.SQRT);
- String2BuiltinCode.put( "exp" , BuiltinCode.EXP);
- String2BuiltinCode.put( "plogp" , BuiltinCode.PLOGP);
- String2BuiltinCode.put( "print" , BuiltinCode.PRINT);
- String2BuiltinCode.put( "printf" , BuiltinCode.PRINTF);
- String2BuiltinCode.put( "eval" , BuiltinCode.EVAL);
- String2BuiltinCode.put( "list" , BuiltinCode.LIST);
- String2BuiltinCode.put( "nrow" , BuiltinCode.NROW);
- String2BuiltinCode.put( "ncol" , BuiltinCode.NCOL);
- String2BuiltinCode.put( "length" , BuiltinCode.LENGTH);
- String2BuiltinCode.put( "round" , BuiltinCode.ROUND);
- String2BuiltinCode.put( "stop" , BuiltinCode.STOP);
- String2BuiltinCode.put( "ceil" , BuiltinCode.CEIL);
- String2BuiltinCode.put( "floor" , BuiltinCode.FLOOR);
- String2BuiltinCode.put( "ucumk+" , BuiltinCode.CUMSUM);
- String2BuiltinCode.put( "urowcumk+" , BuiltinCode.ROWCUMSUM);
- String2BuiltinCode.put( "ucum*" , BuiltinCode.CUMPROD);
- String2BuiltinCode.put( "ucumk+*", BuiltinCode.CUMSUMPROD);
- String2BuiltinCode.put( "ucummin", BuiltinCode.CUMMIN);
- String2BuiltinCode.put( "ucummax", BuiltinCode.CUMMAX);
- String2BuiltinCode.put( "inverse", BuiltinCode.INVERSE);
- String2BuiltinCode.put( "sprop", BuiltinCode.SPROP);
- String2BuiltinCode.put( "sigmoid", BuiltinCode.SIGMOID);
- String2BuiltinCode.put( "typeOf", BuiltinCode.TYPEOF);
- String2BuiltinCode.put( "detectSchema", BuiltinCode.DETECTSCHEMA);
- String2BuiltinCode.put( "isna", BuiltinCode.ISNA);
- String2BuiltinCode.put( "isnan", BuiltinCode.ISNAN);
- String2BuiltinCode.put( "isinf", BuiltinCode.ISINF);
- String2BuiltinCode.put( "dropInvalidType", BuiltinCode.DROP_INVALID_TYPE);
- String2BuiltinCode.put( "freplicate", BuiltinCode.FRAME_ROW_REPLICATE);
- String2BuiltinCode.put( "dropInvalidLength", BuiltinCode.DROP_INVALID_LENGTH);
- String2BuiltinCode.put( "_map", BuiltinCode.MAP);
- String2BuiltinCode.put( "valueSwap", BuiltinCode.VALUE_SWAP);
- String2BuiltinCode.put( "applySchema", BuiltinCode.APPLY_SCHEMA);
- String2BuiltinCode.put( "get_categorical_mask", BuiltinCode.GET_CATEGORICAL_MASK);
+ String2BuiltinCode.put("autoDiff", BuiltinCode.AUTODIFF);
+ String2BuiltinCode.put("sin", BuiltinCode.SIN);
+ String2BuiltinCode.put("cos", BuiltinCode.COS);
+ String2BuiltinCode.put("tan", BuiltinCode.TAN);
+ String2BuiltinCode.put("sinh", BuiltinCode.SINH);
+ String2BuiltinCode.put("cosh", BuiltinCode.COSH);
+ String2BuiltinCode.put("tanh", BuiltinCode.TANH);
+ String2BuiltinCode.put("asin", BuiltinCode.ASIN);
+ String2BuiltinCode.put("acos", BuiltinCode.ACOS);
+ String2BuiltinCode.put("atan", BuiltinCode.ATAN);
+ String2BuiltinCode.put("log", BuiltinCode.LOG);
+ String2BuiltinCode.put("log_nz", BuiltinCode.LOG_NZ);
+ String2BuiltinCode.put("min", BuiltinCode.MIN);
+ String2BuiltinCode.put("max", BuiltinCode.MAX);
+ String2BuiltinCode.put("maxindex", BuiltinCode.MAXINDEX);
+ String2BuiltinCode.put("minindex", BuiltinCode.MININDEX);
+ String2BuiltinCode.put("abs", BuiltinCode.ABS);
+ String2BuiltinCode.put("sign", BuiltinCode.SIGN);
+ String2BuiltinCode.put("sqrt", BuiltinCode.SQRT);
+ String2BuiltinCode.put("exp", BuiltinCode.EXP);
+ String2BuiltinCode.put("plogp", BuiltinCode.PLOGP);
+ String2BuiltinCode.put("print", BuiltinCode.PRINT);
+ String2BuiltinCode.put("printf", BuiltinCode.PRINTF);
+ String2BuiltinCode.put("eval", BuiltinCode.EVAL);
+ String2BuiltinCode.put("list", BuiltinCode.LIST);
+ String2BuiltinCode.put("nrow", BuiltinCode.NROW);
+ String2BuiltinCode.put("ncol", BuiltinCode.NCOL);
+ String2BuiltinCode.put("length", BuiltinCode.LENGTH);
+ String2BuiltinCode.put("round", BuiltinCode.ROUND);
+ String2BuiltinCode.put("stop", BuiltinCode.STOP);
+ String2BuiltinCode.put("ceil", BuiltinCode.CEIL);
+ String2BuiltinCode.put("floor", BuiltinCode.FLOOR);
+ String2BuiltinCode.put("ucumk+", BuiltinCode.CUMSUM);
+ String2BuiltinCode.put("urowcumk+", BuiltinCode.ROWCUMSUM);
+ String2BuiltinCode.put("ucum*", BuiltinCode.CUMPROD);
+ String2BuiltinCode.put("ucumk+*", BuiltinCode.CUMSUMPROD);
+ String2BuiltinCode.put("ucummin", BuiltinCode.CUMMIN);
+ String2BuiltinCode.put("ucummax", BuiltinCode.CUMMAX);
+ String2BuiltinCode.put("inverse", BuiltinCode.INVERSE);
+ String2BuiltinCode.put("sprop", BuiltinCode.SPROP);
+ String2BuiltinCode.put("sigmoid", BuiltinCode.SIGMOID);
+ String2BuiltinCode.put("typeOf", BuiltinCode.TYPEOF);
+ String2BuiltinCode.put("detectSchema", BuiltinCode.DETECTSCHEMA);
+ String2BuiltinCode.put("isna", BuiltinCode.ISNA);
+ String2BuiltinCode.put("isnan", BuiltinCode.ISNAN);
+ String2BuiltinCode.put("isinf", BuiltinCode.ISINF);
+ String2BuiltinCode.put("dropInvalidType", BuiltinCode.DROP_INVALID_TYPE);
+ String2BuiltinCode.put("freplicate", BuiltinCode.FRAME_ROW_REPLICATE);
+ String2BuiltinCode.put("dropInvalidLength", BuiltinCode.DROP_INVALID_LENGTH);
+ String2BuiltinCode.put("_map", BuiltinCode.MAP);
+ String2BuiltinCode.put("valueSwap", BuiltinCode.VALUE_SWAP);
+ String2BuiltinCode.put("applySchema", BuiltinCode.APPLY_SCHEMA);
+ String2BuiltinCode.put("get_categorical_mask", BuiltinCode.GET_CATEGORICAL_MASK);
}
protected Builtin(BuiltinCode bf) {
diff --git a/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryCPInstruction.java b/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryCPInstruction.java
index 86184f47be6..08d28512d5c 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryCPInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryCPInstruction.java
@@ -59,7 +59,7 @@ else if (in1.getDataType() == DataType.TENSOR && in2.getDataType() == DataType.T
return new BinaryTensorTensorCPInstruction(operator, in1, in2, out, opcode, str);
else if (in1.getDataType() == DataType.FRAME && in2.getDataType() == DataType.FRAME)
return new BinaryFrameFrameCPInstruction(operator, in1, in2, out, opcode, str);
- else if (in1.getDataType() == DataType.FRAME && in2.getDataType() == DataType.SCALAR)
+ else if(in1.getDataType() == DataType.FRAME && in2.getDataType() == DataType.SCALAR)
return new BinaryFrameScalarCPInstruction(operator, in1, in2, out, opcode, str);
else if (in1.getDataType() == DataType.FRAME && in2.getDataType() == DataType.MATRIX)
return new BinaryFrameMatrixCPInstruction(operator, in1, in2, out, opcode, str);
diff --git a/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryFrameScalarCPInstruction.java b/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryFrameScalarCPInstruction.java
index 193894fd9bc..de76fca18b8 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryFrameScalarCPInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryFrameScalarCPInstruction.java
@@ -37,8 +37,8 @@
public class BinaryFrameScalarCPInstruction extends BinaryCPInstruction {
// private static final Log LOG = LogFactory.getLog(BinaryFrameFrameCPInstruction.class.getName());
- private static final TfMethod[] UNSUPPORTED_MASK_METHODS = new TfMethod[] {TfMethod.BIN,
- TfMethod.WORD_EMBEDDING, TfMethod.BAG_OF_WORDS, TfMethod.UDF};
+ private static final TfMethod[] UNSUPPORTED_MASK_METHODS = new TfMethod[] {TfMethod.BIN, TfMethod.WORD_EMBEDDING,
+ TfMethod.BAG_OF_WORDS, TfMethod.UDF};
protected BinaryFrameScalarCPInstruction(MultiThreadedOperator op, CPOperand in1, CPOperand in2, CPOperand out,
String opcode, String istr) {
@@ -96,9 +96,9 @@ public void processGetCategorical(ExecutionContext ec, FrameBlock f, ScalarObjec
}
/**
- * Accumulates, per input column, how many output columns it expands to (lengths) and whether those
- * output columns are categorical (categorical). The arrays are allocated lazily: a column that no
- * method touches keeps the implicit default of a single, non-categorical output column.
+ * Accumulates, per input column, how many output columns it expands to (lengths) and whether those output columns
+ * are categorical (categorical). The arrays are allocated lazily: a column that no method touches keeps the
+ * implicit default of a single, non-categorical output column.
*/
private static final class CategoricalMask {
private final FrameBlock f;
diff --git a/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryMatrixMatrixCPInstruction.java b/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryMatrixMatrixCPInstruction.java
index d76dbe0d45e..2c8093c3717 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryMatrixMatrixCPInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/BinaryMatrixMatrixCPInstruction.java
@@ -80,10 +80,10 @@ public void processInstruction(ExecutionContext ec) {
retBlock = inBlock1;
}
else {
- if(LibCommonsMath.isSupportedMatrixMatrixOperation(getOpcode()) ){
+ if(LibCommonsMath.isSupportedMatrixMatrixOperation(getOpcode())) {
if(compressedLeft)
inBlock1 = CompressedMatrixBlock.getUncompressed(inBlock1, getOpcode());
-
+
if(compressedRight)
inBlock2 = CompressedMatrixBlock.getUncompressed(inBlock2, getOpcode());
diff --git a/src/main/java/org/apache/sysds/runtime/instructions/cp/ParameterizedBuiltinCPInstruction.java b/src/main/java/org/apache/sysds/runtime/instructions/cp/ParameterizedBuiltinCPInstruction.java
index e53958ac4b8..97ae151ecc0 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/cp/ParameterizedBuiltinCPInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/cp/ParameterizedBuiltinCPInstruction.java
@@ -350,9 +350,10 @@ else if(opcode.equalsIgnoreCase(Opcodes.TRANSFORMDECODE.toString())) {
String[] colnames = meta.getColumnNames();
// compute transformdecode
- Decoder decoder = DecoderFactory
- .createDecoder(getParameterMap().get("spec"), colnames, null, meta, data.getNumColumns());
- FrameBlock fbout = decoder.decode(data, new FrameBlock(decoder.getSchema()), InfrastructureAnalyzer.getLocalParallelism());
+ Decoder decoder = DecoderFactory.createDecoder(getParameterMap().get("spec"), colnames, null, meta,
+ data.getNumColumns());
+ FrameBlock fbout = decoder.decode(data, new FrameBlock(decoder.getSchema()),
+ InfrastructureAnalyzer.getLocalParallelism());
fbout.setColumnNames(Arrays.copyOfRange(colnames, 0, fbout.getNumColumns()));
// release locks
diff --git a/src/main/java/org/apache/sysds/runtime/instructions/ooc/ReorgOOCInstruction.java b/src/main/java/org/apache/sysds/runtime/instructions/ooc/ReorgOOCInstruction.java
index 40a677e5d71..04353806ca3 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/ooc/ReorgOOCInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/ooc/ReorgOOCInstruction.java
@@ -45,8 +45,8 @@ protected ReorgOOCInstruction(ReorgOperator op, CPOperand in1, CPOperand out, St
this(op, in1, out, null, null, null, opcode, istr);
}
- private ReorgOOCInstruction(Operator op, CPOperand in, CPOperand out, CPOperand col, CPOperand desc, CPOperand ixret,
- String opcode, String istr) {
+ private ReorgOOCInstruction(Operator op, CPOperand in, CPOperand out, CPOperand col, CPOperand desc,
+ CPOperand ixret, String opcode, String istr) {
super(OOCType.Reorg, op, in, out, opcode, istr);
_col = col;
_desc = desc;
@@ -76,8 +76,8 @@ else if(opcode.equalsIgnoreCase(Opcodes.SORT.toString())) {
CPOperand desc = new CPOperand(parts[3]);
CPOperand ixret = new CPOperand(parts[4]);
int k = Integer.parseInt(parts[6]);
- return new ReorgOOCInstruction(new ReorgOperator(new SortIndex(1, false, false), k),
- in, out, col, desc, ixret, opcode, str);
+ return new ReorgOOCInstruction(new ReorgOperator(new SortIndex(1, false, false), k), in, out, col, desc,
+ ixret, opcode, str);
}
else
throw new NotImplementedException();
diff --git a/src/main/java/org/apache/sysds/runtime/instructions/ooc/ReshapeOOCInstruction.java b/src/main/java/org/apache/sysds/runtime/instructions/ooc/ReshapeOOCInstruction.java
index 7590438b949..091c6785b3c 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/ooc/ReshapeOOCInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/ooc/ReshapeOOCInstruction.java
@@ -128,17 +128,20 @@ public void processInstruction(ExecutionContext ec) {
long r = tmp.getIndexes().getRowIndex();
long c = tmp.getIndexes().getColumnIndex();
// adapt index to new position in row
- return new IndexedMatrixValue(new MatrixIndexes(1, (r - 1) * numBlocksPerRowIn + c), tmp.getValue());
+ return new IndexedMatrixValue(new MatrixIndexes(1, (r - 1) * numBlocksPerRowIn + c),
+ tmp.getValue());
});
}
else {
f.join();
- reshapeFullColBlocks(rows, cols, blen, numBlocksPerRowIn, numBlocksPerRowOut, numBlocksPerColOut, singleRowBlocks, qOut);
+ reshapeFullColBlocks(rows, cols, blen, numBlocksPerRowIn, numBlocksPerRowOut, numBlocksPerColOut,
+ singleRowBlocks, qOut);
}
}
else {
f.join();
- reshapePartialColBlocks(rlen, clen, rows, cols, blen, numBlocksPerRowIn, numBlocksPerRowOut, numBlocksPerColOut, singleRowBlocks, qOut);
+ reshapePartialColBlocks(rlen, clen, rows, cols, blen, numBlocksPerRowIn, numBlocksPerRowOut,
+ numBlocksPerColOut, singleRowBlocks, qOut);
}
}
else {
@@ -166,17 +169,20 @@ public void processInstruction(ExecutionContext ec) {
long r = tmp.getIndexes().getRowIndex();
long c = tmp.getIndexes().getColumnIndex();
// adapt index to new position in col
- return new IndexedMatrixValue(new MatrixIndexes((c - 1) * numBlocksPerColIn + r, 1), tmp.getValue());
+ return new IndexedMatrixValue(new MatrixIndexes((c - 1) * numBlocksPerColIn + r, 1),
+ tmp.getValue());
});
}
else {
f.join();
- reshapeFullRowBlocks(rows, cols, blen, numBlocksPerRowOut, numBlocksPerColIn, numBlocksPerColOut, singleColBlocks, qOut);
+ reshapeFullRowBlocks(rows, cols, blen, numBlocksPerRowOut, numBlocksPerColIn, numBlocksPerColOut,
+ singleColBlocks, qOut);
}
}
else {
f.join();
- reshapePartialRowBlocks(rlen, clen, rows, cols, blen, numBlocksPerRowOut, numBlocksPerColIn, numBlocksPerColOut, singleColBlocks, qOut);
+ reshapePartialRowBlocks(rlen, clen, rows, cols, blen, numBlocksPerRowOut, numBlocksPerColIn,
+ numBlocksPerColOut, singleColBlocks, qOut);
}
}
}
@@ -226,7 +232,8 @@ private void reshapeFullColBlocks(long rows, long cols, int blen, int numBlocksP
}
private void reshapePartialColBlocks(long rlen, long clen, long rows, long cols, int blen, int numBlocksPerRowIn,
- int numBlocksPerRowOut, int numBlocksPerColOut, OOCStream singleRowBlocks, OOCStream qOut) {
+ int numBlocksPerRowOut, int numBlocksPerColOut, OOCStream singleRowBlocks,
+ OOCStream qOut) {
// use cache for accessing input rows by index
CachingStream singleRowBlockCache = new CachingStream(singleRowBlocks);
singleRowBlockCache.incrSubscriberCount(1);
@@ -237,14 +244,16 @@ private void reshapePartialColBlocks(long rlen, long clen, long rows, long cols,
int r = 0;
// allocate row of output blocks
- MatrixBlock[] outputBlockRow = allocateSliceBlocks(br, rows, cols, blen, numBlocksPerRowOut, numBlocksPerColOut,true);
+ MatrixBlock[] outputBlockRow = allocateSliceBlocks(br, rows, cols, blen, numBlocksPerRowOut, numBlocksPerColOut,
+ true);
int offsetOut = 0;
int localColsOut = (cols > blen) ? blen : (int) cols;
// iterate through input rows and add to row of output blocks
for(int i = 1; i <= rlen; i++) {
for(int j = 1; j <= numBlocksPerRowIn; j++) {
- try(OOCStream.QueueCallback qcb = singleRowBlockCache.findCached(new MatrixIndexes(i, j))) {
+ try(OOCStream.QueueCallback qcb = singleRowBlockCache
+ .findCached(new MatrixIndexes(i, j))) {
MatrixBlock blk = (MatrixBlock) qcb.get().getValue();
int offsetIn = 0;
@@ -278,10 +287,12 @@ else if(remIn == remOut) {
if(r == outputBlockRow[0].getNumRows()) {
// enqueue filled output blocks and allocate new ones
for(int b = 0; b < outputBlockRow.length; b++)
- qOut.enqueue(new IndexedMatrixValue(new MatrixIndexes(br + 1, b + 1), outputBlockRow[b]));
+ qOut.enqueue(
+ new IndexedMatrixValue(new MatrixIndexes(br + 1, b + 1), outputBlockRow[b]));
br++;
// allocate new block row
- outputBlockRow = allocateSliceBlocks(br, rows, cols, blen, numBlocksPerRowOut, numBlocksPerColOut, true);
+ outputBlockRow = allocateSliceBlocks(br, rows, cols, blen, numBlocksPerRowOut,
+ numBlocksPerColOut, true);
r = 0;
}
bc = 0;
@@ -341,7 +352,8 @@ private void reshapeFullRowBlocks(long rows, long cols, int blen, int numBlocksP
}
private void reshapePartialRowBlocks(long rlen, long clen, long rows, long cols, int blen, int numBlocksPerRowOut,
- int numBlocksPerColIn, int numBlocksPerColOut, OOCStream singleColBlocks, OOCStream qOut) {
+ int numBlocksPerColIn, int numBlocksPerColOut, OOCStream singleColBlocks,
+ OOCStream qOut) {
// use cache for accessing input cols by index
CachingStream singleRowBlockCache = new CachingStream(singleColBlocks);
singleRowBlockCache.incrSubscriberCount(1);
@@ -352,14 +364,16 @@ private void reshapePartialRowBlocks(long rlen, long clen, long rows, long cols,
int c = 0;
// allocate col of output blocks
- MatrixBlock[] outputBlockCol = allocateSliceBlocks(bc, rows, cols, blen, numBlocksPerRowOut, numBlocksPerColOut, false);
+ MatrixBlock[] outputBlockCol = allocateSliceBlocks(bc, rows, cols, blen, numBlocksPerRowOut, numBlocksPerColOut,
+ false);
int offsetOut = 0;
int localRowsOut = (rows > blen) ? blen : (int) rows;
// iterate through input cols and add to col of output blocks
for(int j = 1; j <= clen; j++) {
for(int i = 1; i <= numBlocksPerColIn; i++) {
- try(OOCStream.QueueCallback qcb = singleRowBlockCache.findCached(new MatrixIndexes(i, j))) {
+ try(OOCStream.QueueCallback qcb = singleRowBlockCache
+ .findCached(new MatrixIndexes(i, j))) {
MatrixBlock blk = (MatrixBlock) qcb.get().getValue();
int offsetIn = 0;
@@ -394,11 +408,13 @@ else if(remIn == remOut) {
// enqueue filled output blocks and allocate new ones
for(int b = 0; b < outputBlockCol.length; b++) {
outputBlockCol[b].recomputeNonZeros();
- qOut.enqueue(new IndexedMatrixValue(new MatrixIndexes(b + 1, bc + 1), outputBlockCol[b]));
+ qOut.enqueue(
+ new IndexedMatrixValue(new MatrixIndexes(b + 1, bc + 1), outputBlockCol[b]));
}
bc++;
// allocate new block col
- outputBlockCol = allocateSliceBlocks(bc, rows, cols, blen, numBlocksPerRowOut, numBlocksPerColOut, false);
+ outputBlockCol = allocateSliceBlocks(bc, rows, cols, blen, numBlocksPerRowOut,
+ numBlocksPerColOut, false);
c = 0;
}
br = 0;
@@ -411,16 +427,20 @@ else if(remIn == remOut) {
qOut.closeInput();
}
- private MatrixBlock[] allocateSliceBlocks(int idx, long rows, long cols, int blen, int numBlocksPerRow, int numBlocksPerCol, boolean isBlockRowSlice) {
+ private MatrixBlock[] allocateSliceBlocks(int idx, long rows, long cols, int blen, int numBlocksPerRow,
+ int numBlocksPerCol, boolean isBlockRowSlice) {
int num = isBlockRowSlice ? numBlocksPerRow : numBlocksPerCol;
MatrixBlock[] res = new MatrixBlock[num];
// full inner blocks, adjust for outer blocks
- int localRows = ((!isBlockRowSlice || idx == numBlocksPerCol - 1) && rows % blen != 0) ? (int) rows % blen : blen;
- int localCols = ((isBlockRowSlice || idx == numBlocksPerRow - 1) && cols % blen != 0) ? (int) cols % blen : blen;
+ int localRows = ((!isBlockRowSlice || idx == numBlocksPerCol - 1) && rows % blen != 0) ? (int) rows %
+ blen : blen;
+ int localCols = ((isBlockRowSlice || idx == numBlocksPerRow - 1) && cols % blen != 0) ? (int) cols %
+ blen : blen;
for(int k = 0; k < num - 1; k++) {
- res[k] = isBlockRowSlice ? new MatrixBlock(localRows, blen, false) : new MatrixBlock(blen, localCols, false);
+ res[k] = isBlockRowSlice ? new MatrixBlock(localRows, blen, false) : new MatrixBlock(blen, localCols,
+ false);
res[k].allocateDenseBlock();
}
res[num - 1] = new MatrixBlock(localRows, localCols, false);
@@ -428,10 +448,13 @@ private MatrixBlock[] allocateSliceBlocks(int idx, long rows, long cols, int ble
return res;
}
- private void setOutputEntries(MatrixBlock src, MatrixBlock dest, int idx, int srcOffset, int destOffset, int length, boolean rowWise) {
+ private void setOutputEntries(MatrixBlock src, MatrixBlock dest, int idx, int srcOffset, int destOffset, int length,
+ boolean rowWise) {
if(rowWise)
- ((DenseBlockFP64) dest.getDenseBlock()).setPartialRow(src.getDenseBlock(), idx, srcOffset, destOffset, length);
+ ((DenseBlockFP64) dest.getDenseBlock()).setPartialRow(src.getDenseBlock(), idx, srcOffset, destOffset,
+ length);
else
- ((DenseBlockFP64) dest.getDenseBlock()).setPartialCol(src.getDenseBlock(), idx, srcOffset, destOffset, length);
+ ((DenseBlockFP64) dest.getDenseBlock()).setPartialCol(src.getDenseBlock(), idx, srcOffset, destOffset,
+ length);
}
}
diff --git a/src/main/java/org/apache/sysds/runtime/instructions/spark/QuantilePickSPInstruction.java b/src/main/java/org/apache/sysds/runtime/instructions/spark/QuantilePickSPInstruction.java
index 75f84882478..e25219b80ba 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/spark/QuantilePickSPInstruction.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/spark/QuantilePickSPInstruction.java
@@ -114,8 +114,7 @@ public void processInstruction(ExecutionContext ec) {
case VALUEPICK: {
if( input2.isScalar() ) {
ScalarObject quantile = ec.getScalarInput(input2);
- double[] wt = getWeightedQuantileSummary(in, mc,
- new double[] {quantile.getDoubleValue()}, true);
+ double[] wt = getWeightedQuantileSummary(in, mc, new double[] {quantile.getDoubleValue()}, true);
ec.setScalarOutput(output.getName(), new DoubleObject(wt[3]));
}
else {
diff --git a/src/main/java/org/apache/sysds/runtime/instructions/spark/data/IndexedMatrixValue.java b/src/main/java/org/apache/sysds/runtime/instructions/spark/data/IndexedMatrixValue.java
index 2f83caa5526..f007558ebdc 100644
--- a/src/main/java/org/apache/sysds/runtime/instructions/spark/data/IndexedMatrixValue.java
+++ b/src/main/java/org/apache/sysds/runtime/instructions/spark/data/IndexedMatrixValue.java
@@ -30,8 +30,7 @@
import org.apache.sysds.runtime.matrix.data.MatrixValue;
import org.apache.sysds.runtime.ooc.cache.io.SpillableObject;
-public class IndexedMatrixValue implements SpillableObject, Serializable
-{
+public class IndexedMatrixValue implements SpillableObject, Serializable {
private static final long serialVersionUID = 6723389820806752110L;
private MatrixIndexes _indexes = null;
@@ -110,8 +109,8 @@ public void discard() {
@Override
public void read(DataInput dataInput) throws IOException {
- _indexes = new MatrixIndexes();
- _value = new MatrixBlock();
+ _indexes = new MatrixIndexes();
+ _value = new MatrixBlock();
_indexes.readFields(dataInput);
_value.readFields(dataInput);
}
diff --git a/src/main/java/org/apache/sysds/runtime/io/DeltaKernelUtils.java b/src/main/java/org/apache/sysds/runtime/io/DeltaKernelUtils.java
index c3b9351d3d3..cc8491d4515 100644
--- a/src/main/java/org/apache/sysds/runtime/io/DeltaKernelUtils.java
+++ b/src/main/java/org/apache/sysds/runtime/io/DeltaKernelUtils.java
@@ -87,11 +87,10 @@
import io.delta.kernel.utils.FileStatus;
/**
- * Shared helpers for the native (Spark-free) Delta Lake read/write paths used
- * by both the matrix and frame readers/writers. Centralizes engine creation,
- * path qualification, the scan loop (snapshot -> data files -> logical
- * columnar batches, honoring deletion vectors), and the write transaction
- * (logical data -> parquet -> commit).
+ * Shared helpers for the native (Spark-free) Delta Lake read/write paths used by both the matrix and frame
+ * readers/writers. Centralizes engine creation, path qualification, the scan loop (snapshot -> data files ->
+ * logical columnar batches, honoring deletion vectors), and the write transaction (logical data -> parquet ->
+ * commit).
*/
public class DeltaKernelUtils {
@@ -102,23 +101,29 @@ public class DeltaKernelUtils {
/** Reused thread-safe JSON reader for the per-file Delta stats (numRecords). */
private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
- /** Delta Kernel config key: number of rows per parquet read batch, overridable via
- * {@link org.apache.sysds.conf.DMLConfig#DELTA_READER_BATCH_SIZE}. */
+ /**
+ * Delta Kernel config key: number of rows per parquet read batch, overridable via
+ * {@link org.apache.sysds.conf.DMLConfig#DELTA_READER_BATCH_SIZE}.
+ */
private static final String CONF_READER_BATCH_SIZE = "delta.kernel.default.parquet.reader.batch-size";
- /** Delta Kernel config key: target size (bytes) at which the writer rolls a new data file, overridable via
- * {@link org.apache.sysds.conf.DMLConfig#DELTA_WRITER_TARGET_FILE_SIZE}. */
+ /**
+ * Delta Kernel config key: target size (bytes) at which the writer rolls a new data file, overridable via
+ * {@link org.apache.sysds.conf.DMLConfig#DELTA_WRITER_TARGET_FILE_SIZE}.
+ */
private static final String CONF_WRITER_TARGET_FILE_SIZE = "delta.kernel.default.parquet.writer.targetMaxFileSize";
- /** Internal Delta column type codes shared by the matrix and frame readers to
- * dispatch boxing-free primitive column access. */
- public static final int T_DOUBLE = 0;
- public static final int T_FLOAT = 1;
- public static final int T_LONG = 2;
- public static final int T_INT = 3;
- public static final int T_SHORT = 4;
- public static final int T_BYTE = 5;
+ /**
+ * Internal Delta column type codes shared by the matrix and frame readers to dispatch boxing-free primitive column
+ * access.
+ */
+ public static final int T_DOUBLE = 0;
+ public static final int T_FLOAT = 1;
+ public static final int T_LONG = 2;
+ public static final int T_INT = 3;
+ public static final int T_SHORT = 4;
+ public static final int T_BYTE = 5;
public static final int T_BOOLEAN = 6;
- public static final int T_STRING = 7;
+ public static final int T_STRING = 7;
/**
* Parquet physical type each {@code T_*} column is stored as, indexed by type code (delta int/short/byte columns
@@ -128,22 +133,22 @@ public class DeltaKernelUtils {
PrimitiveTypeName.INT64, PrimitiveTypeName.INT32, PrimitiveTypeName.INT32, PrimitiveTypeName.INT32,
PrimitiveTypeName.BOOLEAN, PrimitiveTypeName.BINARY};
- //derived configuration cached to avoid copying the (large) base conf on every
- //engine creation (createEngine is called once per data file in parallel reads);
- //rebuilt whenever the base conf or the relevant SystemDS settings change.
+ // derived configuration cached to avoid copying the (large) base conf on every
+ // engine creation (createEngine is called once per data file in parallel reads);
+ // rebuilt whenever the base conf or the relevant SystemDS settings change.
private static Configuration cachedConf;
private static Configuration cachedConfBase;
private static int cachedBatchSize;
private static long cachedTargetFileSize;
- private DeltaKernelUtils() {}
+ private DeltaKernelUtils() {
+ }
/**
- * Consumes a whole columnar batch. {@code selected} is {@code null} when all
- * {@code size} rows are live; otherwise {@code selected[r]} indicates whether
- * row {@code r} survived the deletion/selection vector. Batch-level consumption
- * lets callers extract data column-at-a-time (cache friendly, boxing free)
- * instead of paying a per-row callback.
+ * Consumes a whole columnar batch. {@code selected} is {@code null} when all {@code size} rows are live; otherwise
+ * {@code selected[r]} indicates whether row {@code r} survived the deletion/selection vector. Batch-level
+ * consumption lets callers extract data column-at-a-time (cache friendly, boxing free) instead of paying a per-row
+ * callback.
*/
@FunctionalInterface
public interface BatchConsumer {
@@ -151,22 +156,29 @@ public interface BatchConsumer {
}
/**
- * Map a Delta Kernel {@link DataType} to an internal type code (see the
- * {@code T_*} constants). Returned once per column so the per-cell read loop
- * can switch on a primitive int instead of repeating {@code instanceof} checks.
+ * Map a Delta Kernel {@link DataType} to an internal type code (see the {@code T_*} constants). Returned once per
+ * column so the per-cell read loop can switch on a primitive int instead of repeating {@code instanceof} checks.
*
* @param dt the Delta column data type
* @return the matching {@code T_*} code, or {@code -1} if the type is not supported
*/
public static int typeCode(DataType dt) {
- if( dt instanceof DoubleType ) return T_DOUBLE;
- if( dt instanceof FloatType ) return T_FLOAT;
- if( dt instanceof LongType ) return T_LONG;
- if( dt instanceof IntegerType ) return T_INT;
- if( dt instanceof ShortType ) return T_SHORT;
- if( dt instanceof ByteType ) return T_BYTE;
- if( dt instanceof BooleanType ) return T_BOOLEAN;
- if( dt instanceof StringType ) return T_STRING;
+ if(dt instanceof DoubleType)
+ return T_DOUBLE;
+ if(dt instanceof FloatType)
+ return T_FLOAT;
+ if(dt instanceof LongType)
+ return T_LONG;
+ if(dt instanceof IntegerType)
+ return T_INT;
+ if(dt instanceof ShortType)
+ return T_SHORT;
+ if(dt instanceof ByteType)
+ return T_BYTE;
+ if(dt instanceof BooleanType)
+ return T_BOOLEAN;
+ if(dt instanceof StringType)
+ return T_STRING;
return -1;
}
@@ -429,8 +441,10 @@ private static void decodeColumnInto(ColumnReader creader, int maxDef, int nrow,
}
}
- /** Floor on the adaptive writer target file size. Below this the per-file metadata/open
- * overhead (and tiny-file proliferation) outweighs the extra read parallelism. */
+ /**
+ * Floor on the adaptive writer target file size. Below this the per-file metadata/open overhead (and tiny-file
+ * proliferation) outweighs the extra read parallelism.
+ */
public static final long ADAPTIVE_WRITER_MIN_FILE_SIZE = 4L * 1024 * 1024;
private static Configuration buildConf(Configuration base, int batchSize, long targetFileSize) {
@@ -444,9 +458,8 @@ private static synchronized Configuration deltaConf() {
Configuration base = ConfigurationManager.getCachedJobConf();
int batchSize = ConfigurationManager.getDeltaReaderBatchSize();
long targetFileSize = ConfigurationManager.getDeltaWriterTargetFileSize();
- if(cachedConf == null || cachedConfBase != base
- || cachedBatchSize != batchSize || cachedTargetFileSize != targetFileSize)
- {
+ if(cachedConf == null || cachedConfBase != base || cachedBatchSize != batchSize ||
+ cachedTargetFileSize != targetFileSize) {
cachedConf = buildConf(base, batchSize, targetFileSize);
cachedConfBase = base;
cachedBatchSize = batchSize;
@@ -460,12 +473,11 @@ public static Engine createEngine() {
}
/**
- * Compute the parquet target data-file size (bytes) for writing a table of the given
- * estimated size. With adaptive sizing enabled the writer aims for roughly one data
- * file per expected parallel reader (so the native per-file parallel read can use all
- * threads): never above the configured target, and never below
- * {@code ADAPTIVE_WRITER_MIN_FILE_SIZE} unless the configured target is itself smaller
- * than that floor (in which case the configured target wins).
+ * Compute the parquet target data-file size (bytes) for writing a table of the given estimated size. With adaptive
+ * sizing enabled the writer aims for roughly one data file per expected parallel reader (so the native per-file
+ * parallel read can use all threads): never above the configured target, and never below
+ * {@code ADAPTIVE_WRITER_MIN_FILE_SIZE} unless the configured target is itself smaller than that floor (in which
+ * case the configured target wins).
*
* @param estimatedBytes estimate of the table's size (the block in-memory size is a fine proxy)
* @return the target max parquet data-file size in bytes
@@ -476,7 +488,7 @@ public static long adaptiveWriterTargetFileSize(long estimatedBytes) {
return configured;
int par = Math.max(1, OptimizerUtils.getParallelBinaryReadParallelism());
long perReader = Math.max(1, estimatedBytes / par);
- //never above the configured cap, never below the floor (unless the cap itself is lower)
+ // never above the configured cap, never below the floor (unless the cap itself is lower)
long target = Math.min(configured, Math.max(ADAPTIVE_WRITER_MIN_FILE_SIZE, perReader));
if(LOG.isDebugEnabled())
LOG.debug("Delta adaptive file size: est=" + estimatedBytes + "B par=" + par + " -> target=" + target
@@ -485,24 +497,24 @@ public static long adaptiveWriterTargetFileSize(long estimatedBytes) {
}
/**
- * Create an engine for writing a table of the given estimated size, configured with an
- * adaptive target data-file size (see {@link #adaptiveWriterTargetFileSize(long)}). A fresh
- * (uncached) configuration is built since writes happen once per table, not per data file.
+ * Create an engine for writing a table of the given estimated size, configured with an adaptive target data-file
+ * size (see {@link #adaptiveWriterTargetFileSize(long)}). A fresh (uncached) configuration is built since writes
+ * happen once per table, not per data file.
*
* @param estimatedBytes estimate of the table's size (the block in-memory size is a fine proxy)
* @return a Delta Kernel engine for the write
*/
public static Engine createWriteEngine(long estimatedBytes) {
- //the reader batch size is irrelevant on the write path but is set to keep the
- //conf shape identical to deltaConf(); only the target file size matters here.
+ // the reader batch size is irrelevant on the write path but is set to keep the
+ // conf shape identical to deltaConf(); only the target file size matters here.
Configuration c = buildConf(ConfigurationManager.getCachedJobConf(),
ConfigurationManager.getDeltaReaderBatchSize(), adaptiveWriterTargetFileSize(estimatedBytes));
return DefaultEngine.create(c);
}
/**
- * Resolve a (possibly relative) path to a fully-qualified URI so the
- * kernel's default engine can locate the table on the right filesystem.
+ * Resolve a (possibly relative) path to a fully-qualified URI so the kernel's default engine can locate the table
+ * on the right filesystem.
*
* @param fname input path
* @return fully-qualified table path
@@ -519,11 +531,9 @@ public static String qualify(String fname) {
}
/**
- * Opened latest snapshot of a Delta table: the logical schema plus everything
- * needed to (re)read its data files, including the list of per-data-file scan
- * rows. Delta Kernel scan-file rows are self-contained (the kernel's
- * distributed design serializes them to workers), so they can be retained and
- * read independently / in parallel.
+ * Opened latest snapshot of a Delta table: the logical schema plus everything needed to (re)read its data files,
+ * including the list of per-data-file scan rows. Delta Kernel scan-file rows are self-contained (the kernel's
+ * distributed design serializes them to workers), so they can be retained and read independently / in parallel.
*/
public static final class ScanHandle {
public final StructType schema;
@@ -531,19 +541,18 @@ public static final class ScanHandle {
public final StructType physicalReadSchema;
public final List scanFiles;
/**
- * Per-file record counts taken from the Delta {@code numRecords} statistic,
- * aligned with {@link #scanFiles}; {@code -1} where the statistic is absent.
+ * Per-file record counts taken from the Delta {@code numRecords} statistic, aligned with {@link #scanFiles};
+ * {@code -1} where the statistic is absent.
*/
public final long[] numRecords;
/**
- * Per-file flag indicating a deletion vector is present (so the live row
- * count differs from {@link #numRecords}), aligned with {@link #scanFiles}.
+ * Per-file flag indicating a deletion vector is present (so the live row count differs from
+ * {@link #numRecords}), aligned with {@link #scanFiles}.
*/
public final boolean[] hasDeletionVector;
- private ScanHandle(StructType schema, Row scanState, StructType physicalReadSchema,
- List scanFiles, long[] numRecords, boolean[] hasDeletionVector)
- {
+ private ScanHandle(StructType schema, Row scanState, StructType physicalReadSchema, List scanFiles,
+ long[] numRecords, boolean[] hasDeletionVector) {
this.schema = schema;
this.scanState = scanState;
this.physicalReadSchema = physicalReadSchema;
@@ -553,13 +562,12 @@ private ScanHandle(StructType schema, Row scanState, StructType physicalReadSche
}
/**
- * @return true iff every data file carries a {@code numRecords} statistic
- * and none has a deletion vector, i.e. exact per-file row offsets
- * can be derived from metadata without reading the data.
+ * @return true iff every data file carries a {@code numRecords} statistic and none has a deletion vector, i.e.
+ * exact per-file row offsets can be derived from metadata without reading the data.
*/
public boolean hasExactRowCounts() {
- for( int i=0; i scanFileIter = (scan instanceof ScanImpl)
- ? ((ScanImpl) scan).getScanFiles(engine, true)
- : scan.getScanFiles(engine);
+ // request the scan files WITH per-file statistics (numRecords) so callers can
+ // pre-size output and place rows without reading the data; harmless extra
+ // column for the data-read path. Fall back to the stats-less iterator if the
+ // concrete scan does not support it.
+ CloseableIterator scanFileIter = (scan instanceof ScanImpl) ? ((ScanImpl) scan)
+ .getScanFiles(engine, true) : scan.getScanFiles(engine);
List files = new ArrayList<>();
List recs = new ArrayList<>();
List dvs = new ArrayList<>();
- try( CloseableIterator scanFiles = scanFileIter ) {
- while( scanFiles.hasNext() ) {
+ try(CloseableIterator scanFiles = scanFileIter) {
+ while(scanFiles.hasNext()) {
FilteredColumnarBatch scanFileBatch = scanFiles.next();
- try( CloseableIterator scanFileRows = scanFileBatch.getRows() ) {
- while( scanFileRows.hasNext() ) {
+ try(CloseableIterator scanFileRows = scanFileBatch.getRows()) {
+ while(scanFileRows.hasNext()) {
Row scanFileRow = scanFileRows.next();
files.add(scanFileRow);
recs.add(numRecords(scanFileRow));
@@ -609,7 +615,7 @@ public static ScanHandle openScan(Engine engine, String tablePath) throws IOExce
}
long[] numRecords = new long[recs.size()];
boolean[] hasDv = new boolean[dvs.size()];
- for( int i=0; i physicalData = engine.getParquetHandler()
.readParquetFiles(Utils.singletonCloseableIterator(dataFile), physicalReadSchema, Optional.empty());
- try( CloseableIterator logicalData =
- Scan.transformPhysicalData(engine, scanState, scanFileRow, physicalData) )
- {
- while( logicalData.hasNext() )
+ try(CloseableIterator logicalData = Scan.transformPhysicalData(engine, scanState,
+ scanFileRow, physicalData)) {
+ while(logicalData.hasNext())
consumeBatch(logicalData.next(), consumer);
}
}
/**
- * Scan the latest snapshot of a Delta table sequentially, invoking the batch
- * consumer for every data batch. The consumer is created lazily from the table
- * schema (so callers can size buffers / derive per-column types up front).
+ * Scan the latest snapshot of a Delta table sequentially, invoking the batch consumer for every data batch. The
+ * consumer is created lazily from the table schema (so callers can size buffers / derive per-column types up
+ * front).
*
* @param engine delta kernel engine
* @param tablePath fully-qualified table path
@@ -677,11 +679,10 @@ public static void readScanFile(Engine engine, Row scanState, StructType physica
* @throws IOException on read failure
*/
public static StructType scan(Engine engine, String tablePath, Function consumerFactory)
- throws IOException
- {
+ throws IOException {
ScanHandle h = openScan(engine, tablePath);
BatchConsumer consumer = consumerFactory.apply(h.schema);
- for( Row scanFileRow : h.scanFiles )
+ for(Row scanFileRow : h.scanFiles)
readScanFile(engine, h.scanState, h.physicalReadSchema, scanFileRow, consumer);
return h.schema;
}
@@ -690,28 +691,27 @@ private static void consumeBatch(FilteredColumnarBatch fcb, BatchConsumer consum
ColumnarBatch batch = fcb.getData();
int ncol = batch.getSchema().length();
ColumnVector[] cols = new ColumnVector[ncol];
- for( int c=0; c all rows live)
+ // materialize the deletion/selection mask once (null => all rows live)
Optional selVector = fcb.getSelectionVector();
boolean[] selected = null;
- if( selVector.isPresent() ) {
+ if(selVector.isPresent()) {
ColumnVector sv = selVector.get();
selected = new boolean[size];
- for( int r=0; r logicalData) throws IOException
- {
- //replace any existing table at the path (the other SystemDS writers delete
- //the output first; the caching layer does not do it on our behalf)
+ CloseableIterator logicalData) throws IOException {
+ // replace any existing table at the path (the other SystemDS writers delete
+ // the output first; the caching layer does not do it on our behalf)
HDFSTool.deleteFileIfExistOnHDFS(tablePath);
Table table = Table.forPath(engine, tablePath);
- TransactionBuilder txnBuilder = table
- .createTransactionBuilder(engine, ENGINE_INFO, Operation.CREATE_TABLE)
+ TransactionBuilder txnBuilder = table.createTransactionBuilder(engine, ENGINE_INFO, Operation.CREATE_TABLE)
.withSchema(engine, schema);
Transaction txn = txnBuilder.build(engine);
Row txnState = txn.getTransactionState(engine);
- CloseableIterator physicalData =
- Transaction.transformLogicalData(engine, txnState, logicalData, Collections.emptyMap());
- DataWriteContext writeContext =
- Transaction.getWriteContext(engine, txnState, Collections.emptyMap());
+ CloseableIterator physicalData = Transaction.transformLogicalData(engine, txnState,
+ logicalData, Collections.emptyMap());
+ DataWriteContext writeContext = Transaction.getWriteContext(engine, txnState, Collections.emptyMap());
CloseableIterator dataFiles = engine.getParquetHandler()
.writeParquetFiles(writeContext.getTargetDirectory(), physicalData, writeContext.getStatisticsColumns());
- CloseableIterator appendActions =
- Transaction.generateAppendActions(engine, txnState, dataFiles, writeContext);
+ CloseableIterator appendActions = Transaction.generateAppendActions(engine, txnState, dataFiles,
+ writeContext);
txn.commit(engine, CloseableIterable.inMemoryIterable(appendActions));
}
}
diff --git a/src/main/java/org/apache/sysds/runtime/io/ReaderDelta.java b/src/main/java/org/apache/sysds/runtime/io/ReaderDelta.java
index 58a98741975..55d8f8f7c2d 100644
--- a/src/main/java/org/apache/sysds/runtime/io/ReaderDelta.java
+++ b/src/main/java/org/apache/sysds/runtime/io/ReaderDelta.java
@@ -33,29 +33,27 @@
import io.delta.kernel.types.StructType;
/**
- * Single-threaded native Delta Lake reader for matrices, built on the
- * Spark-free Delta Kernel library. It opens the latest snapshot of a Delta
- * table directory, reads its parquet data files through the kernel's default
- * engine (honoring deletion vectors), and materializes the numeric columns
- * into a dense {@link MatrixBlock}.
+ * Single-threaded native Delta Lake reader for matrices, built on the Spark-free Delta Kernel library. It opens the
+ * latest snapshot of a Delta table directory, reads its parquet data files through the kernel's default engine
+ * (honoring deletion vectors), and materializes the numeric columns into a dense {@link MatrixBlock}.
*
- *
Only numeric columns (double/float/long/int/short/byte/boolean) are
- * supported, matching the all-double nature of a SystemDS matrix. Dimensions
- * do not need to be known up front: the row count is discovered while scanning
- * and the column count is taken from the table schema.
+ *
+ * Only numeric columns (double/float/long/int/short/byte/boolean) are supported, matching the all-double nature of a
+ * SystemDS matrix. Dimensions do not need to be known up front: the row count is discovered while scanning and the
+ * column count is taken from the table schema.
+ *
*/
public class ReaderDelta extends MatrixReader {
@Override
public MatrixBlock readMatrixFromHDFS(String fname, long rlen, long clen, int blen, long estnnz)
- throws IOException, DMLRuntimeException
- {
+ throws IOException, DMLRuntimeException {
Engine engine = DeltaKernelUtils.createEngine();
String tablePath = DeltaKernelUtils.qualify(fname);
- //Scan column-at-a-time into one row-major buffer per batch (no per-row
- //allocation, no boxing, no per-cell set()). Buffers are concatenated into
- //the dense output via bulk array copies below.
+ // Scan column-at-a-time into one row-major buffer per batch (no per-row
+ // allocation, no boxing, no per-cell set()). Buffers are concatenated into
+ // the dense output via bulk array copies below.
ArrayList batches = new ArrayList<>();
int[] nrowH = new int[1];
StructType schema = DeltaKernelUtils.scan(engine, tablePath, sch -> {
@@ -72,7 +70,7 @@ public MatrixBlock readMatrixFromHDFS(String fname, long rlen, long clen, int bl
long lestnnz = (estnnz >= 0) ? estnnz : (long) nrow * ncol;
MatrixBlock ret = createOutputMatrixBlock(nrow, ncol, Math.max(nrow, 1), lestnnz, true, false);
- if( nrow > 0 && ncol > 0 )
+ if(nrow > 0 && ncol > 0)
fillDense(ret, batches);
ret.recomputeNonZeros();
ret.examSparsity();
@@ -83,14 +81,14 @@ public MatrixBlock readMatrixFromHDFS(String fname, long rlen, long clen, int bl
static int[] columnTypes(StructType schema) {
int ncol = schema.length();
int[] types = new int[ncol];
- for( int c=0; c batches) {
DenseBlock db = ret.getDenseBlock();
- if( db.isContiguous() ) {
+ if(db.isContiguous()) {
double[] dv = db.valuesAt(0);
int off = 0;
- for( double[] buf : batches ) {
+ for(double[] buf : batches) {
System.arraycopy(buf, 0, dv, off, buf.length);
off += buf.length;
}
}
else {
- //rare large multi-block fallback: route each row through the block API
+ // rare large multi-block fallback: route each row through the block API
int ncol = ret.getNumColumns();
int r = 0;
- for( double[] buf : batches ) {
+ for(double[] buf : batches) {
int rowsInBuf = buf.length / ncol;
- for( int i=0; iThe expensive part of a Delta read is the parquet decode, which the kernel
- * performs per data file; parallelizing across files is therefore the natural
- * way to bridge the gap to the (near-raw) binary reader. A table backed by a
- * single data file (the default for tables <= the parquet target file size)
- * cannot be split this way, so the reader transparently falls back to the
- * sequential {@link ReaderDelta} path in that case.
+ *
+ * The expensive part of a Delta read is the parquet decode, which the kernel performs per data file; parallelizing
+ * across files is therefore the natural way to bridge the gap to the (near-raw) binary reader. A table backed by a
+ * single data file (the default for tables <= the parquet target file size) cannot be split this way, so the reader
+ * transparently falls back to the sequential {@link ReaderDelta} path in that case.
+ *
*/
public class ReaderDeltaParallel extends ReaderDelta {
@@ -57,28 +56,27 @@ public ReaderDeltaParallel() {
@Override
public MatrixBlock readMatrixFromHDFS(String fname, long rlen, long clen, int blen, long estnnz)
- throws IOException, DMLRuntimeException
- {
+ throws IOException, DMLRuntimeException {
Engine engine = DeltaKernelUtils.createEngine();
String tablePath = DeltaKernelUtils.qualify(fname);
DeltaKernelUtils.ScanHandle handle = DeltaKernelUtils.openScan(engine, tablePath);
final int nfiles = handle.scanFiles.size();
- //nothing to gain from parallelism for single-file (or empty) tables
- if( _numThreads <= 1 || nfiles <= 1 )
+ // nothing to gain from parallelism for single-file (or empty) tables
+ if(_numThreads <= 1 || nfiles <= 1)
return super.readMatrixFromHDFS(fname, rlen, clen, blen, estnnz);
final int ncol = handle.schema.length();
final int[] types = columnTypes(handle.schema);
- //fast path: exact per-file row counts are known from metadata and the dense
- //output fits a single contiguous array -> pre-size once and let each thread
- //decode directly into its slice (no intermediate buffers, no serial copy).
- if( useDirectPath(handle) ) {
+ // fast path: exact per-file row counts are known from metadata and the dense
+ // output fits a single contiguous array -> pre-size once and let each thread
+ // decode directly into its slice (no intermediate buffers, no serial copy).
+ if(useDirectPath(handle)) {
long total = 0;
- for( long r : handle.numRecords )
+ for(long r : handle.numRecords)
total += r;
- if( total > 0 && (long) total * ncol <= Integer.MAX_VALUE )
+ if(total > 0 && (long) total * ncol <= Integer.MAX_VALUE)
return readDirect(fname, handle, ncol, types, (int) total, estnnz);
}
@@ -86,11 +84,9 @@ public MatrixBlock readMatrixFromHDFS(String fname, long rlen, long clen, int bl
}
/**
- * Whether the metadata-driven direct-write fast path can be used for this
- * table (exact per-file row counts and no deletion vectors). Visible for
- * testing: the buffered fallback is otherwise only reachable for tables
- * lacking row statistics or carrying deletion vectors, which the SystemDS
- * Delta writer never produces.
+ * Whether the metadata-driven direct-write fast path can be used for this table (exact per-file row counts and no
+ * deletion vectors). Visible for testing: the buffered fallback is otherwise only reachable for tables lacking row
+ * statistics or carrying deletion vectors, which the SystemDS Delta writer never produces.
*
* @param handle the opened scan handle
* @return true if the direct path is applicable
@@ -100,38 +96,37 @@ protected boolean useDirectPath(DeltaKernelUtils.ScanHandle handle) {
}
/**
- * Fast path: each thread decodes one data file straight into the final dense
- * array at a metadata-derived row offset. Single allocation, fully parallel.
+ * Fast path: each thread decodes one data file straight into the final dense array at a metadata-derived row
+ * offset. Single allocation, fully parallel.
*/
- private MatrixBlock readDirect(String fname, DeltaKernelUtils.ScanHandle handle,
- int ncol, int[] types, int nrow, long estnnz) throws IOException
- {
+ private MatrixBlock readDirect(String fname, DeltaKernelUtils.ScanHandle handle, int ncol, int[] types, int nrow,
+ long estnnz) throws IOException {
final int nfiles = handle.scanFiles.size();
final int[] rowOffset = new int[nfiles];
int acc = 0;
- for( int i=0; i> tasks = new ArrayList<>(nfiles);
- for( int i=0; i {
int[] cur = new int[] {base};
Engine eng = DeltaKernelUtils.createEngine();
DeltaKernelUtils.readScanFile(eng, handle.scanState, handle.physicalReadSchema, scanFileRow,
(cols, size, selected) -> {
- if( cur[0] + DeltaKernelUtils.countSelected(size, selected) > limit )
+ if(cur[0] + DeltaKernelUtils.countSelected(size, selected) > limit)
throw new DMLRuntimeException("Delta file produced more rows than its "
+ "numRecords statistic; refusing parallel direct read of " + fname);
cur[0] += extractBatchInto(cols, size, selected, types, ncol, dv, cur[0]);
@@ -147,19 +142,17 @@ private MatrixBlock readDirect(String fname, DeltaKernelUtils.ScanHandle handle,
}
/**
- * Fallback path: decode each file in parallel into per-file buffers (used when
- * row counts are unknown, deletion vectors are present, or the matrix exceeds a
- * single contiguous array), then concatenate in file order.
+ * Fallback path: decode each file in parallel into per-file buffers (used when row counts are unknown, deletion
+ * vectors are present, or the matrix exceeds a single contiguous array), then concatenate in file order.
*/
- private MatrixBlock readBuffered(String fname, DeltaKernelUtils.ScanHandle handle,
- int ncol, int[] types, long estnnz) throws IOException
- {
+ private MatrixBlock readBuffered(String fname, DeltaKernelUtils.ScanHandle handle, int ncol, int[] types,
+ long estnnz) throws IOException {
final int nfiles = handle.scanFiles.size();
@SuppressWarnings("unchecked")
final ArrayList[] fileBufs = new ArrayList[nfiles];
final int[] fileRows = new int[nfiles];
ArrayList> tasks = new ArrayList<>(nfiles);
- for( int i=0; i {
@@ -179,15 +172,15 @@ private MatrixBlock readBuffered(String fname, DeltaKernelUtils.ScanHandle handl
awaitFileTasks(tasks, fname);
int nrow = 0;
- for( int i=0; i ordered = new ArrayList<>();
- for( int i=0; i= 0) ? estnnz : (long) nrow * ncol;
MatrixBlock ret = createOutputMatrixBlock(nrow, ncol, Math.max(nrow, 1), lestnnz, true, false);
- if( nrow > 0 && ncol > 0 )
+ if(nrow > 0 && ncol > 0)
fillDense(ret, ordered);
ret.recomputeNonZeros(_numThreads);
ret.examSparsity();
@@ -195,16 +188,15 @@ private MatrixBlock readBuffered(String fname, DeltaKernelUtils.ScanHandle handl
}
/**
- * Run one decode task per data file on the shared common thread pool and await
- * completion. Full parallelism is requested (the task count, one per data file,
- * naturally caps concurrency); this avoids the per-thread pool-size caching in
- * {@code CommonThreadPool.get(k)} that could otherwise throttle this reader to a
- * smaller pool created earlier on the same thread.
+ * Run one decode task per data file on the shared common thread pool and await completion. Full parallelism is
+ * requested (the task count, one per data file, naturally caps concurrency); this avoids the per-thread pool-size
+ * caching in {@code CommonThreadPool.get(k)} that could otherwise throttle this reader to a smaller pool created
+ * earlier on the same thread.
*/
private void awaitFileTasks(List> tasks, String fname) throws IOException {
ExecutorService pool = CommonThreadPool.get(_numThreads);
try {
- for( Future