/** * (C) Copyright IBM Corp. 2010, 2015 * * 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. *  */ package com.ibm.bi.dml.hops.globalopt.gdfgraph; import java.util.ArrayList; import com.ibm.bi.dml.hops.AggUnaryOp; import com.ibm.bi.dml.hops.DataGenOp; import com.ibm.bi.dml.hops.Hop; import com.ibm.bi.dml.hops.Hop.DataGenMethod; import com.ibm.bi.dml.hops.Hop.Direction; import com.ibm.bi.dml.hops.Hop.FileFormatTypes; import com.ibm.bi.dml.hops.Hop.OpOp1; import com.ibm.bi.dml.hops.Hop.ReOrgOp; import com.ibm.bi.dml.hops.ReorgOp; import com.ibm.bi.dml.hops.UnaryOp; import com.ibm.bi.dml.parser.Expression.DataType; import com.ibm.bi.dml.runtime.controlprogram.Program; import com.ibm.bi.dml.runtime.controlprogram.ProgramBlock; import com.ibm.bi.dml.runtime.controlprogram.parfor.util.IDSequence; /** * The reason of a custom graph structure is to unify both within DAG * and cross DAG enumeration. Conceptually, we would only need interesting * properties of transient reads and could compile locally. * * Furthermore, having a global graph structure also allows for more advanced * algebraic simplification rewrites because the semantics of transient read * inputs are always available. * */ public class GDFNode { public enum NodeType{ HOP_NODE, LOOP_NODE, CROSS_BLOCK_NODE, } private static IDSequence _seqID = new IDSequence(); protected NodeType _type = null; protected long _ID = -1; //references to original program and hop dag protected Hop _hop = null; protected ProgramBlock _pb = null; //input nodes protected ArrayList<GDFNode> _inputs = null; public GDFNode() { _ID = _seqID.getNextID(); } public GDFNode( Hop hop, ProgramBlock pb, ArrayList<GDFNode> inputs ) { this(); _type = NodeType.HOP_NODE; _hop = hop; _pb = pb; _inputs = inputs; } public NodeType getNodeType() { return _type; } public long getID() { return _ID; } public Hop getHop() { return _hop; } public ProgramBlock getProgramBlock() { return _pb; } public Program getProgram() { if( _pb != null ) return _pb.getProgram(); return null; } public ArrayList<GDFNode> getInputs() { return _inputs; } public DataType getDataType() { return _hop.getDataType(); } /** * If the output or any input is a matrix we need to consider * MR configurations. This for examples excludes Literals or * any purely scalar operation. * * @return */ public boolean requiresMREnumeration() { //general rule: MR generation required if at least one matrix input/output boolean ret = (_hop.getDataType() == DataType.MATRIX); for( Hop c : _hop.getInput() ) ret |= (c.getDataType() == DataType.MATRIX); //special cases of CP-only operators if( _hop instanceof UnaryOp && ((UnaryOp)_hop).getOp()==OpOp1.CAST_AS_SCALAR ) //as.scalar ret = false; if( _hop instanceof DataGenOp && ((DataGenOp)_hop).getOp()==DataGenMethod.SINIT ) //matrix(str, ) ret = false; if( _hop instanceof UnaryOp && ((UnaryOp)_hop).getOp()==OpOp1.NROW ) //nrow - meta data only ret = false; if( _hop instanceof UnaryOp && ((UnaryOp)_hop).getOp()==OpOp1.NCOL ) //ncol - meta data only ret = false; return ret; } /** * * @param format * @return */ public boolean isValidInputFormatForOperation( FileFormatTypes format ) { return ( _hop instanceof UnaryOp && format!=FileFormatTypes.CSV || (_hop instanceof AggUnaryOp && ((AggUnaryOp)_hop).getDirection()==Direction.RowCol && format!=FileFormatTypes.CSV) || (_hop instanceof ReorgOp && ((ReorgOp)_hop).getOp()==ReOrgOp.TRANSPOSE && format!=FileFormatTypes.CSV) || format==FileFormatTypes.BINARY ); //any op } /** * * @param deps * @return */ public String explain(String deps) { String ldeps = (deps!=null) ? deps : ""; //node details if( _hop!=null ) return "Node "+ldeps+" ["+_hop.getHopID()+", "+_hop.getOpString()+"]"; else return "Node "+ldeps+" [null]"; } }