Alternating Least Squares (ALS) is a matrix factorization algorithm used for building recommender systems. It can handle both explicit and implicit feedback. The algorithm predicts the feedback of a user on an item based on latent factors inferred from user-item rating patterns. 

If the model is based on explicit feedback, the latent factors are trained by solving an optimization problem. If the model is based on implicit feedback, the latent factors are trained by solving a different optimization problem. 

ALS can be parallelized and solves linear systems during each step. It provides two methods to solve these systems: Cholesky method and conjugate gradient (CG) method. The time and convergence rate of ALS using these methods are similar when the factor number is small, but ALS using the CG method can be faster for large factor numbers.

The ALS algorithm has null handling capabilities, where data with null user ID, item ID, or rating can be discarded or not processed.
------

SET SCHEMA "DM_PAL";

DROP TABLE PAL_ALS_DATA_TBL;
CREATE COLUMN TABLE PAL_ALS_DATA_TBL ("USER" NVARCHAR(100), "MOVIE" NVARCHAR(100), "RATING" DOUBLE);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('A', 'Movie1', 4.8);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('A', 'Movie2', 4.0);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('B', 'Movie2', 4.8);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('B', 'Movie3', 4.8);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('C', 'Movie1', 4.1);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('C', 'Movie2', 4.2);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('D', 'Movie1', 4.5);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('D', 'Movie3', 3.5);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('E', 'Movie1', 4.5);
INSERT INTO PAL_ALS_DATA_TBL VALUES ('E', 'Movie2', 4.0);


DROP TABLE PAL_PARAMETER_TBL;
CREATE COLUMN TABLE PAL_PARAMETER_TBL ("PARAM_NAME" VARCHAR(256), "INT_VALUE" INTEGER, "DOUBLE_VALUE" DOUBLE, "STRING_VALUE" VARCHAR(1000));
INSERT INTO PAL_PARAMETER_TBL VALUES ('FACTOR_NUMBER', 2, NULL, NULL);
INSERT INTO PAL_PARAMETER_TBL VALUES ('REGULARIZATION', NULL, 1e-2, NULL);
INSERT INTO PAL_PARAMETER_TBL VALUES ('MAX_ITERATION', 20, NULL, NULL);
--INSERT INTO PAL_PARAMETER_TBL VALUES ('EXIT_THRESHOLD', NULL, 1e-6, NULL);
--INSERT INTO PAL_PARAMETER_TBL VALUES ('EXIT_INTERVAL', 5, NULL, NULL);
--INSERT INTO PAL_PARAMETER_TBL VALUES ('LINEAR_SYSTEM_SOLVER', 0, NULL, NULL);
INSERT INTO PAL_PARAMETER_TBL VALUES ('THREAD_RATIO', NULL, 0, NULL);
INSERT INTO PAL_PARAMETER_TBL VALUES ('SEED', 1, NULL, NULL);



DROP TABLE PAL_ALS_MODEL_METADATA_TBL;
DROP TABLE PAL_ALS_MODEL_MAP_TBL;
DROP TABLE PAL_ALS_MODEL_FACTORS_TBL;
CREATE COLUMN TABLE PAL_ALS_MODEL_METADATA_TBL ("ROW_INDEX" INTEGER, "METADATA_CONTENT" NVARCHAR(5000));
CREATE COLUMN TABLE PAL_ALS_MODEL_MAP_TBL ("ID" INTEGER, "MAP" NVARCHAR(1000));
CREATE COLUMN TABLE PAL_ALS_MODEL_FACTORS_TBL ("FACTOR_ID" INTEGER, "FACTOR" DOUBLE);

do begin 
	lt_data = select * from PAL_ALS_DATA_TBL;
	lt_control = select * from PAL_PARAMETER_TBL;
	CALL _SYS_AFL.PAL_ALS (:lt_data, :lt_control, lt_meta, lt_map, lt_ft, lt_iter, lt_stat, lt_opt);
	INSERT INTO PAL_ALS_MODEL_METADATA_TBL SELECT * FROM :lt_meta;
	INSERT INTO PAL_ALS_MODEL_MAP_TBL SELECT * FROM :lt_map;
	INSERT INTO PAL_ALS_MODEL_FACTORS_TBL SELECT * FROM :lt_ft;
	SELECT * FROM PAL_ALS_MODEL_MAP_TBL;
	SELECT * FROM PAL_ALS_MODEL_METADATA_TBL;	
	SELECT * FROM PAL_ALS_MODEL_FACTORS_TBL;
	SELECT* FROM :lt_iter;
	SELECT* FROM :lt_stat;
	SELECT* FROM :lt_opt;
end;
