python开环传递函数 如何将开环传递函数转化成闭环传递函数

Python-os的path模块函数大全 在操作文件的时候,我们肯定是要使用到 os 模块的,但是 os 模块里面还有 path 模块,这个模块主要是用来获取文件的属性的 。这篇博客来分享一下 path 模块的函数,希望对学习 Python 的小伙伴有所帮助 。
返回绝对路径:
返回文件名:
返回list(多个路径)中 , 所有path共有的最长的路径:
返回文件路径:
路径存在则返回True,路径损坏返回False:
路径存在则返回True,路径损坏也返回True:
把path中包含的" "和" user"转换成用户目录:
根据环境变量的值替换path中包含的"{name}":
返回最近访问时间(浮点型秒数):
返回最近文件修改时间:
返回文件 path 创建时间:
返回文件大小 , 如果文件不存在就返回错误:
判断是否为绝对路径:
判断路径是否为文件:
判断路径是否为目录:
判断路径是否为链接:
判断路径是否为挂载点:
把目录和文件名合成一个路径:
转换path的大小写和斜杠:
规范path字符串形式:
返回path的真实路径:
从start开始计算相对路径:
判断目录或文件是否相同:
判断fp1和fp2是否指向同一文件:
判断stat tuple stat1和stat2是否指向同一个文件:
把路径分割成 dirname 和 basename , 返回一个元组:
一般用在 windows 下,返回驱动器名和路径组成的元组:
分割路径中的文件名与拓展名:
把路径分割为加载点与文件:
遍历path,进入每个目录都调用visit函数,visit函数必须有3个参数(arg, dirname, names),dirname表示当前目录的目录名 , names代表当前目录下的所有文件名,args则为walk的第三个参数:
设置是否支持unicode路径名:
享学课堂浅谈Python序列内建函数都有哪些1、Python类型操作符和内建函数总结
表4.5列出了所有操作符和内建函数,其中操作符顺序是按优先级从高到低排列python开环传递函数的 。同一种灰度python开环传递函数的操作符拥有同样python开环传递函数的优先级 。注意在operator模块中有这些(和绝大多数Python)操作符相应的同功能的函数可供使用 。
表4.5 标准类型操作符和内建函数
操作符/函数
描述
结果a
字符串表示
``
对象的字符串表示
str
内建函数
cmp(obj1, obj2)
比较两个对象
int
repr(obj)
对象的字符串表示
str
str(obj)
对象的字符串表示
str
type(obj)
检测对象的类型
type
值比较
小于
bool
大于
bool
=
小于或等于
bool
=
大于或等于
bool
==
等于
bool
!=
不等于
bool
不等于
bool
对象比较
is

