int childInitStages[] = new int[getNumChildren()];     int childInitDataNeeded[] = new int[getNumChildren() + 1];    int numChildrenForInit = 0;
    public void computeSchedule()    {        int steadyChildPhases[] = new int[getNumChildren()];        // first compute schedules for all my children        {            int nChild;            for (nChild = 0; nChild < getNumChildren(); nChild++)            {                StreamInterface child = getHierarchicalChild(nChild);                // compute child's schedule                child.computeSchedule();                // get the # of phases that this child needs to have executed                // to complete a steady state schedule                steadyChildPhases[nChild] =                    child.getNumSteadyPhases() * getChildNumExecs(nChild);            }        }        // compute the minimal amount of data necessary in buffers        // after the initialization has taken place        // this is a little tricky - for every child I need to figure out        // exactly how many times I will run it in the init schedule        // including the child's steady-state phases that I'll run to fill        // up the buffers        // store how many init stages and steady-state phases each child will         // need to be executed in order to provide enough data for the steady        // state        int childInitStages[] = new int[getNumChildren()];        // store how many data each child will need in the process of         // initialization        // extra element here is just to simplify the algorithm        int childInitDataNeeded[] = new int[getNumChildren() + 1];        // number of children that HAVE TO execute at least one init stage        // (that includes their own init-stages)        int numChildrenForInit = 0;        // find out how much each child needs to be executed in order to        // process all of the init functions        {            int nChild;            for (nChild = getNumChildren() - 1; nChild >= 0; nChild--)            {                StreamInterface child = getHierarchicalChild(nChild);                childInitStages[nChild] = child.getNumInitStages();                // first figure out how much data this child pops for                // running just the init stages                int initPop = child.getInitPop();                // and how much extra data is needed due to peeking in                 // init and steady state                int initPeek =                    MAX(                        child.getInitPeek() - child.getInitPop(),                        child.getSteadyPeek() - child.getSteadyPop());                int initPush = child.getInitPush();                int nPhase = 0;                // does the next child need more data?                while (initPush < childInitDataNeeded[nChild + 1])                {                    // yes                    // execute another phase                    PhasingSchedule initStage =                        getChildInitStage(child, childInitStages[nChild]);                    childInitStages[nChild]++;                    initPush += initStage.getOverallPush();                    // and don't forget that this means that                     // this child may need more data!                    initPeek =                        MAX(                            initPeek - initStage.getOverallPop(),                            initStage.getOverallPeek()                                - initStage.getOverallPop());                    initPop += initStage.getOverallPop();                    // next phase                    nPhase = (nPhase + 1) % child.getNumSteadyPhases();                }                // store this child's needs for init data                childInitDataNeeded[nChild] = initPop + initPeek;                numChildrenForInit += (childInitStages[nChild] != 0 ? 1 : 0);            }        }        // amount of data in buffers.  Each entry corresponds to the buffer        // ABOVE the correspondingly numbered buffer (dataInBuffers[0] is above        // the pipeline).  The last buffer obviously is the buffer right below        // the last child, which is just below the pipeline.        int dataInBuffers[] = new int[getNumChildren() + 1];        // create the initialization schedule        // The intialization schedule is created by executing the bottom-most        // child, and pulling the data from upper children accordingly.        // This is repeated until all children have had at least        // childInitStages worth of stages or phases executed.  Reasoning for        // this is in my (karczma) notebook, date 02/07/14.        // here I'll force pulling data all the way        // this is necessary because I haven't calculated exactly        // how many times every filter will need to get executed,        // and I want to preserve the pull semantics of this schedule        computeMinLatencySchedule(            new PipelineInitSchedulingUtility(this),            childInitStages,            dataInBuffers,            true);        // here I'll allow the schedule to simply execute the children        // however many times I told it to - this should satisfy the        // pull semantics, because it's a steady schedule, and the        // init schedule is a pull schedule!        computeMinLatencySchedule(            new PipelineSteadySchedulingUtility(this),            steadyChildPhases,            dataInBuffers,            false);    }