Package au.csiro.snorocket.core

Source Code of au.csiro.snorocket.core.AR

/**
* Copyright (c) 2009 International Health Terminology Standards Development
* Organisation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Copyright CSIRO Australian e-Health Research Centre (http://aehrc.com).
* All rights reserved. Use is subject to license terms and conditions.
*/

package au.csiro.snorocket.core;

import java.util.Arrays;
import java.util.BitSet;

import au.csiro.snorocket.core.util.IConceptSet;
import au.csiro.snorocket.core.util.ReadonlyConceptSet;
import au.csiro.snorocket.core.util.SparseConceptHashSet;
import au.csiro.snorocket.core.util.SparseConceptSet;

public class R extends R1 {
    R(int concepts, int roles) {
        super(concepts, roles);
    }

    R(int concepts, int roles, R rr) {
        super(concepts, roles, rr);
    }

    /**
     * Record A [ r.B
     *
     * @param A
     * @param r
     * @param B
     */
    void store(int A, int r, int B) {
        getB(A, r).add(B);
        getA(B, r).add(A);
    }

}

abstract class AR {
    protected int CONCEPTS;
    protected int ROLES;

    AR(final int concepts, final int roles) {
        CONCEPTS = concepts;
        ROLES = roles + 1;
    }
}

/**
* Implements R, which is of the form RoleMap<ConceptMap<ConceptSet>>
* where the two maps are complete/total (ie there is an entry for every key),
* thus it's faster and more space-efficient to just use an array (flattened
* from 2D to 1D).
*
* @author law223
*
*/
abstract class R1 extends AR {

    final private BitSet currentRoles;
    final private IConceptSet[] base;

    private IConceptSet[] data;

    R1(final int concepts, final int roles) {
        this(concepts, roles, null);
    }

    /**
     * The initialState is assumed to be static and the local state is lazily
     * initialised from it as lookup* and get* are called.
     *
     * @param concepts
     * @param roles
     * @param initialState
     *            used as a base state
     */
    R1(int concepts, int roles, R1 initialState) {
        super(concepts, roles);

        this.data = new IConceptSet[(CONCEPTS * ROLES) << 1];
        this.currentRoles = new BitSet(ROLES);

        // This is relatively cheap to initialise up front (unlike this.data)
        if (null != initialState) {
            this.base = initialState.data;
            currentRoles.or(initialState.currentRoles);
        } else {
            this.base = null;
        }
    }

    /**
     * This should only ever be called when the relationships wrap an initial
     * state and no other methods have been called.
     *
     * @param relationships
     */
    public void subtract(R1 relationships) {
        if (null == base) {
            throw new AssertionError("");
        }
        for (int i = 0; i < base.length; i++) {
            if (null == base[i]) {
                continue;
            }
            final IConceptSet set = data[i] = new SparseConceptHashSet();

            set.addAll(base[i]);
            if (null != relationships.data[i]) {
                set.removeAll(relationships.data[i]);
            }
        }
    }

    public boolean containsRole(int role) {
        return currentRoles.get(role);
    }

    /**
     * Returns {B | A [ r.B} or {B | (A,B) in R(r)}
     *
     * @param A
     * @param r
     * @return
     */
    protected IConceptSet getB(int A, int r) {
        if (A >= CONCEPTS) {
            resizeConcepts(A);
        }
        if (r >= ROLES) {
            resizeRoles(r);
        }
        final int index = indexOf(A, r);
        if (null == data[index]) {
            data[index] = new SparseConceptSet();
            addRole(r);

            if (null != base && index < base.length && null != base[index]) {
                data[index].addAll(base[index]);
            }
        }
        return data[index];
    }

    public void addRole(int r) {
        currentRoles.set(r);
    }

