Change:
In PyTorch master 0.4 , variables cannot be indexed. This used to work in PyTorch 0.2 :
This is breaking some of Pyro's inference algorithms on PyTorch master:

Discussion:
throw std::runtime_error(ss.str()); } <ins> static void checkIndexTensorTypes(TensorList indices) { for (auto& tensor : indices) { if (tensor.defined()) { auto& type = tensor.type(); auto scalarType = type.scalarType(); if (scalarType != kLong && scalarType != kByte) { throw std::runtime_error("tensors used as indices must be long or byte tensors"); } } } } </ins> static std::vector<Tensor> expandByteTensors(const Tensor & self, TensorList indices) { // Expands byte tensors (masks) into the equivalent indexing by LongTensors std::vector<Tensor> result;

} // Replace with nonzeros auto nonzero = index.nonzero(); <del> for (int64_t j = 0; j < nonzero.size(1); j++) { result.emplace_back(nonzero.select(1, j)); </del> <ins> auto is_empty = nonzero.numel() == 0; for (int64_t j = 0; j < index.dim(); j++) { if (is_empty) { // We can't call select on an empty tensor so we just create an empty // tensor. result.emplace_back(nonzero.type().tensor()); } else { result.emplace_back(nonzero.select(1, j)); } </ins> } } else { result.emplace_back(index);

transposedIndices.emplace_back(); } } <del> return std::make_tuple<>(self.permute(dims), std::move(transposedIndices)); </del> <ins> return std::make_tuple(self.permute(dims), std::move(transposedIndices)); </ins> } static std::vector<int64_t> computeLinearStride(const Tensor & tensor) {

return linearIndex; } <ins> static bool hasEmptyTensor(TensorList tensors) { for (auto& tensor : tensors) { if (tensor.defined() && tensor.numel() == 0) { return true; } } return false; } </ins> static std::tuple<Tensor, Tensor> makeLinearIndex(Tensor self, TensorList orig) { <ins> checkIndexTensorTypes(orig); </ins> // first expand ByteTensor (boolean masks) into 1 or more LongTensors auto indices = expandByteTensors(self, orig); <ins> if (hasEmptyTensor(indices)) { return std::make_tuple(self, self.type().toScalarType(kLong).tensor()); } </ins> // next broadcast all index tensors together indices = expand_outplace(indices); // add missing null Tensors so that it matches self.dim()

std::tie(self, indices) = transposeToFront(self, indices); } auto linearIndex = computeLinearIndex(self, indices); <del> return std::make_tuple<>(self, linearIndex); </del> <ins> return std::make_tuple(self, linearIndex); </ins> } Tensor index(const Tensor & self, TensorList indices) {

self.assertEqual(v[mask].shape, (3, 7, 3)) self.assertEqual(v[mask], torch.stack([v[0], v[2], v[3]])) <ins> v = Variable(torch.Tensor([1])) self.assertEqual(v[v == 0], Variable(torch.Tensor())) </ins> def test_multiple_byte_mask(self): v = Variable(torch.randn(5, 7, 3)) # note: these broadcast together and are transposed to the first dim

result = x[rows[:, None], columns] self.assertEqual(result.data.tolist(), [[0, 2], [9, 11]]) <ins> def test_empty_index(self): x = Variable(torch.arange(0, 12).view(4, 3)) idx = Variable(torch.LongTensor()) self.assertEqual(x[idx].numel(), 0) </ins> def test_basic_advanced_combined(self): # From the NumPy indexing example x = Variable(torch.arange(0, 12).view(4, 3))

self.assertEqual(a[()], a) self.assertEqual(a[()].data_ptr(), a.data_ptr()) <del> # @unittest.skip('failing') </del> def test_empty_fancy_index(self): # Empty list index creates an empty array a = tensor([1, 2, 3])