/*- * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org> * Copyright (c) 2010 Isilon Systems, Inc. * Copyright (c) 2010 iX Systems, Inc. * Copyright (c) 2010 Panasas, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _LINUX_LIST_H_ #define _LINUX_LIST_H_
#define list_for_each_entry_safe(p, n, h, field) \ for (p = list_first_entry(h, __typeof__(*p), field), \ n = list_entry(p->field.next, __typeof__(*p), field); &p->field != (h);\ p = n, n = list_entry(n->field.next, __typeof__(*n), field))
#define list_for_each_entry_reverse(p, h, field) \ for (p = list_last_entry(h, __typeof__(*p), field); &p->field != (h); \ p = list_entry(p->field.prev, __typeof__(*p), field))
#define list_for_each_prev(p, h) for (p = (h)->prev; p != (h); p = p->prev) #define list_for_each_prev_safe(p, n, h) for (p = (h)->prev, n = p->prev; p != (h); p = n, n = p->prev)
intconst mask = v >> sizeof(int) * CHAR_BIT - 1;//定义一个掩码,值为v算术右移至仅保留最高位
####算法1
1
r = (v + mask) ^ mask;
####算法2 (已被申请专利)
1
r = (v ^ mask) - mask;
####解释:
一些CPU没有取整数绝对值的指令(或者编译器不支持)。在那些跳转开销较大的机器上,上面的程序要比
1
r = (v < 0) ? -(unsigned)v : v;
来的快,即使两者指令数相同。
附注:
2003.3.7,Angus Duggan指出1989年的ANSI C标准没有对有符号数右移的结果给出明确的标准( implementation-defined),所以在一些系统上这些代码可能不能用 (好像很熟悉?是的跟第一个程序的附注是同样的)。我曾阅读ANSI C,里面并未要求整数必须用补码表示,所以程序也有可能因此不能用 。(在一些很古老的机子里用的可能是反码)。2004.3.14,Keith H. Duggar向我发送了上面提到的专利算法。这是我最早提出的算法
1
r=(+1|(v>>(sizeof(int)*CHAR_BIT-1)))*v
的升级版,因为少用了一个乘法。不幸的是,这个算法于2000.6.6被 Vladimir Yu Volkonsky申请了专利并用到了Sun系统上。2006.8.13,Yuriy Kaminskiy告诉我专利可能是无效的,因为在申请专利之前这个方法就已经被公开发表,比如1996年11月9日Agner Fog的《How to Optimize for the Pentium Processor》(如何为奔腾处理器做优化)。Yuriy还提到这个文档1997年的时候被翻译成了俄文,Vladimir可能读过了。此外,网站时光倒流机器(The Internet Archive)也存在到这里的旧链接。2007.1.30,Peter Kankowski 给作者分享了一个版本的求绝对值,灵感来源于Microsoft’s Visual C++编译器的输出。在这里作为最终解决方案。2007.12.6 Hai Jin抱怨运算的结果是有符号的,所以当计算负数中的最大值时,得到的结果还是负数。2008.4.15 Andrew Shapira指出上述三元运算符的方法可能会出现溢出,因为缺少(unsigned)的类型说明;为了最佳的可移植性,他建议写作: (v < 0) ? (1 + ((unsigned)(-1-v))) : (unsigned)v。2008.7.9 Vincent Lefèvre说服作者删除了它(上述的式)而采用了原来的式(解释中提到的那个式子)。因为即使在非二进制补码的机器上,根据ISO C99规范, -(unsigned)v也是正确的。-(unsigned)v运算时,先通过加2^N转换为无符号数,得到v的补码表示,我们称为U。所以U=v+2^N,又因为
-v=2^N - (v+2^N) = 2^N - U = 0 - U = -U ,所以 -(unsigned)v = -U = -v
s.add(x > 10, y == x + 2) print s print"Solving constraints in the solver s ..." print s.check()
print"Create a new scope..." s.push() s.add(y < 11) print s print"Solving updated set of constraints..." print s.check() print"Restoring state..." s.pop() print s print"Solving restored set of constraints..." print s.check()
x = Real('x') s = Solver() s.add(2**x == 3) print s.check()
下面的例子展示了如何将声明的约束式传入求解器,以及如何通过check 方法获取求解器状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
x = Real('x') y = Real('y') s = Solver() s.add(x > 1, y > 1, Or(x + y > 3, x - y < 2)) print"asserted constraints..." for c in s.assertions(): print c
print s.check() print"statistics for the last check method..." print s.statistics() # Traversing statistics for k, v in s.statistics(): print"%s : %s" % (k, v)
当求解器找到解时, check 方法返回 sat 。我们称Z3求出满足约束式的解。我们称这个解为所声明的约束式的一个模型。一个模型是指一种解释,能使所有约束式满足。下面的例子展示了查看模型的基本方法。
1 2 3 4 5 6 7 8 9 10 11
x, y, z = Reals('x y z') s = Solver() s.add(x > 1, y > 1, x + y > 3, z - x < 10) print s.check()
m = s.model() print"x = %s" % m[x]
print"traversing model..." for d in m.decls(): print"%s = %s" % (d.name(), m[d])
x = Real('x') y = Int('y') a, b, c = Reals('a b c') s, r = Ints('s r') print x + y + 1 + (a + s) print ToReal(y) + c
函数ToReal 将一个整型表达式转换为实型。
Z3Py支持所有的基本的运算符。
1 2 3 4 5 6
a, b, c = Ints('a b c') d, e = Reals('d e') solve(a > b + 2, a == 2*c + 10, c + b <= 1000, d >= e)
函数simplify 提供了一些方法,可以对Z3表达式进行简单变换。
1 2 3 4 5 6 7
x, y = Reals('x y') # Put expression in sum-of-monomials form t = simplify((x + y)**3, som=True) print t # Use power operator t = simplify(t, mul_to_power=True) print t
x = Int('x') y = Int('y') f = Function('f', IntSort(), IntSort()) s = Solver() s.add(f(f(x)) == x, f(x) == y, x != y) print s.check() m = s.model() print"f(f(x)) =", m.evaluate(f(f(x))) print"f(x) =", m.evaluate(f(x))
###可满足性和有效性
当一个约束式/公式 F的值在任何有效取值下始终为真,称该公式为普遍有效公式(即恒真公式)。当约束式在一些取值下为真则称公式为可满足的。验证有效性时,即需要找出命题为永真的证明。验证可满足性则是求出一个满足式子的集合。考虑一个包含 a 和 b 的公式 F 。F 是否普遍有效即是否在 a 和 b 的所有取值下F 都为真。如果F 是有效的,则Not(F) 为永假的,即Not(F) 在任何取值下都不为真,即,Not(F) 是不可满足的。所以公式F 在Not(F) 不可满足时为永真的。 同样,当且仅当 Not(F) 不为永真时,F 是可满足的。下面的例子证明了德摩根定理 。
x = BitVec('x', 32) powers = [ 2**i for i in range(32) ] fast = And(x != 0, x & (x - 1) == 0) slow = Or([ x == p for p in powers ]) print fast prove(fast == slow)
print"trying to prove buggy version..." fast = x & (x - 1) == 0 prove(fast == slow)
####相反数
下面的技巧用于测试两个数是否互为相反数。
1 2 3 4 5 6 7 8 9 10 11
x = BitVec('x', 32) y = BitVec('y', 32)
# Claim: (x ^ y) < 0 iff x and y have opposite signs trick = (x ^ y) < 0
# Naive way to check if x and y have opposite signs opposite = Or(And(x < 0, y >= 0), And(x >= 0, y < 0))
# Create 3 integer variables dog, cat, mouse = Ints('dog cat mouse') solve(dog >= 1, # at least one dog cat >= 1, # at least one cat mouse >= 1, # at least one mouse # we want to buy 100 animals dog + cat + mouse == 100, # We have 100 dollars (10000 cents): # dogs cost 15 dollars (1500 cents), # cats cost 1 dollar (100 cents), and # mice cost 25 cents 1500 * dog + 100 * cat + 25 * mouse == 10000)
# 9x9 matrix of integer variables X = [ [ Int("x_%s_%s" % (i+1, j+1)) for j in range(9) ] for i in range(9) ]
# each cell contains a value in {1, ..., 9} cells_c = [ And(1 <= X[i][j], X[i][j] <= 9) for i in range(9) for j in range(9) ]
# each row contains a digit at most once rows_c = [ Distinct(X[i]) for i in range(9) ]
# each column contains a digit at most once cols_c = [ Distinct([ X[i][j] for i in range(9) ]) for j in range(9) ]
# each 3x3 square contains a digit at most once sq_c = [ Distinct([ X[3*i0 + i][3*j0 + j] for i in range(3) for j in range(3) ]) for i0 in range(3) for j0 in range(3) ]
sudoku_c = cells_c + rows_c + cols_c + sq_c
# sudoku instance, we use '0' for empty cells instance = ((0,0,0,0,9,4,0,3,0), (0,0,0,5,1,0,0,0,7), (0,8,9,0,0,0,0,4,0), (0,0,0,0,0,0,2,0,8), (0,6,0,2,0,1,0,5,0), (1,0,2,0,0,0,0,0,0), (0,7,0,0,0,0,5,2,0), (9,0,0,0,6,5,0,0,0), (0,4,0,9,7,0,0,0,0))
instance_c = [ If(instance[i][j] == 0, True, X[i][j] == instance[i][j]) for i in range(9) for j in range(9) ]
s = Solver() s.add(sudoku_c + instance_c) if s.check() == sat: m = s.model() r = [ [ m.evaluate(X[i][j]) for j in range(9) ] for i in range(9) ] print_matrix(r) else: print "failed to solve"
# We know each queen must be in a different row. # So, we represent each queen by a single integer: the column position Q = [ Int('Q_%i' % (i + 1)) for i in range(8) ]
# Each queen is in a column {1, ... 8 } val_c = [ And(1 <= Q[i], Q[i] <= 8) for i in range(8) ]
# At most one queen per column col_c = [ Distinct(Q) ]
# Diagonal constraint diag_c = [ If(i == j, True, And(Q[i] - Q[j] != i - j, Q[i] - Q[j] != j - i)) for i in range(8) for j in range(i) ]
defDependsOn(pack, deps): if is_expr(deps): return Implies(pack, deps) else: return And([ Implies(pack, dep) for dep in deps ])
defConflict(*packs): return Or([ Not(pack) for pack in packs ])
a, b, c, d, e, f, g, z = Bools('a b c d e f g z')
definstall_check(*problem): s = Solver() s.add(*problem) if s.check() == sat: m = s.model() r = [] for x in m: if is_true(m[x]): # x is a Z3 declaration # x() returns the Z3 expression # x.name() returns a string r.append(x()) print r else: print"invalid installation profile"
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.