Home Reference Source Test

packages/causality-sampling/src/negSampling.mixins.js

const NegativeSamplingMixins = (BaseSamplingClass)=> class extends BaseSamplingClass{
    /**
     * Perform negative sampling given the select prob of ids and list of positive samples
     * @param { Number } negativeSize - size to sample
     * @param { Array } positiveSamples - Array of possitive Ids
     * @param { Array } candidateProbs - Array of probablity of candidate Ids
     * @param { Boolean } [replacable=true] - if true, no duplicated sampling Id returned
     * @returns { Array } array of sampled Ids
     */
    negSampling(negativeSize, positiveSamples, candidateProbs, replacable=true){
        const R = this.R, Random = this.Random;
        if(R.any((v)=> !R.type(Number,v) || v > 1 || v < 0, candidateProbs)){
            throw Error(`${JSON.stringify(candidateProbs)} is not allow`);
        }
        let seletionProbs = R.reduce((selectionProbs, pidx)=>{
                                selectionProbs[pidx] = Infinity;//positive candidate never be choosed
                                return selectionProbs;
                            }, R.clone(candidateProbs), positiveSamples);
        let samples = [], takenIdxs = R.clone(seletionProbs);
        const GenNewCandidateIdx = ()=>Random.int(0, seletionProbs.length-1);
        const SelectIfHighProb = (prob)=>{
            let rand = Random.float();
            return rand>prob;
        };
        while(samples.length < negativeSize){
            let idx = GenNewCandidateIdx();
            let selected = SelectIfHighProb(seletionProbs[idx]);
            if(!selected){
                continue;
            }
            if(!replacable && takenIdxs[idx]===null){
                continue;
            }
            samples = [...samples, idx];
            if(!replacable){
                takenIdxs[idx]=null;//non replaceable
            }
        }    
        return samples;
    }
};
export default NegativeSamplingMixins;