/** * Creates output port of mappings of two products of tensors represented as arrays of multipliers, where * each multiplier of {@code from} will be mapped on the multiplier of {@code to} at the same * position. Such ordering can be obtained via {@link cc.redberry.core.transformations.substitutions.ProductsBijectionsPort}. * In contrast to {@link #createPortOfBuffers(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)}, this method * will fully handles mappings of free indices on contracted ones (like e.g. _i^j -> _k^k). * * @param from from tensor * @param to to tensor * @return port of mappings of indices */ public static MappingsPort createBijectiveProductPort(Tensor[] from, Tensor[] to) { if (from.length != to.length) throw new IllegalArgumentException("From length != to length."); if (from.length == 0) return new MappingsPort(IndexMappingProvider.Util.singleton(new IndexMappingBufferImpl())); if (from.length == 1) return new MappingsPort(createPortOfBuffers(from[0], to[0])); return new MappingsPort( new MappingsPortRemovingContracted( new SimpleProductMappingsPort(IndexMappingProvider.Util.singleton(new IndexMappingBufferImpl()), from, to))); }
@Override public IndexMappingBuffer take() { if (currentBuffer == null) return null; while (currentProvider == null) { if (!generator.hasNext()) return null; final int[] permutation = generator.next(); final Tensor[] newTo = new Tensor[to.length]; for (int i = 0; i < to.length; ++i) newTo[i] = to[permutation[i]]; currentProvider = new SimpleProductMappingsPort(IndexMappingProvider.Util.singleton(currentBuffer.clone()), from, newTo); final IndexMappingBuffer buffer = currentProvider.take(); if (buffer != null) return buffer; currentProvider = null; } final IndexMappingBuffer buffer = currentProvider.take(); if (buffer == null) { currentProvider = null; return take(); } return buffer; } }
/** * Tests whether specified {@link IndexMappingBufferTester} is a real mapping of tensor {@code from} * on tensor {@code to}. * * @param tester tester of mappings * @param from from tensor * @param to to tensor * @return {@code true} if there is mapping of tensor {@code from} on tensor {@code to} equal * to specified mapping */ public static boolean test(IndexMappingBufferTester tester, Tensor from, Tensor to) { tester.reset(); final IndexMappingProvider provider = IndexMappings.createPort(IndexMappingProvider.Util.singleton(tester), from, to); provider.tick(); IndexMappingBuffer buffer; while ((buffer = provider.take()) != null) if (!buffer.getSign()) return true; return false; }
/** * Creates output port of mappings of tensor {@code from} on tensor {@code to} with specified * mappings rules defined in specified {@link IndexMappingBuffer}. * * @param buffer initial mapping rules * @param from from tensor * @param to to tensor * @return output port of mapping */ static OutputPort<IndexMappingBuffer> createPortOfBuffers(final IndexMappingBuffer buffer, final Tensor from, final Tensor to) { final IndexMappingProvider provider = createPort(IndexMappingProvider.Util.singleton(buffer), from, to); provider.tick(); return new MappingsPortRemovingContracted(provider); }
/** * Creates output port of mappings of two simple tensors and does not take into account the arguments of fields. * * @param from from tensor * @param to to tensor * @return port of mappings of indices */ public static MappingsPort simpleTensorsPort(SimpleTensor from, SimpleTensor to) { final IndexMappingProvider provider = ProviderSimpleTensor.FACTORY_SIMPLETENSOR.create(IndexMappingProvider.Util.singleton(new IndexMappingBufferImpl()), from, to); provider.tick(); return new MappingsPort(new MappingsPortRemovingContracted(provider)); }
private static boolean mappingExists(Tensor from, Tensor to) { final IndexMappingProvider pp = IndexMappings.createPort( IndexMappingProvider.Util.singleton(new IndexMappingBufferImpl()), from, to); pp.tick(); return pp.take() != null; }