opennlp.tools.fca.BasicLevelMetrics.java Source code

Java tutorial

Introduction

Here is the source code for opennlp.tools.fca.BasicLevelMetrics.java

Source

/*
 * 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.
 */

package opennlp.tools.fca;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections.ListUtils;

public class BasicLevelMetrics {

    ConceptLattice cl;
    ArrayList<ArrayList<Integer>> attributesExtent = null;
    ArrayList<ArrayList<Integer>> objectsIntent = null;
    ArrayList<Integer> attributes = null;
    double[][] objectsSimilarityJ = null;
    double[][] objectsSimilaritySMC = null;

    public BasicLevelMetrics(ConceptLattice cl) {
        this.cl = cl;
        this.attributesExtent = null;
        objectsSimilarityJ = new double[cl.objectCount][cl.objectCount];
        objectsSimilaritySMC = new double[cl.objectCount][cl.objectCount];
    }

    public void setUp() {
        attributesExtent = new ArrayList<ArrayList<Integer>>();
        objectsIntent = new ArrayList<ArrayList<Integer>>();
        attributes = new ArrayList<Integer>();

        for (int i = 0; i < cl.attributeCount; i++) {
            attributesExtent.add((ArrayList<Integer>) cl.getAttributeExtByID(i));
            attributes.add(i);
        }

        for (int i = 0; i < cl.objectCount; i++) {
            objectsIntent.add((ArrayList<Integer>) cl.getObjectIntByID(i));
        }

        double[] buf = new double[2];

        for (int i = 0; i < cl.objectCount; i++) {
            for (int j = i + 1; j < cl.objectCount; j++) {
                buf = simJ_SMC(objectsIntent.get(i), objectsIntent.get(j));
                objectsSimilarityJ[i][j] = buf[0];
                objectsSimilarityJ[j][i] = buf[0];
                objectsSimilaritySMC[i][j] = buf[1];
                objectsSimilaritySMC[j][i] = buf[1];
            }
            objectsSimilarityJ[i][i] = 1;
            objectsSimilaritySMC[i][i] = 1;
        }

        //System.out.println("J");
        //System.out.println(Arrays.deepToString(objectsSimilarityJ));
        //System.out.println("SMC");
        //System.out.println(Arrays.deepToString(objectsSimilaritySMC));

    }

    //Utility functions for  Similarity approach (S)
    public double simSMC(ArrayList<Integer> intent1, ArrayList<Integer> intent2) {
        int tp = (ListUtils.intersection(intent1, intent2)).size();
        ArrayList<Integer> fnlst = new ArrayList<Integer>();
        fnlst.addAll(this.attributes);
        fnlst.removeAll(ListUtils.union(intent1, intent2));
        int fn = fnlst.size();
        return (this.attributes.size() > 0) ? 1. * (tp + fn) / this.attributes.size() : 0;
    }

    public double simJ(ArrayList<Integer> intent1, ArrayList<Integer> intent2) {
        return 1. * (ListUtils.intersection(intent1, intent2)).size() / (ListUtils.union(intent1, intent2)).size();
    }

    public double[] simJ_SMC(ArrayList<Integer> intent1, ArrayList<Integer> intent2) {
        double simJ = 0;
        double simSMC = 0;
        Set<Integer> intersection = new HashSet<Integer>();
        intersection.addAll(intent1);
        intersection.retainAll(intent2);

        Set<Integer> union = new HashSet<Integer>();
        union.addAll(intent1);
        union.addAll(intent2);
        int fn = 0;
        Set<Integer> unionOut = new HashSet<Integer>();
        unionOut.addAll(this.attributes);
        unionOut.removeAll(union);
        simSMC = (this.attributes.size() > 0)
                ? 1. * (intersection.size() + unionOut.size()) / this.attributes.size()
                : 0;
        simJ = (union.size() > 0) ? 1. * intersection.size() / union.size() : 0;
        return new double[] { simJ, simSMC };
    }

    public double avgCohSMC(FormalConcept c) {
        double sum = 0;
        if (c.extent.size() == 1)
            return 1.;//c.intent.size();
        if (c.extent.size() == 0)
            return 0.;
        else {
            for (Integer i : c.extent) {
                for (Integer j : c.extent) {
                    if (i < j)
                        sum += objectsSimilaritySMC[i][j];
                }
            }
            return (c.extent.size() > 1) ? 2. * sum / c.extent.size() / (c.extent.size() - 1) : 0;//  2,    
        }
    }

