org.apache.sysml.hops.rewrite.HopRewriteUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of systemml Show documentation
Show all versions of systemml Show documentation
Declarative Machine Learning
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.sysml.hops.rewrite;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.sysml.api.DMLScript;
import org.apache.sysml.api.DMLScript.RUNTIME_PLATFORM;
import org.apache.sysml.hops.AggBinaryOp;
import org.apache.sysml.hops.AggUnaryOp;
import org.apache.sysml.hops.BinaryOp;
import org.apache.sysml.hops.DataOp;
import org.apache.sysml.hops.Hop;
import org.apache.sysml.hops.Hop.AggOp;
import org.apache.sysml.hops.Hop.DataGenMethod;
import org.apache.sysml.hops.DataGenOp;
import org.apache.sysml.hops.Hop.DataOpTypes;
import org.apache.sysml.hops.Hop.Direction;
import org.apache.sysml.hops.Hop.FileFormatTypes;
import org.apache.sysml.hops.Hop.OpOp2;
import org.apache.sysml.hops.Hop.ParamBuiltinOp;
import org.apache.sysml.hops.Hop.ReOrgOp;
import org.apache.sysml.hops.Hop.VisitStatus;
import org.apache.sysml.hops.HopsException;
import org.apache.sysml.hops.LeftIndexingOp;
import org.apache.sysml.hops.LiteralOp;
import org.apache.sysml.hops.MemoTable;
import org.apache.sysml.hops.ParameterizedBuiltinOp;
import org.apache.sysml.hops.ReorgOp;
import org.apache.sysml.hops.UnaryOp;
import org.apache.sysml.hops.Hop.OpOp1;
import org.apache.sysml.parser.DataExpression;
import org.apache.sysml.parser.DataIdentifier;
import org.apache.sysml.parser.Statement;
import org.apache.sysml.parser.Expression.DataType;
import org.apache.sysml.parser.Expression.ValueType;
import org.apache.sysml.runtime.DMLRuntimeException;
import org.apache.sysml.runtime.instructions.cp.BooleanObject;
import org.apache.sysml.runtime.instructions.cp.DoubleObject;
import org.apache.sysml.runtime.instructions.cp.IntObject;
import org.apache.sysml.runtime.instructions.cp.ScalarObject;
import org.apache.sysml.runtime.instructions.cp.StringObject;
import org.apache.sysml.runtime.util.UtilFunctions;
public class HopRewriteUtils
{
/**
*
* @param op
* @return
*/
public static boolean isValueTypeCast( OpOp1 op )
{
return ( op == OpOp1.CAST_AS_BOOLEAN
|| op == OpOp1.CAST_AS_INT
|| op == OpOp1.CAST_AS_DOUBLE );
}
//////////////////////////////////
// literal handling
/**
*
* @param op
* @return
* @throws HopsException
*/
public static boolean getBooleanValue( LiteralOp op )
throws HopsException
{
switch( op.getValueType() )
{
case DOUBLE: return op.getDoubleValue() != 0;
case INT: return op.getLongValue() != 0;
case BOOLEAN: return op.getBooleanValue();
default: throw new HopsException("Invalid boolean value: "+op.getValueType());
}
}
public static boolean getBooleanValueSafe( LiteralOp op )
{
try
{
switch( op.getValueType() )
{
case DOUBLE: return op.getDoubleValue() != 0;
case INT: return op.getLongValue() != 0;
case BOOLEAN: return op.getBooleanValue();
default: throw new HopsException("Invalid boolean value: "+op.getValueType());
}
}
catch(Exception ex){
//silently ignore error
}
return false;
}
/**
*
* @param op
* @return
* @throws HopsException
*/
public static double getDoubleValue( LiteralOp op )
throws HopsException
{
switch( op.getValueType() )
{
case DOUBLE: return op.getDoubleValue();
case INT: return op.getLongValue();
case BOOLEAN: return op.getBooleanValue() ? 1 : 0;
default: throw new HopsException("Invalid double value: "+op.getValueType());
}
}
/**
*
* @param op
* @return
*/
public static double getDoubleValueSafe( LiteralOp op )
{
try
{
switch( op.getValueType() )
{
case DOUBLE: return op.getDoubleValue();
case INT: return op.getLongValue();
case BOOLEAN: return op.getBooleanValue() ? 1 : 0;
default: throw new HopsException("Invalid double value: "+op.getValueType());
}
}
catch(Exception ex){
//silently ignore error
}
return Double.MAX_VALUE;
}
/**
* Return the int value of a LiteralOp (as a long).
*
* Note: For comparisons, this is *only* to be used in situations
* in which the value is absolutely guaranteed to be an integer.
* Otherwise, a safer alternative is `getDoubleValue`.
*/
public static long getIntValue( LiteralOp op )
throws HopsException
{
switch( op.getValueType() )
{
case DOUBLE: return UtilFunctions.toLong(op.getDoubleValue());
case INT: return op.getLongValue();
case BOOLEAN: return op.getBooleanValue() ? 1 : 0;
default: throw new HopsException("Invalid int value: "+op.getValueType());
}
}
/**
*
* @param op
* @return
*/
public static long getIntValueSafe( LiteralOp op )
{
try
{
switch( op.getValueType() )
{
case DOUBLE: return UtilFunctions.toLong(op.getDoubleValue());
case INT: return op.getLongValue();
case BOOLEAN: return op.getBooleanValue() ? 1 : 0;
default:
throw new RuntimeException("Invalid int value: "+op.getValueType());
}
}
catch(Exception ex){
//silently ignore error
}
return Long.MAX_VALUE;
}
/**
*
* @param op
* @return
* @throws HopsException
*/
public static ScalarObject getScalarObject( LiteralOp op )
{
ScalarObject ret = null;
try
{
switch( op.getValueType() )
{
case DOUBLE: ret = new DoubleObject(op.getDoubleValue()); break;
case INT: ret = new IntObject(op.getLongValue()); break;
case BOOLEAN: ret = new BooleanObject(op.getBooleanValue()); break;
case STRING: ret = new StringObject(op.getStringValue()); break;
default:
throw new DMLRuntimeException("Invalid scalar object value type: "+op.getValueType());
}
}
catch(Exception ex)
{
throw new RuntimeException("Failed to create scalar object for constant. Continue.", ex);
}
return ret;
}
///////////////////////////////////
// hop dag transformations
public static int getChildReferencePos( Hop parent, Hop child )
{
ArrayList childs = parent.getInput();
return childs.indexOf(child);
}
public static void removeChildReference( Hop parent, Hop child )
{
//remove child reference
parent.getInput().remove( child );
child.getParent().remove( parent );
}
public static void removeChildReferenceByPos( Hop parent, Hop child, int posChild )
{
//remove child reference
parent.getInput().remove( posChild );
child.getParent().remove( parent );
}
public static void removeChildReferenceByPos( Hop parent, Hop child, int posChild, int posParent )
{
//remove child reference
parent.getInput().remove( posChild );
child.getParent().remove( posParent );
}
public static void removeAllChildReferences( Hop parent )
{
//remove parent reference from all childs
for( Hop child : parent.getInput() )
child.getParent().remove(parent);
//remove all child references
parent.getInput().clear();
}
public static void addChildReference( Hop parent, Hop child )
{
parent.getInput().add( child );
child.getParent().add( parent );
}
public static void addChildReference( Hop parent, Hop child, int pos )
{
parent.getInput().add( pos, child );
child.getParent().add( parent );
}
/**
*
* @param input
* @param value
* @return
* @throws HopsException
*/
public static Hop createDataGenOp( Hop input, double value )
throws HopsException
{
Hop rows = (input.getDim1()>0) ? new LiteralOp(input.getDim1()) :
new UnaryOp("tmprows", DataType.SCALAR, ValueType.INT, OpOp1.NROW, input);
Hop cols = (input.getDim2()>0) ? new LiteralOp(input.getDim2()) :
new UnaryOp("tmpcols", DataType.SCALAR, ValueType.INT, OpOp1.NCOL, input);
Hop val = new LiteralOp(value);
HashMap params = new HashMap();
params.put(DataExpression.RAND_ROWS, rows);
params.put(DataExpression.RAND_COLS, cols);
params.put(DataExpression.RAND_MIN, val);
params.put(DataExpression.RAND_MAX, val);
params.put(DataExpression.RAND_PDF, new LiteralOp(DataExpression.RAND_PDF_UNIFORM));
params.put(DataExpression.RAND_LAMBDA, new LiteralOp(-1.0));
params.put(DataExpression.RAND_SPARSITY, new LiteralOp(1.0));
params.put(DataExpression.RAND_SEED, new LiteralOp(DataGenOp.UNSPECIFIED_SEED) );
//note internal refresh size information
Hop datagen = new DataGenOp(DataGenMethod.RAND, new DataIdentifier("tmp"), params);
datagen.setRowsInBlock(input.getRowsInBlock());
datagen.setColsInBlock(input.getColsInBlock());
if( value==0 )
datagen.setNnz(0);
return datagen;
}
/**
* Assumes that min and max are literal ops, needs to be checked from outside.
*
* @param inputGen
* @param scale
* @param intercept
* @return
* @throws HopsException
*/
public static DataGenOp copyDataGenOp( DataGenOp inputGen, double scale, double shift )
throws HopsException
{
HashMap params = inputGen.getParamIndexMap();
Hop rows = inputGen.getInput().get(params.get(DataExpression.RAND_ROWS));
Hop cols = inputGen.getInput().get(params.get(DataExpression.RAND_COLS));
Hop min = inputGen.getInput().get(params.get(DataExpression.RAND_MIN));
Hop max = inputGen.getInput().get(params.get(DataExpression.RAND_MAX));
Hop pdf = inputGen.getInput().get(params.get(DataExpression.RAND_PDF));
Hop mean = inputGen.getInput().get(params.get(DataExpression.RAND_LAMBDA));
Hop sparsity = inputGen.getInput().get(params.get(DataExpression.RAND_SPARSITY));
Hop seed = inputGen.getInput().get(params.get(DataExpression.RAND_SEED));
//check for literal ops
if( !(min instanceof LiteralOp) || !(max instanceof LiteralOp))
return null;
//scale and shift
double smin = getDoubleValue((LiteralOp) min);
double smax = getDoubleValue((LiteralOp) max);
smin = smin * scale + shift;
smax = smax * scale + shift;
Hop sminHop = new LiteralOp(smin);
Hop smaxHop = new LiteralOp(smax);
HashMap params2 = new HashMap();
params2.put(DataExpression.RAND_ROWS, rows);
params2.put(DataExpression.RAND_COLS, cols);
params2.put(DataExpression.RAND_MIN, sminHop);
params2.put(DataExpression.RAND_MAX, smaxHop);
params2.put(DataExpression.RAND_PDF, pdf);
params2.put(DataExpression.RAND_LAMBDA, mean);
params2.put(DataExpression.RAND_SPARSITY, sparsity);
params2.put(DataExpression.RAND_SEED, seed );
//note internal refresh size information
DataGenOp datagen = new DataGenOp(DataGenMethod.RAND, new DataIdentifier("tmp"), params2);
datagen.setRowsInBlock(inputGen.getRowsInBlock());
datagen.setColsInBlock(inputGen.getColsInBlock());
if( smin==0 && smax==0 ) {
datagen.setNnz(0);
}
return datagen;
}
public static Hop createDataGenOp( Hop rowInput, Hop colInput, double value )
throws HopsException
{
Hop rows = (rowInput.getDim1()>0) ? new LiteralOp(rowInput.getDim1()) :
new UnaryOp("tmprows", DataType.SCALAR, ValueType.INT, OpOp1.NROW, rowInput);
Hop cols = (colInput.getDim2()>0) ? new LiteralOp(colInput.getDim2()) :
new UnaryOp("tmpcols", DataType.SCALAR, ValueType.INT, OpOp1.NCOL, colInput);
Hop val = new LiteralOp(value);
HashMap params = new HashMap();
params.put(DataExpression.RAND_ROWS, rows);
params.put(DataExpression.RAND_COLS, cols);
params.put(DataExpression.RAND_MIN, val);
params.put(DataExpression.RAND_MAX, val);
params.put(DataExpression.RAND_PDF, new LiteralOp(DataExpression.RAND_PDF_UNIFORM));
params.put(DataExpression.RAND_LAMBDA, new LiteralOp(-1.0));
params.put(DataExpression.RAND_SPARSITY, new LiteralOp(1.0));
params.put(DataExpression.RAND_SEED, new LiteralOp(DataGenOp.UNSPECIFIED_SEED) );
//note internal refresh size information
Hop datagen = new DataGenOp(DataGenMethod.RAND, new DataIdentifier("tmp"), params);
datagen.setRowsInBlock(rowInput.getRowsInBlock());
datagen.setColsInBlock(colInput.getColsInBlock());
if( value==0 )
datagen.setNnz(0);
return datagen;
}
public static Hop createDataGenOp( Hop rowInput, boolean tRowInput, Hop colInput, boolean tColInput, double value )
throws HopsException
{
long nrow = tRowInput ? rowInput.getDim2() : rowInput.getDim1();
long ncol = tColInput ? colInput.getDim1() : rowInput.getDim2();
Hop rows = (nrow>0) ? new LiteralOp(nrow) :
new UnaryOp("tmprows", DataType.SCALAR, ValueType.INT, tRowInput?OpOp1.NCOL:OpOp1.NROW, rowInput);
Hop cols = (ncol>0) ? new LiteralOp(ncol) :
new UnaryOp("tmpcols", DataType.SCALAR, ValueType.INT, tColInput?OpOp1.NROW:OpOp1.NCOL, colInput);
Hop val = new LiteralOp(value);
HashMap params = new HashMap();
params.put(DataExpression.RAND_ROWS, rows);
params.put(DataExpression.RAND_COLS, cols);
params.put(DataExpression.RAND_MIN, val);
params.put(DataExpression.RAND_MAX, val);
params.put(DataExpression.RAND_PDF, new LiteralOp(DataExpression.RAND_PDF_UNIFORM));
params.put(DataExpression.RAND_LAMBDA,new LiteralOp(-1.0));
params.put(DataExpression.RAND_SPARSITY, new LiteralOp(1.0));
params.put(DataExpression.RAND_SEED, new LiteralOp(DataGenOp.UNSPECIFIED_SEED) );
//note internal refresh size information
Hop datagen = new DataGenOp(DataGenMethod.RAND, new DataIdentifier("tmp"), params);
datagen.setRowsInBlock(rowInput.getRowsInBlock());
datagen.setColsInBlock(colInput.getColsInBlock());
if( value==0 )
datagen.setNnz(0);
return datagen;
}
public static Hop createDataGenOpByVal( Hop rowInput, Hop colInput, double value )
throws HopsException
{
Hop val = new LiteralOp(value);
HashMap params = new HashMap();
params.put(DataExpression.RAND_ROWS, rowInput);
params.put(DataExpression.RAND_COLS, colInput);
params.put(DataExpression.RAND_MIN, val);
params.put(DataExpression.RAND_MAX, val);
params.put(DataExpression.RAND_PDF, new LiteralOp(DataExpression.RAND_PDF_UNIFORM));
params.put(DataExpression.RAND_LAMBDA, new LiteralOp(-1.0));
params.put(DataExpression.RAND_SPARSITY, new LiteralOp(1.0));
params.put(DataExpression.RAND_SEED, new LiteralOp(DataGenOp.UNSPECIFIED_SEED) );
//note internal refresh size information
Hop datagen = new DataGenOp(DataGenMethod.RAND, new DataIdentifier("tmp"), params);
datagen.setRowsInBlock(rowInput.getRowsInBlock());
datagen.setColsInBlock(colInput.getColsInBlock());
if( value==0 )
datagen.setNnz(0);
return datagen;
}
/**
*
* @param input
* @return
*/
public static ReorgOp createTranspose(Hop input) {
return createReorg(input, ReOrgOp.TRANSPOSE);
}
/**
*
* @param input
* @param rop
* @return
*/
public static ReorgOp createReorg(Hop input, ReOrgOp rop)
{
ReorgOp transpose = new ReorgOp(input.getName(), input.getDataType(), input.getValueType(), rop, input);
HopRewriteUtils.setOutputBlocksizes(transpose, input.getRowsInBlock(), input.getColsInBlock());
HopRewriteUtils.copyLineNumbers(input, transpose);
transpose.refreshSizeInformation();
return transpose;
}
/**
*
* @param input
* @param type
* @return
* @throws HopsException
*/
public static UnaryOp createUnary(Hop input, OpOp1 type)
throws HopsException
{
UnaryOp unary = new UnaryOp(input.getName(), input.getDataType(), input.getValueType(), type, input);
HopRewriteUtils.setOutputBlocksizes(unary, input.getRowsInBlock(), input.getColsInBlock());
HopRewriteUtils.copyLineNumbers(input, unary);
unary.refreshSizeInformation();
return unary;
}
/**
*
* @param input
* @return
*/
public static BinaryOp createMinus(Hop input)
{
BinaryOp minus = new BinaryOp(input.getName(), input.getDataType(), input.getValueType(), OpOp2.MINUS, new LiteralOp(0), input);
HopRewriteUtils.setOutputBlocksizes(minus, input.getRowsInBlock(), input.getColsInBlock());
HopRewriteUtils.copyLineNumbers(input, minus);
minus.refreshSizeInformation();
return minus;
}
/**
*
* @param input1
* @param input2
* @param op
* @return
*/
public static BinaryOp createBinary(Hop input1, Hop input2, OpOp2 op)
{
BinaryOp bop = new BinaryOp(input1.getName(), input1.getDataType(),
input1.getValueType(), op, input1, input2);
HopRewriteUtils.setOutputBlocksizes(bop, input1.getRowsInBlock(), input1.getColsInBlock());
HopRewriteUtils.copyLineNumbers(input1, bop);
bop.refreshSizeInformation();
return bop;
}
/**
*
* @param input
* @return
*/
public static AggUnaryOp createSum( Hop input ) {
return createAggUnaryOp(input, AggOp.SUM, Direction.RowCol);
}
/**
*
* @param input
* @param op
* @param dir
* @return
*/
public static AggUnaryOp createAggUnaryOp( Hop input, AggOp op, Direction dir )
{
DataType dt = (dir==Direction.RowCol) ? DataType.SCALAR : input.getDataType();
AggUnaryOp auop = new AggUnaryOp(input.getName(), dt, input.getValueType(), op, dir, input);
auop.setRowsInBlock(input.getRowsInBlock());
auop.setColsInBlock(input.getColsInBlock());
auop.refreshSizeInformation();
return auop;
}
/**
*
* @param left
* @param right
* @return
*/
public static AggBinaryOp createMatrixMultiply(Hop left, Hop right)
{
AggBinaryOp mmult = new AggBinaryOp(left.getName(), left.getDataType(), left.getValueType(), OpOp2.MULT, AggOp.SUM, left, right);
mmult.setRowsInBlock(left.getRowsInBlock());
mmult.setColsInBlock(right.getColsInBlock());
mmult.refreshSizeInformation();
return mmult;
}
public static Hop createValueHop( Hop hop, boolean row )
throws HopsException
{
Hop ret = null;
if( row ){
ret = (hop.getDim1()>0) ? new LiteralOp(hop.getDim1()) :
new UnaryOp("tmprows", DataType.SCALAR, ValueType.INT, OpOp1.NROW, hop);
}
else{
ret = (hop.getDim2()>0) ? new LiteralOp(hop.getDim2()) :
new UnaryOp("tmpcols", DataType.SCALAR, ValueType.INT, OpOp1.NCOL, hop);
}
return ret;
}
public static DataGenOp createSeqDataGenOp( Hop input )
throws HopsException
{
return createSeqDataGenOp(input, true);
}
public static DataGenOp createSeqDataGenOp( Hop input, boolean asc )
throws HopsException
{
Hop to = (input.getDim1()>0) ? new LiteralOp(input.getDim1()) :
new UnaryOp("tmprows", DataType.SCALAR, ValueType.INT, OpOp1.NROW, input);
HashMap params = new HashMap();
if( asc ) {
params.put(Statement.SEQ_FROM, new LiteralOp(1));
params.put(Statement.SEQ_TO, to);
params.put(Statement.SEQ_INCR, new LiteralOp(1));
}
else {
params.put(Statement.SEQ_FROM, to);
params.put(Statement.SEQ_TO, new LiteralOp(1));
params.put(Statement.SEQ_INCR, new LiteralOp(-1));
}
//note internal refresh size information
DataGenOp datagen = new DataGenOp(DataGenMethod.SEQ, new DataIdentifier("tmp"), params);
datagen.setRowsInBlock(input.getRowsInBlock());
datagen.setColsInBlock(input.getColsInBlock());
return datagen;
}
public static void setOutputBlocksizes( Hop hop, long brlen, long bclen )
{
hop.setRowsInBlock( brlen );
hop.setColsInBlock( bclen );
}
public static void setOutputParameters( Hop hop, long rlen, long clen, long brlen, long bclen, long nnz )
{
hop.setDim1( rlen );
hop.setDim2( clen );
hop.setRowsInBlock( brlen );
hop.setColsInBlock( bclen );
hop.setNnz( nnz );
}
public static void setOutputParametersForScalar( Hop hop )
{
hop.setDim1( 0 );
hop.setDim2( 0 );
hop.setRowsInBlock( -1 );
hop.setColsInBlock( -1 );
hop.setNnz( -1 );
}
public static void refreshOutputParameters( Hop hnew, Hop hold )
{
hnew.setDim1( hold.getDim1() );
hnew.setDim2( hold.getDim2() );
hnew.setRowsInBlock(hold.getRowsInBlock());
hnew.setColsInBlock(hold.getColsInBlock());
hnew.refreshSizeInformation();
}
public static void copyLineNumbers( Hop src, Hop dest )
{
dest.setAllPositions(src.getBeginLine(), src.getBeginColumn(), src.getEndLine(), src.getEndColumn());
}
/**
*
* @param hop
* @param brlen
* @param bclen
* @param src
*/
public static void updateHopCharacteristics( Hop hop, long brlen, long bclen, Hop src )
{
updateHopCharacteristics(hop, brlen, bclen, new MemoTable(), src);
}
/**
*
* @param hop
* @param brlen
* @param bclen
* @param memo
* @param src
*/
public static void updateHopCharacteristics( Hop hop, long brlen, long bclen, MemoTable memo, Hop src )
{
//update block sizes and dimensions
setOutputBlocksizes(hop, brlen, bclen);
hop.refreshSizeInformation();
//compute memory estimates (for exec type selection)
hop.computeMemEstimate(memo);
//update line numbers
HopRewriteUtils.copyLineNumbers(src, hop);
}
///////////////////////////////////
// hop size information
public static boolean isDimsKnown( Hop hop )
{
return ( hop.getDim1()>0 && hop.getDim2()>0 );
}
public static boolean isEmpty( Hop hop )
{
return ( hop.getNnz()==0 );
}
public static boolean isEqualSize( Hop hop1, Hop hop2 )
{
return (hop1.dimsKnown() && hop2.dimsKnown()
&& hop1.getDim1() == hop2.getDim1()
&& hop1.getDim2() == hop2.getDim2());
}
/**
*
* @param hop
* @return
*/
public static boolean isSingleBlock( Hop hop ) {
return isSingleBlock(hop, true)
&& isSingleBlock(hop, false);
}
/**
* Checks our BLOCKSIZE CONSTRAINT, w/ awareness of forced single node
* execution mode.
*
* @param hop
* @param cols
* @return
*/
public static boolean isSingleBlock( Hop hop, boolean cols )
{
//awareness of forced exec single node (e.g., standalone), where we can
//guarantee a single block independent of the size because always in CP.
if( DMLScript.rtplatform == RUNTIME_PLATFORM.SINGLE_NODE ) {
return true;
}
//check row- or column-wise single block constraint
return cols ? (hop.getDim2()>0 && hop.getDim2()<=hop.getColsInBlock())
: (hop.getDim1()>0 && hop.getDim1()<=hop.getRowsInBlock());
}
public static boolean isEqualValue( LiteralOp hop1, LiteralOp hop2 )
throws HopsException
{
//check for string (no defined double value)
if( hop1.getValueType()==ValueType.STRING
|| hop2.getValueType()==ValueType.STRING )
{
return false;
}
double val1 = getDoubleValue(hop1);
double val2 = getDoubleValue(hop2);
return ( val1 == val2 );
}
public static boolean isNotMatrixVectorBinaryOperation( Hop hop )
{
boolean ret = true;
if( hop instanceof BinaryOp )
{
BinaryOp bop = (BinaryOp) hop;
Hop left = bop.getInput().get(0);
Hop right = bop.getInput().get(1);
boolean mv = (left.getDim1()>1 && right.getDim1()==1)
|| (left.getDim2()>1 && right.getDim2()==1);
ret = isDimsKnown(bop) && !mv;
}
return ret;
}
/**
*
* @param hop
* @return
*/
public static boolean isTransposeOperation(Hop hop)
{
return (hop instanceof ReorgOp && ((ReorgOp)hop).getOp()==ReOrgOp.TRANSPOSE);
}
/**
*
* @param hop1
* @param hop2
* @return
*/
public static boolean isTransposeOfItself(Hop hop1, Hop hop2)
{
return hop1 instanceof ReorgOp && ((ReorgOp)hop1).getOp()==ReOrgOp.TRANSPOSE && hop1.getInput().get(0) == hop2
|| hop2 instanceof ReorgOp && ((ReorgOp)hop2).getOp()==ReOrgOp.TRANSPOSE && hop2.getInput().get(0) == hop1;
}
/**
*
* @param pred
* @param hop
* @return
*/
public static boolean isNonZeroIndicator(Hop pred, Hop hop )
{
if( pred instanceof BinaryOp && ((BinaryOp)pred).getOp()==OpOp2.NOTEQUAL
&& pred.getInput().get(0) == hop //depend on common subexpression elimination
&& pred.getInput().get(1) instanceof LiteralOp
&& HopRewriteUtils.getDoubleValueSafe((LiteralOp)pred.getInput().get(1))==0 )
{
return true;
}
return false;
}
/**
*
* @param hop
* @return
*/
public static boolean isFullColumnIndexing(LeftIndexingOp hop)
{
boolean colPred = hop.getColLowerEqualsUpper(); //single col
Hop rl = hop.getInput().get(2);
Hop ru = hop.getInput().get(3);
return colPred && rl instanceof LiteralOp && getDoubleValueSafe((LiteralOp)rl)==1
&& ru instanceof LiteralOp && getDoubleValueSafe((LiteralOp)ru)==hop.getDim1();
}
/**
*
* @param hop
* @return
*/
public static boolean isFullRowIndexing(LeftIndexingOp hop)
{
boolean rowPred = hop.getRowLowerEqualsUpper(); //single row
Hop cl = hop.getInput().get(4);
Hop cu = hop.getInput().get(5);
return rowPred && cl instanceof LiteralOp && getDoubleValueSafe((LiteralOp)cl)==1
&& cu instanceof LiteralOp && getDoubleValueSafe((LiteralOp)cu)==hop.getDim2();
}
/**
*
* @param hop
* @return
*/
public static boolean isBasic1NSequence(Hop hop)
{
boolean ret = false;
if( hop instanceof DataGenOp )
{
DataGenOp dgop = (DataGenOp) hop;
if( dgop.getOp() == DataGenMethod.SEQ ){
Hop from = dgop.getInput().get(dgop.getParamIndex(Statement.SEQ_FROM));
Hop incr = dgop.getInput().get(dgop.getParamIndex(Statement.SEQ_INCR));
ret = (from instanceof LiteralOp && getDoubleValueSafe((LiteralOp)from)==1)
&&(incr instanceof LiteralOp && getDoubleValueSafe((LiteralOp)incr)==1);
}
}
return ret;
}
/**
*
* @param hop
* @return
*/
public static boolean isBasicN1Sequence(Hop hop)
{
boolean ret = false;
if( hop instanceof DataGenOp )
{
DataGenOp dgop = (DataGenOp) hop;
if( dgop.getOp() == DataGenMethod.SEQ ){
Hop to = dgop.getInput().get(dgop.getParamIndex(Statement.SEQ_TO));
Hop incr = dgop.getInput().get(dgop.getParamIndex(Statement.SEQ_INCR));
ret = (to instanceof LiteralOp && getDoubleValueSafe((LiteralOp)to)==1)
&&(incr instanceof LiteralOp && getDoubleValueSafe((LiteralOp)incr)==-1);
}
}
return ret;
}
/**
*
* @param hop
* @return
* @throws HopsException
*/
public static double getBasic1NSequenceMax(Hop hop)
throws HopsException
{
if( hop instanceof DataGenOp )
{
DataGenOp dgop = (DataGenOp) hop;
if( dgop.getOp() == DataGenMethod.SEQ ){
Hop to = dgop.getInput().get(dgop.getParamIndex(Statement.SEQ_TO));
if( to instanceof LiteralOp )
return getDoubleValueSafe((LiteralOp)to);
}
}
throw new HopsException("Failed to retrieve 'to' argument from basic 1-N sequence.");
}
/**
*
* @param hop
* @return
* @throws HopsException
*/
public static LiteralOp getBasic1NSequenceMaxLiteral(Hop hop)
throws HopsException
{
if( hop instanceof DataGenOp )
{
DataGenOp dgop = (DataGenOp) hop;
if( dgop.getOp() == DataGenMethod.SEQ ){
Hop to = dgop.getInput().get(dgop.getParamIndex(Statement.SEQ_TO));
if( to instanceof LiteralOp )
return (LiteralOp)to;
}
}
throw new HopsException("Failed to retrieve 'to' argument from basic 1-N sequence.");
}
/**
*
* @param hop
* @param inclTransient
* @param inclPersistent
* @return
*/
public static boolean hasOnlyWriteParents( Hop hop, boolean inclTransient, boolean inclPersistent )
{
boolean ret = true;
ArrayList parents = hop.getParent();
for( Hop p : parents )
{
if( inclTransient && inclPersistent )
ret &= ( p instanceof DataOp && (((DataOp)p).getDataOpType()==DataOpTypes.TRANSIENTWRITE
|| ((DataOp)p).getDataOpType()==DataOpTypes.PERSISTENTWRITE));
else if(inclTransient)
ret &= ( p instanceof DataOp && ((DataOp)p).getDataOpType()==DataOpTypes.TRANSIENTWRITE);
else if(inclPersistent)
ret &= ( p instanceof DataOp && ((DataOp)p).getDataOpType()==DataOpTypes.PERSISTENTWRITE);
}
return ret;
}
/**
*
* @param hop
* @return
*/
public static boolean hasTransformParents( Hop hop )
{
boolean ret = false;
ArrayList parents = hop.getParent();
for( Hop p : parents )
{
if( p instanceof ParameterizedBuiltinOp
&& ((ParameterizedBuiltinOp)p).getOp()==ParamBuiltinOp.TRANSFORM) {
ret = true;
}
}
return ret;
}
/**
*
* @param hop
* @return
*/
public static boolean alwaysRequiresReblock(Hop hop)
{
return ( hop instanceof DataOp
&& ((DataOp)hop).getDataOpType()==DataOpTypes.PERSISTENTREAD
&& ((DataOp)hop).getInputFormatType()!=FileFormatTypes.BINARY);
}
/**
*
* @param root
* @param var
* @return
*/
public static boolean rHasSimpleReadChain(Hop root, String var)
{
if( root.getVisited()==VisitStatus.DONE )
return false;
boolean ret = false;
//handle leaf node for variable
if( root instanceof DataOp && ((DataOp)root).isRead()
&& root.getName().equals(var) )
{
ret = (root.getParent().size()<=1);
}
//recursively process childs (on the entire path to var, all
//intermediates are supposed to have at most one consumer, but
//side-ways inputs can have arbitrary dag structures)
for( Hop c : root.getInput() ) {
if( rHasSimpleReadChain(c, var) )
ret |= root.getParent().size()<=1;
}
root.setVisited(Hop.VisitStatus.DONE);
return ret;
}
/**
*
* @param root
* @param var
* @param includeMetaOp
* @return
*/
public static boolean rContainsRead(Hop root, String var, boolean includeMetaOp)
{
if( root.getVisited()==VisitStatus.DONE )
return false;
boolean ret = false;
//handle leaf node for variable
if( root instanceof DataOp && ((DataOp)root).isRead()
&& root.getName().equals(var) )
{
boolean onlyMetaOp = true;
if( !includeMetaOp ){
for( Hop p : root.getParent() ) {
onlyMetaOp &= (p instanceof UnaryOp
&& (((UnaryOp)p).getOp()==OpOp1.NROW
|| ((UnaryOp)p).getOp()==OpOp1.NCOL) );
}
ret = !onlyMetaOp;
}
else
ret = true;
}
//recursively process childs
for( Hop c : root.getInput() )
ret |= rContainsRead(c, var, includeMetaOp);
root.setVisited(Hop.VisitStatus.DONE);
return ret;
}
//////////////////////////////////////
// utils for lookup tables
public static boolean isValidOp( AggOp input, AggOp[] validTab )
{
for( AggOp valid : validTab )
if( valid == input )
return true;
return false;
}
public static boolean isValidOp( OpOp1 input, OpOp1[] validTab )
{
for( OpOp1 valid : validTab )
if( valid == input )
return true;
return false;
}
public static boolean isValidOp( OpOp2 input, OpOp2[] validTab )
{
for( OpOp2 valid : validTab )
if( valid == input )
return true;
return false;
}
public static boolean isValidOp( ReOrgOp input, ReOrgOp[] validTab )
{
for( ReOrgOp valid : validTab )
if( valid == input )
return true;
return false;
}
public static int getValidOpPos( OpOp2 input, OpOp2[] validTab )
{
for( int i=0; i