【问题标题】:How to get rid of solutions with -0.0 in SBV如何摆脱 SBV 中 -0.0 的解决方案
【发布时间】:2015-03-26 16:01:29
【问题描述】:

以下代码(使用 SBV):

{-# LANGUAGE ScopedTypeVariables #-}
import Data.SBV
main :: IO ()
main = do
    res <- allSat zeros
    putStrLn $ show res

zeros :: Predicate
zeros = do
    z1 <- sDouble "Z1"
    constrain $ z1 .== 0.0
    return true

生成两种解决方案:

Solution #1:
  Z1 = 0.0 :: SDouble
Solution #2:
  Z1 = -0.0 :: SDouble
Found 2 different solutions.

如何消除无趣的-0.0 解决方案?我不能使用z1 ./= -0.0,因为当z10.0 时也是如此。

【问题讨论】:

  • 要识别 x=-0,您可以执行 x==0 && (1/x)
  • 好问题。我的第一反应是signum (-0.0)(不,返回零)和isNegativeZero(不,没有SDouble 的实例)。
  • 正如@augustss 所说,翻译成SBV:(x .== 0) &amp;&amp;&amp; ((1 / x) .&lt; 0)
  • 不幸的是,添加 ` (1/x)

标签: haskell smt


【解决方案1】:

[在 Hackage (http://hackage.haskell.org/package/sbv) 上发布 SBV 4.4 后更新,提供了适当的支持。]

假设您的 SBV >= 4.4,您现在可以这样做:

Prelude Data.SBV> allSat $ \z -> z .== (0::SDouble)
Solution #1:
  s0 = 0.0 :: Double
Solution #2:
  s0 = -0.0 :: Double
Found 2 different solutions.
Prelude Data.SBV> allSat $ \z -> z .== (0::SDouble) &&& bnot (isNegativeZeroFP z)
Solution #1:
  s0 = 0.0 :: Double
This is the only solution.

【讨论】:

    【解决方案2】:

    基于 cmets,以下代码仅产生一个解决方案:

    zeros :: Predicate
    zeros = do
        z1 <- sDouble "Z1"
        constrain $ z1 .== 0.0 &&& ((1 / z1) .> 0)
        return true
    

    输出:

    Solution #1:
      Z1 = 0.0 :: SDouble
    This is the only solution.
    

    【讨论】:

    • SBV 有一些浮点识别器:isFPPoint(识别点浮点数,即没有 NaN 或 Infinities)、isSNaN(识别 NaN),我们绝对可以将 isSNegativeZero/isSPositiveZero 等添加到混合。同时,上述解决方案是足够的,但它实际上是昂贵的,因为它涉及到底层求解器可以更有效地实现的这个微不足道的测试的算术和比较。随时在 SBV github 页面提交票证,我将在下一个版本中添加它 (github.com/LeventErkok/sbv/issues)。
    • 是的,它实际上非常昂贵。我创建了以下用于定义概率的函数:probability :: String -&gt; Symbolic SDouble probability varName = do { x &lt;- sDouble varName; constrain $ x .&gt;= 0.0 &amp;&amp;&amp; x .&lt;= 1 &amp;&amp;&amp; ((1 / x) .&gt; 0); return x } 即使是微不足道的模型也比没有&amp;&amp;&amp; ((1 / x) .&gt; 0) 部分需要更长的时间。有什么我们可以直接在 SMT-Lib 中使用的吗?
    • 我可能足以将测试 isPositive :: SDouble -&gt; SBool 添加为 (fp.isPositive (_ FloatingPoint eb sb) Bool)
    • 如果它会严重减慢求解速度,为什么还要将其添加为约束?只需过滤掉不需要的结果,直到有人用有效的方法修补 SBV。
    • @ThomasM.DuBuisson 提出了一个很好的观点:一个好的选择是提取结果并丢弃 Haskell 端的结果。当然,拥有可用的谓词是更好的选择。 SBV 的一个目标是让用户可以使用所有东西,这样就可以编写任意程序来构建问题和处理输出模型,所以我想知道您是否尝试这样做并遇到任何问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 2015-08-09
    • 2011-04-29
    • 2013-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多