    public double avgCohJ(FormalConcept c) {
        double sum = 0;
        if (c.extent.size() == 1)
            return 1.;//c.intent.size();
        if (c.extent.size() == 0)
            return 0.;
        else {
            for (Integer i : c.extent) {
                for (Integer j : c.extent) {
                    if (i < j) {
                        sum += objectsSimilarityJ[i][j];
                    }
                }
            }
            return (c.extent.size() > 1) ? 2. * sum / c.extent.size() / (c.extent.size() - 1) : 0;
        }
    }

    public double minCohJ(FormalConcept c) {
        double min = Integer.MAX_VALUE, val = 0;

        for (Integer i : c.extent) {
            for (Integer j : c.extent) {
                val = objectsSimilarityJ[i][j];
                if (val < min)
                    min = val;
            }
        }
        return (min < Integer.MAX_VALUE) ? min : 0;
    }

    public double minCohSMC(FormalConcept c) {
        double min = Integer.MAX_VALUE, val = 0;
        for (Integer i : c.extent) {
            for (Integer j : c.extent) {
                val = objectsSimilaritySMC[i][j];
                if (val < min)
                    min = val;
            }
        }
        return (min < Integer.MAX_VALUE) ? min : 0;
    }

    public double upperCohAvgByAvgJ(FormalConcept c, float tetta) {
        //average alpha with average cohesion J
        double sum = 0;
        Set<Integer> upperNeighbors = c.parents;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        for (Integer i : upperNeighbors) {
            if (c.cohAvgJ > cl.conceptList.get(i).cohAvgJ) {
                rightNeighborsNumber++;
                sum += 1. * cl.conceptList.get(i).cohAvgJ / c.cohAvgJ;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / upperNeighbors.size() >= tetta) ? 1 : 0;
            //truthDegree =  (float) Math.min(1.0, truthDegree);
            return (1 - sum / rightNeighborsNumber) * truthDegree;
        }
    }

