/** * Creates output port of mappings of tensor {@code from} on tensor {@code to}. * * @param from from tensor * @param to to tensor * @return output port of mappings */ static OutputPort<IndexMappingBuffer> createPortOfBuffers(Tensor from, Tensor to) { return createPortOfBuffers(new IndexMappingBufferImpl(), from, to); }
static IndexMappingBuffer getFirstBuffer(Tensor from, Tensor to) { return createPortOfBuffers(from, to).take(); }
/** * Returns the first mapping of tensor {@code from} on tensor {@code to}. * * @param from from tensor * @param to to tensor * @return mapping of indices of tensor {@code from} on tensor {@code to} */ public static Mapping getFirst(Tensor from, Tensor to) { IndexMappingBuffer buffer = createPortOfBuffers(from, to).take(); if (buffer == null) return null; return new Mapping(buffer); }
/** * Returns {@code true} if there is positive mapping of tensor {@code from} on tensor {@code to}. * * @param from from tensor * @param to to tensor * @return {@code true} if there is positivemapping of tensor {@code from} on tensor {@code to} */ public static boolean positiveMappingExists(Tensor from, Tensor to) { IndexMappingBuffer buffer; OutputPort<IndexMappingBuffer> port = createPortOfBuffers(from, to); while ((buffer = port.take()) != null) if (!buffer.getSign()) return true; return false; }
/** * Creates output port of mappings from tensor <i>{@code from}</i> onto tensor <i>{@code to}</i>. * * @param from from tensor * @param to to tensor * @return output port of mappings */ public static MappingsPort createPort(Tensor from, Tensor to) { return new MappingsPort(createPortOfBuffers(new IndexMappingBufferImpl(), from, to)); }
@Override public IndexMappingProvider create(IndexMappingProvider opu, Tensor from, Tensor to) { if (IndexMappings.createPortOfBuffers(from.get(0), to.get(0)).take() != null) return new DummyIndexMappingProvider(opu); return IndexMappingProvider.Util.EMPTY_PROVIDER; } };
@Override public IndexMappingProvider create(IndexMappingProvider opu, Tensor from, Tensor to) { IndexMappingBuffer buffer; if ((buffer = IndexMappings.createPortOfBuffers(from.get(0), to.get(0)).take()) != null && !buffer.getSign()) return new DummyIndexMappingProvider(opu); return IndexMappingProvider.Util.EMPTY_PROVIDER; } };
@Override public IndexMappingBuffer take() { if (currentBuffer == null) return null; IndexMappingBuffer buf; while (true) { if (currentSource != null && (buf = currentSource.take()) != null) return buf; if (!permutationGenerator.hasNext()) { currentBuffer = null; return null; } currentPermutation = permutationGenerator.next(); currentSource = IndexMappings.createPortOfBuffers(currentBuffer.clone(), from[0], to[currentPermutation[0]]); } }
/** * Returns {@code true} if specified tensor is zero in consequence of its symmetries: is both symmetric and * asymmetric with respect to some permutation at the same time. * * @param t tensor * @return {@code true} if specified tensor is zero in consequence of its symmetries */ public static boolean isZeroDueToSymmetry(Tensor t) { int[] indices = IndicesUtils.getIndicesNames(t.getIndices().getFree()); IndexMappingBufferTester bufferTester = new IndexMappingBufferTester(indices, false); OutputPort<IndexMappingBuffer> mp = IndexMappings.createPortOfBuffers(bufferTester, t, t); IndexMappingBuffer buffer; while ((buffer = mp.take()) != null) if (buffer.getSign()) return true; return false; }
@Override public IndexMappingProvider create(IndexMappingProvider opu, Tensor from, Tensor to) { OutputPort<IndexMappingBuffer> mp = IndexMappings.createPortOfBuffers(from.get(0), to.get(0)); IndexMappingBuffer buffer; byte state = 0; while ((buffer = mp.take()) != null) { state |= (byte) (buffer.getSign() ? 0x10 : 0x01); if (state == 0x11) break; } switch (state) { case 0x00: return IndexMappingProvider.Util.EMPTY_PROVIDER; case 0x01: return new DummyIndexMappingProvider(opu); case 0x10: return new MinusIndexMappingProvider(opu); case 0x11: return new PlusMinusIndexMappingProvider(opu); default: throw new RuntimeException("Ups"); } } };
/** * Returns {@code true} if tensor u mathematically (not programming) equals to tensor v, * {@code false} if they they differ only in the sign and {@code null} otherwise. * * @param u tensor * @param v tensor * @return {@code true} {@code false} if tensor u mathematically (not programming) equals to tensor v, * {@code true} if they they differ only in the sign and {@code null} otherwise */ public static Boolean compare1(Tensor u, Tensor v) { Indices freeIndices = u.getIndices().getFree(); if (!freeIndices.equalsRegardlessOrder(v.getIndices().getFree())) return null; int[] free = freeIndices.getAllIndices().copy(); IndexMappingBuffer tester = new IndexMappingBufferTester(free, false); IndexMappingBuffer buffer = IndexMappings.createPortOfBuffers(tester, u, v).take(); if (buffer == null) return null; return buffer.getSign(); }
/** * Returns {@code true} if tensor u mathematically (not programming) equals to tensor v. * * @param u tensor * @param v tensor * @return {@code true} if specified tensors are mathematically (not programming) equal */ public static boolean equals(Tensor u, Tensor v) { if (u == v) return true; Indices freeIndices = u.getIndices().getFree(); if (!freeIndices.equalsRegardlessOrder(v.getIndices().getFree())) return false; int[] free = freeIndices.getAllIndices().copy(); IndexMappingBuffer tester = new IndexMappingBufferTester(free, false); OutputPort<IndexMappingBuffer> mp = IndexMappings.createPortOfBuffers(tester, u, v); IndexMappingBuffer buffer; while ((buffer = mp.take()) != null) if (!buffer.getSign()) return true; return false; }
/** * 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))); }