private void AddEdge(
            LayeredGraph graph,
            int fromIntervalIdx,
            int fromStateIdx,
            int toStateIdx)
        {
            int fromRow = fromIntervalIdx;

            if (this.instance.StateDiagramTime[fromStateIdx][toStateIdx].HasValue == false)
            {
                // No valid transition from one state to another.
                return;
            }

            // Transition to the next interval if from state is the same as to state (similarly with power consumption).
            int transitionTime = fromStateIdx == toStateIdx ?
                                 1
                : this.instance.StateDiagramTime[fromStateIdx][toStateIdx].Value;

            var toRow = fromRow + transitionTime;

            if (toRow >= graph.RowsCount)
            {
                // Transition outside of the intervals range.
                return;
            }

            int powerConsumption = fromStateIdx == toStateIdx
                ? this.instance.StatePowerConsumption[fromStateIdx]
                : this.instance.StateDiagramPowerConsumption[fromStateIdx][toStateIdx].Value;

            var weight = this.instance.TotalEnergyCost(
                fromIntervalIdx,
                fromIntervalIdx + transitionTime - 1,
                powerConsumption);

            graph.AddEdge(fromRow, fromStateIdx, toRow, toStateIdx, weight);
        }
        private LayeredGraph ConstructFullGraph()
        {
            var graph = new LayeredGraph(
                this.instance.States.Length,
                this.instance.Intervals.Length);

            // Inner edges.
            for (int fromIntervalIdx = 0; fromIntervalIdx < this.instance.Intervals.Length; fromIntervalIdx++)
            {
                if (fromIntervalIdx == 0)
                {
                    // Only edge between base off from interval 0 to interval 1.
                    this.AddEdge(
                        graph,
                        fromIntervalIdx,
                        this.instance.BaseOffStateIdx,
                        this.instance.BaseOffStateIdx);
                    continue;
                }

                for (int fromStateIdx = 0; fromStateIdx < this.instance.States.Length; fromStateIdx++)
                {
                    for (int toStateIdx = 0; toStateIdx < this.instance.States.Length; toStateIdx++)
                    {
                        this.AddEdge(graph, fromIntervalIdx, fromStateIdx, toStateIdx);
                    }
                }
            }

            // Edge to sink from the last base off state.
            graph.AddEdgeToSink(
                this.instance.Intervals.Length - 1,
                this.instance.BaseOffStateIdx,
                this.instance.Intervals.Last().EnergyCost *this.instance.OffPowerConsumption[this.instance.BaseOffStateIdx]);

            return(graph);
        }