    public double upperCohAvgByMinJ(FormalConcept c, float tetta) {
        //average alpha with min cohesion J
        double sum = 0;
        Set<Integer> upperNeighbors = c.parents;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        for (Integer i : upperNeighbors) {
            if (c.cohMinJ > cl.conceptList.get(i).cohMinJ) {
                rightNeighborsNumber++;
                sum += 1. * cl.conceptList.get(i).cohMinJ / c.cohMinJ;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / upperNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (1 - sum / rightNeighborsNumber) * truthDegree;
        }
    }

    public double upperCohMinByAvgJ(FormalConcept c, float tetta) {
        //min alpha whth average cohesion J
        double max = Integer.MIN_VALUE, val = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> upperNeighbors = c.parents;
        for (Integer i : upperNeighbors) {
            if (c.cohAvgJ > cl.conceptList.get(i).cohAvgJ) {
                rightNeighborsNumber++;
                val = 1. * cl.conceptList.get(i).cohAvgJ / c.cohAvgJ;
                if (val > max)
                    max = val;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / upperNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (1 - max) * truthDegree;
        }
    }

    public double upperCohMinByMinJ(FormalConcept c, float tetta) {
        //min alpha whth average cohesion J
        double max = Integer.MIN_VALUE, val = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> upperNeighbors = c.parents;
        for (Integer i : upperNeighbors) {
            if (c.cohMinJ > cl.conceptList.get(i).cohMinJ) {
                rightNeighborsNumber++;
                val = 1. * cl.conceptList.get(i).cohMinJ / c.cohMinJ;
                if (val > max)
                    max = val;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            //truthDegree = rightNeighborsNumber/tetta/upperNeighbors.size();
            truthDegree = (1. * rightNeighborsNumber / upperNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (1 - max) * truthDegree;
        }
    }

    public double upperCohAvgByAvgSMC(FormalConcept c, float tetta) {
        //average alpha with average cohesion SMC
        double sum = 0;
        Set<Integer> upperNeighbors = c.parents;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        for (Integer i : upperNeighbors) {
            if (c.cohAvgSMC > cl.conceptList.get(i).cohAvgSMC) {
                rightNeighborsNumber++;
                sum += 1. * cl.conceptList.get(i).cohAvgSMC / c.cohAvgSMC;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / upperNeighbors.size() >= tetta) ? 1 : 0;
            return (1 - sum / rightNeighborsNumber) * truthDegree;
        }
    }

    public double upperCohAvgByMinSMC(FormalConcept c, float tetta) {
        //average alpha with min cohesion SMC
        double sum = 0;
        Set<Integer> upperNeighbors = c.parents;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        for (Integer i : upperNeighbors) {
            if (c.cohMinSMC > cl.conceptList.get(i).cohMinSMC) {
                rightNeighborsNumber++;
                sum += 1. * cl.conceptList.get(i).cohMinSMC / c.cohMinSMC;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / upperNeighbors.size() >= tetta) ? 1 : 0;
            return (1 - sum / rightNeighborsNumber) * truthDegree;
        }
    }

    public double upperCohMinByAvgSMC(FormalConcept c, float tetta) {
        //min alpha whth average cohesion J

        double max = Integer.MIN_VALUE, val = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> upperNeighbors = c.parents;
        for (Integer i : upperNeighbors) {
            if (c.cohAvgSMC > cl.conceptList.get(i).cohAvgSMC) {
                rightNeighborsNumber++;
                val = 1. * cl.conceptList.get(i).cohAvgSMC / c.cohAvgSMC;
                if (val > max)
                    max = val;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / upperNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (1 - max) * truthDegree;
        }
    }

    public double upperCohMinByMinSMC(FormalConcept c, float tetta) {
        //min alpha whth average cohesion J
        double max = Integer.MIN_VALUE, val = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> upperNeighbors = c.parents;
        for (Integer i : upperNeighbors) {
            if (c.cohMinSMC > cl.conceptList.get(i).cohMinSMC) {
                rightNeighborsNumber++;
                val = 1. * cl.conceptList.get(i).cohMinSMC / c.cohMinSMC;
                if (val > max)
                    max = val;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / upperNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (1 - max) * truthDegree;
        }
    }

    public double lowerCohAvgByAvgJ(FormalConcept c, float tetta) {
        double sum = 0;
        Set<Integer> lowerNeighbors = c.childs;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        for (Integer i : lowerNeighbors) {
            if (c.cohAvgJ < cl.conceptList.get(i).cohAvgJ) {
                rightNeighborsNumber++;
                sum += 1. * c.cohAvgJ / cl.conceptList.get(i).cohAvgJ;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / lowerNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (sum / rightNeighborsNumber) * truthDegree;
        }
    }

    public double lowerCohAvgByMinJ(FormalConcept c, float tetta) {
        double sum = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> lowerNeighbors = c.childs;
        for (Integer i : lowerNeighbors) {
            if (c.cohMinJ < cl.conceptList.get(i).cohMinJ) {
                rightNeighborsNumber++;
                sum += 1. * c.cohMinJ / cl.conceptList.get(i).cohMinJ;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            //truthDegree = rightNeighborsNumber/tetta/lowerNeighbors.size();
            truthDegree = (1. * rightNeighborsNumber / lowerNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (sum / rightNeighborsNumber) * truthDegree;
        }
    }

    public double lowerCohMinByAvgJ(FormalConcept c, float tetta) {
        double min = Integer.MAX_VALUE, val = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> lowerNeighbors = c.childs;
        for (Integer i : lowerNeighbors) {
            if (c.cohAvgJ < cl.conceptList.get(i).cohAvgJ) {
                rightNeighborsNumber++;
                val = 1. * c.cohAvgJ / cl.conceptList.get(i).cohAvgJ;
                if (val < min)
                    min = val;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / lowerNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (min) * truthDegree;
        }
    }

    public double lowerCohMinByMinJ(FormalConcept c, float tetta) {
        double min = Integer.MAX_VALUE, val = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> lowerNeighbors = c.childs;
        for (Integer i : lowerNeighbors) {
            if (c.cohMinJ < cl.conceptList.get(i).cohMinJ) {
                rightNeighborsNumber++;
                val = 1. * c.cohMinJ / cl.conceptList.get(i).cohMinJ;
                if (val < min)
                    min = val;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / lowerNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (min) * truthDegree;
        }
    }

    public double lowerCohAvgByAvgSMC(FormalConcept c, float tetta) {
        double sum = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> lowerNeighbors = c.childs;
        for (Integer i : lowerNeighbors) {
            if (c.cohAvgSMC < cl.conceptList.get(i).cohAvgSMC) {
                rightNeighborsNumber++;
                sum += 1. * c.cohAvgSMC / cl.conceptList.get(i).cohAvgSMC;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / lowerNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (sum / rightNeighborsNumber) * truthDegree;
        }
    }

    public double lowerCohAvgByMinSMC(FormalConcept c, float tetta) {
        double sum = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> lowerNeighbors = c.childs;
        for (Integer i : lowerNeighbors) {
            if (c.cohMinSMC < cl.conceptList.get(i).cohMinSMC) {
                rightNeighborsNumber++;
                sum += 1. * c.cohMinSMC / cl.conceptList.get(i).cohMinSMC;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / lowerNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (sum / rightNeighborsNumber) * truthDegree;
        }
    }

    public double lowerCohMinByAvgSMC(FormalConcept c, float tetta) {
        double min = Integer.MAX_VALUE, val = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> lowerNeighbors = c.childs;
        for (Integer i : lowerNeighbors) {
            if (c.cohAvgSMC <= cl.conceptList.get(i).cohAvgSMC) {
                rightNeighborsNumber++;
                val = 1. * c.cohAvgSMC / cl.conceptList.get(i).cohAvgSMC;
                if (val < min)
                    min = val;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / lowerNeighbors.size() >= tetta) ? 1 : 0;
            truthDegree = (float) Math.min(1.0, truthDegree);
            return (min) * truthDegree;
        }
    }

    public double lowerCohMinByMinSMC(FormalConcept c, float tetta) {
        double min = Integer.MAX_VALUE, val = 0;
        int rightNeighborsNumber = 0;
        float truthDegree = 0;
        Set<Integer> lowerNeighbors = c.childs;
        for (Integer i : lowerNeighbors) {
            if (c.cohMinSMC < cl.conceptList.get(i).cohMinSMC) {
                rightNeighborsNumber++;
                val = 1. * c.cohMinSMC / cl.conceptList.get(i).cohMinSMC;
                if (val < min)
                    min = val;
            }
        }
        if (rightNeighborsNumber == 0)
            return 0;
        else {
            truthDegree = (1. * rightNeighborsNumber / lowerNeighbors.size() >= tetta) ? 1 : 0;
            return (min) * truthDegree;
        }
    }

    //Similarity approach (S)
    //group of metrics: 
    // SMC avg_avg, avg_min, min_avg
    //   J avg_avg, avg_min, min_avg
    public void similarityGoguenNorm() {

        //           
        //         
        double[] buf = new double[2];

        if (objectsSimilaritySMC == null)
            this.setUp();

        //upper neighbors - alpha2
        //lower neighbors - alpha3
        for (FormalConcept c : cl.conceptList) {
            c.cohAvgJ = avgCohJ(c);
            c.cohMinJ = minCohJ(c);
            c.cohAvgSMC = avgCohSMC(c);
            c.cohMinSMC = minCohSMC(c);

        }
        for (FormalConcept c : cl.conceptList) {
            float tetta = 1;
            c.blS_Jaa = (c.cohAvgJ != 0) ? c.cohAvgJ * upperCohAvgByAvgJ(c, tetta) * lowerCohAvgByAvgJ(c, tetta)
                    : 0;
            c.blS_Jma = (c.cohMinJ != 0) ? c.cohMinJ * upperCohAvgByMinJ(c, tetta) * lowerCohAvgByMinJ(c, tetta)
                    : 0;
            c.blS_Jam = (c.cohAvgJ != 0) ? c.cohAvgJ * upperCohMinByAvgJ(c, tetta) * lowerCohMinByAvgJ(c, tetta)
                    : 0;
            c.blS_Jmm = (c.cohMinJ != 0) ? c.cohMinJ * upperCohMinByMinJ(c, tetta) * lowerCohMinByMinJ(c, tetta)
                    : 0;
            c.blS_SMCaa = (c.cohAvgSMC != 0)
                    ? c.cohAvgSMC * upperCohAvgByAvgSMC(c, tetta) * lowerCohAvgByAvgSMC(c, tetta)
                    : 0;
            c.blS_SMCma = (c.cohMinSMC != 0)
                    ? c.cohMinSMC * upperCohAvgByMinSMC(c, tetta) * lowerCohAvgByMinSMC(c, tetta)
                    : 0;
            c.blS_SMCam = (c.cohAvgSMC != 0)
                    ? c.cohAvgSMC * upperCohMinByAvgSMC(c, tetta) * lowerCohMinByAvgSMC(c, tetta)
                    : 0;
            c.blS_SMCmm = (c.cohMinSMC != 0)
                    ? c.cohMinSMC * upperCohMinByMinSMC(c, tetta) * lowerCohMinByMinSMC(c, tetta)
                    : 0;
        }
    }

    //Cue validity approach (CV)
    public void cueValidity() {

        if (attributesExtent == null)
            this.setUp();

        ArrayList<Integer> attrExtent;
        Set<Integer> intersection;
        double sum = 0;
        for (FormalConcept c : cl.conceptList) {
            sum = 0;
            for (Integer i : c.intent) {
                intersection = new HashSet<Integer>();
                intersection.addAll(c.extent);
                attrExtent = attributesExtent.get(i);
                intersection.retainAll(attrExtent);
                sum += (double) intersection.size() * 1. / attrExtent.size();
            }
            c.blCV = Double.isNaN(sum) ? 0 : sum;

        }
    }

    //Category feature collocation approach
    public void categoryFeatureCollocation() {
        if (attributesExtent == null)
            this.setUp();

        ArrayList<Integer> attrExtent;
        Set<Integer> intersection;
        double sum = 0;
        int latticeSize = cl.conceptList.size();
        for (FormalConcept c : cl.conceptList) {
            sum = 0;
            for (int i = 0; i < cl.attributeCount; i++) {
                intersection = new HashSet<Integer>();
                intersection.addAll(c.extent);
                attrExtent = attributesExtent.get(i);
                intersection.retainAll(attrExtent);
                sum += (double) intersection.size() * 1. / attrExtent.size() * intersection.size()
                        / c.extent.size();
            }
            c.blCFC = Double.isNaN(sum) ? 0 : sum;
        }
    }

    //Category utility approach
    public void categoryUtility() {
        if (attributesExtent == null)
            this.setUp();

        ArrayList<Integer> attrExtent;
        Set<Integer> intersection;
        double sum = 0;
        int attrSize = cl.objectCount;
        int cExtentSize = 0;
        for (FormalConcept c : cl.conceptList) {
            sum = 0;
            for (int i = 0; i < cl.attributeCount; i++) {
                intersection = new HashSet<Integer>();
                intersection.addAll(c.extent);
                cExtentSize = c.extent.size();
                attrExtent = attributesExtent.get(i);
                intersection.retainAll(attrExtent);
                sum += (double) Math.pow(intersection.size() * 1. / cExtentSize, 2)
                        - Math.pow(1. * attrExtent.size() / attrSize, 2);
            }
            c.blCU = Double.isNaN(1. * cExtentSize / attrSize * sum) ? 0 : 1. * cExtentSize / attrSize * sum;
        }
    }

    //Predictability approach (P)
    public void predictability() {

        if (attributesExtent == null)
            this.setUp();
        ArrayList<Integer> attributes = new ArrayList<Integer>();
        ArrayList<Integer> outOfIntent = new ArrayList<Integer>();
        Set<Integer> intersection;
        ArrayList<Integer> attrExtent;
        double sum, term;

        for (int i = 0; i < cl.attributeCount; i++) {
            attributes.add(i);
        }
        for (FormalConcept c : cl.conceptList) {
            sum = 0;
            outOfIntent = new ArrayList<Integer>();
            outOfIntent.addAll(attributes);
            outOfIntent.removeAll(c.intent);
            for (Integer y : outOfIntent) {
                intersection = new HashSet<Integer>();
                intersection.addAll(c.extent);
                attrExtent = attributesExtent.get(y);
                intersection.retainAll(attrExtent);
                term = 1. * intersection.size() / c.extent.size();

                if (term > 0) {
                    sum -= term * Math.log(term);
                }
            }
            c.blP = Double.isNaN(1 - sum / outOfIntent.size()) ? 0 : 1 - sum / outOfIntent.size();
        }

    }
}