Package com.orientechnologies.orient.graph.sql.functions

Source Code of com.orientechnologies.orient.graph.sql.functions.OSQLFunctionPathFinder

/*
  *
  *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
  *  *
  *  *  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.
  *  *
  *  * For more information: http://www.orientechnologies.com
  *
  */
package com.orientechnologies.orient.graph.sql.functions;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;

import com.orientechnologies.orient.core.command.OCommandContext;
import com.orientechnologies.orient.core.id.ORID;
import com.orientechnologies.orient.core.sql.functions.math.OSQLFunctionMathAbstract;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientBaseGraph;
import com.tinkerpop.blueprints.impls.orient.OrientVertex;

/**
* Abstract class to find paths between nodes.
*
* @author Luca Garulli (l.garulli--at--orientechnologies.com)
*
*/
public abstract class OSQLFunctionPathFinder extends OSQLFunctionMathAbstract {
  protected OrientBaseGraph         db;
  protected Set<OrientVertex>       unSettledNodes;
  protected Map<ORID, OrientVertex> predecessors;
  protected Map<ORID, Float>        distance;

  protected OrientVertex            paramSourceVertex;
  protected OrientVertex            paramDestinationVertex;
  protected Direction               paramDirection = Direction.OUT;
  protected OCommandContext         context;

  protected static final float      MIN            = 0f;

  public OSQLFunctionPathFinder(final String iName, final int iMinParams, final int iMaxParams) {
    super(iName, iMinParams, iMaxParams);
  }

  protected LinkedList<OrientVertex> execute(final OCommandContext iContext) {
    context = iContext;
    unSettledNodes = new HashSet<OrientVertex>();
    distance = new HashMap<ORID, Float>();
    predecessors = new HashMap<ORID, OrientVertex>();
    distance.put(paramSourceVertex.getIdentity(), MIN);
    unSettledNodes.add(paramSourceVertex);

    int maxDistances = 0;
    int maxSettled = 0;
    int maxUnSettled = 0;
    int maxPredecessors = 0;

    while (continueTraversing()) {
      final OrientVertex node = getMinimum(unSettledNodes);
      unSettledNodes.remove(node);
      findMinimalDistances(node);

      if (distance.size() > maxDistances)
        maxDistances = distance.size();
      if (unSettledNodes.size() > maxUnSettled)
        maxUnSettled = unSettledNodes.size();
      if (predecessors.size() > maxPredecessors)
        maxPredecessors = predecessors.size();

      if (!isVariableEdgeWeight() && distance.containsKey(paramDestinationVertex.getIdentity()))
        // FOUND
        break;

      if (!context.checkTimeout())
        break;
    }

    context.setVariable("maxDistances", maxDistances);
    context.setVariable("maxSettled", maxSettled);
    context.setVariable("maxUnSettled", maxUnSettled);
    context.setVariable("maxPredecessors", maxPredecessors);

    distance = null;

    return getPath();
  }

  protected boolean isVariableEdgeWeight() {
    return false;
  }

  /*
   * This method returns the path from the source to the selected target and NULL if no path exists
   */
  public LinkedList<OrientVertex> getPath() {
    final LinkedList<OrientVertex> path = new LinkedList<OrientVertex>();
    OrientVertex step = paramDestinationVertex;
    // Check if a path exists
    if (predecessors.get(step.getIdentity()) == null)
      return null;

    path.add(step);
    while (predecessors.get(step.getIdentity()) != null) {
      step = predecessors.get(step.getIdentity());
      path.add(step);
    }
    // Put it into the correct order
    Collections.reverse(path);
    return path;
  }

  public boolean aggregateResults() {
    return false;
  }

  @Override
  public Object getResult() {
    return getPath();
  }

  protected void findMinimalDistances(final OrientVertex node) {
    for (OrientVertex neighbor : getNeighbors(node)) {
      final float d = sumDistances(getShortestDistance(node), getDistance(node, neighbor));

      if (getShortestDistance(neighbor) > d) {
        distance.put(neighbor.getIdentity(), d);
        predecessors.put(neighbor.getIdentity(), node);
        unSettledNodes.add(neighbor);
      }
    }

  }

  protected Set<OrientVertex> getNeighbors(final Vertex node) {
    context.incrementVariable("getNeighbors");

    final Set<OrientVertex> neighbors = new HashSet<OrientVertex>();
    if (node != null) {
      for (Vertex v : node.getVertices(paramDirection)) {
        final OrientVertex ov = (OrientVertex) v;
        if (ov != null && isNotSettled(ov))
          neighbors.add(ov);
      }
    }
    return neighbors;
  }

  protected OrientVertex getMinimum(final Set<OrientVertex> vertexes) {
    OrientVertex minimum = null;
    Float minimumDistance = null;
    for (OrientVertex vertex : vertexes) {
      if (minimum == null || getShortestDistance(vertex) < minimumDistance) {
        minimum = vertex;
        minimumDistance = getShortestDistance(minimum);
      }
    }
    return minimum;
  }

  protected boolean isNotSettled(final OrientVertex vertex) {
    return unSettledNodes.contains(vertex) || !distance.containsKey(vertex.getIdentity());
  }

  protected boolean continueTraversing() {
    return unSettledNodes.size() > 0;
  }

  protected float getShortestDistance(final OrientVertex destination) {
    if (destination == null)
      return Float.MAX_VALUE;

    final Float d = distance.get(destination.getIdentity());
    return d == null ? Float.MAX_VALUE : d;
  }

  protected float sumDistances(final float iDistance1, final float iDistance2) {
    return iDistance1 + iDistance2;
  }

  protected abstract float getDistance(final OrientVertex node, final OrientVertex target);
}
TOP

Related Classes of com.orientechnologies.orient.graph.sql.functions.OSQLFunctionPathFinder

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.