Отношения между специальными векторами в питоне - PullRequest
0 голосов
/ 27 августа 2018

Мне интересно, есть ли способ установить связь между какими-то особыми "векторами".

Пример:

Предположим, это мои векторы (я выберу только 3 специальных вектора):

   a=[1,2,[1]]
   b=[1,2,[2]]
   c=[1,3,[1]]

и я хочу добавить следующие правила при их сравнении (лексикографический порядок):

Я хочу сказать, что

   a<b 

потому что

  a[0]=b[0] and a[1]=b[1] but *a[2]<b[2]*

но я тоже хочу сказать

  a<c

потому что

  a[0]=b[0] and a[1]<c[1] and a[2]<=c[2]

но обратите внимание, что вещи немного отличаются для "b" и "c", поскольку они несопоставимы, потому что даже если

  b[0]=c[0] and b[1]<c[1], the last term changes everything since b[2]>c[2]

Другими словами, правила, которые я применяю, сначала сравнивают «нормальные» записи двух векторов x и y, если определенная запись вектора x больше определенной записи вектора y, мы посмотрим на последняя запись Если последняя запись вектора x больше Or равна, то мы говорим x> y, если это не так, то x и y несопоставимы.

В случае, если все «нормальные» записи x и y совпадают, мы сравниваем последнюю запись. Если последняя запись x больше последней записи y, мы также говорим x> y.

Я думаю, что это связано с циклом while.

Ответы [ 2 ]

0 голосов
/ 27 августа 2018

Вы можете сделать vector подклассом list и перегрузить методы __lt__ и __gt__, чтобы последний элемент проверялся перед поведением по умолчанию. Также перегружайте методы __le__ и __ge__ для полноты:

class vector(list):
    def __lt__(self, other):
        lt = super().__lt__(other)
        if lt and self[-1] > other[-1]:
            return False
        return lt
    def __gt__(self, other):
        gt = super().__gt__(other)
        if gt and self[-1] < other[-1]:
            return False
        return gt
    def __le__(self, other):
        if self == other:
            return True
        return self < other
    def __ge__(self, other):
        if self == other:
            return True
        return self > other

так что:

a=vector([1,2,[1]])
b=vector([1,2,[2]])
c=vector([1,3,[1]])
print(a<b)
print(a<c)
print(b<c)
print(c<b)
print(b>c)
print(c>b)
print(b<=c)
print(c<=b)

выведет:

True
True
False
False
False
False
False
False

РЕДАКТИРОВАТЬ : В свете комментариев, сделанных ниже, я также хотел бы отметить, что это тот случай, когда functools.total_ordering не работает из-за нетипичной логики, требуемой ОП, где один объект может быть не меньше, не больше и не равен другому одновременно.

Поэтому, если мы определим только метод __lt__ для класса vector и применим декоратор total_ordering:

from functools import total_ordering
@total_ordering
class vector(list):
    def __lt__(self, other):
        lt = super().__lt__(other)
        if lt and self[-1] > other[-1]:
            return False
        return lt

Тестовый код, приведенный выше, выдаст следующий неправильный вывод:

True
True
False
False
False
True
True
False
0 голосов
/ 27 августа 2018

Вы можете легко написать функцию для выполнения того, что вы описали.

def special_lt(vec1, vec2):

Вы определили «нормальные» значения как все, кроме последнего, и «специальные» значения как последние, так что это просто:

    normal1, normal2 = vec1[:-1], vec2[:-1]
    special1, special2 = vec1[-1], vec2[-1]

Теперь, если я правильно понимаю, вы хотите провести лексикографическое сравнение нормальных значений, а затем перейти к специальным значениям, если они равны ...

    if normal1 == normal2:
        return special1 < special2

… но в противном случае используйте специальные значения в качестве проверки, чтобы убедиться, что они упорядочены так же, как нормальные значения:

    elif normal1 < normal2:
        if special1 <= special2:
            return True
        raise ValueError('not comparable')
    else:
        if special2 <= special1:
            return False
        raise ValueError('not comparable')

Обратите внимание, что для сравнения списков нормальных значений и списков специальных значений я не использовал цикл; Я просто сравнил списки. Это связано с тем, что списки уже сравниваются лексикографически (что, конечно, внутренне выполняется с помощью цикла, но мне не нужно его писать).

...