iOS 开发实训第四周周报

一、学习笔记

( 摘自《iOS开发:从零基础到精通》)

多线程

  • NSThread 类:

    • NSThread 类是苹果官方提供的管理线程的类,提供了一些线程管理的方法,但是随着 GCD 和 NSOperation 的推出,NSThread 的使用场景已经大大减少,在实际的应用开发中,偶尔会使用 NSThread 类来获取一些线程信息,常用的方法如下:

      // 获取当前线程对象
      +(NSThread *)currentThread; 
      // 获取主线程对象
      +(NSThread *)mainThread; 
      // 使主线程休眠ti秒
      +(void)sleepForTimeInterval:(NSTimeInterval)ti; 
      
  • GCD(Grand Central Dispatch):

    • GCD 是 Apple 开发的一个多核编程的较新的解决方法,它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统,是一个在线程池模式的基础上执行的并发任务,GCD 已经完全屏蔽了有关线程的概念,而是引入了任务和队列,使用时只需要把任务(通常封装到一个 Block 中)添加到一个队列中执行即可,有关线程调用的工作将完全由 GCD 完成

    • 任务和队列:

      • 任务:即要执行的操作,通常封装到一个 Block 里,执行任务有两种方式:同步执行(sync)和异步执行(async),两者的主要区别是:是否等待队列的任务执行结束,以及是否具备开启新线程的能力

        // 异步:不需要等待,可以直接执行,具备开启新线程的能力
        dispatch_sync(queue, ^{
            // 这里放异步执行任务代码
        });
        
        // 同步:等到队列里面所有任务完成之后再执行,不具备开启新线程的能力
        dispatch_async(queue, ^{
            // 这里放同步执行任务代码
        });
        
      • 队列:即要执行任务的等待队列,队列是一种特殊的线性表,按照 FIFO 的原则,按任务添加到队列的顺序来对队列进行处理,可以分为并行队列和串行队列,两者的主要区别是:执行顺序不同,以及开启线程数不同

        // 获取系统定义的全局并行队列,一般不需要自己创建并行队列,而是用系统提供的
        // 第一个参数表示队列优先级,一般用DISPATCH_QUEUE_PRIORITY_DEFAULT;第二个参数暂时没用,用0即可
        dispatch_get_global_queue(long identifier, unsigned long flags);
        
        // 创建队列,一般用来创建串行队列
        // 第一个参数表示队列的唯一标识符,用于DEBUG,可为空,推荐使用应用程序ID这种逆序全程域名;第二个参数用来识别是串行队列还是并发队列,DISPATCH_QUEUE_SERIAL表示串行队列,DISPATCH_QUEUE_CONCURRENT 表示并发队列
        dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
        

        还有一种常用的队列是主队列,主队列也是串行队列,所有主队列中的任务都在主线程中执行

        // 获取主队列
        dispatch_get_main_queue(void);
        
      • 队列和任务的组合:因为有两种类型的任务和三种类型的队列,所以总共有六种组合使用的情况,区别如下:

        并行队列串行队列主队列
        同步任务没有开启新线程,串行执行任务没有开启新线程,串行执行任务主线程调用:死锁卡住不执行;其他线程调用:没有开启新线程,串行执行任务
        异步任务有开启新线程,并行执行任务只会开启一个新线程,串行执行任务不会开启新线程,串行执行任务
    • 线程间通信:

      • 由于 UI 的更新和操作是由主线程负责的,因此,当使用子线程获取到数据时(例如通过网络获取到了服务器返回的数据),需要返回主线程对 UI 进行更新,这就涉及了线程之间的通信,通常是在任务的最后加上一个访问主线程并更新 UI 的子任务
      - (IBAction)downLoadImageView:(id)sender {
          // 获取并行队列
          dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
          
          NSLog(@"0---%@", [NSThread currentThread]);
          
          // 异步任务
          dispatch_async(queue, ^{
              // 从网络下载图片
              NSString *urlString = @"http://7xta2c.com1.z0.glb.clouddn.com/99logo.png";
              NSURL *url = [NSURL URLWithString:urlString];
              NSData *imageData = [NSData dataWithContentsOfURL:url];
              UIImage *image = [UIImage imageWithData:imageData];
              NSLog(@"1---%@", [NSThread currentThread]);
              
              // 返回主线程设置UI
              dispatch_async(dispatch_get_main_queue(), ^{
                  self.imageView.image = image;
                  NSLog(@"2---%@", [NSThread currentThread]);
              });
              
          });
          
          NSLog(@"3---%@", [NSThread currentThread]);
      }
      
    • 队列组:

      • 使用 GCD 时,有时候会希望若干个任务之间有先后执行的依赖关系,比如当 A 、B 两个异步任务完成后再去做 C 任务,如果是用串行队列自然是可以实现,但是对于并行队列,任务会被自动分配到不同的线程中执行,任务完成的顺序是不确定的,这时候就要用到任务组 dispatch group

      • 相关的 API 如下:

        // 创建队列组
        dispatch_group_t dispatch_group_create(void);
        
        // 向队列组中插入一个异步任务
        void dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);
        
        // 队列组中其他任务完成后执行的任务,通常可以用来设置 UI
        void dispatch_group_notify(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);
        
      • 示例:点击按钮后启动两个异步下载任务,图片下载完成后更新屏幕上的 UIImageView,等两个下载都完成后,更新界面上的下载任务状态 Label 为下载完成

        - (IBAction)startTask:(id)sender {
            NSLog(@"0--%@", [NSThread currentThread]);
            // 创建队列组
            dispatch_group_t group = dispatch_group_create();
            // 创建并行队列
            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
            // 创建队列组中的第一个异步任务
            dispatch_group_async(group, queue, ^{
                NSLog(@"1.1--%@", [NSThread currentThread]);
                // 下载网络图片
                NSString *urlStr = @"http://7xta2c.com1.z0.glb.clouddn.com/99logo.png";
                NSURL *url = [NSURL URLWithString:urlStr];
                NSData *imageData = [NSData dataWithContentsOfURL:url];
                UIImage *image = [UIImage imageWithData:imageData];
                // 返回主队列设置图片
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"1.2--%@", [NSThread currentThread]);
                    self.task1ImageView.image = image;
                });
            });
            // 创建队列组中的第二个异步任务
            dispatch_group_async(group, queue, ^{
                NSLog(@"2.1--%@", [NSThread currentThread]);
                // 下载网络图片
                NSString *urlStr = @"http://7xta2c.com1.z0.glb.clouddn.com/99logo.png";
                NSURL *url = [NSURL URLWithString:urlStr];
                NSData *imageData = [NSData dataWithContentsOfURL:url];
                UIImage *image = [UIImage imageWithData:imageData];
                // 返回主队列设置图片
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"2.2--%@", [NSThread currentThread]);
                    self.task2ImageView.image = image;
                });
            });
            // 任务组中的任务完成后,执行的动作
            dispatch_group_notify(group, dispatch_get_main_queue(), ^{
                NSLog(@"3--%@", [NSThread currentThread]);
                self.taskLabel.text = @"下载完成";
            });
        }
        
    • 延迟执行操作:

      • GCD 中的 dispatch_after 方法:

        - (void)after {
            NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印当前线程
            NSLog(@"asyncMain---begin");
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                // 2.0秒后异步追加任务代码到主队列,并开始执行
                NSLog(@"after---%@",[NSThread currentThread]); // 打印当前线程
            });
        }
        

        需要注意的是:dispatch_after 函数并不是在指定时间之后才开始执行处理,而是在指定时间之后将任务追加到主队列中,严格来说,这个时间并不是绝对准确的,但想要大致延迟执行任务,dispatch_after 函数是很有效的

      • NSRunLoop 类中的方法:

        - (void)viewDidLoad {
            [super viewDidLoad];
            // 延迟2秒执行 printLog
            [self performSelector:@selector(printLog) withObject:nil afterDelay:2.0];
        }
        
        -(void) printLog {
            NSLog(@"延迟2.0秒后打印出来的日志!");
        }
        
        

        这个方法是对 NSObject 类的扩展,因此所有类都可以使用

  • NSOperation:

    • NSOperation 是基于 GCD 更高一层的封装,完全面向对象,但是比 GCD 更简单易用、代码可读性也更高,GCD 中的任务分别对应 NSOperation 中的操作和操作队列:

      • 操作(Operation):
        • 即在线程中要进行的操作(代码),在 GCD 中任务是放在 block 中的,而在 NSOperation 中,因为NSOperation 是个抽象类,是使用 NSOperation 子类 NSInvocationOperation、NSBlockOperation,或者自定义子类 CustomOperation(通过实现内部相应的方法)来封装操作的
      • 操作队列(Operation Queues):
        • 即用来存放操作的队列
        • 不同于 GCD 中的调度队列 FIFO(先进先出)的原则,NSOperationQueue 对于添加到队列中的操作,首先进入准备就绪的状态(就绪状态取决于操作之间的依赖关系),然后进入就绪状态的操作的开始执行顺序(不是结束执行顺序)由操作之间相对的优先级决定(优先级是操作对象自身的属性)
        • 操作队列通过设置最大并发操作数(maxConcurrentOperationCount)来控制并发或者串行
        • NSOperationQueue 为我们提供了两种不同类型的队列:主队列和自定义队列,主队列运行在主线程之上,而自定义队列在后台执行
    • 创建操作:

      • NSInvocationOperation:需要执行的任务直接指定已定义的方法
      - (void)useInvocationOperation {
          // 创建 NSInvocationOperation 对象
          NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task1) object:nil];
      
          // 在不创建队列的情况下,可以直接调用 NSOperation 类的 start 方法来执行某个任务,该任务会在当前线程开始执行
          [op start];
      }
      
      - (void)task1 {
          for (int i = 0; i < 2; i++) {
              [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
              NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程
          }
      }
      
      
      • NSBlockOperation:需要执行的任务封装在 Block 中
      - (void)useBlockOperation {
          // 创建 NSBlockOperation 对象
          NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
              for (int i = 0; i < 2; i++) {
                  [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
                  NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程
              }
          }];
      
          // 调用 start 方法开始执行操作
          [op start];
      }
      
      
      • 自定义继承自 NSOperation 的子类:可以通过重写 main 或者 start 方法 来定义自己的 NSOperation 对象,重写 main 方法比较简单,我们不需要管理操作的状态属性 isExecuting 和 isFinished,当 main 执行完返回的时候,这个操作就结束了

        • 先定义一个继承自 NSOperation 的子类,重写 main 方法

          // YSCOperation.h 文件
          #import <Foundation/Foundation.h>
          
          @interface YSCOperation : NSOperation
          
          @end
          
          // YSCOperation.m 文件
          #import "YSCOperation.h"
          
          @implementation YSCOperation
          
          - (void)main {
              if (!self.isCancelled) {
                  for (int i = 0; i < 2; i++) {
                      [NSThread sleepForTimeInterval:2];
                      NSLog(@"1---%@", [NSThread currentThread]);
                  }
              }
          }
          
          @end
          
          
        • 然后使用的时候导入头文件 YSCOperation.h

          - (void)useCustomOperation {
              // 创建 YSCOperation 对象
              YSCOperation *op = [[YSCOperation alloc] init];
              // 调用 start 方法开始执行操作
              [op start];
          }
          
          
    • 创建队列:

      • 主队列:凡是添加到主队列中的操作,都会放到主线程中执行(不包括操作使用addExecutionBlock 方法添加的额外操作,额外操作可能在其他线程执行)

        NSOperationQueue *queue = [NSOperationQueue mainQueue];
        
        
      • 自定义队列:添加到这种队列中的操作,就会自动放到子线程中执行

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        
        
    • 在任务中添加新任务:

      • 通过 addExecutionBlock 就可以为某个 NSOperation 对象添加额外的操作,当把这些新增的操作放到队列中执行时,也是并行执行的
      -(void)addTaskInOperation {
          NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
              NSLog(@"task1-----%@", [NSThread currentThread]);
          }];
          NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
              NSLog(@"task2-----%@", [NSThread currentThread]);
          }];
          // task1中添加task
          [task1 addExecutionBlock:^{
              NSLog(@"task1 add task-----%@", [NSThread currentThread]);
          }];
          // task2中添加task
          [task2 addExecutionBlock:^{
              NSLog(@"task2 add task-----%@", [NSThread currentThread]);
          }];
          // 创建队列
          NSOperationQueue *queue = [[NSOperationQueue alloc] init];
          // 添加任务到队列
          [queue addOperation:task1];
          [queue addOperation:task2];
      }
      
      
    • 在队列中添加任务:

      • 通过调用 NSOperationQueue 的 addOperationWithBlock 方法,可以向队列中直接添加任务
      -(void) addTaskInQueue {
          NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
              NSLog(@"task1-----%@", [NSThread currentThread]);
          }];
          NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
              NSLog(@"task2-----%@", [NSThread currentThread]);
          }];
          // 创建队列
          NSOperationQueue *queue = [[NSOperationQueue alloc] init];
          // 添加任务到队列
          [queue addOperation:task1];
          [queue addOperation:task2];
          // 在queue中添加任务
          [queue addOperationWithBlock:^{
              NSLog(@"queue task-----%@", [NSThread currentThread]);
          }];
      }
      
      
    • NSOperationQueue 控制串行执行、并行执行:

      • 通过设置最大并发操作数 maxConcurrentOperationCount 来控制并发或者串行
        • maxConcurrentOperationCount 默认情况下为-1,表示不进行限制,可以并发执行
        • maxConcurrentOperationCount 为1时,队列为串行队列,只能串行执行
        • maxConcurrentOperationCount 大于1时,队列为并发队列,操作并发执行,当然这个值不应超过系统限制,即使自己设置一个很大的值,系统也会自动调整为 min{自己设定的值,系统设定的默认最大值}
      - (void)setMaxConcurrentOperationCount {
      
          // 创建队列
          NSOperationQueue *queue = [[NSOperationQueue alloc] init];
      
          // 设置最大并发操作数
          queue.maxConcurrentOperationCount = 1; // 串行队列
      //  queue.maxConcurrentOperationCount = 2; // 并发队列
      //  queue.maxConcurrentOperationCount = 8; // 并发队列
      
          // 添加操作
          [queue addOperationWithBlock:^{
              for (int i = 0; i < 2; i++) {
                  [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
                  NSLog(@"1---%@", [NSThread currentThread]); // 打印当前线程
              }
          }];
          [queue addOperationWithBlock:^{
              for (int i = 0; i < 2; i++) {
                  [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
                  NSLog(@"2---%@", [NSThread currentThread]); // 打印当前线程
              }
          }];
          [queue addOperationWithBlock:^{
              for (int i = 0; i < 2; i++) {
                  [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
                  NSLog(@"3---%@", [NSThread currentThread]); // 打印当前线程
              }
          }];
          [queue addOperationWithBlock:^{
              for (int i = 0; i < 2; i++) {
                  [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
                  NSLog(@"4---%@", [NSThread currentThread]); // 打印当前线程
              }
          }];
      }
      
      
    • 线程间通信:于 GCD 类似

      - (IBAction)downloadImage:(id)sender {
          // 创建任务
          NSBlockOperation *downloadTask = [NSBlockOperation blockOperationWithBlock:^{
              // 下载网络图片
              NSString *urlStr = @"http://7xta2c.com1.z0.glb.clouddn.com/99logo.png";
              NSURL *url = [NSURL URLWithString:urlStr];
              NSData *imageData = [NSData dataWithContentsOfURL:url];
              UIImage *image = [UIImage imageWithData:imageData];
              // 返回主线程设置 UI
              NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
              [mainQueue addOperationWithBlock:^{
                  self.imageView.image = image;
              }];
          }];
          // 创建队列
          NSOperationQueue *queue = [[NSOperationQueue alloc] init];
          [queue addOperation:downloadTask];
      }
      
      
    • 任务间添加依赖:

      • 常用接口:

        // 添加依赖,使当前操作依赖于操作 op 的完成
        - (void)addDependency:(NSOperation *)op;
        
        // 移除依赖,取消当前操作对操作 op 的依赖
        - (void)removeDependency:(NSOperation *)op;
        
        // 在当前操作开始执行之前完成执行的所有操作对象数组
        @property (readonly, copy) NSArray<NSOperation *> *dependencies;
        
        
      • 示例:点击按钮后启动两个异步下载任务,图片下载完成后更新屏幕上的 UIImageView,等两个下载都完成后,更新界面上的下载任务状态 Label 为下载完成

        - (IBAction)downloadTwoImage:(id)sender {
            // 创建两个任务,两个任务完成后,返回主线程执行第三个更新Label的任务
            NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
                // 下载网络图片
                NSString *urlStr = @"http://7xta2c.com1.z0.glb.clouddn.com/99logo.png";
                NSURL *url = [NSURL URLWithString:urlStr];
                NSData *imageData = [NSData dataWithContentsOfURL:url];
                UIImage *image1 = [UIImage imageWithData:imageData];
                NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
                [mainQueue addOperationWithBlock:^{
                    self.imageView1.image = image1;
                }];
            }];
            NSBlockOperation *task2 = [NSBlockOperation blockOperationWithBlock:^{
                // 下载网络图片
                NSString *urlStr = @"http://7xta2c.com1.z0.glb.clouddn.com/99logo.png";
                NSURL *url = [NSURL URLWithString:urlStr];
                NSData *imageData = [NSData dataWithContentsOfURL:url];
                UIImage *image2 = [UIImage imageWithData:imageData];
                NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
                [mainQueue addOperationWithBlock:^{
                    self.imageView2.image = image2;
                }];
            }];
            NSBlockOperation *task3 = [NSBlockOperation blockOperationWithBlock:^{
                NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
                [mainQueue addOperationWithBlock:^{
                    self.label.text = @"下载完成";
                }];
            }];
            // 设置任务之间的执行依赖关系
            [task3 addDependency:task1];
            [task3 addDependency:task2];
            [task2 addDependency:task1];
            NSOperationQueue *queue = [[NSOperationQueue alloc] init];
            [queue addOperation:task1];
            [queue addOperation:task2];
            [queue addOperation:task3];
        }
        
        
    • 在任务中创建 completionBlock:

      • 可以通过设置 completionBlock 来创建所有任务执行完后自动调用的一个 Block,这个 Block 中的任务会在新的线程中执行
      -(void) addCompletionBlock {
          NSBlockOperation *task1 = [NSBlockOperation blockOperationWithBlock:^{
              NSLog(@"task1-----%@", [NSThread currentThread]);
          }];
          // task1中添加task
          [task1 addExecutionBlock:^{
              NSLog(@"task1 add task-----%@", [NSThread currentThread]);
          }];
          task1.completionBlock = ^{
              NSLog(@"task1 end!!! %@", [NSThread currentThread]);
          };
          // 创建队列
          NSOperationQueue *queue = [[NSOperationQueue alloc] init];
          // 添加任务到队列
          [queue addOperation:task1];
      }
      
      
    • 设置操作的优先级:

      • 只适用于同一操作队列中的操作,不适用于不同操作队列中的操作

      • 当一个操作的所有依赖都已经完成时,操作对象通常会进入准备就绪状态,等待执行

      • 进入就绪状态的操作的开始执行顺序(不是非结束执行顺序)由操作之间相对的优先级决定(优先级是操作对象自身的属性)

      • 优先级不能取代依赖关系

      • 默认情况下,所有新创建的操作对象优先级都是 NSOperationQueuePriorityNormal,但是我们可以通过 setQueuePriority 方法来改变当前操作在同一队列中的执行优先级

        // 优先级的取值
        typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
            NSOperationQueuePriorityVeryLow = -8L,
            NSOperationQueuePriorityLow = -4L,
            NSOperationQueuePriorityNormal = 0,
            NSOperationQueuePriorityHigh = 4,
            NSOperationQueuePriorityVeryHigh = 8
        };
        
        
  • GCD 和 NSOperation 的区别:

    • GCD 是底层的 C 语言构成的 API,而 NSOperationQueue 及相关对象是 Objective-C 的对象,在 GCD 中,在队列中执行的是由 Block 构成的任务,这是一个轻量级的数据结构;而 NSOperation 作为一个对象,提供了更多选择
    • 在 NSOperationQueue 中,可以随时取消已经设定要准备执行的任务(已经开始的任务无法阻止),而 GCD 要停止已经加入 queue 的 Block 需要极其复杂的操作
    • NSOperation 能够方便地设置依赖关系,可以让一个 Operation 依赖于另一个 Operation,这样的话尽管两个 Operation 在同一个并行队列中,前者也会等到后者执行完再执行
    • KVO 可以应用在 NSOperation 中,可以监听一个 Operation 是否完成或取消,这样能比 GCD 更有效地掌控执行的后台任务
    • 在 NSOperation 中,能够设置 NSOperation 的 priority 优先级,能够使同一个并行队列中的任务区分先后地进行;而在 GCD 中,只能区分不同任务队列的优先级,如果要区分 Block 任务的优先级,需要大量复杂的代码
    • 用户能对 NSOperation 进行继承,在这之上添加成员变量和成员方法,提高整个代码的复用度,这比简单地将 Block 任务排入执行队列更有自由度,能够在其之上添加更多自定制的功能
使用优化算法,以优化VMD算法的惩罚因子惩罚因子 (α) 和分解层数 (K)。 1、将量子粒子群优化(QPSO)算法与变分模态分解(VMD)算法结合 VMD算法背景: VMD算法是一种自适应信号分解算法,主要用于分解信号为不同频率带宽的模态。 VMD的关键参数包括: 惩罚因子 α:控制带宽的限制。 分解层数 K:决定分解出的模态数。 QPSO算法背景: 量子粒子群优化(QPSO)是一种基于粒子群优化(PSO)的一种改进算法,通过量子行为模型增强全局搜索能力。 QPSO通过粒子的量子行为使其在搜索空间中不受位置限制,从而提高算法的收敛速度与全局优化能力。 任务: 使用QPSO优化VMD中的惩罚因子 α 和分解层数 K,以获得信号分解的最佳效果。 计划: 定义适应度函数:适应度函数根据VMD分解的效果来定义,通常使用重构信号的误差(例如均方误差、交叉熵等)来衡量分解的质量。 初始化QPSO粒子:定义粒子的位置和速度,表示 α 和 K 两个参数。初始化时需要在一个合理的范围内为每个粒子分配初始位置。 执行VMD分解:对每一组 α 和 K 参数,运行VMD算法分解信号。 更新QPSO粒子:使用QPSO算法更新粒子的状态,根据适应度函数调整粒子的搜索方向和位置。 迭代求解:重复QPSO的粒子更新步骤,直到满足终止条件(如适应度函数达到设定阈值,或最大迭代次数)。 输出优化结果:最终,QPSO算法会返回一个优化的 α 和 K,从而使VMD分解效果最佳。 2、将极光粒子(PLO)算法与变分模态分解(VMD)算法结合 PLO的优点与适用性 强大的全局搜索能力:PLO通过模拟极光粒子的运动,能够更高效地探索复杂的多峰优化问题,避免陷入局部最优。 鲁棒性强:PLO在面对高维、多模态问题时有较好的适应性,因此适合海上风电时间序列这种非线性、多噪声的数据。 应用场景:PLO适合用于优化VMD参数(α 和 K),并将其用于风电时间序列的预测任务。 进一步优化的建议 a. 实现更细致的PLO更新策略,优化极光粒子的运动模型。 b. 将PLO优化后的VMD应用于真实的海上风电数据,结合LSTM或XGBoost等模型进行风电功率预测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值