package ec.gp.semantic;

/**
 * @author Tomasz Pawlak
 */
public interface ISemantics extends Cloneable, Comparable<ISemantics>, Iterable {

    public Object getValue();

    ISemantics clone();

    ISemantics getMidpointBetweenMeAnd(ISemantics other);

    Object getValue(int fitnessCase);

    /**
     * Determines if this semantics is on the segment under Minkowski metric Lp, for given p > 0, between two other
     * semantics.
     *
     * @param semantics1
     * @param semantics2
     * @param p
     * @return
     */
    boolean isBetween(ISemantics semantics1, ISemantics semantics2, double p);

    /**
     * Determines if any component of this semantics is smaller than the corresponding component of the other semantics.
     *
     * @param other
     * @return
     */
    boolean isAnyComponentSmallerThan(ISemantics other);

    /**
     * Determines if any component of this semantics is bigger than the corresponding component of the other semantics.
     *
     * @param other
     * @return
     */
    boolean isAnyComponentBiggerThan(ISemantics other);

    /**
     * Determines if semantics has the same value for each fitness case.
     *
     * @return
     */
    boolean isConstant();

    /**
     * Calculates minimum of each component of this and other semantics.
     *
     * @param other
     * @return
     */
    ISemantics min(ISemantics other);

    /**
     * Calculates maximum of each component of this and other semantics.
     *
     * @param other
     * @return
     */
    ISemantics max(ISemantics other);


    /**
     * Calculates Minkowski distance Lp, for a given p.
     *
     * @param other
     * @param p
     * @return
     */
    double distanceTo(ISemantics other, double p);

    /**
     * Calculates Minkowski distance Lp, for a given p, without calculating the root. I.e. the monotonicity would be
     * maintained, however the absolute value not.
     *
     * @param other
     * @param p
     * @return
     */
    double fastDistanceTo(ISemantics other, double p);

    /**
     * Calculates distance according to the 'default' metric for a given domain.
     *
     * @param other
     * @return
     */
    double distanceTo(ISemantics other);

    /**
     * Calculates distance according to the 'default' metric for a given domain, without calculating the root. I.e. the
     * monotonicity would be maintained, however the absolute value not.
     *
     * @param other
     * @return
     */
    double fastDistanceTo(ISemantics other);

    /**
     * Calculates distance of this semantics to the segment appointed by starting and ending points. The distance metric
     * is Manhattan metric.
     *
     * @param startingPoint
     * @param endingPoint
     * @return
     */
    double distanceToManhattanSegment(ISemantics startingPoint, ISemantics endingPoint);

    /**
     * Calculates semantics that is counterpoint of given semantics w.r.t. this semantics. Assuming a metric d, the
     * counterpoint fulfills the equation d(other, this) + d(this, calculated) = d(other, calculated).
     *
     * @param other
     * @return
     */
    ISemantics counterpointTo(ISemantics other);

    /**
     * Returns value indicating that semantics has all values set and fixed to a certain value, i.e. NaN and Infinite
     * are not allowed for doubles.
     *
     * @return
     */
    boolean isWellDefined();

    int size();
}
