354 lines
11 KiB
Python
354 lines
11 KiB
Python
# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import unittest
|
|
|
|
from paddle.jit.sot.opcode_translator.executor.mutable_data import (
|
|
MutableData,
|
|
MutableDictLikeData,
|
|
MutableListLikeData,
|
|
)
|
|
|
|
|
|
class VariableBase:
|
|
def __init__(self): ...
|
|
|
|
|
|
class ConstVariable(VariableBase):
|
|
def __init__(self, value):
|
|
self.value = value
|
|
|
|
def __repr__(self):
|
|
return f"ConstVariable({self.value})"
|
|
|
|
def __eq__(self, other):
|
|
if not isinstance(other, ConstVariable):
|
|
return False
|
|
return self.value == other.value
|
|
|
|
|
|
class DictVariable(VariableBase):
|
|
def __init__(self, data):
|
|
self.data = data
|
|
self.proxy = MutableDictLikeData(data, DictVariable.proxy_getter)
|
|
|
|
@staticmethod
|
|
def proxy_getter(proxy, key):
|
|
if key not in proxy.original_data:
|
|
return MutableData.Empty()
|
|
return ConstVariable(proxy.original_data[key])
|
|
|
|
def getitem(self, key):
|
|
res = self.proxy.get(key)
|
|
if isinstance(res, MutableData.Empty):
|
|
raise KeyError(f"Key {key} not found")
|
|
return res
|
|
|
|
def setitem(self, key, value):
|
|
self.proxy.set(key, value)
|
|
|
|
def delitem(self, key):
|
|
self.proxy.delete(key)
|
|
|
|
|
|
class ListVariable(VariableBase):
|
|
def __init__(self, data):
|
|
self.data = data
|
|
self.proxy = MutableListLikeData(data, ListVariable.proxy_getter)
|
|
|
|
@staticmethod
|
|
def proxy_getter(proxy, key):
|
|
if key < 0 or key >= len(proxy.original_data):
|
|
return MutableData.Empty()
|
|
return ConstVariable(proxy.original_data[key])
|
|
|
|
def getitem(self, key):
|
|
if isinstance(key, int):
|
|
res = self.proxy.get(key)
|
|
if isinstance(res, MutableData.Empty):
|
|
raise IndexError(f"Index {key} out of range")
|
|
return res
|
|
elif isinstance(key, slice):
|
|
return self.proxy.get_all()[key]
|
|
else:
|
|
raise TypeError(f"Invalid key type {type(key)}")
|
|
|
|
def __getitem__(self, key):
|
|
return self.getitem(key)
|
|
|
|
def setitem(self, key, value):
|
|
if isinstance(key, int):
|
|
self.proxy.set(key, value)
|
|
elif isinstance(key, slice):
|
|
start, end, step = key.indices(self.proxy.length)
|
|
indices = list(range(start, end, step))
|
|
if step == 1:
|
|
# replace a continuous range
|
|
for i, idx in enumerate(indices):
|
|
self.proxy.delete(idx - i)
|
|
for i, item in enumerate(value):
|
|
self.proxy.insert(start + i, item)
|
|
else:
|
|
# replace some elements
|
|
if len(indices) != len(value):
|
|
raise ValueError(
|
|
f"Attempt to replace {len(indices)} items with {len(value)}"
|
|
)
|
|
for i, idx in enumerate(indices):
|
|
self.proxy.set(idx, value[i])
|
|
|
|
def delitem(self, key):
|
|
self.proxy.delete(key)
|
|
|
|
def insert(self, index, value):
|
|
self.proxy.insert(index, value)
|
|
|
|
def append(self, value):
|
|
self.proxy.insert(self.proxy.length, value)
|
|
|
|
def extend(self, value):
|
|
for item in value:
|
|
self.append(item)
|
|
|
|
def pop(self, index=-1):
|
|
res = self.getitem(index)
|
|
self.delitem(index)
|
|
return res
|
|
|
|
def clear(self):
|
|
for i in range(self.proxy.length):
|
|
self.delitem(0)
|
|
|
|
def remove(self, value):
|
|
for i in range(self.proxy.length):
|
|
if self.getitem(i) == value:
|
|
self.delitem(i)
|
|
return
|
|
raise ValueError(f"Value {value} not found")
|
|
|
|
def sort(self, key=None, reverse=False):
|
|
if key is None:
|
|
key = lambda x: x
|
|
permutation = list(range(self.proxy.length))
|
|
permutation.sort(
|
|
key=lambda x: key(self.getitem(x).value), reverse=reverse
|
|
)
|
|
self.proxy.permutate(permutation)
|
|
|
|
def reverse(self):
|
|
permutation = list(range(self.proxy.length))
|
|
permutation.reverse()
|
|
self.proxy.permutate(permutation)
|
|
|
|
|
|
class TestMutableDictLikeVariable(unittest.TestCase):
|
|
def test_getitem(self):
|
|
data = {"a": 1, "b": 2}
|
|
var = DictVariable(data)
|
|
self.assertEqual(var.getitem("a"), ConstVariable(1))
|
|
self.assertEqual(var.getitem("b"), ConstVariable(2))
|
|
|
|
def test_setitem(self):
|
|
data = {"a": 1, "b": 2}
|
|
var = DictVariable(data)
|
|
var.setitem("a", ConstVariable(3))
|
|
self.assertEqual(var.getitem("a"), ConstVariable(3))
|
|
var.setitem("c", ConstVariable(4))
|
|
self.assertEqual(var.getitem("c"), ConstVariable(4))
|
|
|
|
def test_delitem(self):
|
|
data = {"a": 1, "b": 2}
|
|
var = DictVariable(data)
|
|
var.delitem("a")
|
|
with self.assertRaises(KeyError):
|
|
var.getitem("a")
|
|
|
|
def test_keys(self):
|
|
data = {"a": 1, "b": 2}
|
|
var = DictVariable(data)
|
|
self.assertEqual(list(var.proxy.get_all().keys()), ["a", "b"])
|
|
|
|
|
|
class TestMutableListLikeVariable(unittest.TestCase):
|
|
def test_getitem(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
self.assertEqual(var.getitem(0), ConstVariable(1))
|
|
self.assertEqual(var.getitem(1), ConstVariable(2))
|
|
self.assertEqual(var.getitem(2), ConstVariable(3))
|
|
|
|
def test_getitem_slice_1(self):
|
|
data = [1, 2, 3, 4, 5, 6, 7]
|
|
var = ListVariable(data)
|
|
self.assertEqual(
|
|
var.getitem(slice(0, 3)),
|
|
[ConstVariable(1), ConstVariable(2), ConstVariable(3)],
|
|
)
|
|
self.assertEqual(
|
|
var.getitem(slice(4, 1, -1)),
|
|
[ConstVariable(5), ConstVariable(4), ConstVariable(3)],
|
|
)
|
|
self.assertEqual(
|
|
var.getitem(slice(1, 5, 2)),
|
|
[ConstVariable(2), ConstVariable(4)],
|
|
)
|
|
|
|
def test_getitem_slice_2(self):
|
|
data = [1, 2, 3, 4, 5, 6, 7]
|
|
var = ListVariable(data)
|
|
self.assertEqual(
|
|
var[0:3],
|
|
[ConstVariable(1), ConstVariable(2), ConstVariable(3)],
|
|
)
|
|
self.assertEqual(
|
|
var[4:1:-1],
|
|
[ConstVariable(5), ConstVariable(4), ConstVariable(3)],
|
|
)
|
|
self.assertEqual(
|
|
var[1:5:2],
|
|
[ConstVariable(2), ConstVariable(4)],
|
|
)
|
|
|
|
def test_setitem(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
var.setitem(0, ConstVariable(4))
|
|
self.assertEqual(var.getitem(0), ConstVariable(4))
|
|
var.append(ConstVariable(5))
|
|
self.assertEqual(var.getitem(3), ConstVariable(5))
|
|
|
|
def test_setitem_slice_1(self):
|
|
data = [1, 2, 3, 4, 5, 6, 7]
|
|
var = ListVariable(data)
|
|
var.setitem(slice(0, 3), [ConstVariable(4), ConstVariable(5)])
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [4, 5, 4, 5, 6, 7]],
|
|
)
|
|
var.setitem(
|
|
slice(4, 1, -1),
|
|
[ConstVariable(8), ConstVariable(9), ConstVariable(10)],
|
|
)
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [4, 5, 10, 9, 8, 7]],
|
|
)
|
|
|
|
def test_setitem_slice_2(self):
|
|
data = [1, 2, 3, 4, 5, 6, 7]
|
|
var = ListVariable(data)
|
|
var.setitem(slice(2, 5, 2), [ConstVariable(8), ConstVariable(9)])
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [1, 2, 8, 4, 9, 6, 7]],
|
|
)
|
|
|
|
def test_delitem(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
var.delitem(0)
|
|
with self.assertRaises(IndexError):
|
|
var.getitem(2)
|
|
var.pop()
|
|
with self.assertRaises(IndexError):
|
|
var.getitem(1)
|
|
|
|
def test_insert(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
var.insert(0, ConstVariable(4))
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [4, 1, 2, 3]],
|
|
)
|
|
var.insert(2, ConstVariable(5))
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [4, 1, 5, 2, 3]],
|
|
)
|
|
|
|
def test_append(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
var.append(ConstVariable(4))
|
|
self.assertEqual(var.getitem(3), ConstVariable(4))
|
|
|
|
def test_extend(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
var.extend([ConstVariable(4), ConstVariable(5)])
|
|
self.assertEqual(var.getitem(3), ConstVariable(4))
|
|
self.assertEqual(var.getitem(4), ConstVariable(5))
|
|
|
|
def test_pop(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
self.assertEqual(var.pop(), ConstVariable(3))
|
|
self.assertEqual(var.pop(0), ConstVariable(1))
|
|
|
|
def test_clear(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
var.clear()
|
|
self.assertEqual(var.proxy.length, 0)
|
|
|
|
def test_remove(self):
|
|
data = [1, 2, 3]
|
|
var = ListVariable(data)
|
|
var.remove(ConstVariable(2))
|
|
self.assertEqual(var.getitem(0), ConstVariable(1))
|
|
self.assertEqual(var.getitem(1), ConstVariable(3))
|
|
with self.assertRaises(ValueError):
|
|
var.remove(ConstVariable(2))
|
|
|
|
def test_sort(self):
|
|
data = [2, 3, 0, 4, 1, 5]
|
|
var = ListVariable(data)
|
|
var.sort()
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [0, 1, 2, 3, 4, 5]],
|
|
)
|
|
|
|
def test_sort_with_key(self):
|
|
data = [-1, -4, 2, 0, 5, -3]
|
|
var = ListVariable(data)
|
|
var.sort(key=lambda x: x**2)
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [0, -1, 2, -3, -4, 5]],
|
|
)
|
|
|
|
def test_sort_reverse(self):
|
|
data = [2, 3, 0, 4, 1, 5]
|
|
var = ListVariable(data)
|
|
var.sort(reverse=True)
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [5, 4, 3, 2, 1, 0]],
|
|
)
|
|
|
|
def test_reverse(self):
|
|
data = [2, 3, 0, 4, 1, 5]
|
|
var = ListVariable(data)
|
|
var.reverse()
|
|
self.assertEqual(
|
|
[var.getitem(i) for i in range(var.proxy.length)],
|
|
[ConstVariable(n) for n in [5, 1, 4, 0, 3, 2]],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|