Преобразовать транзитивную функцию из Python в Racket

#python #racket #relation

#python #racket #отношение

Вопрос:

Я хотел бы реализовать эту функцию в Racket. Как я мог переписать эту функцию в Racket?

Мой КОД НА PYTHON

 # function to check transitive relation
def is_transitive(relation):
    # for all (a, b) and (b, c) in Relation ; (a, c) must belong to Relation
    for a,b in relation:
        for c,d in relation:
            if b == c and ((a,d) not in relation):
                return False
    return True
  

transitive? принимает список пар в качестве единственного входного сигнала. Этот список пар представляет двоичное отношение. Функция должна возвращать #t , если это двоичное отношение является транзитивным, как показано ниже.

 > (transitive? '((1 2) (2 3) (1 3)))
#t
> (transitive? '((1 3) (1 2) (2 3)))
#t
> (transitive? '((1 2) (2 3)))
#f
> (transitive? '((1 1) (1 2) (2 1) (2 2) (3 3)))
#t
> (transitive? '((1 2) (3 3) (2 2) (2 1) (1 1)))
#t
> (transitive? '((2 3) (3 3) (1 2) (1 1)))
#f
  

Вот что у меня есть в Racket до сих пор:

 (define (get-all-relations-of x set)
  (if (null? set)
      '()
      (if (equal? x (car (car set)))
          (cons (cdr (car set))
                (get-all-relations-of x (cdr set)))
          (get-all-relations-of x (cdr set)))))
    
(define (exist-relation? r set)
  (if (null? set)
      #f
      (if (equal? r (car set))
          #t
          (exist-relation? r (cdr set)))))
    
(define (exist-all-transitive-relations-of? x r set)
  (if (null? r)
      #t
      (if (not (exist-relation? (cons x (car r)) set))
          #f
          (exist-all-transitive-relations-of? x (cdr r) set))))
    
(define (transitive? set)
  (if (null? set)
      #t
      (if (and (not (null? (get-all-relations-of (cdr (car set)) set)))
               (not (exist-all-transitive-relations-of?
                     (car (car set))
                     (get-all-relations-of (cdr (car set)) set)
                     set)))
          #f
          (transitive? (cdr set)))))
  

Это работает только тогда, когда(exist-all-transitive-relations-of? x r set) имеет значение true.

Вот мой вывод :

 >(exist-all-transitive-relations-of? 1 '(2 5 6) '((1 2) (1 5) (6 8)))))
> #t
>(define (transitive? '((1 2) (2 6)))
> #f
>(define (transitive? '((1 2) (2 6)(2 7)(1 7)))
> #f
>(define (transitive? '((1 2) (2 6)(2 7)(1 7)(1 6)))
> #t
  

Как я могу изменить свой код? так что мне не нужно проверять, если (define (exist-all-transitive-relations-of? x r set) выполняется отдельно

Комментарии:

1. И что вы пробовали до сих пор? Любой код Racket, которым вы хотите поделиться?

2. Только что добавил свой код ^

3. Работает ли код Racket? Если нет, что происходит не так? Вы проверили get-all-relations-of , exist-relation? , и exist-all-transitive-relations-of? с помощью тестовых примеров, чтобы выяснить, ведут ли они себя так, как ожидалось?

4. код работает, только если я проверяю наличие всех транзитивных отношений? Первый

5. Каков ожидаемый результат для приведенных вами примеров? Потому что код python выдает один и тот же результат для всех ваших примеров

Ответ №1:

Просто несколько комментариев к racket, которые у вас есть здесь:

Когда вы делаете:

 (if (condition) #f (else))
  

вы можете использовать короткое замыкание, чтобы преобразовать его в

 (and (condition) (else))
  

Аналогично для

 (if (condition) #t (else))
  

сделать

 (or (condition) (else))
  

Наконец, очень важно учитывать существующие абстракции списков, когда вы думаете о замене циклов for в python. В этом случае вы берете список и сжимаете его в один фрагмент данных, в частности логическое значение, если свойство прерывается для одного элемента. Поэтому вам следует использовать andmap , что значительно сократит ваш код:

 (define (transitive? set)
  (andmap (lambda (x) (andmap (lambda (y)
       (local [(define a (first x))
               (define b (second x))
               (define c (first y))
               (define d (second y))]
       (not (and (= b c) (not (member `(,a ,d) set)))))) set)) set))
  

Примечания: (,a ,d) может быть заменен на (list a d) (без квазиквоты), если хотите. И first и second с car помощью и cadr .

Комментарии:

1. Большое вам спасибо, я изменил = на equal ? чтобы она работала не только для чисел.

2. ` является квазиквотой, которая работает как ‘, но кавычка превращает все элементы списка в символы (таким образом, вы получите (list 'a 'd) ), и это приведет a к тому, что and d не будет заменен. Quasiquote позволяет вам отменить кавычки ( , ) внутри и эффективно «устраняет» этот quasiquote. Таким образом, она расширяется до «(list ,a , d)», который расширяется до (list a d) и a и d заменяются. Вот HTDP для нее htdp.org/2018-01-06/Book/i2-3.html