All Downloads are FREE. Search and download functionalities are using the official Maven repository.

uk.ac.ebi.beam.Topology Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2013, European Bioinformatics Institute (EMBL-EBI)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the FreeBSD Project.
 */

package uk.ac.ebi.beam;

import java.util.Arrays;
import java.util.List;

import static uk.ac.ebi.beam.Configuration.AL1;
import static uk.ac.ebi.beam.Configuration.AL2;
import static uk.ac.ebi.beam.Configuration.ANTI_CLOCKWISE;
import static uk.ac.ebi.beam.Configuration.CLOCKWISE;
import static uk.ac.ebi.beam.Configuration.DB1;
import static uk.ac.ebi.beam.Configuration.DB2;
import static uk.ac.ebi.beam.Configuration.OH1;
import static uk.ac.ebi.beam.Configuration.OH2;
import static uk.ac.ebi.beam.Configuration.SP1;
import static uk.ac.ebi.beam.Configuration.SP2;
import static uk.ac.ebi.beam.Configuration.SP3;
import static uk.ac.ebi.beam.Configuration.TB1;
import static uk.ac.ebi.beam.Configuration.TB2;
import static uk.ac.ebi.beam.Configuration.TH1;
import static uk.ac.ebi.beam.Configuration.TH2;
import static uk.ac.ebi.beam.Configuration.Type.DoubleBond;
import static uk.ac.ebi.beam.Configuration.Type.ExtendedTetrahedral;
import static uk.ac.ebi.beam.Configuration.Type.Implicit;
import static uk.ac.ebi.beam.Configuration.Type.SquarePlanar;
import static uk.ac.ebi.beam.Configuration.Type.Tetrahedral;
import static uk.ac.ebi.beam.Configuration.Type.TrigonalBipyramidal;

/**
 * Defines the relative topology around a vertex (atom).
 *
 * @author John May
 */
abstract class Topology {

    /**
     * The vertex/atom which this topology describes.
     *
     * @return vertex
     * @throws IllegalArgumentException unknown topology
     */
    abstract int atom();

    /**
     * The configuration of the topology.
     *
     * @return configuration for this topology
     */
    abstract Configuration configuration();

    /**
     * The configuration of the topology when it's carriers have the specified
     * ranks.
     *
     * @return configuration for this topology
     */
    Configuration configurationOf(int[] rank) {
        Topology topology = orderBy(rank);
        return topology != null ? topology.configuration() : Configuration.UNKNOWN;
    }

    /**
     * What type of configuration is defined by this topology (e.g. Tetrahedral,
     * DoubleBond etc).
     *
     * @return the type of the configuration
     */
    Configuration.Type type() {
        return configuration().type();
    }

    /**
     * Arrange the topology relative to a given ranking of vertices.
     *
     * @param rank ordering of vertices
     * @return a new topology with the neighbors arranged by the given rank
     */
    abstract Topology orderBy(int[] rank);

    /**
     * Transform the topology to one with the given {@literal mapping}.
     *
     * @param mapping the mapping used to transform the topology
     * @return a new topology with it's vertices mapped
     */
    abstract Topology transform(int[] mapping);
    
    abstract void copy(int[] dest);

