def test_evaluate_node_fractional(self):
        bb = BranchAndBound(small_branch,
                            Node=PCBDFSNode,
                            pseudo_costs={},
                            strong_branch_iters=5)
        bb._evaluate_node(bb.root_node)

        # check attributes
        self.assertFalse(bb._best_solution, 'best solution should not change')
        self.assertTrue(bb.global_upper_bound == float('inf'),
                        'shouldnt change')
        self.assertTrue(bb.global_lower_bound > -float('inf'), 'should change')
        self.assertTrue(bb._node_queue.qsize() == 2,
                        'should branch and add two nodes')
        self.assertTrue(bb._kwargs['pseudo_costs'], 'something should be set')
        self.assertTrue(bb._kwargs['strong_branch_iters'],
                        'something should be set')
        self.assertTrue(bb.evaluated_nodes == 1,
                        'only one node should be evaluated')

        # check function calls - recycle object since it has attrs already set
        with patch.object(bb, '_process_rtn') as pr, \
                patch.object(bb, '_process_branch_rtn') as pbr, \
                patch.object(bb.root_node, 'bound') as bd, \
                patch.object(bb.root_node, 'branch') as bh:
            bb._evaluate_node(bb.root_node)
            self.assertTrue(pr.call_count == 1)  # direct calls
            self.assertTrue(pbr.call_count == 1)
            self.assertTrue(0 == pbr.call_args.args[0],
                            'root node id should be first call arg')
            self.assertTrue(bd.call_count == 1)
            self.assertTrue(bh.call_count == 1)
    def test_evaluate_node_infeasible(self):
        bb = BranchAndBound(infeasible)
        bb._evaluate_node(bb.root_node)

        # check attributes
        self.assertTrue(bb._node_queue.empty(),
                        'inf model should create no nodes')
        self.assertFalse(bb._best_solution, 'best solution should not change')
        self.assertTrue(bb.global_upper_bound == float('inf'),
                        'shouldnt change')
        self.assertTrue(bb.global_lower_bound == float('inf'),
                        'shouldnt change')
        self.assertTrue(bb.evaluated_nodes == 1,
                        'only one node should be evaluated')

        # check function calls - recycle object since it has attrs already set
        with patch.object(bb, '_process_rtn') as pr, \
                patch.object(bb, '_process_branch_rtn') as pbr, \
                patch.object(bb.root_node, 'bound') as bd, \
                patch.object(bb.root_node, 'branch') as bh:
            bb._evaluate_node(bb.root_node)
            self.assertTrue(pr.call_count == 1)
            self.assertTrue(pbr.call_count == 0)
            self.assertTrue(bd.call_count == 1)
            self.assertTrue(bh.call_count == 0)
    def test_evaluate_node_unbounded(self):
        bb = BranchAndBound(unbounded)
        bb._evaluate_node(bb.root_node)

        # check attributes
        self.assertTrue(bb._unbounded)
        self.assertTrue(bb.evaluated_nodes == 1,
                        'only one node should be evaluated')
 def test_evaluate_node_properly_prunes(self):
     bb = BranchAndBound(no_branch)
     bb._global_upper_bound = -2
     called_node = BaseNode(bb.model.lp, bb.model.integerIndices, -4)
     pruned_node = BaseNode(bb.model.lp, bb.model.integerIndices, 0)
     with patch.object(called_node, 'bound') as cnb, \
             patch.object(pruned_node, 'bound') as pnb:
         cnb.return_value = {}
         pnb.return_value = {}
         bb._node_queue.put(called_node)
         bb._node_queue.put(pruned_node)
         bb._evaluate_node(bb._node_queue.get())
         bb._evaluate_node(bb._node_queue.get())
         self.assertTrue(cnb.call_count == 1, 'first node should run')
         self.assertFalse(pnb.call_count, 'second node should get pruned')
         self.assertTrue(bb._node_queue.empty())
    def test_evaluate_node_integer(self):
        bb = BranchAndBound(no_branch)
        bb._evaluate_node(bb._root_node)

        # check attributes
        self.assertTrue(all(bb._best_solution == [1, 1, 0]))
        self.assertTrue(bb._global_upper_bound == -2)
        self.assertTrue(bb._node_queue.empty(),
                        'immediately optimal model should create no nodes')

        # check function calls - recycle object since it has attrs already set
        with patch.object(bb, '_process_rtn') as pr, \
                patch.object(bb, '_process_branch_rtn') as pbr, \
                patch.object(bb._root_node, 'bound') as bd, \
                patch.object(bb._root_node, 'branch') as bh:
            bb._evaluate_node(bb._root_node)
            self.assertTrue(pr.call_count == 1)
            self.assertTrue(pbr.call_count == 0)
            self.assertTrue(bd.call_count == 1)
            self.assertTrue(bh.call_count == 0)
    def test_evaluate_node_fractional(self):
        bb = BranchAndBound(small_branch, Node=PCBDFSNode)
        bb._evaluate_node(bb._root_node)

        # check attributes
        self.assertFalse(bb._best_solution, 'best solution should not change')
        self.assertTrue(bb._global_upper_bound == float('inf'),
                        'shouldnt change')
        self.assertTrue(bb._node_queue.qsize() == 2,
                        'should branch and add two nodes')
        self.assertTrue(bb._pseudo_costs, 'something should be set')

        # check function calls - recycle object since it has attrs already set
        with patch.object(bb, '_process_rtn') as pr, \
                patch.object(bb, '_process_branch_rtn') as pbr, \
                patch.object(bb._root_node, 'bound') as bd, \
                patch.object(bb._root_node, 'branch') as bh:
            bb._evaluate_node(bb._root_node)
            self.assertTrue(pr.call_count == 1)  # direct calls
            self.assertTrue(pbr.call_count == 1)
            self.assertTrue(bd.call_count == 1)
            self.assertTrue(bh.call_count == 1)
    def test_evaluate_node_unbounded(self):
        bb = BranchAndBound(unbounded)
        bb._evaluate_node(bb._root_node)

        # check attributes
        self.assertTrue(bb._unbounded)