    /**
     *
     * @param B
     * @param r
     * @return Set of concepts A such that A [ r.B
     */
    public IConceptSet lookupA(int B, int r) {
        if (B >= CONCEPTS || r >= ROLES) {
            return IConceptSet.EMPTY_SET;
        }
        final int index = indexOf(B, r) + 1;
        if (null == data[index]) {
            if (null != base && index < base.length && null != base[index]) {
                data[index] = new SparseConceptSet();
                data[index].addAll(base[index]);
                return new ReadonlyConceptSet(data[index]);
            } else {
                return IConceptSet.EMPTY_SET;
            }
        } else {
            return new ReadonlyConceptSet(data[index]);
        }
    }

    /**
     *
     * @param A
     * @param r
     * @return Set of concepts B such that A [ r.B
     */
    public IConceptSet lookupB(int A, int r) {
        if (A >= CONCEPTS || r >= ROLES) {
            return IConceptSet.EMPTY_SET;
        }
        final int index = indexOf(A, r);
        if (null == data[index]) {
            if (null != base && index < base.length && null != base[index]) {
                data[index] = new SparseConceptSet();
                data[index].addAll(base[index]);
                return new ReadonlyConceptSet(data[index]);
            } else {
                return IConceptSet.EMPTY_SET;
            }
        } else {
            return new ReadonlyConceptSet(data[index]);
        }
    }

    /**
     * Returns {A | A [ r.B} or {A | (A,B) in R(r)}
     *
     * Lazily initialise data from base as a side-effect of this call.
     *
     * @param B
     * @param r
     * @return
     */
    protected IConceptSet getA(int B, int r) {
        if (B >= CONCEPTS) {
            resizeConcepts(B);
        }
        if (r >= ROLES) {
            resizeRoles(r);
        }
        // Note the "+1" in the following line:
        final int index = indexOf(B, r) + 1;
        if (null == data[index]) {
            data[index] = new SparseConceptSet();
            addRole(r);

            if (null != base && index < base.length && null != base[index]) {
                data[index].addAll(base[index]);
            }
        }
        return data[index];
    }

    private int indexOf(int concept, int role) {
        if (role >= ROLES) {
            throw new IllegalArgumentException("role " + role
                    + " must be smaller than " + ROLES);
        }
        return ((concept * ROLES) + role) << 1;
    }

    public void clear() {
        Arrays.fill(data, null);
        currentRoles.clear();
    }

    private void resizeConcepts(int maxConcept) {
        final IConceptSet[] oldData = data;

        CONCEPTS = maxConcept + 1;
        data = new IConceptSet[(CONCEPTS * ROLES) << 1];
        System.arraycopy(oldData, 0, data, 0, oldData.length);
    }

    private void resizeRoles(int maxRole) {
        final int OLD_ROLES = ROLES;
        final IConceptSet[] oldData = data;

        ROLES = maxRole + 1;
        data = new IConceptSet[(CONCEPTS * ROLES) << 1];
        for (int c = 0; c < CONCEPTS; c++) {
            for (int r = 0; r < OLD_ROLES; r++) {
                final int newI = ((c * ROLES) + r) << 1;
                final int oldI = ((c * OLD_ROLES) + r) << 1;
                data[newI] = oldData[oldI];
                data[newI + 1] = oldData[oldI + 1];
            }
        }
    }

    public void grow(int newTotalConcepts) {
        resizeConcepts(newTotalConcepts);
    }

    public String toString() {
        final StringBuilder sb = new StringBuilder();
        boolean separator = false;

        for (int index = 0; index < data.length; index += 2) {
            if (null != data[index]) {
                if (separator) {
                    sb.append(", ");
                }
                final int hash = index >> 1;
                int r = (int) Math.IEEEremainder(hash, ROLES);
                int A = (hash - r) / ROLES;

                sb.append(A).append(" [ ").append(r).append(".")
                        .append(data[index]);

                separator = true;
            }
        }

        return sb.toString();
    }

}
TOP

Related Classes of au.csiro.snorocket.core.AR

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.