001package conexp.fx.core.context;
002
003import java.io.File;
004import java.util.HashMap;
005import java.util.HashSet;
006import java.util.Map;
007import java.util.Map.Entry;
008
009/*
010 * #%L
011 * Concept Explorer FX
012 * %%
013 * Copyright (C) 2010 - 2023 Francesco Kriegel
014 * %%
015 * This program is free software: you can redistribute it and/or modify
016 * it under the terms of the GNU General Public License as
017 * published by the Free Software Foundation, either version 3 of the
018 * License, or (at your option) any later version.
019 * 
020 * This program is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU General Public License for more details.
024 * 
025 * You should have received a copy of the GNU General Public
026 * License along with this program.  If not, see
027 * <http://www.gnu.org/licenses/gpl-3.0.html>.
028 * #L%
029 */
030
031import java.util.Random;
032import java.util.Set;
033
034import org.ujmp.core.booleanmatrix.BooleanMatrix;
035import org.ujmp.core.calculation.Calculation.Ret;
036
037import conexp.fx.core.collections.setlist.SetList;
038import conexp.fx.core.collections.setlist.SetLists;
039import conexp.fx.core.exporter.CXTExporter;
040import conexp.fx.core.importer.CXTImporter;
041
042public class Contexts {
043
044  public static final MatrixContext<Integer, Integer>
045      randomWithDensity(final int objects, final int attributes, final int density) {
046    final MatrixContext<Integer, Integer> cxt =
047        new MatrixContext<>(SetLists.integers(objects), SetLists.integers(attributes), false);
048    final Random rng = new Random();
049    final int target = (int) (((double) (objects * attributes * density)) / 100d);
050    int current = 0;
051    while (current < target) {
052      final int g = rng.nextInt(objects), m = rng.nextInt(attributes);
053      if (!cxt.matrix().getBoolean(g, m)) {
054        cxt.matrix().setBoolean(true, g, m);
055        current++;
056      }
057    }
058    return cxt;
059  }
060
061  public static final MatrixContext<Integer, Integer>
062      randomWithProbability(final int objects, final int attributes, final int probability) {
063    final MatrixContext<Integer, Integer> cxt =
064        new MatrixContext<>(SetLists.integers(objects), SetLists.integers(attributes), false);
065    final Random rng = new Random();
066    for (int g = 0; g < objects; g++)
067      for (int m = 0; m < attributes; m++)
068        if (rng.nextDouble() <= probability)
069          cxt.addFast(g, m);
070    return cxt;
071  }
072
073  /**
074   * 
075   * computes all pseudo-intents of a {@link MatrixContext}. This method may be slow, it is only intended for testing
076   * purposes.
077   * 
078   * Definition: For a given context {@code (G,M,I)} a {@literal pseudo-intent} is a subset {@code B} of the codomain
079   * {@code M}, such that it is no intent (i.e. {@code B≠B''}) and furthermore each strictly smaller pseudo-intent
080   * {@code D⊊B} has its closure in {@code B} (i.e. {@code D''⊆B}).
081   * 
082   * @param cxt
083   *          {@link MatrixContext}
084   * @return a {@link Map} whose keys are all pseudo-intents and their intents as values
085   */
086  public final static <G, M> Map<Set<M>, Set<M>> pseudoIntents(final MatrixContext<G, M> cxt) {
087    final Map<Set<M>, Set<M>> pseudoIntents = new HashMap<Set<M>, Set<M>>();
088    // computes all pseudo-intents from smallest to biggest
089    for (Set<M> attributes : SetLists.powerSet(cxt.colHeads())) {
090      Set<M> intent = cxt.intent(attributes);
091      // checks whether attributes is already an intent
092      if (attributes.containsAll(intent))
093        continue;
094      // checks if all strictly smaller pseudo-intents have their closure in attributes
095      boolean isPseudoIntent = true;
096      for (Entry<Set<M>, Set<M>> pseudoIntent : pseudoIntents.entrySet())
097        if (attributes.size() > pseudoIntent.getKey().size() && attributes.containsAll(pseudoIntent.getKey())
098            && !attributes.containsAll(pseudoIntent.getValue())) {
099          // no pseudo-intent
100          isPseudoIntent = false;
101          break;
102        }
103      if (isPseudoIntent) {
104        intent = new HashSet<M>(intent);
105        intent.removeAll(attributes);
106        pseudoIntents.put(attributes, intent);
107      }
108    }
109    return pseudoIntents;
110  }
111
112  public static final void extractFast(final File input, final File output, final int steps) throws Exception {
113    final MatrixContext<String, String> cxt = new MatrixContext<String, String>(false);
114    CXTImporter.read(cxt, input);
115    final SetList<String> domain = cxt.rowHeads();
116    final SetList<String> codomain = cxt.colHeads();
117    final BooleanMatrix matrix = cxt.matrix();
118    final int objs = domain.size();
119    final int atts = codomain.size();
120    for (int att = steps; att < atts; att = att + steps) {
121      final BooleanMatrix submatrix = matrix.subMatrix(Ret.LINK, 0, 0, objs - 1, att - 1).toBooleanMatrix();
122      CXTExporter.export(
123          new MatrixContext<String, String>(domain, codomain.subList(0, att), submatrix, false),
124          new File(output.getAbsolutePath().replace(".cxt", "_" + att + ".cxt")));
125    }
126  }
127
128  public static final void extractAttributeSubcontextFamily(final File input, final File output, final int steps)
129        throws Exception {
130      final MatrixContext<String, String> cxt = new MatrixContext<String, String>(false);
131      CXTImporter.read(cxt, input);
132      final int atts = cxt.colHeads().size();
133      for (int att = steps; att < atts; att = att + steps) {
134        final MatrixContext<String, String> subcxt =
135            cxt.subRelation(cxt.rowHeads(), cxt.colHeads().subList(0, att)).clone();
136        System.out.println(subcxt.rowHeads().size());
137        System.out.println(subcxt.colHeads().size());
138  //      CXTExporter.export(subcxt, new File(output.getAbsolutePath().replace(".cxt", "_" + att + ".cxt")));
139      }
140    }
141
142  public static final void extractSubcontext(final File input, final File output, final int objs, final int atts)
143      throws Exception {
144    final MatrixContext<String, String> context = new MatrixContext<String, String>(false);
145    CXTImporter.read(context, input);
146    final MatrixContext<String, String> subcxt =
147        context.subRelation(context.rowHeads().subList(0, objs), context.colHeads().subList(0, atts)).clone();
148    CXTExporter.export(subcxt, output);
149  }
150
151}