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}