【问题标题】:Prolog: Random LabelingProlog:随机标记
【发布时间】:2012-01-31 09:38:47
【问题描述】:

我有一个使用约束用 Sicstus Prolog 编写的程序。 我的目标是使用 labeling/2 和其他一些方法来获得我的变量的随机实例化。

例子:

X #> 2, Y #= 2*X, Z #<10

如果我使用

List = [X,Y,Z],
labeling([], List)

获得的第一个结果将是 X = Y = Z = 0。您认为返回一组随机值的 X、Y 和 Z 的最佳方法是什么?

【问题讨论】:

    标签: prolog sicstus-prolog clpfd


    【解决方案1】:

    我对最近 SICStus 版本中的标签选项了解不多,但是使用 SWI-Prolog 的 library(clpfd),有 random_variable(Seed) 和 random_value(Seed) 选项,您可以将它们与标签一起使用([随机变量(10),随机值(10)],列表)。也许您可以让 SICStus 的作者整合类似的选项?

    【讨论】:

    • 我似乎无法使用 random_variable 和 random_value 作为标签选项,即使我正在使用该库。! Domain error in argument 1 of user:labeling/2 ! expected labeling_options, but found random_variable(10) ! goal: labeling(user:[random_variable(10),random_value(10)],[_134])
    • 我不能在 SICStus 中使用这些选项真是太可惜了,因为我不得不使用它而不是 SWI。
    • 未记录,请参阅新问题:github.com/SWI-Prolog/swipl-devel/issues/398
    【解决方案2】:

    你可以使用 all_different([X,Y,Z]) 以获得不同的值 但是,在 Sicstus 中使用随机种子可能会很棘手,您可能需要定义一个函数来更改种子或再次启动随机函数。 检查下面 www.sics.se/sicstus/docs/3.7.1/html/sicstus_23.html

    【讨论】:

      【解决方案3】:

      在 sicstus 中,这是通过自定义选择变量/值来完成的。

      在你的情况下,只需:

      labeling([value(mySelValores)], List)
      
      mySelValores(Var, _Rest, BB, BB1) :-
          fd_set(Var, Set),
          select_best_value(Set, Value),
          (   
              first_bound(BB, BB1), Var #= Value
              ;   
              later_bound(BB, BB1), Var #\= Value
          ).
      
      select_best_value(Set, BestValue):-
          fdset_to_list(Set, Lista),
          length(Lista, Len),
          random(0, Len, RandomIndex),
          nth0(RandomIndex, Lista, BestValue).
      

      查看https://sicstus.sics.se/sicstus/docs/4.0.4/html/sicstus/Enumeration-Predicates.html中的值(枚举)。

      希望对你有所帮助;)

      【讨论】:

      【解决方案4】:

      我选择了 Jekejeke Prolog,用于连接新谓词 random_labeling/1 使用 CLP(FD) 从知识库中隐式获取随机数生成器 可以通过 sys_random Prolog 标志访问和修改。

      Jekejeke Prolog 3, Runtime Library 1.3.4
      (c) 1985-2019, XLOG Technologies GmbH, Switzerland
      
      ?- use_module(library(finite/clpfd)).
      % 20 consults and 0 unloads in 944 ms.
      Yes
      
      ?- use_module(library(basic/random)).
      % 0 consults and 0 unloads in 0 ms.
      Yes
      
      ?- random_new(111,R), set_prolog_flag(sys_random,R), 
         X in 0..5, Y #= X*X, random_label([X,Y]), 
         write(X-Y), nl, fail; true.
      4-16
      3-9
      5-25
      1-1
      2-4
      0-0
      Yes
      
      ?- random_new(111,R), set_prolog_flag(sys_random,R), 
         X in 0..5, Y #= X*X, random_label([X,Y]), 
         write(X-Y), nl, fail; true.
      4-16
      3-9
      5-25
      1-1
      2-4
      0-0
      

      我正在计划进一步的谓词 random_labeling/2。但它不需要种子,而是 Java java.util.Random 实例。这比种子更通用。但我想将 API 更改为 labeling/2 和一些选项将是最好的方法。

      编辑 29.12.2018:我现在会做笔记,因为我想这是个好主意 采用indomain/2,目前我已经实现了random_indomain/1, 并从此实现 random_label/1。另见此处:

      indomain/2 来自 ECLiPSe Prolog random:以随机顺序尝试枚举。回溯时, 先前测试的值被删除。此方法使用 random/1 来 创建随机数,之前使用 seed/1 以使结果可重现。 http://eclipseclp.org/doc/bips/lib/gfd_search/indomain-2.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多