使用谓词函数进行图搜索,以跟踪跃点限制

时间:2017-08-11 07:58:39

标签: lambda functional-programming scheme racket predicate

以下代码搜索图形并返回true或false,具体取决于作为参数传递的谓词函数。

图表以邻接列表的形式表示。

假设图表不包含周期。

代码:

(define (search predicate? key)
  (define value-list (lookup key))
  (if (not (empty? value-list))
      (if (findf predicate? value-list)
          #t
          (ormap (curry search predicate?) value-list))
      #f))

循环函数用于在散列表上进行查找并返回其相应的路径。

搜索函数获取路径,如果发现非空,则尝试使用谓词函数查找元素,如果找到则返回true,否则为列表中的每个元素调用search()。

这似乎有效。

现在陷入困境以实现以下目标:

目前,搜索功能遍历完整图并将谓词应用于其所有节点。

我希望创建一个谓词函数,它不仅包括要搜索的元素,还包括跳跃限制。

例如: 如果hop-limit为1:当且仅当搜索节点在1跳内时,谓词函数才返回true,否则返回false。

我希望在不修改search()的情况下概括n的跳跃限制。

到目前为止我想到的解决这个问题的事情:

1.我可以更改搜索功能以将跳数作为参数传递,并使用它来终止递归,但我不想更改搜索功能。

2.计算可以使用给定的hop-limit访问的节点数,并将该信息存储在谓词函数内,并且对于谓词函数的每次调用,减少计数,如果count命中0,则每次返回false 。 (但是我不确定如何实现上述(可能是闭包?),我也不认为这会起作用,因为计数可以用于最长的节点列表)

3.如果我能在谓词函数中找到调用者,即如果调用者是findf则不增加计数,如果调用者搜索谓词中存在的计数的增量并使用它。 这导致我: Detecting the caller of a function in Scheme or Racket

然而这没有帮助。

我被困,并且出于想法,任何帮助都会受到赞赏。

修改

对我为什么认为方法2不起作用的一点澄清。

功能搜索正在进行部门首次搜索。

我认为方法2不适用于以下两个原因。

让我们假设图表

acyclic graph

Say Start Position为'A',搜索元素为'I',跳数限制为2。

现在计数器值=可以从'A'开始的2个跃点计数访问的节点数 那是 : 计数= 0(最初)

在跳数1:'C'和'D'中,count = 2

在跳数2中:'F','G','H','I',count = 2 + 4 = 6.

让我们从'A'开始,代码的工作方式是

访问的节点(在findf中)将是'C'和'D',count = 6 - 2 = 4

让我们假设左半部分先被拿走。

现在'C'成为关键,并且访问了所有子子

访问的节点(在findf中)将是'F','G','H',count = 4-3 = 1

'F'没有subclild所以没有probs。

'G'有一个子项,因此它访问'K'并且计数变为= 1-1 = 0。

因此,此后所有迭代都会返回false,因为如果遵循方法2,我们会计算最大节点数。

解决问题的一种方法是正确调整计数,但我觉得我们最终可能会对元素进行完整的搜索,以便跟踪正确的计数。

1 个答案:

答案 0 :(得分:0)

对这个答案的警告:我认为问题是脑筋急转弯型谜题;我认为解决这个问题的最佳方法是通过问题中概述的方法#1。但是,如果我们假设我们不允许修改//: [Next](@next) ,无论出于何种原因......

...我们假设我们传入的search允许维护状态调用predicate?中使用的lookup }(并且是图表的基本表示),...

然后我认为可以通过让search自己跟踪它遇到的所有节点的跳数来实现你的目标。

然后,只要想知道它遇到的节点是否太远,它就可以查询该跳数表。

以下是我为解释这一点而编写的代码:

predicate?

以下是DrRacket交互窗口中的一些示例调用:

(define (is-parent-of? maybe-parent maybe-child)
  (member maybe-child (lookup maybe-parent)))

(define (hist-capturing-pred root pred?)
  (let ((hop-counts (list (list root (box 0)))))
    (lambda (n)
      (let* ((parents (filter (lambda (entry) (is-parent-of? (car entry) n))
                              hop-counts))
             (min-count (apply min (map unbox (map cadr parents)))))
             ;; the `min-count` above represents a distance given what we
             ;; know so far. Its possible that we actually encountered `n`
             ;; *previously* via a *longer* path, in which case not only
             ;; will there already be an entry for `n` in the `hop-counts`
             ;; table, but it will have recorded a non-globally-minimum
             ;; hop-count.
             ;;
             ;; So, check if there is an entry for `n`, and if so, make
             ;; sure it holds the currently known minimum value.
        (cond ((assoc n hop-counts)
               => (lambda (entry)
                    (set-box! (cadr entry)
                              (min min-count (unbox (cadr entry))))))
              (else
               ;; otherwise, add a new entry for `n` to the table
               (set! hop-counts (cons (list n (box (+ 1 min-count)))
                                      hop-counts))))
        (pred? (map (lambda (entry) (list (car entry) (unbox (cadr entry))))
                    hop-counts)
               n)))))