bool
is not
不是
bool
布尔操作符
not
逻辑反
bool
and
逻辑与
bool
or
逻辑或
bool
2、Python数值类型操作符和内建函数
一、工厂函数
数值工厂函数总结类(工厂函数) 操作
bool(obj) b返回obj对象的布尔值 , 也就是 obj.__nonzero__()方法的返回值 。
int(obj, base=10)返回一个字符串或数值对象的整数表 示,类似string.atoi();
从Python 1.6起,引入了可选的进制参数 。
long(obj, base=10)返回一个字符或数据对象的长整数表 示,类似string.atol(),
从Python1.6起, 引入了可选的进制参数 float(obj) ,
返回一个字符串或数据对象的浮点数 表示,类似string.atof() 。
complex(str) or返回一个字符串的复数表示,或 者根据给定的实数,
complex(real, imag=0.0) ?。耙桓隹裳?的虚数部分)生成一个复数对象 。
二、内建函数
1、分类
Python 有五个运算内建函数用于数值运算:
abs(num), coerce(num1,num2), divmod(num1,num2), pow(num1,num2,mod=1)和 round(flt,ndig=0)
其中abs()返回给定参数的绝对值 。如果参数是一个复数 , 那么就返回math.sqrt(num.real2num.imag2).
coerce()是一个数据类型转换函数,不过它的行为更像一个运算符.数coerce()为程序员提供了不依赖Python 解释器,而是自定义两个数值类型转换的方法 。对一种新创建的数值类型来说,这个特性非常有用.函数coerce()仅返回一个包含类型转换完毕的两个数值元素的元组.
divmod()内建函数把除法和取余运算结合起来, 返回一个包含商和余数的元组.对整数来说,它的返回值就是地板除和取余操作的结果.对浮点数来说,返回的商部分是math.floor(num1/num2),对复数来说,商部分是ath.floor((num1/num2).real).
pow()它和双星号 (**)运算符都可以进行指数运算.不过二者的区别并不仅仅在于一个是运算符,一个是内建函数.在Python 1.5 之前,并没有 ** 运算符,内建函数pow()还接受第三个可选的参数,一个余数参数.如果有这个参数的, pow() 先进行指数运算,然后将运算结果和第三个参数进行取余运算.这个特性主要用于密码运算,并且比 pow(x,y) % z 性能更好,这是因为这个函数的实现类似于C 函数pow(x,y,z).
round()用于对浮点数进行四舍五入运算 。它有一个可选的小数位数参数.如果不提供小数位参数, 它返回与第一个参数最接近的整数(但仍然是浮点类型).第二个参数告诉round 函数将结果精确到小数点后指定位数.
2、函数int()/round()/math.floor()它们之间的不同之处:
函数 int()直接截去小数部分.(返回值为整数)
函数 floor() 得到最接近原数但小于原数的整数.(返回值为浮点数)
函数 round() 得到最接近原数的整数.(返回值为浮点数)
3、进制转换函数:
返回字符串表示的8 进制和16 进制整数,它们分别是内建函数:
oct()和 hex(). oct(255)='0377'/hex(255)='0xff'
函数chr()接受一个单字节整数值(0到255) , 返回一个字符串(ASCII),其值为对应的字符.chr(97)='a'
函数ord()则相反,它接受一个字符(ASCII 或 Unicode) , 返回其对应的整数值.ord('A')=65
3、Python字符串函数
(一)标准类型操作符和标准内建函数
1)、标准类型操作符
,,=,=,==,!=,对象值得比较
注:做比较时字符串是按ASCII值的大小来比较的
is 对象身份比较
and,or,not 布尔类型
2)标准内建函数
type(obj)
cmp(obj1,obj2)
str(obj)和repr(obj) 或反引号运算符(``) 可以方便的以字符串的方式获取对象的
内容、类型、数值属性等信息 。str()函数得到的字符串可读性好 , 而repr()函数得到的字符
串通常可以用来重新获得该对象, 通常情况下 obj == eval(repr(obj)) 这个等式是成立的
isinstance(obj,type) 判断对象的类型
(二)序列操作
1、序列操作
字符串属于序列对象,可以使用所有序列的操作和函数
切片 [] [:] [::]
简单总结:
*索引(S[i])获取特定偏移的元素 。
——第一个元素偏移为0
——(S[0])获取第一个元素 。
——负偏移索引意味着从最后或右边反向进行计数
——(S[-2])获取倒数第二个元素(就像S[len(s)-2]一样
*分片[S[i:j]提取对应的部分作为一个序列
——右边界不包含在内
——分片的边界默认为0和序列的长度,如果没有给出的话S[:]
——(S[1:3])获取了从偏移为1,直到但不包括偏移为3的元素
——(S[1:])获取从偏移为1到末尾之间的元素
——(S[:3])获取从偏移为0直到但不包括偏移为3的元素
——(S[:-1])获取从偏移为0直到但不包括最后一个元素之间的元素
——(S[:])获取从偏移为0到末尾之间的元素,这有效地实现了顶层S拷贝
拷贝了一个相同值,但是是不同内存区域的对象 。对象字符串这样不可变的对象不是很有用,但是对于可以实地修改的对象来说很有用 。
比如列表 。
扩展分片:第三个限制值 【步进】
完整形式:X[I:J:K]:这标识索引X对象的元素 , 从偏移为I直到J-1,每隔K元素索引一次 。第三个限制值 , K,默认为1
实例
Python Code
1
2
3
4
5
S='abcdefghijk'
S[1:10]
'bcdefghij'
S[1:10:2]
'bdfhj
也可以使用负数作为步进 。
分片表达式
Python Code
1
2
"hello"[::-1]
'olleh'
通过负数步进 , 两个边界的意义实际上进行了反转 。
3、成员操作符 in , not in
返回布尔值True 或False
可以使用string模块来判断输入字符的合法性,可见成品中的idcheck.py
4、字符串连接
连接字符串 ‘name’ ' ' 'jin'
字符串格式化 '%s %s' % ('name','jin')
join()方法 ' '.join(('name','jin')) ' '.join(['name','jin'])
5、删除清空字符串
del aString
aString=''
(三)、序列函数
序列类型函数
len(str) 返回字串的长度
enumerate(iter):接受一个可迭代对象作为参数,返回一个enumerate
max(str)/min(str):max()和min()函数对其他的序列类型可能更有用,但对于string类型它们能很好地运行,返回最大或者最小的字符(按照ASCII 码值排列),
zip([it0, it1,... itN]) 返回一个列表 , 其第一个元素是it0,it1,...这些元素的第一个元素组成的一个元组,第二个...,类推.
reversed(seq)c 接受一个序列作为参数,返回一个以逆序访问的迭代器(PEP 322)
sorted(iter,func=None,key=None,reverse=False) 接受一个可迭代对象作为参数,返回一个有序的列表;可选参数func,key 和reverse 的含义跟list.sort()内建函数的参数含义一样.
注意:
sorted等需要在原处修改的函数无法用在字符串对象,但可以产生新的对象
sum处理的对象是数字,不能用在字符串
sorted(s)
['a', 'e', 'e', 'g', 'g', 'g', 'o']
(四)只适合于字符串类型的函数
1)raw_input()函数
内建的raw_input()函数使用给定字符串提示用户输入并将这个输入返回 , 下面是一个使
用raw_input()的例子:
user_input = raw_input("Enter your name: ")
prin user_input
2)str() and unicode()
str()和unicode()函数都是工厂函数,就是说产生所对应的类型的对象.它们接受一个任
意类型的对象,然后创建该对象的可打印的或者Unicode 的字符串表示. 它们和basestring 都
可以作为参数传给isinstance()函数来判断一个对象的类型
3)chr(), unichr(), and ord()
chr()函数用一个范围在range(256)内的(就是0 到255)整数做参数,返回一个对应的字符.unichr()跟它一样,只不过返回的是Unicode 字符
ord()函数是chr()函数(对于8 位的ASCII 字符串)或unichr()函数(对于Unicode 对象)
的配对函数,它以一个字符(长度为1 的字符串)作为参数,返回对应的ASCII 数值,或者Unicode
数值,如果所给的Unicode 字符超出了你的Python 定义范围,则会引发一个TypeError 的异常
(五)、只适用于字符串的操作符
1、格式化操作符 %
字符串格式化符号
格式化字符 转换方式
%c 转换成字符(ASCII 码值 , 或者长度为一的字符串)
%ra 优先用repr()函数进行字符串转换
%s 优先用str()函数进行字符串转换
%d / %i 转成有符号十进制数
\ub 转成无符号十进制数
%ob 转成无符号八进制数
%xb/%Xb (Unsigned)转成无符号十六进制数(x/X 代表转换后的十六进制字符的大
小写)
%e/%E 转成科学计数法(e/E 控制输出e/E)
%f/%F 转成浮点数(小数部分自然截断)
%g/%G %e 和%f/%E 和%F 的简写
%% 输出%
格式化操作符辅助指令
符号 作用
* 定义宽度或者小数点精度
- 用做左对齐
在正数前面显示加号()
sp 在正数前面显示空格
# 在八进制数前面显示零('0'),在十六进制前面显示'0x'或者'0X'(取决于
用的是'x'还是'X')
0 显示的数字前面填充‘0’而不是默认的空格
% '%%'输出一个单一的'%'
(var) 映射变量(字典参数)
m.n m 是显示的最小总宽度,n 是小数点后的位数(如果可用的话)
2、字符串模板: 更简单的替代品
由于新式的字符串Template 对象的引进使得string 模块又重新活了过来,Template 对象
有两个方法,substitute()和safe_substitute().前者更为严谨,在key 缺少的情况下它会报一
个KeyError 的异常出来,而后者在缺少key 时,直接原封不动的把字符串显示出
3、原始字符串操作符( r/R )
字符串抑制转义r'带特殊符号的字串'
myfile=open(r'C:\new\text.data','w')
4、Unicode 字符串操作符( u/U )
u'abc' U 0061 U 0062 U 0063
u'?' U 1234
u'abc?\n' U 0061 U 0062 U 0063 U 1234 U 0012
(六)字符串对象的方法:
1、删减
T2.lstrip() 移除字符串前面字符(默认空格),返回字符串
T2.rstrip() 移除字符串后面字符(默认空格),返回字符串
T2.strip() 移除字符串前后面空格,返回字符串 默认空格,可以其他字符 S.strip('"')
2、切割
partition(sep),
rpartition(sep),
splitlines([keepends]),#把S按照行分割符分为一个list,keepends是一个bool值 , 如果为真每行后而会保留行分割符
split([sep [,maxsplit]]),#以sep为分隔符 , 把S分成一个list 。maxsplit表示分割的次数 。默认的分割符为空白字符
rsplit([sep[,maxsplit]]) #从右到左切割
备注:
partition()函数族是2.5版本新增的方法 。它接受一个字符串参数,并返回一个3个元素的 tuple 对象 。
如果sep没出现在母串中,返回值是 (sep, ‘’, ‘’);
否则,返回值的第一个元素是 sep 左端的部分,第二个元素是 sep 自身 , 第三个元素是 sep 右端的部分 。
S.partition(';')
('', ';', ' generated by /sbin/dhclient-script\nnameserver 172.16.10.171\nnameserver 8.8.8.8\nnameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n')
参数 maxsplit 是分切的次数 , 即最大的分切次数,所以返回值最多有 maxsplit 1 个元素 。
s.split() 和 s.split(‘ ‘)的返回值不尽相同
' hello world!'.split()
['hello', 'world!']
【python开环传递函数 如何将开环传递函数转化成闭环传递函数】 ' hello world!'.split(' ')
['', '', 'hello', '', '', 'world!']
S.split('\n',3)
['; generated by /sbin/dhclient-script', 'nameserver 172.16.10.171', 'nameserver 8.8.8.8', 'nameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n']
超过最大切割个数后面的全部为一个元素
按行切割
S
'; generated by /sbin/dhclient-script\nnameserver 172.16.10.171\nnameserver 8.8.8.8\nnameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n'
S.splitlines()
['; generated by /sbin/dhclient-script', 'nameserver 172.16.10.171', 'nameserver 8.8.8.8', 'nameserver 172.16.0.2', 'nameserver 178.79.131.110', 'nameserver 202.96.199.133']
产生差异的原因在于当忽略 sep 参数或sep参数为 None 时与明确给 sep 赋予字符串值时 split() 采用两种不同的算法 。
对于前者,split() 先去除字符串两端的空白符,然后以任意长度的空白符串作为界定符分切字符串
即连续的空白符串被当作单一的空白符看待;
对于后者则认为两个连续的 sep 之间存在一个空字符串 。因此对于空字符串(或空白符串) , 它们的返回值也是不同的:
''.split()
[]
''.split(' ')
['']
3、变形
lower(),#全部小写
upper(),#全部小写
capitalize(),#首字母大写
swapcase(),#大小写交换
title()#每个单词第一个大写,其他小写
备注
因为title() 函数并不去除字符串两端的空白符也不会把连续的空白符替换为一个空格 ,
所以建议使用string 模块中的capwords(s)函数,它能够去除两端的空白符,再将连续的空白符用一个空格代替 。
Python Code
1
2
3
4
' hello world!'.title()
' Hello World!'
string.capwords(' hello world!')
'Hello World!'
4、连接
join(seq)
join() 函数的高效率(相对于循环相加而言),使它成为最值得关注的字符串方法之一 。
它的功用是将可迭代的字符串序列连接成一条长字符串 , 如:
conf = {'host':'127.0.0.1',
... 'db':'spam',
... 'user':'sa',
... 'passwd':'eggs'}
';'.join("%s=%s"%(k, v) for k, v in conf.iteritems())
'passswd=eggs;db=spam;user=sa;host=127.0.0.1'
S=''.join(T) #使用空字符串分割把字符列表转换为字符串
5、查找
count( sub[, start[, end]]),#计算substr在S中出现的次数
find( sub[, start[, end]]),#返回S中出现sub的第一个字母的标号,如果S中没有sub则返回-1 。start和end作用就相当于在S[start:end]中搜索
index( substr[, start[, end]]),#与find()相同,只是在S中没有substr时 , 会返回一个运行时错误
rfind( sub[, start[,end]]),#返回S中最后出现的substr的第一个字母的标号,如果S中没有substr则返回-1,也就是说从右边算起的第一次出现的substr的首字母标号
rindex( sub[, start[, end]])
T2.find('ie') 字符串方法调用:搜索
find()----找到的第一个符合字符的index
rfind()-----找到最后一个符合的字符的index
备注:
find()函数族找不到时返回-1 , index()函数族则抛出ValueError异常 。
另,也可以用 in 和 not in 操作符来判断字符串中是否存在某个模板
6、替换
replace(old, new[,count]),#把S中的oldstar替换为newstr , count为替换次数 。这是替换的通用形式,还有一些函数进行特殊字符的替换
translate(table[,deletechars]) #使用上面的函数产后的翻译表 , 把S进行翻译,并把deletechars中有的字符删掉
备注:
replace()函数的 count 参数用以指定最大替换次数
translate() 的参数 table 可以由 string.maketrans(frm, to) 生成
translate() 对 unicode 对象的支持并不完备,建议不要使用
7、判定
isalnum(),#是否全是字母和数字,并至少有一个字符
isalpha(),是否全是字母,并至少有一个字符
isdigit(),是否全是数字,并至少有一个字符 ,如果是全数字返回True,否则返回False
islower(),#S中的字母是否全是小写
isupper(),#S中的字母是否是大写
isspace(),#是否全是空白字符,并至少有一个字符
istitle(),S是否是首字母大写的
startswith(prefix[, start[, end]]), #是否以prefix开头
endswith(suffix[,start[, end]]),#以suffix结尾
备注:
这些函数都比较简单,顾名知义 。需要注意的是*with()函数族可以接受可选的 start, end 参数,善加利用,可以优化性能 。
另 , 自 Py2.5 版本起,*with() 函数族的 prefix 参数可以接受 tuple 类型的实参,当实参中的某人元素能够匹配,即返回 True 。
8、填充
字符串在输出时的对齐:
center(width[, fillchar]), 字符串中间对齐
ljust(width[, fillchar]), 字符串左对齐,不足部分用fillchar填充,默认的为空格
rjust(width[, fillchar]), 字符串右对齐,不足部分用fillchar填充 , 默认的为空格
zfill(width), 把字符串变成width长,并在右对齐,不足部分用0补足
expandtabs([tabsize])把字符串中的制表符(tab)转换为适当数量的空格 。
fillchar 参数指定了用以填充的字符,默认为空格
zfill的z为zero的缩写,顾名思义,是以字符0进行填充,用于数值输出
expandtabs()的tabsize 参数默认为8 。它的功能是把字符串中的制表符(tab)转换为适当数量的空格 。
9、编码
encode([encoding[,errors]]),
decode([encoding[,errors]])
这是一对互逆操作的方法 , 用以编码和解码字符串 。因为str是平台相关的,它使用的内码依赖于操作系统环境,
而unicode是平台无关的,是Python内部的字符串存储
跟轨迹画好之后分析是用闭环传递函数分析吗那个就是上面式子python开环传递函数的实部和虚部分开写的得到两个方程 。求频率w的时候先利用虚部的方程得到w的值 。再带入实部的方程中求得k值在时域分析中已经看到,控制系统的性能取决于系统的闭环传递函数,因此,可以根据系统闭环传递函数的零、极点研究控制系统性能 。但对于高阶系统,采用解析法求取系统的闭环特征方程根(闭环极点)通常是比较困难的,且当系统某一参数(如开环增益)发生变化时,又需要重新计算,这就给系统分析带来很大的不便 。
1948年,伊万思根据反馈系统中开、闭环传递函数间的内在联系 , 提出python开环传递函数了求解闭环特征方程根的比较简易的图解方法,这种方法称为根轨迹法 。因为根轨迹法直观形象,所以在控制工程中获得了广泛应用 。根轨迹是当开环系统某一参数(如根轨迹增益 )从零变化到无穷时 , 闭环特征方程的根在S平面上移动的轨迹 。根轨迹增益K * 是首1形式开环传递函数对应的系数 。
?
在介绍图解法之前,先用直接求根的方法来说明根轨迹的含义 。控制系统如上图所示 。其开环传递函数为:利用计算结果在S平面上描点并用平滑曲线将其连接,便得到K * (或K)从零变化到无穷大时闭环极点在S平面上移动的轨迹,即根轨迹,如下图所示 。图中,根轨迹用粗实线表示,箭头表示K * (或K)增大时两条根轨迹移动的方向根轨迹的概念
开环系统某一参数从零变换到无穷,闭环系统特征方程式的根在s平面上变化的轨迹 。其中某一参数主要是指根轨迹增益,当然也可以是系统中其他的实参数 。
根轨迹方程
?
将上式写为相角及模值条件,根据这两个条件可以完全确定s平面上的根轨迹和根轨迹上的K*值 。
?
根轨迹与系统性能
1 稳定性
当参数由零变化到无穷时,根轨迹不会越过虚轴进入s右半平面则说明系统对于所有的K值都是稳定的,如果根轨迹越过虚轴进入s右半平面,则系统进入不稳定的状态 。
2稳态特性
一般情况下 , 根轨迹图上标注的参数不是开环增益而是根轨迹增益,根轨迹增益与稳态误差系数之间仅相差一个比例常数,
3动态特性
当所有闭环极点都位于实轴上时,系统为过阻尼系统;
当极点重合时,系统为临界阻尼系统;
当闭环极点为共轭复数极点,系统为欠阻尼系统,单位阶跃响应是衰减振荡过程,且超调量将随着K值的增大而增大 。
确定闭环系统的零极点
当根轨迹增益确定时 , 传递函数也同时确定下来了,那么闭环系统的零极点位置就在根轨迹上确定下来了,通过位置可以判断系统的稳定性能 。
打开CSDN,阅读体验更佳
matlab求系统根轨迹和系统增益,控制系统的根轨迹分析
一、根轨迹分析方法的概念所谓根轨迹是指,当开环系统某一参数从零变到无穷大时,闭环系统特征方程的根在s平面上的轨迹 。一般来说,这一参数选作开环系统的增益K,而在无零极点对消时,闭环系统特征方程的根就是闭环传递函数的极点 。根轨迹分析方法是分析和设计线性定常控制系统的图解方法,使用十分简便 。利用它可以对系统进行各种性能分析,1.稳定性当开环增益K从零到无穷大变化时,图中的根轨迹不会越过虚轴进入右半s平面...
继续访问
【自动控制原理】根轨迹Root Locus-笔记
重点掌握根的变化规律 。从而设计控制器/补偿器 。“根”——“极点”(一样的概念)一阶系统比如这个系统传递函数为,对这个系统施加一个冲击u(t)=,的Laplace变换=1 。所以系统的输出为,令s a=0,得“根”P=-a进行Laplace的逆变换 , 得到这个系统的时间函数,这里的-a就是它的根当a0时,它在时间轴上的表现为指数衰减对于一般的一阶系统来说,如果把它的根在复平面上(横轴为实数,竖轴为虚数)表达出来的话,它一定落在实轴上 , 如图一阶函数的 。...
继续访问
?
一阶系统开环传递函数表达式_古典控制理论(三)根轨迹法(闭环系统)
1 根轨迹与系统性能(1)定义:指系统某一参数从零变化到无穷大时,闭环系统特征方程式的根(闭环极点)在s平面上变化的轨迹 。Matlab命令:rlocus(sys),默认变化参数为开环传递函数的增益k 。(2)功能:根轨迹可以直接给出闭环系统时间相应的全部信息 , 而且可以指明开环零、极点应该如何变化才能满足给定的闭环系统的性能指标要求 。根轨迹方法可以求解高阶代数方程的根,实际上就是解决闭环特征方程...
继续访问
传递函数根轨迹
根轨迹 以及时域响应,自动控制,各个方面的自动控制都有用,直接出根轨迹
Simulink模型闭环传递函数导出及Matlab对simulink模型进行频域分析(含实现程序)
Simulink模型闭环传递函数导出及使用Matlab函数对simulink模型进行频域分析,并在文章中给出含实现程序 。
继续访问
?
控制教程 —— 介绍篇:4.根轨迹控制器设计
在本教程中 , python开环传递函数我们将介绍根轨迹 , 展示如何使用MATLAB来创建根轨迹 , 并演示如何通过使用根轨迹来设计满足某些性能指标的反馈控制器 。本教程中使用的主要MATLAB命令包括:feedback,rlocus,step,controlSystemDesigner 。闭环极点 开环传递函数 H(s)H(s)H(s) 的根轨迹通常是在比例增益 KKK 在0到 ∞\infty∞ 变化时,形成的闭环极点的轨迹曲线...
继续访问
?
根轨迹和频率响应
首先我们来了解一下根的定义,在一个闭环一阶系统中,存在过度函数G(s)为s的一个式子,那么它可能会存在零点和极点,说到极点想必大家都非常熟悉了,在此,我们可以理解为“根”=“极点” 。根轨迹的画法呢我简单提一下,根轨迹是有开环极点指向开环零点,从左向右 , 两两对应,如果缺少对应的,则以无穷极点/零点代替(举个例子,假如只有一个极点,没有零点,那么根轨迹就是由这个极点指向负无穷),另外,根轨迹是对称于实轴的,其汇合点和分离点并非重点,感兴趣的同学可以自己搜索一下了解一下 。最终可由增益的取值范围判断系统的稳定性 。.
继续访问
?
根轨迹和系统参数的确定
1、根轨迹 前面有讲到通过闭环传递函数的极点分布情况来判断系统是否稳定 。当然还有些更简单的判别方式 , 例如:劳斯稳定性判据、赫尔维茨稳定性判据等 。但都是判断系统是否稳定的 , 那么怎么判断系统的稳定程度(稳定裕度)呢python开环传递函数?或者说当一个系统参数 ...
继续访问
?
matlab闭环传函的根轨迹,自动控制系统的设计--基于根轨迹的串联校正设计
与频域法相似,利用根轨迹法进行系统的设计也有两种方法:1)常规方法;2)Matlab方法 。Matlab的根轨迹方法允许进行可视化设计,具有操作简单、界面直观、交互性好、设计效率高等优点 。目前常用的Matlab设计方法有:1)直接编程法;2)Matlab控制工具箱提供的强大的Rltool工具;3)第三方提供的应用程序,如CTRLLAB等 。本节在给出根轨迹的设计思路的基础上,将重点介绍第一、二种方法 。...
继续访问
?
20200518 如何快速画出闭环特征方程的根轨迹
Q: 什么是根轨迹法? A: 给一个闭环的特征方程,随着某一个参数变化,闭环特征方程的根(即闭环传递函数的极点)不断变化,描述根的变化轨迹的图叫做根轨迹图 。Q: 针对的是开环系统还是闭环系统? A: 利用开环系统的零极点研究闭环系统的极点(根) 。Q: 开环传递函数和闭环传递函数的区别? A: 闭环传递函数是G1 GH\frac{G}{1 GH}1 GHG,开环传递函数是GHGHGH 。Q: 如何快速近似画出根轨迹? A: 首先介绍不著名的异性相吸理论(瞎编的) 。......
继续访问
?
绘制课本中的根轨迹图与零极点分布图
《信号与系统》第三版下册-郑君里 例11-8 已知反馈系统结构如图11-21所示,试绘制其根轨迹图 。这个图绘制的是A(s)F(s)的根轨迹图,并不是整个闭环系统的根轨迹图,也不是A(s)的根轨迹图 这道题的解析部分其实是为了计算在横轴上的交汇点 。---------------------------------------------------------------------------------------------------------------------
继续访问
?
应用根轨迹分析系统性能
应用根轨迹分析系统性能 本节通过几个实例简要介绍根轨迹方法在分析和设计系统中的应用 。5.3.1 单参数设计 例 5.4: 已知系统的方框图如下:试通过根轨迹方法确定合适的反馈系数 k ,使得系统具有阻尼比为 0.4 的闭环共轭复数极点 。解:由方框图可得系统的开环传递函数为:
继续访问
根轨迹分析
应用MATLAB进行根轨迹分析
继续访问
?
matlab闭环传函的根轨迹,开环传递函数的跟轨迹与虚轴的交点怎么算
大学自动控制原理,已知开环传递函数求闭环根轨迹图中的一个步骤不懂计算(求根轨迹与虚轴的交点)一个复数等于0,结果是实部等于0虚部等于0,这个太简单了吧再问:详细点还是不懂再答:-w^3j-6w^2 9wj k=0 , (-w^3 9w)j (-6w^2 k)=0,得-w^3 9w=0,-6w^2如何matlab画开环传递函数的奈奎斯特图用MATLAB做出奈奎斯特曲线图%k=10k=10;d=conv(...
继续访问
【自动控制原理】 根轨迹法之根轨迹法分析系统性能
本文主要讲述了使用根轨迹法分析系统稳定性的原理,以及根据根轨迹设计参数Kg的方法步骤 。最后给出了主导极点、偶极子对和开环零点对系统性能的影响
继续访问
?
matlab求系统根轨迹和系统增益,《自动控制原理》实验报告(线性系统的根轨迹)...
实验四线性系统的根轨迹一、实验目的1.熟悉 MATLAB 用于控制系统中的一些基本编程语句和格式 。2.利用 MATLAB 语句绘制系统的根轨迹 。3.掌握用根轨迹分析系统性能的图解方法 。4.掌握系统参数变化对特征根位置的影响 。基础知识及 MATLAB函数根轨迹是指系统的某一参数从零变到无穷大时,特征方程的根在 s 平面上的变化轨迹 。这个参数一般选为开环系统的增益 K。课本中介绍的手工绘制根轨迹的方...
继续访问
最新发布 817自动控制原理-1-开环传递函数与闭环传递函数
首先,开环传递函数是针对闭环系统而言的,而不是指开环系统的传递函数 。eg.输入作用下的开环传递函数:G(s)=G1H2H3/(1-G2H1)输入作用下的误差传递函数:R(s)/E(s)=(1-G2H2)/(1-G2H2 G1G2H3)
继续访问
热门推荐 【自控原理】第四章 根轨迹法
文章目录A 根轨迹法的基本概念B 根轨迹方程C 绘制根轨迹的法则C.a 根轨迹法则介绍C.b 根轨迹法则(常规根轨迹)D 利用根轨迹分析系统的方法 引言 闭环控制系统的稳定性和性能指标主要由闭环系统的极点在复数平面上的位置决定 。分析和设计系统时确定闭环极点(即特征根)在复平 面的位置是十分有意义的: 闭环系统的极点在复平面的位置决定了系统的稳 定性 系统的性能指标也主要由闭环极点的位置决定 ...
继续访问
?
matlab-自控原理 rlocus 根轨迹 根据传递函数画图
2019独角兽企业重金招聘Python工程师标准 ...
继续访问
其他
?写评论
?
评论
?
1
?
点赞
?

?
分享
前往CSDN APP阅读全文
阅读体验更佳
?
CSDN
成就一亿技术人
前往
?
夸克浏览器
根轨迹的概念
开环系统某一参数从零变换到无穷,闭环系统特征方程式的根在s平面上变化的轨迹 。其中某一参数主要是指根轨迹增益 , 当然也可以是系统中其他的实参数 。
根轨迹方程
?
将上式写为相角及模值条件,根据这两个条件可以完全确定s平面上的根轨迹和根轨迹上的K*值 。
?
根轨迹与系统性能
1 稳定性
当参数由零变化到无穷时,根轨迹不会越过虚轴进入s右半平面则说明系统对于所有的K值都是稳定的 , 如果根轨迹越过虚轴进入s右半平面,则系统进入不稳定的状态 。
2稳态特性
一般情况下,根轨迹图上标注的参数不是开环增益而是根轨迹增益,根轨迹增益与稳态误差系数之间仅相差一个比例常数,
3动态特性
当所有闭环极点都位于实轴上时,系统为过阻尼系统;
当极点重合时 , 系统为临界阻尼系统;
当闭环极点为共轭复数极点 , 系统为欠阻尼系统,单位阶跃响应是衰减振荡过程,且超调量将随着K值的增大而增大 。
确定闭环系统的零极点
当根轨迹增益确定时,传递函数也同时确定下来了,那么闭环系统的零极点位置就在根轨迹上确定下来了 , 通过位置可以判断系统的稳定性能 。
打开CSDN , 阅读体验更佳
matlab求系统根轨迹和系统增益,控制系统的根轨迹分析
一、根轨迹分析方法的概念所谓根轨迹是指,当开环系统某一参数从零变到无穷大时,闭环系统特征方程的根在s平面上的轨迹 。一般来说,这一参数选作开环系统的增益K,而在无零极点对消时,闭环系统特征方程的根就是闭环传递函数的极点 。根轨迹分析方法是分析和设计线性定常控制系统的图解方法,使用十分简便 。利用它可以对系统进行各种性能分析,1.稳定性当开环增益K从零到无穷大变化时,图中的根轨迹不会越过虚轴进入右半s平面...
继续访问
【自动控制原理】根轨迹Root Locus-笔记
重点掌握根的变化规律 。从而设计控制器/补偿器 。“根”——“极点”(一样的概念)一阶系统比如这个系统传递函数为,对这个系统施加一个冲击u(t)= , 的Laplace变换=1 。所以系统的输出为,令s a=0 , 得“根”P=-a进行Laplace的逆变换,得到这个系统的时间函数,这里的-a就是它的根当a0时,它在时间轴上的表现为指数衰减对于一般的一阶系统来说,如果把它的根在复平面上(横轴为实数,竖轴为虚数)表达出来的话,它一定落在实轴上,如图一阶函数的 。...
继续访问
?
一阶系统开环传递函数表达式_古典控制理论(三)根轨迹法(闭环系统)
1 根轨迹与系统性能(1)定义:指系统某一参数从零变化到无穷大时,闭环系统特征方程式的根(闭环极点)在s平面上变化的轨迹 。Matlab命令:rlocus(sys),默认变化参数为开环传递函数的增益k 。(2)功能:根轨迹可以直接给出闭环系统时间相应的全部信息,而且可以指明开环零、极点应该如何变化才能满足给定的闭环系统的性能指标要求 。根轨迹方法可以求解高阶代数方程的根,实际上就是解决闭环特征方程...
继续访问
传递函数根轨迹
根轨迹 以及时域响应,自动控制,各个方面的自动控制都有用,直接出根轨迹
Simulink模型闭环传递函数导出及Matlab对simulink模型进行频域分析(含实现程序)
Simulink模型闭环传递函数导出及使用Matlab函数对simulink模型进行频域分析 , 并在文章中给出含实现程序 。
继续访问
?
控制教程 —— 介绍篇:4.根轨迹控制器设计
在本教程中,我们将介绍根轨迹,展示如何使用MATLAB来创建根轨迹,并演示如何通过使用根轨迹来设计满足某些性能指标的反馈控制器 。本教程中使用的主要MATLAB命令包括:feedback,rlocus,step,controlSystemDesigner 。闭环极点 开环传递函数 H(s)H(s)H(s) 的根轨迹通常是在比例增益 KKK 在0到 ∞\infty∞ 变化时,形成的闭环极点的轨迹曲线...
继续访问
?
根轨迹和频率响应
首先我们来了解一下根的定义,在一个闭环一阶系统中,存在过度函数G(s)为s的一个式子,那么它可能会存在零点和极点,说到极点想必大家都非常熟悉了 , 在此,我们可以理解为“根”=“极点” 。根轨迹的画法呢我简单提一下,根轨迹是有开环极点指向开环零点,从左向右,两两对应,如果缺少对应的 , 则以无穷极点/零点代替(举个例子,假如只有一个极点,没有零点,那么根轨迹就是由这个极点指向负无穷),另外,根轨迹是对称于实轴的 , 其汇合点和分离点并非重点,感兴趣的同学可以自己搜索一下了解一下 。最终可由增益的取值范围判断系统的稳定性 。.
继续访问
?
根轨迹和系统参数的确定
1、根轨迹 前面有讲到通过闭环传递函数的极点分布情况来判断系统是否稳定 。当然还有些更简单的判别方式,例如:劳斯稳定性判据、赫尔维茨稳定性判据等 。但都是判断系统是否稳定的 , 那么怎么判断系统的稳定程度(稳定裕度)呢?或者说当一个系统参数 ...
继续访问
?
matlab闭环传函的根轨迹,自动控制系统的设计--基于根轨迹的串联校正设计
与频域法相似,利用根轨迹法进行系统的设计也有两种方法:1)常规方法;2)Matlab方法 。Matlab的根轨迹方法允许进行可视化设计 , 具有操作简单、界面直观、交互性好、设计效率高等优点 。目前常用的Matlab设计方法有:1)直接编程法;2)Matlab控制工具箱提供的强大的Rltool工具;3)第三方提供的应用程序,如CTRLLAB等 。本节在给出根轨迹的设计思路的基础上,将重点介绍第一、二种方法 。...
继续访问
?
20200518 如何快速画出闭环特征方程的根轨迹
Q: 什么是根轨迹法? A: 给一个闭环的特征方程,随着某一个参数变化 , 闭环特征方程的根(即闭环传递函数的极点)不断变化,描述根的变化轨迹的图叫做根轨迹图 。Q: 针对的是开环系统还是闭环系统? A: 利用开环系统的零极点研究闭环系统的极点(根) 。Q: 开环传递函数和闭环传递函数的区别? A: 闭环传递函数是G1 GH\frac{G}{1 GH}1 GHG,开环传递函数是GHGHGH 。Q: 如何快速近似画出根轨迹? A: 首先介绍不著名的异性相吸理论(瞎编的) 。......
继续访问
?
绘制课本中的根轨迹图与零极点分布图
《信号与系统》第三版下册-郑君里 例11-8 已知反馈系统结构如图11-21所示 , 试绘制其根轨迹图 。这个图绘制的是A(s)F(s)的根轨迹图,并不是整个闭环系统的根轨迹图,也不是A(s)的根轨迹图 这道题的解析部分其实是为了计算在横轴上的交汇点 。---------------------------------------------------------------------------------------------------------------------
继续访问
?
应用根轨迹分析系统性能
应用根轨迹分析系统性能 本节通过几个实例简要介绍根轨迹方法在分析和设计系统中的应用 。5.3.1 单参数设计 例 5.4: 已知系统的方框图如下:试通过根轨迹方法确定合适的反馈系数 k , 使得系统具有阻尼比为 0.4 的闭环共轭复数极点 。解:由方框图可得系统的开环传递函数为:
继续访问
根轨迹分析
应用MATLAB进行根轨迹分析
继续访问
?
matlab闭环传函的根轨迹,开环传递函数的跟轨迹与虚轴的交点怎么算
大学自动控制原理,已知开环传递函数求闭环根轨迹图中的一个步骤不懂计算(求根轨迹与虚轴的交点)一个复数等于0,结果是实部等于0虚部等于0,这个太简单了吧再问:详细点还是不懂再答:-w^3j-6w^2 9wj k=0,(-w^3 9w)j (-6w^2 k)=0,得-w^3 9w=0,-6w^2如何matlab画开环传递函数的奈奎斯特图用MATLAB做出奈奎斯特曲线图%k=10k=10;d=conv(...
继续访问
【自动控制原理】 根轨迹法之根轨迹法分析系统性能
本文主要讲述了使用根轨迹法分析系统稳定性的原理 , 以及根据根轨迹设计参数Kg的方法步骤 。最后给出了主导极点、偶极子对和开环零点对系统性能的影响
继续访问
?
matlab求系统根轨迹和系统增益,《自动控制原理》实验报告(线性系统的根轨迹)...
实验四线性系统的根轨迹一、实验目的1.熟悉 MATLAB 用于控制系统中的一些基本编程语句和格式 。2.利用 MATLAB 语句绘制系统的根轨迹 。3.掌握用根轨迹分析系统性能的图解方法 。4.掌握系统参数变化对特征根位置的影响 。基础知识及 MATLAB函数根轨迹是指系统的某一参数从零变到无穷大时,特征方程的根在 s 平面上的变化轨迹 。这个参数一般选为开环系统的增益 K。课本中介绍的手工绘制根轨迹的方...
继续访问
最新发布 817自动控制原理-1-开环传递函数与闭环传递函数
首先,开环传递函数是针对闭环系统而言的,而不是指开环系统的传递函数 。eg.输入作用下的开环传递函数:G(s)=G1H2H3/(1-G2H1)输入作用下的误差传递函数:R(s)/E(s)=(1-G2H2)/(1-G2H2 G1G2H3)
继续访问
热门推荐 【自控原理】第四章 根轨迹法
文章目录A 根轨迹法的基本概念B 根轨迹方程C 绘制根轨迹的法则C.a 根轨迹法则介绍C.b 根轨迹法则(常规根轨迹)D 利用根轨迹分析系统的方法 引言 闭环控制系统的稳定性和性能指标主要由闭环系统的极点在复数平面上的位置决定 。分析和设计系统时确定闭环极点(即特征根)在复平 面的位置是十分有意义的: 闭环系统的极点在复平面的位置决定了系统的稳 定性 系统的性能指标也主要由闭环极点的位置决定 ...
继续访问
?
matlab-自控原理 rlocus 根轨迹 根据传递函数画图
2019独角兽企业重金招聘Python工程师标准 ...
继续访问
其他
?写评论
?
评论
?
1
?
点赞
?

?
分享
前往CSDN APP阅读全文
阅读体验更佳
?
CSDN
成就一亿技术人
前往
?
夸克浏览器
如何用Python编写一个素数环此文主要目的,是向大家展示如何才能用python语言,来部署STARK算法 。
STARKs(可扩容的透明知识论证)是创建一种证明的技术,这项证明中f(x)=y,其中f可能要花很长的时间来进行计算,但是这个证明可以被很快验证 。STARK是“双重扩容”:对于一个需要t步骤的计算,这会花费大约O(t * log(t))步骤才能完成这个证明,这可能是最优的情况,而且这需要通过~O(log2(t))个步骤才能验证,对于中等大小的T值,它比原始计算快得多 。STARKs也拥有隐私保护的“零知识证明”的特性,虽然我们将这类使用案例应用到其中,从而完成可验证的延迟功能,不需要这类性质,所以我们不用担心 。
首先,先请几项说明:
这个代码还没有完全审核;在实际使用案例中的情况,还不能保证
这部分代码是还没有达到理想状态(是用Python语言写的)
STARKs 的“真实情况” 倾向于使用二进制字段而不是素数域的特定应用程序效率的原因;但是,他们确实也表现出,这里写出的代码是合法并且可用的 。
没有一个真实的方法来使用STARK 。它是一个非常宽泛的加密和数学架构,同时为不同的应用有不同的设置,以及连续的研究来减少证明者和验证者的复杂性 , 同时提高可用性 。
此文希望大家能够知道 , 模运算和素数域是如何运行的 ,
并且和多项式概念 , 插值和估值进行结合 。
现在 , 让我们一起来了解吧!
MIMC
下面是STARK的功能展示:
def mimc(inp, steps, round_constants): start_time = time.time() for i in range(steps-1): inp = (inp**3round_constants[i % len(round_constants)]) % modulus print("MIMC computed in %.4f sec" % (time.time() - start_time)) return inp
我们选择MIMC作为案例,因为它(i)很容易理解,(ii)在真实世界使用的很多 。函数功能见下图:
注意:在很多关于MIMC的讨论中,你可以典型地看出使用了XOR,而不是 ;这是因为MIMC可以在二进制情况下使用,其中添加是XOR;这里我们会在素数领域进行 。
在我们的案例中,常数相对而言会是比较小的列表(例如 , 64位),这会一直连续地进行周期循环(也就说,在k[64]之后) 。MIMC自身可以获得这个特性,因为MIMC可以向后进行计算(从相应的输出获得输入),但是往后计算需要比向前计算多花费100倍的时间(并且没有方向可以同步进行) 。所以你可以将往后计算的功能想象成计算不能同步的工作量证明,并且往前方向计算的功能可以作为验证的过程 。
x - x(2p-1)/3 是x - x3 的反函数;根据费马小定理,这是真实的,尽管这个定理没有费马大定理出名,但是依然对数学的贡献很大 。
我们尝试使用STARK来进行更加有效的验证 , 而不是让验证者必须在向前方向运行MIMC , 在完成向后计算之后,证明者可以在向前方向进行STARK计算,并且验证者可以很简单地验证STARK 。我们希望计算STARK可以比MIMC向前和向后之间的运行速度差别要小,所以证明者的时间仍然是有初始的向后计算来主导的 。而并不是STARK计算 。STARK的认证会相对较快(在python语言算法中,可以是0.05-0.3秒),不论初始的计算时间有多长 。
所有的计算会在2256 – 351 * 2321个模内完成;我们使用素数模 , 因为它是小于2256 最大的素数,其中乘法群包含了232 个子集(也就是说,有这样一个数g,从而在完全232次循环之后,G素数环的连续幂模绕回到1),而且是按照6k 5的形式 。首个特性是保证FFT和FRI算法的有效版本,其次是保证MIMC实际上可以向后计算(请见上面提到的x - x(2p-1)/3 使用方法) 。
素域操作
我们通过建立方便的等级来进行素域的操作,同时也有多项式的操作 。代码如下,收首先是小数位数:
class PrimeField(): def __init__(self, modulus): # Quick primality test assert pow(2, modulus, modulus) == 2 self.modulus = modulus def add(self, x, y): return (x y) % self.modulus def sub(self, x, y): return (x-y) % self.modulus def mul(self, x, y): return (x*y) % self.modulus
并且使用扩展欧几里得算法 , 来计算模块逆转(这和在素域中计算1/x相同):
# Modular inverse using the extended Euclidean algorithm def inv(self, a): if a == 0: return 0 lm, hm = 1, 0 low, high = a % self.modulus, self.modulus while low1: r = high//low nm, new = hm-lm*r, high-low*r lm, low, hm, high = nm, new, lm, low return lm % self.modulus
上面的算法是相对昂贵的;幸运地是,对于特定的案例,我们需要做很多的模逆计算,有一个数学方法可以让我们来计算很多逆运算 , 被称为蒙哥马利批量求逆:
使用蒙哥马利批量求逆来计算模逆 , 其输入为紫色,输出为绿色,乘法门为黑色,红色方块是唯一的模逆 。
下面的代码是算法的体现 , 其中包含一些特别的逻辑 。如果我们正在求逆的集合中包含零 , 那么它会将这些零的逆设置为 0 并继续前进 。
def multi_inv(self, values): partials = [1] for i in range(len(values)): partials.append(self.mul(partials[-1], values[i] or 1)) inv = self.inv(partials[-1]) outputs = [0] * len(values) for i in range(len(values), 0, -1): outputs[i-1] = self.mul(partials[i-1], inv) if values[i-1] else 0 inv = self.mul(inv, values[i-1] or 1) return outputs
这部分算法接下来会验证称为非常重要的东西,特别是当我们开始和不同阶的多项式进行计算的时候 。
现在我们来看看一些多项式计算 。我们把多项式当做一个数据集,其中的i是第i阶(例如,x32x1变成[1, 2, 0, 1]) 。下面就是在一个点进行多项式估算的方法:
# Evaluate a polynomial at a point def eval_poly_at(self, p, x): y = 0 power_of_x = 1 for i, p_coeff in enumerate(p): y= power_of_x * p_coeff power_of_x = (power_of_x * x) % self.modulus return y % self.modulus
困难和挑战
f.eval_poly_at([4, 5, 6], 2)的输出是多少?模是31吗?
下面的解释就是答案
.其实也有代码是多项式加法,减法 , 乘法和除法;这是很长的加减乘除运算 。有一个很重要的内容是拉格朗日插值,它将一组 x 和 y 坐标作为输入,并返回通过所有这些点的最小多项式(你可以将其视为多项式求值的逆):
# Build a polynomial that returns 0 at all specified xs def zpoly(self, xs): root = [1] for x in xs: root.insert(0, 0) for j in range(len(root)-1): root[j] -= root[j 1] * x return [x % self.modulus for x in root] def lagrange_interp(self, xs, ys): # Generate master numerator polynomial, eg. (x - x1) * (x - x2) * ... * (x - xn) root = self.zpoly(xs) # Generate per-value numerator polynomials, eg. for x=x2, # (x - x1) * (x - x3) * ... * (x - xn), by dividing the master # polynomial back by each x coordinate nums = [self.div_polys(root, [-x, 1]) for x in xs] # Generate denominators by evaluating numerator polys at each x denoms = [self.eval_poly_at(nums[i], xs[i]) for i in range(len(xs))] invdenoms = self.multi_inv(denoms) # Generate output polynomial, which is the sum of the per-value numerator # polynomials rescaled to have the right y values b = [0 for y in ys] for i in range(len(xs)): yslice = self.mul(ys[i], invdenoms[i]) for j in range(len(ys)): if nums[i][j] and ys[i]: b[j]= nums[i][j] * yslice return [x % self.modulus for x in b]
相关数学知识请参见此文的M-N部分 。需要注意,我们也会有特别的方法lagrange_interp_4和lagrange_interp_2来加速次数小于 2 的拉格朗日插值和次数小于 4 的多项式运算 。
快速傅立叶变换
如果你仔细阅读上面的算法,你也许会发现拉格朗日插值和多点求值(即求在N个点处次数小于N的多项式的值)都需要耗费2次时间 , 例如对于1000个点求拉格朗日插值,需要几百万个步骤,而且100万个点的拉格朗日插值需要万亿个步骤 。这是不可接受的低效率,所以我们需要使用更加有效的算法,快速傅立叶变换 。
FFT只需要花费O(n * log(n))的时间(也就是说,1000个点的计算需要10,000步,100万个点的计算需要2000步),虽然它的范围更受限制;x坐标必须是单位根部的完全集合 , 必须满足N = 2k 阶 。也就是说,如果有N个点,那么x坐标必须某个P值的连续幂,1, p, p2, p3…,其中pN = 1 。这个算法能够用来进行多点计算和插值计算 , 而且只需要调整一个小参数 。
下面就是算法详情(这是个简单的表达方式;更详细内容可以参阅此处代码)
def fft(vals, modulus, root_of_unity): if len(vals) == 1: return vals L = fft(vals[::2], modulus, pow(root_of_unity, 2, modulus)) R = fft(vals[1::2], modulus, pow(root_of_unity, 2, modulus)) o = [0 for i in vals] for i, (x, y) in enumerate(zip(L, R)): y_times_root = y*pow(root_of_unity, i, modulus) o[i] = (x y_times_root) % modulus o[i len(L)] = (x-y_times_root) % modulus return o def inv_fft(vals, modulus, root_of_unity): f = PrimeField(modulus) # Inverse FFT invlen = f.inv(len(vals)) return [(x*invlen) % modulus for x in fft(vals, modulus, f.inv(root_of_unity))]
你可以自己通过一些输入来运行代码,并且看看是否能得到想要的结果,当你使用eval_poly_at的时候,给出你期望得到的答案 。例如:
fft.fft([3,1,4,1,5,9,2,6], 337, 85, inv=True) [46, 169, 29, 149, 126, 262, 140, 93]f = poly_utils.PrimeField(337)[f.eval_poly_at([46, 169, 29, 149, 126, 262, 140, 93], f.exp(85, i)) for i in range(8)] [3, 1, 4, 1, 5, 9, 2, 6]
傅里叶变换会把[x[0] …. x[n-1]]作为输入,并且它的目标是输出x[0]x[1]…x[n-1]作为首个元素,x[0]x[1] * 2…x[n-1] * w**(n-1)作为第二个元素,等等;快速傅里叶变换可以通过把数据分为两半,来完成这个 , 在两边都进行FFT,然后将结果结合在一起 。
上图就是信息如何进行FFT运算的解释 。请注意FFT是如何进行两次数据复制,并且进行粘合 , 直到你得到一个元素 。
现在,我们把所有部分组合起来 , 看看整件事情是如何:def mk_mimc_proof(inp, steps, round_constants),它生成运行 MIMC 函数的执行结果的证明,其中给定的输入为步骤数 。首先,是一些 assert 函数:
# Calculate the set of x coordinates xs = get_power_cycle(root_of_unity, modulus) column = [] for i in range(len(xs)//4): x_poly = f.lagrange_interp_4( [xs[i len(xs)*j//4] for j in range(4)], [values[i len(values)*j//4] for j in range(4)], ) column.append(f.eval_poly_at(x_poly, special_x))
扩展因子是我们将要拉伸的计算轨迹(执行 MIMC 函数的“中间值”的集合) 。
m2 = merkelize(column) # Pseudo-randomly select y indices to sample # (m2[1] is the Merkle root of the column) ys = get_pseudorandom_indices(m2[1], len(column), 40) # Compute the Merkle branches for the values in the polynomial and the column branches = [] for y in ys: branches.append([mk_branch(m2, y)][mk_branch(m, y(len(xs) // 4) * j) for j in range(4)])
我们需要步数乘以扩展因子最多为 2^32,因为当 k32 时 , 我们没有 2^k 次的单位根 。
computational_trace_polynomial = inv_fft(computational_trace, modulus, subroot) p_evaluations = fft(computational_trace_polynomial, modulus, root_of_unity)
我们首个计算会是得出计算轨迹;也就是说,所有的计算中间值,从输入到输出 。
assert steps = 2**32 // extension_factor assert is_a_power_of_2(steps) and is_a_power_of_2(len(round_constants)) assert len(round_constants)steps
然后,我们会从将计算轨迹转换为多项式,在单位根 g (其中,g^steps = 1)的连续幂的轨迹上“放下”连续值,然后我们对更大的集合——即单位根 g2 的连续幂,其中 g2^steps * 8 = 1(注意 g2^8 = g)的多项式求值 。
# Generate the computational trace computational_trace = [inp] for i in range(steps-1): computational_trace.append((computational_trace[-1]**3round_constants[i % len(round_constants)]) % modulus) output = computational_trace[-1]
黑色: g1 的幂 。紫色: g2 的幂 。橙色:1 。你可以将连续的单位根看作一个按这种方式排列的圆圈 。我们沿着 g1的幂“放置”计算轨迹,然后扩展它来计算在中间值处(即 g2 的幂)的相同多项式的值 。
我们可以将MIMC的循环常数转换为多项式 。因为这些循环常数链是非常通常发生地(在我们的测试中 , 每64个步骤都会进行),最终证明他们形成了64阶的多项式,而且外面可以很容易计算出它的表达式,以及扩展式:
skips2 = steps // len(round_constants) constants_mini_polynomial = fft(round_constants, modulus, f.exp(subroot, skips2), inv=True) constants_polynomial = [0 if i % skips2 else constants_mini_polynomial[i//skips2] for i in range(steps)] constants_mini_extension = fft(constants_mini_polynomial, modulus, f.exp(root_of_unity, skips2))
假设其中有8192个步骤,并且有64个循环常数 。这是我们想要做的:我们正在进行FFT,从而计算循环常数来作为g1128 的功能 。然后我们在之间加入很多零,来完成g1本身的功能 。因为g1128 大约每64步进行循环,我们知道g1这个功能也会同样 。我们只计算这个扩展中的512个步骤,因为我们知道这个扩展会在每512步之后重复 。现在,我们按照斐波那契案例中那样 , 计算C(P(x)),除了这次是计算,需要注意,我们不在计算使用系数形式的多项式;而是根据高次单位根的连续幂来对多项式进行求值 。
c_of_p需要满足Q(x) = C(P(x), P(g1*x),K(x)) = P(g1*x) – P(x)**3 – K(x);目标是对于任何我们放入计算轨道的x(除了最后一步,因为在最后一步之后,就没有步骤),计算轨迹中的下个数值就和之前的相等,再加上循环常量 。与第1部分中的斐波那契示例不同,其中如果某个计算步骤是在k向量,下个就会是k 1向量 , 我们把低次单位根( g1 )的连续幂放下计算轨迹,所以如果某个计算步骤是在x = g1i , 下个步骤就会在g1i 1 = g1i * g1 = x * g1 。因此,对于低阶单位根( g1 )的每一个幂,我们希望最终会是P(x*g1) = P(x)**3K(x) , 或者P(x*g1) – P(x)**3 – K(x) = Q(x) = 0 。因此,Q(x) 会在低次单位根 g 的所有连续幂上等于零(除了最后一个) 。
# Create the composed polynomial such that # C(P(x), P(g1*x), K(x)) = P(g1*x) - P(x)**3 - K(x) c_of_p_evaluations = [(p_evaluations[(i extension_factor)%precision] - f.exp(p_evaluations[i], 3) - constants_mini_extension[i % len(constants_mini_extension)]) % modulus for i in range(precision)] print('Computed C(P, K) polynomial')
有个代数定理证明 , 如果Q(x)在所有这些x坐标,都等于零,那么最小多项式的乘积就会在所有这些x坐标等于零:Z(x) = (x – x_1) * (x – x_2) * … * (x – x_n) 。通过证明在任何单个的坐标,Q(x)是等于零,我们想要证明这个很难 , 因为验证这样的证明比运行原始计算需要耗费更长的时间,我们会使用一个间接的方式来证明Q(x)是Z(x)的乘积 。并且我们会怎么做呢?通过证明D(x) = Q(x) / Z(x),并且使用FRI来证明它其实是个多项式 , 而不是个分数 。
我们选择低次单位根和高次单位根的特定排列,因为事实证明,计算Z(x) , 而且除以Z(x)也十分简单:Z 的表达式是两项的一部分 。
需要注意地是,直接计算Z的分子和分母,然后使用批量模逆的方法将除以Z转换为乘法,随后通过 Z(X) 的逆来逐点乘以 Q(x) 的值 。需要注意 , 对于低次单位根的幂,除了最后一个,都可以得到Z(x) = 0,所以这个计算包含其逆计算就会中断 。这是非常不幸的,虽然我们会通过简单地修改随机检查和FRI算法来堵住这个漏洞 , 所以就算我们计算错误,也没关系 。
因为Z(x)可以简洁地表达,我们也可以获得另个好处:验证者对于任何特别的x , 可以快速计算Z(x),而且还不需要任何提前计算 。对于证明者来说,我们可以接受证明者必须处理大小等于步数的多项式,但我们不想让验证者做同样的事情 , 因为我们希望验证过程足够简洁 。
# Compute D(x) = Q(x) / Z(x) # Z(x) = (x^steps - 1) / (x - x_atlast_step) z_num_evaluations = [xs[(i * steps) % precision] - 1 for i in range(precision)] z_num_inv = f.multi_inv(z_num_evaluations) z_den_evaluations = [xs[i] - last_step_position for i in range(precision)] d_evaluations = [cp * zd * zni % modulus for cp, zd, zni in zip(c_of_p_evaluations, z_den_evaluations, z_num_inv)] print('Computed D polynomial')
在几个随机点上,进行概念检测D(x) * Z(x) = Q(x),从而可以验证转账约束,每个计算步骤是之前步骤的有效结果 。但是我们也想验证边界约束,其中计算的输入和输出就是证明者所说的那样 。只是要求证明者提供P(1), D(1), P(last_step)还有D(last_step)的数值,这些都是很脆弱的;没有证明 , 那些数值都是在同个多项式 。所以,我们使用类似的多项式除法技巧:
# Compute interpolant of ((1, input), (x_atlast_step, output)) interpolant = f.lagrange_interp_2([1, last_step_position], [inp, output]) i_evaluations = [f.eval_poly_at(interpolant, x) for x in xs] zeropoly2 = f.mul_polys([-1, 1], [-last_step_position, 1]) inv_z2_evaluations = f.multi_inv([f.eval_poly_at(quotient, x) for x in xs]) # B = (P - I) / Z2 b_evaluations = [((p - i) * invq) % modulus for p, i, invq in zip(p_evaluations, i_evaluations, inv_z2_evaluations)] print('Computed B polynomial')
那么 , 我们的论证如下 。证明者想要证明P(1) == input和P(last_step) == output 。如果我们将I(x)作为插值,那么就是穿越(1, input)和(last_step, output)亮点的线,于是P(x) – I(x)就会在这亮点上等于零 。因此,它会证明P(x) – I(x)是P(x) – I(x)的乘积,并且我们通过提高商数来证明这点 。
紫色:计算轨迹多项式 (P)。绿色:插值 (I)(注意插值是如何构造的,其在 x = 1 处等于输入(应该是计算轨迹的第一步),在 x=g^(steps-1) 处等于输出(应该是计算轨迹的最后一步) 。红色:P-I 。黄色:在x = 1和 x=g^(steps-1)(即 Z2)处等于 0 的最小多项式 。粉红色:(P – I) / Z2 。
现在 , 我们来看看将P,D和B的默克尔根部组合在一起 。
现在,我们需要证明P,D和B其实都是多项式,并且是最大的正确阶数 。但是FRI证明是很大且昂贵的,而且我们不想有三个FRI证明,所以 , 我们计算 P,D 和 B 的伪随机线性组合,并且基于它来进行FRI证明:
# Compute their Merkle roots mtree = merkelize([pval.to_bytes(32, 'big')dval.to_bytes(32, 'big')bval.to_bytes(32, 'big') for pval, dval, bval in zip(p_evaluations, d_evaluations, b_evaluations)]) print('Computed hash root')
除非所有这三个多项式有正确的低阶,不然几乎不可能有随机选择的线性组合 , 所以这很足够 。
我们想要证明D的阶数小于2 * steps,而且P 和 B 的次数小于steps,所以我们其实使用了随机的P, P * xsteps, B, Bsteps 和 D的随机组合,并且可以看出这部分组合是小于2 * steps 。
现在,我们来检查下所有的多项式组合 。我们先获得很多随机的索引,然后在这些索引上为默克尔树枝提供多项式:
k1 = int.from_bytes(blake(mtree[1]b'\x01'), 'big') k2 = int.from_bytes(blake(mtree[1]b'\x02'), 'big') k3 = int.from_bytes(blake(mtree[1]b'\x03'), 'big') k4 = int.from_bytes(blake(mtree[1]b'\x04'), 'big') # Compute the linear combination. We don't even bother calculating it # in coefficient form; we just compute the evaluations root_of_unity_to_the_steps = f.exp(root_of_unity, steps) powers = [1] for i in range(1, precision): powers.append(powers[-1] * root_of_unity_to_the_steps % modulus) l_evaluations = [(d_evaluations[i]p_evaluations[i] * k1p_evaluations[i] * k2 * powers[i]b_evaluations[i] * k3b_evaluations[i] * powers[i] * k4) % modulus for i in range(precision)]
get_pseudorandom_indices函数会回复[0…precision-1]范围中的随机索引,而且exclude_multiples_of参数并不会给出特定参数倍数的值 。这就保证了,我们不会沿着原始计算轨迹进行采样,否则就会获得错误的答案 。
证明是由一组默克尔根、经过抽查的分支以及随机线性组合的低次证明组成:
# Do some spot checks of the Merkle tree at pseudo-random coordinates, excluding # multiples of `extension_factor` branches = [] samples = spot_check_security_factor positions = get_pseudorandom_indices(l_mtree[1], precision, samples, exclude_multiples_of=extension_factor) for pos in positions: branches.append(mk_branch(mtree, pos)) branches.append(mk_branch(mtree, (posskips) % precision)) branches.append(mk_branch(l_mtree, pos)) print('Computed %d spot checks' % samples)
整个证明最长的部分是默克尔树分支,还有FRI证明,这是有更多分支来组成的 。这是验证者的实质结果:
o = [mtree[1], l_mtree[1], branches, prove_low_degree(l_evaluations, root_of_unity, steps * 2, modulus, exclude_multiples_of=extension_factor)]
在每个位置 , 证明者需要提供一个默克尔证明,从而让验证者能够检查这个默克尔证明,并且检查C(P(x), P(g1*x), K(x)) = Z(x) * D(x)以及B(x) * Z2(x)I(x) = P(x)(提醒:对于不在初始计算轨道上的x,Z(x)不会是零,所以C(P(x), P(g1*x), K(x)也不会是零) 。验证者也会检查线性组合是正确的,然后调用 。
for i, pos in enumerate(positions): x = f.exp(G2, pos) x_to_the_steps = f.exp(x, steps) mbranch1 = verify_branch(m_root, pos, branches[i*3]) mbranch2 = verify_branch(m_root, (pos skips)%precision, branches[i*3 1]) l_of_x = verify_branch(l_root, pos, branches[i*32], output_as_int=True) p_of_x = int.from_bytes(mbranch1[:32], 'big') p_of_g1x = int.from_bytes(mbranch2[:32], 'big') d_of_x = int.from_bytes(mbranch1[32:64], 'big') b_of_x = int.from_bytes(mbranch1[64:], 'big') zvalue = https://www.04ip.com/post/f.div(f.exp(x, steps) - 1, x - last_step_position) k_of_x = f.eval_poly_at(constants_mini_polynomial, f.exp(x, skips2)) # Check transition constraints Q(x) = Z(x) * D(x) assert (p_of_g1x - p_of_x ** 3 - k_of_x - zvalue * d_of_x) % modulus == 0 # Check boundary constraints B(x) * Z2(x)I(x) = P(x) interpolant = f.lagrange_interp_2([1, last_step_position], [inp, output]) zeropoly2 = f.mul_polys([-1, 1], [-last_step_position, 1]) assert (p_of_x - b_of_x * f.eval_poly_at(zeropoly2, x) - f.eval_poly_at(interpolant, x)) % modulus == 0 # Check correctness of the linear combination assert (l_of_x - d_of_x - k1 * p_of_x - k2 * p_of_x * x_to_the_steps - k3 * b_of_x - k4 * b_of_x * x_to_the_steps) % modulus == 0
其实还没有完成成功;证明对跨多项式检查和 FRI 所需的抽查次数的可靠性分析是非常棘手的 。但是这些就是所有代码,至少你不用担心进行疯狂的优化 。当我运行以上代码的时候 , 我们会获得STARK证明 , 会有300-400倍的证明成本例如,一个需要 0.2 秒的 MIMC 计算需要 60 秒来证明) 。这就使得4核机器计算MIMC中的 STARK,实际上可以比后向计算 MIMC 更快 。也就是说,在python语言,这会相对低效的实现,并且这也会证明运行时间比例会不同 。同时,也值得指出,MIMC 的 STARK 证明成本非常低 , 因为MIMC几乎是完美地可计算 , 它的数学形式很简单 。对于平均计算 , 会包含更少的清晰计算(例如,检查一个数是大于还是小于另一个),其计算成本可能会更高,会有大约10000-50000倍 。
python开环传递函数的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于如何将开环传递函数转化成闭环传递函数、python开环传递函数的信息别忘了在本站进行查找喔 。

    推荐阅读