使用smtlib我想使用QF_UFNRA制作类似模数的东西。这使我无法使用mod,to_int,to_real这样的东西。
最后,我想在以下代码中获取z的小数部分:
(set-logic QF_UFNRA)
(declare-fun z () Real)
(declare-fun z1 () Real)
(define-fun zval_1 ((x Real)) Real
x
)
(declare-fun zval (Real) Real)
(assert (= z 1.5));
(assert (=> (and (<= 0.0 z) (< z 1.0)) (= (zval z) (zval_1 z))))
(assert (=> (>= z 1.0) (= (zval z) (zval (- z 1.0)))))
(assert (= z1 (zval z)))
当然,正如我在这里提出这个问题所暗示的那样,它没有成功。
有没有人知道如何使用逻辑QF_UFNRA将z的小数部分转换为z1?
答案 0 :(得分:2)
这是一个很好的问题。不幸的是,如果您将自己限制为QF_UFNRA
,那么您想要做的就是 不 。
如果你可以编码这样的功能,那么你可以决定任意丢番图方程。你只需在实数上投射一个给定的丢番图方程,计算&#34;分数&#34;这种所谓方法的真实解决方案,并断言该分数为0
。由于实数是可判定的,这将为您提供丢番图方程的决策程序,实现不可能。 (这被称为希尔伯特的第10个问题。)
因此,尽管任务看起来无辜,但实际上并不可行。但这并不意味着你不能用一些扩展来编码它,并且可能让解算器成功地决定了它的实例。
如果你允许自己使用量词和递归函数,那么你可以写:
(set-logic UFNRA)
(define-fun-rec frac ((x Real)) Real (ite (< x 1) x (frac (- x 1))))
(declare-fun res () Real)
(assert (= (frac 1.5) res))
(check-sat)
(get-value (res))
z3回应:
sat
((res (/ 1.0 2.0)))
请注意,我们使用了允许量化的UFNRA
逻辑,由于使用了define-fun-rec
构造,这里隐式需要量化。 (有关详细信息,请参阅SMTLib手册。)这基本上是您在问题中尝试编码的内容,而是使用递归函数定义工具而不是隐式编码。但是,在SMTLib中使用递归函数有几点需要注意:特别是,您可以编写使系统不易相容的函数。有关详细信息,请参阅http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.5-draft.pdf的第4.2.3节。
如果您转到QF_UFNIRA
,即允许混合实数和整数,则编码很简单:
(set-logic QF_UFNIRA)
(declare-fun z () Real)
(declare-fun zF () Real)
(declare-fun zI () Int)
(assert (= z (+ zF zI)))
(assert (<= 0 zF))
(assert (< zF 1))
(assert (= z 1.5))
(check-sat)
(get-value (zF zI))
z3回应:
sat
((zF (/ 1.0 2.0))
(zI 1))
(在zI
时,您可能必须小心z < 0
的计算,但这个想法是一样的。)
请注意,仅仅因为编码很简单并不意味着z3将始终能够成功回答查询。由于Real
&Integer
和z
的混合,如前所述,问题仍然不明。如果您对unknown
有其他限制,则z3可能会很好地回复sin
此编码。在这种特殊情况下,它恰好足够简单,因此z3能够找到一个模型。
pi
和sin
:这更像是一个思想实验,而不是一个真正的替代品。如果SMTLib允许pi
和sin (zI * pi)
,那么您可以检查0
是否为zI
,适用于受限制的zI
。对此查询的任何令人满意的模型都将确保zI
为整数。然后,您可以使用此值从z
中减去sin
来提取小数部分。
但这是徒劳的,因为SMTLib既不允许pi
也不允许sin
。并且有充分的理由:可判定性将会丢失。话虽如此,也许一些勇敢的灵魂可以设计一个支持pi
,unknown
等的逻辑,并成功地正确回答了您的查询,同时当问题变得太难以返回QF_UFNIRA
时解算器。非线性算法和using FluentValidation.TestHelper;
using NUnit.Framework;
using MyProject.Models...
using MyProject...
namespace MyProject.Tests.Classes.Validation
{
[TestFixture]
public class SomeFormValidatorTest
{
private SomeFormValidator SomeFormValidator;
[SetUp]
public void Setup()
{
SomeFormValidator = new SomeFormValidator();
}
[Test]
public void Should_display_correct_error_message_MyClass_is_null()
{
//arrange
MyClass myClass = null;
//act
var result = SomeFormValidator.ShouldHaveValidationErrorFor(x => x.MyClass, myClass);
//assert
result.WithErrorMessage("MyClass is required");
//first attempt prior to finding WithErrorMessage exists
//foreach (var r in result)
//{
// Assert.AreEqual("MyClass is required", r.ErrorMessage);
//}
}
}
片段就是这种情况:求解器可能会放弃,但它所采用的启发式方法可能会解决实际问题。
从理论上讲,事实证明,如果你只限于理性(而不是实际的实数),那么你确实可以编写一个一阶公式来识别整数。然而,编码不适合胆小的人:http://math.mit.edu/~poonen/papers/ae.pdf。此外,由于编码涉及量词,因此SMT求解器很可能不会很好地处理基于此思想的公式。
[顺便说一下,我要感谢我的同事;这个问题是为了一次很棒的午餐时间对话!]