    /**
     * Compute the permutation parity of the vertices {@literal vs} for the
     * given {@literal rank}. The parity defines the oddness or evenness of a
     * permutation and is the number of inversions (swaps) one would need to
     * make to place the 'vs' in the order specified by rank.
     *
     * @param vs   array of vertices
     * @param rank rank of vertices, |R| = max(vs) + 1
     * @return sign of the permutation, -1=odd or 1=even
     * @see = c.ordinal()) {
            int order = 1 + c.ordinal() - Configuration.TB1.ordinal();
            return new TrigonalBipyramidal(u, vs, order);
        }
        return null;
    }

    static Topology octahedral(int u, int[] vs, Configuration c) {
        if (Configuration.OH1.ordinal() <= c.ordinal() &&
                Configuration.OH30.ordinal() >= c.ordinal()) {
            int order = 1 + c.ordinal() - Configuration.OH1.ordinal();
            return new Octahedral(u, vs, order);
        }
        return null;
    }

    /**
     * Convert an implicit configuration ('@' or '@@') c, to an explicit one
     * (e.g. @TH1).
     *
     * 
     * Implicit Valence Explicit Example
     *
     * @param g chemical graph
     * @param u the atom to which the configuration is associated
     * @param c implicit configuration ({@link Configuration#ANTI_CLOCKWISE or
     *          Configuration#CLOCKWISE})
     * @return an explicit configuration or {@link Configuration#UNKNOWN}
     * @ 4       @TH1     O[C@H](N)C or O[C@]([H])(N)C
     * @@ 4       @TH2     O[C@@H](N)C or O[C@@]([H])(N)C
     * @ 3       @TH1     C[S@](N)=O
     * @@ 3       @TH2     C[S@@](N)=O
     * @ 2       @AL1     OC=[C@]=CO
     * @ 2       @AL2     OC=[C@@]=CO
     * @ 5       @TB1     S[As@](F)(Cl)(Br)C=O
     * @@ 5       @TB2     S[As@@](F)(Cl)(Br)C=O
     * @ 5       @OH1     S[Co@@](F)(Cl)(Br)(I)C=O
     * @@ 5       @OH2     O=C[Co@](F)(Cl)(Br)(I)S 
*/ static Configuration toExplicit(Graph g, int u, Configuration c) { // already explicit if (c.type() != Implicit) return c; int deg = g.degree(u); int valence = deg + g.atom(u).hydrogens(); // tetrahedral topology, square planar must always be explicit if (valence == 4) { return c == ANTI_CLOCKWISE ? TH1 : TH2; } // tetrahedral topology with implicit lone pair or double bond (Sp2) // atoms (todo) else if (valence == 3) { // XXX: sulfoxide and selenium special case... would be better to compute // hybridization don't really like doing this here but is sufficient // for now if (g.atom(u).element() == Element.Sulfur || g.atom(u).element() == Element.Selenium) { int sb = 0, db = 0; final int d = g.degree(u); for (int j=0; j es, Configuration c) { if (c.type() == Implicit) throw new IllegalArgumentException("configuration must be explicit, @TH1/@TH2 instead of @/@@"); // only tetrahedral is handled for now if (c.type() == Tetrahedral) { return tetrahedral(u, vs, c); } else if (c.type() == DoubleBond) { return trigonal(u, vs, c); } else if (c.type() == ExtendedTetrahedral) { return extendedTetrahedral(u, vs, c); } else if (c.type() == SquarePlanar) { return squarePlanar(u, vs, c); } else if (c.type() == TrigonalBipyramidal) { return trigonalBipyramidal(u, vs, c); } else if (c.type() == Configuration.Type.Octahedral) { return octahedral(u, vs, c); } return unknown(); } private static Topology UNKNOWN = new Topology() { @Override int atom() { throw new IllegalArgumentException("unknown topology"); } @Override Configuration configuration() { return Configuration.UNKNOWN; } @Override Topology orderBy(int[] rank) { return this; } @Override Topology transform(int[] mapping) { return this; } @Override void copy(int[] dest) { } }; private static final class Tetrahedral extends Topology { private final int u; private final int[] vs; private final int p; private Tetrahedral(int u, int[] vs, int p) { if (vs.length != 4) throw new IllegalArgumentException("Tetrahedral topology requires 4 vertices - use the 'centre' vertex to mark implicit verticies"); this.u = u; this.vs = vs; this.p = p; } /** @inheritDoc */ @Override int atom() { return u; } /** @inheritDoc */ @Override Configuration configuration() { return p < 0 ? Configuration.TH1 : Configuration.TH2; } /** @inheritDoc */ @Override Topology orderBy(int[] rank) { return new Tetrahedral(u, sort(vs, rank), p * parity4(vs, rank)); } /** @inheritDoc */ @Override Topology transform(final int[] mapping) { int[] ws = new int[vs.length]; for (int i = 0; i < vs.length; i++) ws[i] = mapping[vs[i]]; return new Tetrahedral(mapping[u], ws, p); } @Override void copy(int[] dest) { System.arraycopy(vs, 0, dest, 0, 4); } @Override Configuration configurationOf(int[] rank) { return p * parity4(vs, rank) < 0 ? TH1 : TH2; } public String toString() { return u + " " + Arrays.toString(vs) + ":" + p; } } private static final class ExtendedTetrahedral extends Topology { private final int u; private final int[] vs; private final int p; private ExtendedTetrahedral(int u, int[] vs, int p) { if (vs.length != 4) throw new IllegalArgumentException("Tetrahedral topology requires 4 vertices - use the 'centre' vertex to mark implicit verticies"); this.u = u; this.vs = vs; this.p = p; } /** @inheritDoc */ @Override int atom() { return u; } /** @inheritDoc */ @Override Configuration configuration() { return p < 0 ? Configuration.AL1 : Configuration.AL2; } /** @inheritDoc */ @Override Topology orderBy(int[] rank) { return new ExtendedTetrahedral(u, sort(vs, rank), p * parity4(vs, rank)); } /** @inheritDoc */ @Override Topology transform(final int[] mapping) { int[] ws = new int[vs.length]; for (int i = 0; i < vs.length; i++) ws[i] = mapping[vs[i]]; return new ExtendedTetrahedral(mapping[u], ws, p); } @Override void copy(int[] dest) { System.arraycopy(vs, 0, dest, 0, 4); } public String toString() { return u + " " + Arrays.toString(vs) + ":" + p; } } private static final int A = 0; private static final int B = 1; private static final int C = 2; private static final int D = 3; private static final int E = 4; private static final int F = 5; private static boolean check(int[] dest, int[] src, int[] perm, int step, int skip) { for (int i = 0; i < perm.length;) { int j; for (j = 0; j < step; j++) { if (dest[perm[i + j]] != src[j]) break; } if (j == 0) i += skip * step; else if (j == step) return true; else i+= step; } return false; } private static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } private static void indirectSort(int[] dst, int[] rank) { for (int i = 0; i < dst.length; i++) for (int j = i; j > 0 && rank[dst[j-1]] > rank[dst[j]]; j--) Topology.swap(dst, j, j - 1); } private static int[] applyInv(int[] src, int[] perm) { int[] res = new int[src.length]; for (int i = 0; i < src.length; i++) res[i] = src[perm[i]]; return res; } private static Integer[] toObjArray(int[] arr) { Integer[] res = new Integer[arr.length]; for (int i = 0; i < arr.length; i++) res[i] = arr[i]; return res; } private static int[] toIntArray(Integer[] arr) { int[] res = new int[arr.length]; for (int i = 0; i < arr.length; i++) res[i] = arr[i]; return res; } private static final class SquarePlanar extends Topology { private final int u; private final int[] vs; private final int order; private static final int[][] PERMUTATIONS = new int[][]{ {A, B, C, D, A, D, C, B, B, C, D, A, B, A, D, C, C, D, A, B, C, B, A, D, D, C, B, A, D, A, B, C}, // SP1 (U) {A, C, B, D, A, D, B, C, B, D, A, C, B, C, A, D, C, A, D, B, C, B, D, A, D, B, C, A, D, A, C, B}, // SP2 (4) {A, B, D, C, A, C, D, B, B, A, C, D, B, D, C, A, C, D, B, A, C, A, B, D, D, C, A, B, D, B, A, C} // SP3 (Z) }; private SquarePlanar(int u, int[] vs, int p) { if (vs.length != 4) throw new IllegalArgumentException("SquarePlanar topology requires 4 vertices"); this.u = u; this.vs = vs; this.order = p; } /** @inheritDoc */ @Override int atom() { return u; } /** @inheritDoc */ @Override Configuration configuration() { switch (order) { case 1: return SP1; case 2: return SP2; case 3: return SP3; default: return Configuration.UNKNOWN; } } /** @inheritDoc */ @Override Topology orderBy(final int[] rank) { int[] src = Topology.applyInv(vs, PERMUTATIONS[order - 1]); int[] dst = src.clone(); indirectSort(dst, rank); if (order < 1 || order > 20) return null; for (int i = 1; i <= 3; i++) { if (Topology.check(dst, src, PERMUTATIONS[i-1], 4, 2)) return new SquarePlanar(u, dst, i); } return null; } /** @inheritDoc */ @Override Topology transform(final int[] mapping) { int[] ws = new int[vs.length]; for (int i = 0; i < vs.length; i++) ws[i] = mapping[vs[i]]; return new SquarePlanar(mapping[u], ws, order); } @Override void copy(int[] dest) { System.arraycopy(vs, 0, dest, 0, vs.length); } public String toString() { return u + " " + Arrays.toString(vs) + ":" + order; } } private static final class TrigonalBipyramidal extends Topology { private final int u; private final int[] vs; private final int order; private static final int[][] PERMUTATIONS = new int[][]{ {A, B, C, D, E, A, C, D, B, E, A, D, B, C, E, E, D, C, B, A, E, B, D, C, A, E, C, B, D, A }, // TB1 a -> e @ {A, D, C, B, E, A, C, B, D, E, A, B, D, C, E, E, B, C, D, A, E, D, B, C, A, E, C, D, B, A }, // TB2 a -> e @@ {A, B, C, E, D, A, C, E, B, D, A, E, B, C, D, D, E, C, B, A, D, B, E, C, A, D, C, B, E, A }, // TB3 a -> d @ {A, E, C, B, D, A, C, B, E, D, A, B, E, C, D, D, B, C, E, A, D, E, B, C, A, D, C, E, B, A }, // TB4 a -> d @@ {A, B, D, E, C, A, D, E, B, C, A, E, B, D, C, C, E, D, B, A, C, B, E, D, A, C, D, B, E, A }, // TB5 a -> c @ {A, E, D, B, C, A, D, B, E, C, A, B, E, D, C, C, B, D, E, A, C, E, B, D, A, C, D, E, B, A }, // TB6 a -> c @@ {A, C, D, E, B, A, D, E, C, B, A, E, C, D, B, B, E, D, C, A, B, C, E, D, A, B, D, C, E, A }, // TB7 a -> b @ {A, E, D, C, B, A, D, C, E, B, A, C, E, D, B, B, C, D, E, A, B, E, C, D, A, B, D, E, C, A }, // TB8 a -> b @@ {B, A, C, D, E, B, C, D, A, E, B, D, A, C, E, E, D, C, A, B, E, A, D, C, B, E, C, A, D, B }, // TB9 b -> e @ {B, A, C, E, D, B, C, E, A, D, B, E, A, C, D, D, E, C, A, B, D, A, E, C, B, D, C, A, E, B }, // TB10 b -> d @ {B, D, C, A, E, B, C, A, D, E, B, A, D, C, E, E, A, C, D, B, E, D, A, C, B, E, C, D, A, B }, // TB11 b -> e @@ {B, E, C, A, D, B, C, A, E, D, B, A, E, C, D, D, A, C, E, B, D, E, A, C, B, D, C, E, A, B }, // TB12 b -> d @@ {B, A, D, E, C, B, D, E, A, C, B, E, A, D, C, C, E, D, A, B, C, A, E, D, B, C, D, A, E, B }, // TB13 b -> c @ {B, E, D, A, C, B, D, A, E, C, B, A, E, D, C, C, A, D, E, B, C, E, A, D, B, C, D, E, A, B }, // TB14 b -> c @@ {C, A, B, D, E, C, B, D, A, E, C, D, A, B, E, E, D, B, A, C, E, A, D, B, C, E, B, A, D, C }, // TB15 c -> e @ {C, A, B, E, D, C, B, E, A, D, C, E, A, B, D, D, E, B, A, C, D, A, E, B, C, D, B, A, E, C }, // TB16 c -> d @ {D, A, B, C, E, D, B, C, A, E, D, C, A, B, E, E, C, B, A, D, E, A, C, B, D, E, B, A, C, D }, // TB17 d -> e @ {D, C, B, A, E, D, B, A, C, E, D, A, C, B, E, E, A, B, C, D, E, C, A, B, D, E, B, C, A, D }, // TB18 d -> e @@ {C, E, B, A, D, C, B, A, E, D, C, A, E, B, D, D, A, B, E, C, D, E, A, B, C, D, B, E, A, C }, // TB19 c -> d @@ {C, D, B, A, E, C, B, A, D, E, C, A, D, B, E, E, A, B, D, C, E, D, A, B, C, E, B, D, A, C }, // TB20 c -> e @@ }; private TrigonalBipyramidal(int u, int[] vs, int order) { if (vs.length != 5) throw new IllegalArgumentException("TrigonalBipyramidal topology requires 5 vertices"); this.u = u; this.vs = vs; this.order = order; } /** @inheritDoc */ @Override int atom() { return u; } /** @inheritDoc */ @Override Configuration configuration() { if (order >= 1 && order <= 20) return Configuration.values()[Configuration.TB1.ordinal() + order - 1]; return Configuration.UNKNOWN; } /** @inheritDoc */ @Override Topology orderBy(final int[] rank) { int[] src = Topology.applyInv(vs, PERMUTATIONS[order-1]); int[] dst = src.clone(); indirectSort(dst, rank); for (int i = 1; i <= 20; i++) { if (Topology.check(dst, src, PERMUTATIONS[i-1], 5, 3)) return new TrigonalBipyramidal(u, dst, i); } return null; } /** @inheritDoc */ @Override Topology transform(final int[] mapping) { int[] ws = new int[vs.length]; for (int i = 0; i < vs.length; i++) ws[i] = mapping[vs[i]]; return new TrigonalBipyramidal(mapping[u], ws, order); } @Override void copy(int[] dest) { System.arraycopy(vs, 0, dest, 0, vs.length); } public String toString() { return u + " " + Arrays.toString(vs) + ":" + order; } } private static final class Octahedral extends Topology { private final int u; private final int[] vs; private final int order; private static final int[][] PERMUTATIONS = new int[][]{// @OH1 {A, B, C, D, E, F, A, C, D, E, B, F, A, D, E, B, C, F, A, E, B, C, D, F, B, A, E, F, C, D, B, C, A, E, F, D, B, E, F, C, A, D, B, F, C, A, E, D, C, A, B, F, D, E, C, B, F, D, A, E, C, D, A, B, F, E, C, F, D, A, B, E, D, A, C, F, E, B, D, C, F, E, A, B, D, E, A, C, F, B, D, F, E, A, C, B, E, A, D, F, B, C, E, B, A, D, F, C, E, D, F, B, A, C, E, F, B, A, D, C, F, B, E, D, C, A, F, C, B, E, D, A, F, D, C, B, E, A, F, E, D, C, B, A}, // @OH2 {A, B, E, D, C, F, A, C, B, E, D, F, A, D, C, B, E, F, A, E, D, C, B, F, B, A, C, F, E, D, B, C, F, E, A, D, B, E, A, C, F, D, B, F, E, A, C, D, C, A, D, F, B, E, C, B, A, D, F, E, C, D, F, B, A, E, C, F, B, A, D, E, D, A, E, F, C, B, D, C, A, E, F, B, D, E, F, C, A, B, D, F, C, A, E, B, E, A, B, F, D, C, E, B, F, D, A, C, E, D, A, B, F, C, E, F, D, A, B, C, F, B, C, D, E, A, F, C, D, E, B, A, F, D, E, B, C, A, F, E, B, C, D, A}, // @OH3 {A, B, C, D, F, E, A, C, D, F, B, E, A, D, F, B, C, E, A, F, B, C, D, E, B, A, F, E, C, D, B, C, A, F, E, D, B, E, C, A, F, D, B, F, E, C, A, D, C, A, B, E, D, F, C, B, E, D, A, F, C, D, A, B, E, F, C, E, D, A, B, F, D, A, C, E, F, B, D, C, E, F, A, B, D, E, F, A, C, B, D, F, A, C, E, B, E, B, F, D, C, A, E, C, B, F, D, A, E, D, C, B, F, A, E, F, D, C, B, A, F, A, D, E, B, C, F, B, A, D, E, C, F, D, E, B, A, C, F, E, B, A, D, C}, // @OH4 {A, B, C, E, D, F, A, C, E, D, B, F, A, D, B, C, E, F, A, E, D, B, C, F, B, A, D, F, C, E, B, C, A, D, F, E, B, D, F, C, A, E, B, F, C, A, D, E, C, A, B, F, E, D, C, B, F, E, A, D, C, E, A, B, F, D, C, F, E, A, B, D, D, A, E, F, B, C, D, B, A, E, F, C, D, E, F, B, A, C, D, F, B, A, E, C, E, A, C, F, D, B, E, C, F, D, A, B, E, D, A, C, F, B, E, F, D, A, C, B, F, B, D, E, C, A, F, C, B, D, E, A, F, D, E, C, B, A, F, E, C, B, D, A}, // @OH5 {A, B, C, F, D, E, A, C, F, D, B, E, A, D, B, C, F, E, A, F, D, B, C, E, B, A, D, E, C, F, B, C, A, D, E, F, B, D, E, C, A, F, B, E, C, A, D, F, C, A, B, E, F, D, C, B, E, F, A, D, C, E, F, A, B, D, C, F, A, B, E, D, D, A, F, E, B, C, D, B, A, F, E, C, D, E, B, A, F, C, D, F, E, B, A, C, E, B, D, F, C, A, E, C, B, D, F, A, E, D, F, C, B, A, E, F, C, B, D, A, F, A, C, E, D, B, F, C, E, D, A, B, F, D, A, C, E, B, F, E, D, A, C, B}, // @OH6 {A, B, C, E, F, D, A, C, E, F, B, D, A, E, F, B, C, D, A, F, B, C, E, D, B, A, F, D, C, E, B, C, A, F, D, E, B, D, C, A, F, E, B, F, D, C, A, E, C, A, B, D, E, F, C, B, D, E, A, F, C, D, E, A, B, F, C, E, A, B, D, F, D, B, F, E, C, A, D, C, B, F, E, A, D, E, C, B, F, A, D, F, E, C, B, A, E, A, C, D, F, B, E, C, D, F, A, B, E, D, F, A, C, B, E, F, A, C, D, B, F, A, E, D, B, C, F, B, A, E, D, C, F, D, B, A, E, C, F, E, D, B, A, C}, // @OH7 {A, B, C, F, E, D, A, C, F, E, B, D, A, E, B, C, F, D, A, F, E, B, C, D, B, A, E, D, C, F, B, C, A, E, D, F, B, D, C, A, E, F, B, E, D, C, A, F, C, A, B, D, F, E, C, B, D, F, A, E, C, D, F, A, B, E, C, F, A, B, D, E, D, B, E, F, C, A, D, C, B, E, F, A, D, E, F, C, B, A, D, F, C, B, E, A, E, A, F, D, B, C, E, B, A, F, D, C, E, D, B, A, F, C, E, F, D, B, A, C, F, A, C, D, E, B, F, C, D, E, A, B, F, D, E, A, C, B, F, E, A, C, D, B}, // @OH8 {A, B, D, C, E, F, A, C, E, B, D, F, A, D, C, E, B, F, A, E, B, D, C, F, B, A, E, F, D, C, B, D, A, E, F, C, B, E, F, D, A, C, B, F, D, A, E, C, C, A, D, F, E, B, C, D, F, E, A, B, C, E, A, D, F, B, C, F, E, A, D, B, D, A, B, F, C, E, D, B, F, C, A, E, D, C, A, B, F, E, D, F, C, A, B, E, E, A, C, F, B, D, E, B, A, C, F, D, E, C, F, B, A, D, E, F, B, A, C, D, F, B, E, C, D, A, F, C, D, B, E, A, F, D, B, E, C, A, F, E, C, D, B, A}, // @OH9 {A, B, D, C, F, E, A, C, F, B, D, E, A, D, C, F, B, E, A, F, B, D, C, E, B, A, F, E, D, C, B, D, A, F, E, C, B, E, D, A, F, C, B, F, E, D, A, C, C, A, D, E, F, B, C, D, E, F, A, B, C, E, F, A, D, B, C, F, A, D, E, B, D, A, B, E, C, F, D, B, E, C, A, F, D, C, A, B, E, F, D, E, C, A, B, F, E, B, F, C, D, A, E, C, D, B, F, A, E, D, B, F, C, A, E, F, C, D, B, A, F, A, C, E, B, D, F, B, A, C, E, D, F, C, E, B, A, D, F, E, B, A, C, D}, // @OH10 {A, B, E, C, D, F, A, C, D, B, E, F, A, D, B, E, C, F, A, E, C, D, B, F, B, A, D, F, E, C, B, D, F, E, A, C, B, E, A, D, F, C, B, F, E, A, D, C, C, A, E, F, D, B, C, D, A, E, F, B, C, E, F, D, A, B, C, F, D, A, E, B, D, A, C, F, B, E, D, B, A, C, F, E, D, C, F, B, A, E, D, F, B, A, C, E, E, A, B, F, C, D, E, B, F, C, A, D, E, C, A, B, F, D, E, F, C, A, B, D, F, B, D, C, E, A, F, C, E, B, D, A, F, D, C, E, B, A, F, E, B, D, C, A}, // @OH11 {A, B, F, C, D, E, A, C, D, B, F, E, A, D, B, F, C, E, A, F, C, D, B, E, B, A, D, E, F, C, B, D, E, F, A, C, B, E, F, A, D, C, B, F, A, D, E, C, C, A, F, E, D, B, C, D, A, F, E, B, C, E, D, A, F, B, C, F, E, D, A, B, D, A, C, E, B, F, D, B, A, C, E, F, D, C, E, B, A, F, D, E, B, A, C, F, E, B, D, C, F, A, E, C, F, B, D, A, E, D, C, F, B, A, E, F, B, D, C, A, F, A, B, E, C, D, F, B, E, C, A, D, F, C, A, B, E, D, F, E, C, A, B, D}, // @OH12 {A, B, E, C, F, D, A, C, F, B, E, D, A, E, C, F, B, D, A, F, B, E, C, D, B, A, F, D, E, C, B, D, E, A, F, C, B, E, A, F, D, C, B, F, D, E, A, C, C, A, E, D, F, B, C, D, F, A, E, B, C, E, D, F, A, B, C, F, A, E, D, B, D, B, F, C, E, A, D, C, E, B, F, A, D, E, B, F, C, A, D, F, C, E, B, A, E, A, B, D, C, F, E, B, D, C, A, F, E, C, A, B, D, F, E, D, C, A, B, F, F, A, C, D, B, E, F, B, A, C, D, E, F, C, D, B, A, E, F, D, B, A, C, E}, // @OH13 {A, B, F, C, E, D, A, C, E, B, F, D, A, E, B, F, C, D, A, F, C, E, B, D, B, A, E, D, F, C, B, D, F, A, E, C, B, E, D, F, A, C, B, F, A, E, D, C, C, A, F, D, E, B, C, D, E, A, F, B, C, E, A, F, D, B, C, F, D, E, A, B, D, B, E, C, F, A, D, C, F, B, E, A, D, E, C, F, B, A, D, F, B, E, C, A, E, A, C, D, B, F, E, B, A, C, D, F, E, C, D, B, A, F, E, D, B, A, C, F, F, A, B, D, C, E, F, B, D, C, A, E, F, C, A, B, D, E, F, D, C, A, B, E}, // @OH14 {A, B, D, E, C, F, A, C, B, D, E, F, A, D, E, C, B, F, A, E, C, B, D, F, B, A, C, F, D, E, B, C, F, D, A, E, B, D, A, C, F, E, B, F, D, A, C, E, C, A, E, F, B, D, C, B, A, E, F, D, C, E, F, B, A, D, C, F, B, A, E, D, D, A, B, F, E, C, D, B, F, E, A, C, D, E, A, B, F, C, D, F, E, A, B, C, E, A, D, F, C, B, E, C, A, D, F, B, E, D, F, C, A, B, E, F, C, A, D, B, F, B, C, E, D, A, F, C, E, D, B, A, F, D, B, C, E, A, F, E, D, B, C, A}, // @OH15 {A, B, D, F, C, E, A, C, B, D, F, E, A, D, F, C, B, E, A, F, C, B, D, E, B, A, C, E, D, F, B, C, E, D, A, F, B, D, A, C, E, F, B, E, D, A, C, F, C, A, F, E, B, D, C, B, A, F, E, D, C, E, B, A, F, D, C, F, E, B, A, D, D, A, B, E, F, C, D, B, E, F, A, C, D, E, F, A, B, C, D, F, A, B, E, C, E, B, C, F, D, A, E, C, F, D, B, A, E, D, B, C, F, A, E, F, D, B, C, A, F, A, D, E, C, B, F, C, A, D, E, B, F, D, E, C, A, B, F, E, C, A, D, B}, // @OH16 {A, B, F, D, C, E, A, C, B, F, D, E, A, D, C, B, F, E, A, F, D, C, B, E, B, A, C, E, F, D, B, C, E, F, A, D, B, E, F, A, C, D, B, F, A, C, E, D, C, A, D, E, B, F, C, B, A, D, E, F, C, D, E, B, A, F, C, E, B, A, D, F, D, A, F, E, C, B, D, C, A, F, E, B, D, E, C, A, F, B, D, F, E, C, A, B, E, B, C, D, F, A, E, C, D, F, B, A, E, D, F, B, C, A, E, F, B, C, D, A, F, A, B, E, D, C, F, B, E, D, A, C, F, D, A, B, E, C, F, E, D, A, B, C}, // @OH17 {A, B, E, F, C, D, A, C, B, E, F, D, A, E, F, C, B, D, A, F, C, B, E, D, B, A, C, D, E, F, B, C, D, E, A, F, B, D, E, A, C, F, B, E, A, C, D, F, C, A, F, D, B, E, C, B, A, F, D, E, C, D, B, A, F, E, C, F, D, B, A, E, D, B, C, F, E, A, D, C, F, E, B, A, D, E, B, C, F, A, D, F, E, B, C, A, E, A, B, D, F, C, E, B, D, F, A, C, E, D, F, A, B, C, E, F, A, B, D, C, F, A, E, D, C, B, F, C, A, E, D, B, F, D, C, A, E, B, F, E, D, C, A, B}, // @OH18 {A, B, F, E, C, D, A, C, B, F, E, D, A, E, C, B, F, D, A, F, E, C, B, D, B, A, C, D, F, E, B, C, D, F, A, E, B, D, F, A, C, E, B, F, A, C, D, E, C, A, E, D, B, F, C, B, A, E, D, F, C, D, B, A, E, F, C, E, D, B, A, F, D, B, C, E, F, A, D, C, E, F, B, A, D, E, F, B, C, A, D, F, B, C, E, A, E, A, F, D, C, B, E, C, A, F, D, B, E, D, C, A, F, B, E, F, D, C, A, B, F, A, B, D, E, C, F, B, D, E, A, C, F, D, E, A, B, C, F, E, A, B, D, C}, // @OH19 {A, B, D, E, F, C, A, D, E, F, B, C, A, E, F, B, D, C, A, F, B, D, E, C, B, A, F, C, D, E, B, C, D, A, F, E, B, D, A, F, C, E, B, F, C, D, A, E, C, B, F, E, D, A, C, D, B, F, E, A, C, E, D, B, F, A, C, F, E, D, B, A, D, A, B, C, E, F, D, B, C, E, A, F, D, C, E, A, B, F, D, E, A, B, C, F, E, A, D, C, F, B, E, C, F, A, D, B, E, D, C, F, A, B, E, F, A, D, C, B, F, A, E, C, B, D, F, B, A, E, C, D, F, C, B, A, E, D, F, E, C, B, A, D}, // @OH20 {A, B, D, F, E, C, A, D, F, E, B, C, A, E, B, D, F, C, A, F, E, B, D, C, B, A, E, C, D, F, B, C, D, A, E, F, B, D, A, E, C, F, B, E, C, D, A, F, C, B, E, F, D, A, C, D, B, E, F, A, C, E, F, D, B, A, C, F, D, B, E, A, D, A, B, C, F, E, D, B, C, F, A, E, D, C, F, A, B, E, D, F, A, B, C, E, E, A, F, C, B, D, E, B, A, F, C, D, E, C, B, A, F, D, E, F, C, B, A, D, F, A, D, C, E, B, F, C, E, A, D, B, F, D, C, E, A, B, F, E, A, D, C, B}, // @OH21 {A, B, E, D, F, C, A, D, F, B, E, C, A, E, D, F, B, C, A, F, B, E, D, C, B, A, F, C, E, D, B, C, E, A, F, D, B, E, A, F, C, D, B, F, C, E, A, D, C, B, F, D, E, A, C, D, E, B, F, A, C, E, B, F, D, A, C, F, D, E, B, A, D, A, E, C, F, B, D, C, F, A, E, B, D, E, C, F, A, B, D, F, A, E, C, B, E, A, B, C, D, F, E, B, C, D, A, F, E, C, D, A, B, F, E, D, A, B, C, F, F, A, D, C, B, E, F, B, A, D, C, E, F, C, B, A, D, E, F, D, C, B, A, E}, // @OH22 {A, B, F, D, E, C, A, D, E, B, F, C, A, E, B, F, D, C, A, F, D, E, B, C, B, A, E, C, F, D, B, C, F, A, E, D, B, E, C, F, A, D, B, F, A, E, C, D, C, B, E, D, F, A, C, D, F, B, E, A, C, E, D, F, B, A, C, F, B, E, D, A, D, A, F, C, E, B, D, C, E, A, F, B, D, E, A, F, C, B, D, F, C, E, A, B, E, A, D, C, B, F, E, B, A, D, C, F, E, C, B, A, D, F, E, D, C, B, A, F, F, A, B, C, D, E, F, B, C, D, A, E, F, C, D, A, B, E, F, D, A, B, C, E}, // @OH23 {A, B, E, F, D, C, A, D, B, E, F, C, A, E, F, D, B, C, A, F, D, B, E, C, B, A, D, C, E, F, B, C, E, A, D, F, B, D, C, E, A, F, B, E, A, D, C, F, C, B, D, F, E, A, C, D, F, E, B, A, C, E, B, D, F, A, C, F, E, B, D, A, D, A, F, C, B, E, D, B, A, F, C, E, D, C, B, A, F, E, D, F, C, B, A, E, E, A, B, C, F, D, E, B, C, F, A, D, E, C, F, A, B, D, E, F, A, B, C, D, F, A, E, C, D, B, F, C, D, A, E, B, F, D, A, E, C, B, F, E, C, D, A, B}, // @OH24 {A, B, F, E, D, C, A, D, B, F, E, C, A, E, D, B, F, C, A, F, E, D, B, C, B, A, D, C, F, E, B, C, F, A, D, E, B, D, C, F, A, E, B, F, A, D, C, E, C, B, D, E, F, A, C, D, E, F, B, A, C, E, F, B, D, A, C, F, B, D, E, A, D, A, E, C, B, F, D, B, A, E, C, F, D, C, B, A, E, F, D, E, C, B, A, F, E, A, F, C, D, B, E, C, D, A, F, B, E, D, A, F, C, B, E, F, C, D, A, B, F, A, B, C, E, D, F, B, C, E, A, D, F, C, E, A, B, D, F, E, A, B, C, D}, // @OH25 {A, C, D, E, F, B, A, D, E, F, C, B, A, E, F, C, D, B, A, F, C, D, E, B, B, C, F, E, D, A, B, D, C, F, E, A, B, E, D, C, F, A, B, F, E, D, C, A, C, A, F, B, D, E, C, B, D, A, F, E, C, D, A, F, B, E, C, F, B, D, A, E, D, A, C, B, E, F, D, B, E, A, C, F, D, C, B, E, A, F, D, E, A, C, B, F, E, A, D, B, F, C, E, B, F, A, D, C, E, D, B, F, A, C, E, F, A, D, B, C, F, A, E, B, C, D, F, B, C, A, E, D, F, C, A, E, B, D, F, E, B, C, A, D}, // @OH26 {A, C, D, F, E, B, A, D, F, E, C, B, A, E, C, D, F, B, A, F, E, C, D, B, B, C, E, F, D, A, B, D, C, E, F, A, B, E, F, D, C, A, B, F, D, C, E, A, C, A, E, B, D, F, C, B, D, A, E, F, C, D, A, E, B, F, C, E, B, D, A, F, D, A, C, B, F, E, D, B, F, A, C, E, D, C, B, F, A, E, D, F, A, C, B, E, E, A, F, B, C, D, E, B, C, A, F, D, E, C, A, F, B, D, E, F, B, C, A, D, F, A, D, B, E, C, F, B, E, A, D, C, F, D, B, E, A, C, F, E, A, D, B, C}, // @OH27 {A, C, E, D, F, B, A, D, F, C, E, B, A, E, D, F, C, B, A, F, C, E, D, B, B, C, F, D, E, A, B, D, E, C, F, A, B, E, C, F, D, A, B, F, D, E, C, A, C, A, F, B, E, D, C, B, E, A, F, D, C, E, A, F, B, D, C, F, B, E, A, D, D, A, E, B, F, C, D, B, F, A, E, C, D, E, B, F, A, C, D, F, A, E, B, C, E, A, C, B, D, F, E, B, D, A, C, F, E, C, B, D, A, F, E, D, A, C, B, F, F, A, D, B, C, E, F, B, C, A, D, E, F, C, A, D, B, E, F, D, B, C, A, E}, // @OH28 {A, C, F, D, E, B, A, D, E, C, F, B, A, E, C, F, D, B, A, F, D, E, C, B, B, C, E, D, F, A, B, D, F, C, E, A, B, E, D, F, C, A, B, F, C, E, D, A, C, A, E, B, F, D, C, B, F, A, E, D, C, E, B, F, A, D, C, F, A, E, B, D, D, A, F, B, E, C, D, B, E, A, F, C, D, E, A, F, B, C, D, F, B, E, A, C, E, A, D, B, C, F, E, B, C, A, D, F, E, C, A, D, B, F, E, D, B, C, A, F, F, A, C, B, D, E, F, B, D, A, C, E, F, C, B, D, A, E, F, D, A, C, B, E}, // @OH29 {A, C, E, F, D, B, A, D, C, E, F, B, A, E, F, D, C, B, A, F, D, C, E, B, B, C, D, F, E, A, B, D, F, E, C, A, B, E, C, D, F, A, B, F, E, C, D, A, C, A, D, B, E, F, C, B, E, A, D, F, C, D, B, E, A, F, C, E, A, D, B, F, D, A, F, B, C, E, D, B, C, A, F, E, D, C, A, F, B, E, D, F, B, C, A, E, E, A, C, B, F, D, E, B, F, A, C, D, E, C, B, F, A, D, E, F, A, C, B, D, F, A, E, B, D, C, F, B, D, A, E, C, F, D, A, E, B, C, F, E, B, D, A, C}, // @OH30 {A, C, F, E, D, B, A, D, C, F, E, B, A, E, D, C, F, B, A, F, E, D, C, B, B, C, D, E, F, A, B, D, E, F, C, A, B, E, F, C, D, A, B, F, C, D, E, A, C, A, D, B, F, E, C, B, F, A, D, E, C, D, B, F, A, E, C, F, A, D, B, E, D, A, E, B, C, F, D, B, C, A, E, F, D, C, A, E, B, F, D, E, B, C, A, F, E, A, F, B, D, C, E, B, D, A, F, C, E, D, A, F, B, C, E, F, B, D, A, C, F, A, C, B, E, D, F, B, E, A, C, D, F, C, B, E, A, D, F, E, A, C, B, D} }; private Octahedral(int u, int[] vs, int order) { if (vs.length != 6) throw new IllegalArgumentException("Octahedral topology requires 6 vertices"); this.u = u; this.vs = vs; this.order = order; } /** @inheritDoc */ @Override int atom() { return u; } /** @inheritDoc */ @Override Configuration configuration() { if (order >= 1 && order <= 30) return Configuration.values()[Configuration.OH1.ordinal() + order - 1]; return Configuration.UNKNOWN; } /** @inheritDoc */ @Override Topology orderBy(final int[] rank) { int[] src = Topology.applyInv(vs, PERMUTATIONS[order-1]); int[] dst = src.clone(); indirectSort(dst, rank); for (int i = 1; i <= 30; i++) { if (Topology.check(dst, src, PERMUTATIONS[i-1], 6, 4)) return new Octahedral(u, dst, i); } return null; } /** @inheritDoc */ @Override Topology transform(final int[] mapping) { int[] ws = new int[vs.length]; for (int i = 0; i < vs.length; i++) ws[i] = mapping[vs[i]]; return new Octahedral(mapping[u], ws, order); } @Override void copy(int[] dest) { System.arraycopy(vs, 0, dest, 0, vs.length); } public String toString() { return u + " " + Arrays.toString(vs) + ":" + order; } } private static final class Trigonal extends Topology { private final int u; private final int[] vs; private final int p; private Trigonal(int u, int[] vs, int p) { if (vs.length != 3) throw new IllegalArgumentException("Trigonal topology requires 3 vertices - use the 'centre' vertex to mark implicit verticies"); this.u = u; this.vs = vs; this.p = p; } /** @inheritDoc */ @Override int atom() { return u; } /** @inheritDoc */ @Override Configuration configuration() { return p < 0 ? Configuration.DB1 : Configuration.DB2; } /** @inheritDoc */ @Override Topology orderBy(int[] rank) { return new Trigonal(u, sort(vs, rank), p * parity(vs, rank)); } /** @inheritDoc */ @Override Topology transform(final int[] mapping) { int[] ws = new int[vs.length]; for (int i = 0; i < vs.length; i++) ws[i] = mapping[vs[i]]; return new Trigonal(mapping[u], ws, p); } @Override void copy(int[] dest) { System.arraycopy(vs, 0, dest, 0, 3); } public String toString() { return u + " " + Arrays.toString(vs) + ":" + p; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy