1

问题

考虑这些类:

class BookCase { ArrayList<Book> books }

class Book { ArrayList<Page> pages }

class Page { String color }

考虑到这个自然语言规则:

当书柜中的所有页面都是黑色时,执行 A

简单的方法是嵌套 forall 子句,但在 Drools 中不能这样做,因为 forall 子句只允许在里面使用模式(不是条件元素,什么是 forall 子句)!

那么我该如何在 Drools 中表达这一点呢?

4

3 回答 3

1

这很接近,但并不完全正确:

rule "all black pages"
when
  BookCase( $books: books )
  $book: Book( $pages: pages ) from $books
  not Page( color != "black" ) from $pages
then
  System.out.println( "doing A" );
end

问题是对于所有页面都是黑色的每本书都会触发一次。要评估所有书籍中的所有页面,可以组合所有页面的列表并确保它们都是黑色的:

rule "all black pages, take 2"
when
  BookCase( $books: books )
  $pages: ArrayList() from accumulate( Book( $ps: pages ) from $books,
       init( ArrayList list = new ArrayList(); ),
       action( list.addAll( $ps ); ),
       result( list ) )
  not Page( color != "black" ) from $pages
then
  System.out.println( "doing A" );
end
于 2016-04-07T16:01:29.520 回答
0

如果不使用forall(p1 p2 p3...),实际上可以嵌套多个 foralls ,但等效 not(p1 and not(and p2 p3...))的. 然后,为了防止个别书籍和页面触发规则,请exists在其中插入一个。

rule 'all pages in bookcase are black'
    when
        (and
        $bookCase: BookCase()
            (not (exists (and
                $book: Book() from $bookCase.books
                not( (and
                    not( (exists (and
                        $page: Page() from $book.pages
                        not( (and
                            // slightly different constraint than I used in question
                            eval($page.color == $book.color)
                        ) )
                    ) ) )
                ) )
            ) ) )
        )
    then
        ...
end

accumulate用于创建所有页面的平面列表不同,这将保持 的上下文$page,也就是说,当页面与其父书如上例一样受到约束时,在此解决方案中,Drools 仍然“知道”父书书是。

于 2016-07-20T09:34:55.110 回答
-1

当我写这个问题时,我想我自己找到了答案:

BookCase($caseContents : books)
$bookWithOnlyBlackPages : ArrayList<Page>() from $caseContents
forall ( $page : Page(this memberOf $bookWithOnlyBlackPages)
                 Page(this == $page,
                      color == "black") )
forall ( $bookInCase : ArrayList<Page>(this memberOf $caseContents)
                       ArrayList<Page>(this == $bookInCase,
                                       this == $bookWithOnlyBlackPages) )
于 2016-04-07T15:06:59.757 回答