def test_base_branch(self): node = BaseNode(small_branch.lp, small_branch.integerIndices, -float('inf')) node.bound() idx = 2 rtn = node._base_branch(2) # check each node for name, n in rtn.items(): self.assertTrue( all(n._lp.matrix.elements == node._lp.matrix.elements)) self.assertTrue(all(n._lp.objective == node._lp.objective)) self.assertTrue( all(n._lp.constraintsLower == node._lp.constraintsLower)) self.assertTrue( all(n._lp.constraintsUpper == node._lp.constraintsUpper)) if name == 'down': self.assertTrue(all(n._lp.variablesUpper >= [1e10, 1e10, 1])) self.assertTrue(n._lp.variablesUpper[idx] == 1) self.assertTrue( all(n._lp.variablesLower == node._lp.variablesLower)) else: self.assertTrue( all(n._lp.variablesUpper == node._lp.variablesUpper)) self.assertTrue(all(n._lp.variablesLower == [0, 0, 2])) # check basis statuses work - i.e. are warm started for i in [0, 1]: self.assertTrue( all(node._lp.getBasisStatus()[i] == n._lp.getBasisStatus() [i]), 'bases should match')
def test_base_branch(self): node = BaseNode(small_branch.lp, small_branch.integerIndices) node.bound() idx = 2 out = {next_node_idx: node._base_branch(2, next_node_idx) for next_node_idx in [None, 1]} # confirm current node is no longer a leaf self.assertFalse(node.is_leaf) # check each node for next_node_idx, rtn in out.items(): for name, n in rtn.items(): if name not in ['left', 'right']: continue self.assertTrue(all(n.lp.matrix.elements == node.lp.matrix.elements)) self.assertTrue(all(n.lp.objective == node.lp.objective)) self.assertTrue(all(n.lp.constraintsLower == node.lp.constraintsLower)) self.assertTrue(all(n.lp.constraintsUpper == node.lp.constraintsUpper)) self.assertTrue(n._integer_indices == node._integer_indices) self.assertTrue(n.lower_bound == node.objective_value) self.assertTrue(n._b_idx == idx) self.assertTrue(n._b_val == 1.5) self.assertTrue(n.depth == 1) if name == 'left': self.assertTrue(all(n.lp.variablesUpper == [10, 10, 1])) self.assertTrue(n.lp.variablesUpper[idx] == 1) self.assertTrue(all(n.lp.variablesLower == node.lp.variablesLower)) self.assertTrue(n.lineage == (1, ) if next_node_idx else n.lineage is None) self.assertTrue(n.idx == 1 if next_node_idx else n.idx is None) self.assertTrue(n._b_dir == 'left') else: self.assertTrue(all(n.lp.variablesUpper == node.lp.variablesUpper)) self.assertTrue(all(n.lp.variablesLower == [0, 0, 2])) self.assertTrue(n.lineage == (2,) if next_node_idx else n.lineage is None) self.assertTrue(n.idx == 2 if next_node_idx else n.idx is None) self.assertTrue(n._b_dir == 'right') # check basis statuses work - i.e. are warm started for i in [0, 1]: self.assertTrue(all(node.lp.getBasisStatus()[i] == n.lp.getBasisStatus()[i]), 'bases should match') # check other returns self.assertTrue(rtn['next_node_idx'] == 3 if next_node_idx else rtn['next_node_idx'] is None)
def test_strong_branch(self): iters = 5 node = BaseNode(random.lp, random.integerIndices, 0) node.bound() idx = node._most_fractional_index # test we stay within iters and improve bound/stay same rtn = node._strong_branch(idx, iterations=iters) for direction, child_node in rtn.items(): self.assertTrue(child_node.lp.iteration <= iters) if child_node.lp.getStatusCode() in [0, 3]: self.assertTrue(child_node.lp.objectiveValue >= node.objective_value) # test call base_branch node = BaseNode(random.lp, random.integerIndices) node.bound() idx = node._most_fractional_index children = node._base_branch(idx) with patch.object(node, '_base_branch') as bb: bb.return_value = children rtn = node._strong_branch(idx, iterations=iters) self.assertTrue(bb.called)