def __init__(self, graph, inflowRate, numberOfIntervals, outputDirectory,
                 templateFile, scipFile, cleanUpBool, timeout):
        """
        :param graph: Networkx Digraph instance
        :param inflowRate: u_0
        :param numberOfIntervals: number of intervals that will be computed. -1 if all
        :param outputDirectory: path where output should be saved
        :param templateFile: Selected method, i.e. 0,1,2
        :param scipFile: path to scip binary
        :param cleanUpBool: If true, then cleanup
        :param timeout: seconds until timeout. Deactivated if equal to 0
        """

        self.network = graph.copy()
        self.inflowRate = inflowRate  # For the moment: constant
        self.numberOfIntervals = numberOfIntervals  # No. of intervals to compute
        self.outputDirectory = outputDirectory

        # Template File from /source/templates
        self.templateFile = os.path.join(
            os.getcwd(), 'source', 'templates',
            'algorithm_' + str(templateFile + 1) + '.zpl')
        self.allInOne = (templateFile == 1)
        self.advancedAlgo = (
            templateFile == 2
        )  # If true, then advanced backtracking with preprocessing is performed

        self.scipFile = scipFile
        self.cleanUpBool = cleanUpBool
        self.numberOfSolvedIPs = 0
        self.computationalTime = 0
        self.infinityReached = False  # True if last interval has alpha = +inf
        self.timeout = timeout

        self.minCapacity = Utilities.compute_min_attr_of_network(self.network)
        self.counter = 0
        self.preprocessedNodes = 0
        self.preprocessedEdges = 0

        # Create directory for Nash-Flow
        self.rootPath = os.path.join(self.outputDirectory,
                                     'NashFlow-' + Utilities.get_time())
        Utilities.create_dir(self.rootPath)

        self.flowIntervals = [
        ]  # List containing triplets of form (lowerBound, upperBound, FlowInterval-instance)
        self.lowerBoundsToIntervalDict = OrderedDict()
        self.animationIntervals = {edge: [] for edge in self.network.edges()}
    def compute_NTF(self):
        """Computes NTF in current tab"""
        originalNetwork = self.gttr('network')
        network = deepcopy(originalNetwork)
        # Remove inactive edges from network
        inactiveEdges = [
            edge for edge in originalNetwork.edges()
            if not originalNetwork[edge[0]][edge[1]]['TFC']['active']
        ]
        network.remove_edges_from(inactiveEdges)
        # Remove nodes that are now no longer reachable
        L = []
        for (v, d) in network.in_degree():
            if d == 0 and v != 's':
                # Non-reachable node found
                L.append(v)
        network.remove_nodes_from(L)

        # Validate input
        returnCode = self.validate_thinflow_input(network)
        if returnCode != 0:
            # Invalid input has been given
            # Spawn warning
            QtWidgets.QMessageBox.question(QtWidgets.QWidget(),
                                           'Abort: Input error',
                                           self.get_error_message(returnCode),
                                           QtWidgets.QMessageBox.Ok)
            return

        # Drop current NTF plot
        self.re_init_NTF_frame()

        # Get necessary data
        resettingEdges = [
            edge for edge in network.edges()
            if network[edge[0]][edge[1]]['TFC']['resettingEnabled']
        ]
        lowerBoundTime = 0  # No needed for different times as only one flowInterval is being computed
        inflowRate = float(self.inflowLineEdit.text())
        minCapacity = Utilities.compute_min_attr_of_network(network)
        counter = "Standalone"
        rootPath = self.outputDirectory
        self.templateFile = self.templateComboBox.currentIndex()

        if self.currentTF == 'general':
            templateFile = os.path.join(
                os.getcwd(), 'templates',
                'algorithm_' + str(self.templateFile + 1) + '.zpl')
        elif self.currentTF == 'spillback':
            print(
                "Note: For spillback only the basic algorithm [1] is available and hence run now."
            )
            templateFile = os.path.join(os.getcwd(), 'templates',
                                        'algorithm_spillback_1.zpl')
        scipFile = self.scipFile
        timeout = float(self.timeoutLineEdit.text())

        self.save_config()

        if self.currentTF == 'general':
            self.interval_general = FlowInterval(network,
                                                 resettingEdges=resettingEdges,
                                                 lowerBoundTime=lowerBoundTime,
                                                 inflowRate=inflowRate,
                                                 minCapacity=minCapacity,
                                                 counter=counter,
                                                 outputDirectory=rootPath,
                                                 templateFile=templateFile,
                                                 scipFile=scipFile,
                                                 timeout=timeout)
        elif self.currentTF == 'spillback':
            fullEdges = []
            minInflowBound = float('inf')
            for e in network.edges():
                (v, w) = e
                minInflowBound = min(minInflowBound,
                                     network[v][w]['TFC']['inflowBound'])
            self.interval_spillback = FlowInterval_spillback(
                network,
                resettingEdges=resettingEdges,
                fullEdges=fullEdges,
                lowerBoundTime=lowerBoundTime,
                inflowRate=inflowRate,
                minCapacity=minCapacity,
                counter=counter,
                outputDirectory=rootPath,
                templateFile=templateFile,
                scipFile=scipFile,
                timeout=timeout,
                minInflowBound=minInflowBound)

        # Set shortest path network manually to entire graph (is the deepcopy really needed?)
        interval = self.gttr('interval')
        interval.shortestPathNetwork = deepcopy(network)
        if self.currentTF == 'spillback':
            interval.transfer_inflowBound(interval.shortestPathNetwork)

        self.advancedAlgo = (
            self.templateFile == 2
        )  # If true, then advanced backtracking with preprocessing is performed

        if self.currentTF == 'general':
            if self.advancedAlgo:
                interval.get_ntf_advanced()
            else:
                interval.get_ntf()
        elif self.currentTF == 'spillback':
            interval.get_ntf()

        self.sttr(
            'plotNTFCanvas', self.currentTF,
            PlotNTFCanvas(
                interval.shortestPathNetwork,
                self,
                intervalID=None,
                stretchFactor=self.plotNTFCanvasStretchFactor,
                showNoFlowEdges=self.showEdgesWithoutFlowCheckBox.isChecked(),
                onlyNTF=True))

        self.gttr('plotNTFFrameLayout').addWidget(self.gttr('plotNTFCanvas'))
        self.cleanup()
    def compute_flowInterval(self):
        """Method to compute a single flowInterval"""
        # Get lowerBoundTime
        lowerBoundTime = 0 if not self.flowIntervals else self.flowIntervals[
            -1][1]
        # Compute resettingEdges
        cmp_queue = lambda v, w, t: \
            Utilities.is_greater_tol(self.node_label(w, t),
                                     self.node_label(v, t) + self.network[v][w]['transitTime'])

        resettingEdges = [(v, w) for v, w in self.network.edges() if cmp_queue(v, w, lowerBoundTime)] \
            if lowerBoundTime > 0 else []

        edges_to_choose_from = self.network.edges(
        )  # Fulledges can be non resetting!
        fullEdges = [(v, w) for v, w in edges_to_choose_from
                     if self.is_full(v, w, self.node_label(v, lowerBoundTime))
                     ] if lowerBoundTime > 0 else []

        minInflowBound = None
        interval = FlowInterval_spillback(self.network,
                                          resettingEdges=resettingEdges,
                                          fullEdges=fullEdges,
                                          lowerBoundTime=lowerBoundTime,
                                          inflowRate=self.inflowRate,
                                          minCapacity=self.minOutCapacity,
                                          counter=self.counter,
                                          outputDirectory=self.rootPath,
                                          templateFile=self.templateFile,
                                          scipFile=self.scipFile,
                                          timeout=self.timeout,
                                          minInflowBound=minInflowBound)

        if lowerBoundTime == 0:
            interval.shortestPathNetwork = Utilities.get_shortest_path_network(
                self.network)  # Compute shortest path network
            for v, w in interval.shortestPathNetwork.edges():
                interval.shortestPathNetwork[v][w][
                    'inflowBound'] = self.network[v][w]['inCapacity']
        else:
            interval.shortestPathNetwork = Utilities.get_shortest_path_network(
                self.network,
                labels={
                    v: self.node_label(v, lowerBoundTime)
                    for v in self.network
                })  # Compute shortest path network

            for v, w in interval.shortestPathNetwork.edges():
                vTimeLower = self.node_label(v, lowerBoundTime)
                minimizer = self.get_outflow(
                    v, w, vTimeLower) if (v, w) in fullEdges else float('inf')
                interval.shortestPathNetwork[v][w]['inflowBound'] = min(
                    minimizer, self.network[v][w]['inCapacity'])

        minInflowBound = Utilities.compute_min_attr_of_network(
            interval.shortestPathNetwork, 'inflowBound')
        interval.set_minInflowBound(minInflowBound)

        start = time.time()
        interval.get_ntf()
        '''
        if self.advancedAlgo:
            interval.get_ntf_advanced()
        else:
            interval.get_ntf()
        '''
        end = time.time()
        self.computationalTime += (end - start)
        interval.computationalTime = end - start
        self.preprocessedNodes += interval.preprocessedNodes
        self.preprocessedEdges += interval.preprocessedEdges
        self.lowerBoundsToIntervalDict[lowerBoundTime] = interval

        if lowerBoundTime == 0:
            self.init_edge_properties()

        interval.compute_alpha({
            node: self.node_label(node, lowerBoundTime)
            for node in self.network
        })
        self.flowIntervals.append(
            (interval.lowerBoundTime, interval.upperBoundTime, interval))

        # Update in/out-flow rates
        self.update_edge_properties(lowerBoundTime, interval)

        self.counter += 1
        self.numberOfSolvedIPs += interval.numberOfSolvedIPs

        self.infinityReached = (interval.alpha == float('inf'))