/** * Creates a partial mapping. * * <p>Initially, no element is mapped to any other: * * <table border="1"> * <caption>Example</caption> * <tr> * <th>source</th> * <td>0</td> * <td>1</td> * <td>2</td> * </tr> * <tr> * <th>target</th> * <td>-1</td> * <td>-1</td> * <td>-1</td> * </tr> * </table> * * <table border="1"> * <caption>Example</caption> * <tr> * <th>target</th> * <td>0</td> * <td>1</td> * <td>2</td> * <td>3</td> * </tr> * <tr> * <th>source</th> * <td>-1</td> * <td>-1</td> * <td>-1</td> * <td>-1</td> * </tr> * </table> * * @param sourceCount Number of source elements * @param targetCount Number of target elements * @param mappingType Mapping type; must not allow multiple sources per target or multiple * targets per source */ public PartialMapping(int sourceCount, int targetCount, MappingType mappingType) { this.mappingType = mappingType; assert mappingType.isSingleSource() : mappingType; assert mappingType.isSingleTarget() : mappingType; this.sources = new int[targetCount]; this.targets = new int[sourceCount]; Arrays.fill(sources, -1); Arrays.fill(targets, -1); }
/** * Creates a partial mapping from a list. For example, <code> * PartialMapping({1, 2, 4}, 6)</code> creates the mapping * * <table border="1"> * <caption>Example</caption> * <tr> * <th>source</th> * <td>0</td> * <td>1</td> * <td>2</td> * <td>3</td> * <td>4</td> * <td>5</td> * </tr> * <tr> * <th>target</th> * <td>-1</td> * <td>0</td> * <td>1</td> * <td>-1</td> * <td>2</td> * <td>-1</td> * </tr> * </table> * * @param sourceList List whose i'th element is the source of target #i * @param sourceCount Number of elements in the source domain * @param mappingType Mapping type, must be {@link * org.eigenbase.util.mapping.MappingType#PARTIAL_SURJECTION} or stronger. */ public PartialMapping(List<Integer> sourceList, int sourceCount, MappingType mappingType) { this.mappingType = mappingType; assert mappingType.isSingleSource(); assert mappingType.isSingleTarget(); int targetCount = sourceList.size(); this.targets = new int[sourceCount]; this.sources = new int[targetCount]; Arrays.fill(sources, -1); for (int i = 0; i < sourceList.size(); ++i) { final int source = sourceList.get(i); sources[i] = source; if (source >= 0) { targets[source] = i; } else { assert !this.mappingType.isMandatorySource(); } } }
public void set(int source, int target) { if ((target < 0) && mappingType.isMandatorySource()) { throw new IllegalArgumentException("Target is required"); } if ((target >= targetCount) && (targetCount >= 0)) { throw new IllegalArgumentException("Target must be less than target count, " + targetCount); } targets[source] = target; }
public PartialFunctionImpl(int sourceCount, int targetCount, MappingType mappingType) { super(); if (sourceCount < 0) { throw new IllegalArgumentException("Sources must be finite"); } this.sourceCount = sourceCount; this.targetCount = targetCount; this.mappingType = mappingType; if (!mappingType.isSingleTarget()) { throw new IllegalArgumentException("Must have at most one target"); } this.targets = new int[sourceCount]; Arrays.fill(targets, -1); }
/** Creates a mapping with required properties. */ public static Mapping create(MappingType mappingType, int sourceCount, int targetCount) { switch (mappingType) { case BIJECTION: assert sourceCount == targetCount; return new Permutation(sourceCount); case INVERSE_SURJECTION: assert sourceCount >= targetCount; return new SurjectionWithInverse(sourceCount, targetCount); case PARTIAL_SURJECTION: case SURJECTION: return new Mappings.PartialMapping(sourceCount, targetCount, mappingType); case PARTIAL_FUNCTION: case FUNCTION: return new PartialFunctionImpl(sourceCount, targetCount, mappingType); case INVERSE_FUNCTION: case INVERSE_PARTIAL_FUNCTION: return new InverseMapping(create(mappingType.inverse(), targetCount, sourceCount)); default: throw Util.needToImplement("no known implementation for mapping type " + mappingType); } }
public Mapping inverse() { return new PartialMapping(targets.clone(), sources.clone(), mappingType.inverse()); }