我尝试创建一个聚合函数,该函数在列中找到最小值,然后添加拉普拉斯噪声。 我正在使用Postregres PL / pgSQL语言。
汇总工作正常,但是我想知道是否有任何方法可以改善我编写的代码。
/*
* PLpgSQL function which behaves to aggregate the MIN(col) function then adds the laplacian noise.
* For the sensivity (which is the upper bound of the query), We use the halfed maximum value of the column called.
* Passing the array which contains the entire column values, that will be compared, to establish which one is the minimum.
* Then we compute Laplacian distribution (sensivity/epsilon). This given value is added to the minimum Value that will disturb
* the final result
*/
CREATE OR REPLACE FUNCTION addLaplacianNoiseMin (real[]) RETURNS real AS $$
DECLARE
i real;
minVal real; --minimum value which is found in the column and then disturbed
laplaceNoise real; --laplacian distribution which is computed finding the halfed maximum value, divided by an arbitrary epsilon (small value)
epsilon real := 1.2;
sensivity real; --our computed upper bound
maxVal real;
BEGIN
minVal := $1[1];
maxVal := $1[1];
IF ARRAY_LENGTH($1,1) > 0 THEN --Checking whether the array is empty or not
<<confrontoMinimo>>
FOREACH i IN ARRAY $1 LOOP --Looping through the entire array, passed as parameter
IF minVal >= i THEN
minVal := i;
ELSE
maxVal := i;
END IF;
END LOOP confrontoMinimo;
ELSE
RAISE NOTICE 'Invalid parameter % passed to the aggregate function',$1;
--Raising exception if the parameter passed as argument points to null.
RAISE EXCEPTION 'Cannot find MIN value. Parameter % is null', $1
USING HINT = 'You cannot pass a null array! Check the passed parameter';
END IF;
sensivity := maxVal/2;
laplaceNoise := sensivity/(epsilon);
RAISE NOTICE 'minVal: %, maxVal: %, sensivity: %, laplaceNoise: %', minVal, maxVal, sensivity,laplaceNoise;
minVal := laplaceNoise + minVal;
RETURN minVal;
END;
$$ LANGUAGE plpgsql;
CREATE AGGREGATE searchMinValueArray (real)
(
sfunc = array_append,
stype = real[],
finalfunc = addLaplacianNoiseMin,
initCond = '{}'
);
答案 0 :(得分:1)
是的,您可以通过不使用数组作为聚合的状态,而是使用类似以下的复合类型来改善此问题:
CREATE TYPE aggstate AS (minval real, maxval real);
然后,您可以在SFUNC
中从循环执行操作,而不必在内存中保留可能会变得非常大的数组。这样FINALFUNC
就会变得非常简单。