『圖論』LCA 最近公共祖先

概述篇

LCA (Least Common Ancestors) ,即最近公共祖先,是指這樣的一個問題:在一棵有根樹中,找出某兩個節點 u 和 v 最近的公共祖先。

LCA 可分為在線算法與離線算法

  • 在線算法:指程序可以以序列化的方式一個一個處理輸入,也就是說在一開始並不需要知道所有的輸入。
  • 離線算法:指一開始就需要知道問題的所有輸入數據,而在解決一個問題后立即輸出結果。

算法篇

對於該問題,很容易想到的做法是從 u、v 分別回溯到根節點,然後這兩條路徑中的第一個交點即為 u、v 的最近公共祖先,在一棵平衡二叉樹中,該算法的時間複雜度可以達到 O(logn)O(log⁡n) ,但是對於某些退化為鏈狀的樹來說,算法的時間複雜度最壞為 O(n)O(n) ,顯然無法滿足更高頻率的查詢。

本節將介紹幾種比較高效的算法來解決這一問題,常見的算法有三種:在線 DFS + ST 算法、倍增算法、離線 Tarjan 算法。

接下來我們來一一解釋這三種 /* 看似高深,其實也不簡單 */ 的算法。

在線 DFS + ST 算法

首先看到 ST 你會想到什麼呢?(腦補許久都沒有想到它會是哪個單詞的縮寫)

看過前文 『數據結構』RMQ 問題 的話你便可以明白 ST算法 的思路啦~

So ,關於 LCA 的這種在線算法也是可以建立在 RMQ 問題的基礎上咯~

我們設 LCA(T,u,v) 為在有根樹 T 中節點 u、v 的最近公共祖先, RMQ(A,i,j) 為線性序列 A 中區間 [i,j] 上的最小(大)值。

如下圖這棵有根樹:

我們令節點編號滿足父節點編號小於子節點編號(編號條件)

可以看出 LCA(T,4,5) = 2, LCA(T,2,8) = 1, LCA(T,3,9) = 3 。

設線性序列 A 為有根樹 T 的中序遍歷,即 A = [4,2,5,1,8,6,9,3,7] 。

由中序遍歷的性質我們可以知道,任意兩點 u、v 的最近公共祖先總在以該兩點所在位置為端點的區間內,且編號最小。

舉個栗子:

假設 u = 8, v = 7 ,則該兩點所確定的一段區間為 [8,6,9,3,7] ,而區間最小值為 3 ,也就是說,節點 3 為 u、v 的最近公共祖先。

解決區間最值問題我們可以採用 RMQ 問題中的 ST 算法 。

但是在有些問題中給出的節點並不一定滿足我們所說的父節點編號小於子節點編號,因此我們可以利用節點間的關係建圖,然後採用前序遍歷來為每一個節點重新編號以生成線性序列 A ,於是問題又被轉化為了區間最值的查詢,和之前一樣的做法咯~

時間複雜度: n×O(logn)n×O(log⁡n) 預處理 + O(1)O(1) 查詢

想了解 RMQ 問題 的解法可以戳上面的鏈接哦~

以上部分介紹了 LCA 如何轉化為 RMQ 問題,而在實際中這兩種方案之間可以相互轉化

類比之前的做法,我們如何將一個線性序列轉化為滿足編號條件的有根樹呢?

  1. 設序列中的最小值為 AkAk ,建立優先級為 AkAk 的根節點 TkTk
  2. 將 A[1…k−1]A[1…k−1] 遞歸建樹作為 TkTk 的左子樹
  3. 將 A[k+1…n]A[k+1…n] 遞歸建樹作為 TkTk 的右子樹

讀者可以試着利用此方法將之前的線性序列 A = [4,2,5,1,8,6,9,3,7] 構造出有根樹 T ,結果一定滿足之前所說的編號條件,但卻不一定唯一。

離線 Tarjan 算法

Tarjan 算法是一種常見的用於解決 LCA 問題的離線算法,它結合了深度優先搜索與並查集,整個算法為線性處理時間。

首先來介紹一下 Tarjan 算法的基本思路:

  1. 任選一個節點為根節點,從根節點開始
  2. 遍歷該點 u 的所有子節點 v ,並標記 v 已經被訪問過
  3. 若 v 還有子節點,返回 2 ,否則下一步
  4. 合併 v 到 u 所在集合
  5. 尋找與當前點 u 有詢問關係的點 e
  6. 若 e 已經被訪問過,則可以確定 u、e 的最近公共祖先為 e 被合併到的父親節點

偽代碼:

Tarjan(u)               // merge 和 find 為並查集合併函數和查找函數
{
    for each(u,v)       // 遍歷 u 的所有子節點 v
    {
        Tarjan(v);      // 繼續往下遍歷
        merge(u,v);     // 合併 v 到 u 這一集合
        標記 v 已被訪問過;
    }
    for each(u,e)       // 遍歷所有與 u 有查詢關係的 e
    {
        if (e 被訪問過)
            u, e 的最近公共祖先為 find(e);
    }
}
C++

感覺講到這裏已經沒有其它內容了,但是一定會有好多人沒有理解怎麼辦呢?

我們假設在如下樹中模擬 Tarjan 過程(節點數量少一點可以畫更少的圖o( ̄▽ ̄)o)

存在查詢: LCA(T,3,4)、LCA(T,4,6)、LCA(T,2,1) 。

注意:每個節點的顏色代表它當前屬於哪一個集合,橙色線條為搜索路徑,黑色線條為合併路徑。

當前所在位置為 u = 1 ,未遍歷孩子集合 v = {2,5} ,向下遍歷。

當前所在位置為 u = 2 ,未遍歷孩子集合 v = {3,4} ,向下遍歷。

當前所在位置為 u = 3 ,未遍歷孩子集合 v = {} ,遞歸到達最底層,遍歷所有相關查詢發現存在 LCA(T,3,4) ,但是節點 4 此時標記未訪問,因此什麼也不做,該層遞歸結束。

遞歸返回,當前所在位置 u = 2 ,合併節點 3 到 u 所在集合,標記 vis[3] = true ,此時未遍歷孩子集合 v = {4} ,向下遍歷。

當前所在位置 u = 4 ,未遍歷孩子集合 v = {} ,遍歷所有相關查詢發現存在 LCA(T,3,4) ,且 vis[3] = true ,此時得到該查詢的解為節點 3 所在集合的首領,即 LCA(T,3,4) = 2 ;又發現存在相關查詢 LCA(T,4,6) ,但是節點 6 此時標記未訪問,因此什麼也不做。該層遞歸結束。

遞歸返回,當前所在位置 u = 2 ,合併節點 4 到 u 所在集合,標記 vis[4] = true ,未遍歷孩子集合 v = {} ,遍歷相關查詢發現存在 LCA(T,2,1) ,但是節點 1 此時標記未訪問,因此什麼也不做,該層遞歸結束。

遞歸返回,當前所在位置 u = 1 ,合併節點 2 到 u 所在集合,標記 vis[2] = true ,未遍歷孩子集合 v = {5} ,繼續向下遍歷。

當前所在位置 u = 5 ,未遍歷孩子集合 v = {6} ,繼續向下遍歷。

當前所在位置 u = 6 ,未遍歷孩子集合 v = {} ,遍歷相關查詢發現存在 LCA(T,4,6) ,且 vis[4] = true ,因此得到該查詢的解為節點 4 所在集合的首領,即 LCA(T,4,6) = 1 ,該層遞歸結束。

遞歸返回,當前所在位置 u = 5 ,合併節點 6 到 u 所在集合,並標記 vis[6] = true ,未遍歷孩子集合 v = {} ,無相關查詢因此該層遞歸結束。

遞歸返回,當前所在位置 u = 1 ,合併節點 5 到 u 所在集合,並標記 vis[5] = true ,未遍歷孩子集合 v = {} ,遍歷相關查詢發現存在 LCA(T,2,1) ,此時該查詢的解便是節點 2 所在集合的首領,即 LCA(T,2,1) = 1 ,遞歸結束。

至此整個 Tarjan 算法便結束啦~

PS:不要在意最終根節點的顏色和其他節點顏色有一點點小小差距,可能是在染色的時候沒仔細看,總之就這樣咯~

PPS:所謂的首領就是、就是首領啦~

倍增算法

哇!還有一個倍增算法以後繼續補充吧!

總結篇

對於不同的 LCA 問題我們可以選擇不同的算法。

假若一棵樹存在動態更新,此時離線算法就顯得有點力不從心了,但是在其他情況下,離線算法往往效率更高(雖然不能保證得到解的順序與輸入一致,不過我們有 sort 呀)

總之,喜歡哪種風格的 code 是我們自己的意願咯~

另外, LCA 和 RMQ 問題是兩個非常基礎的問題,很多複雜問題都可以轉化為這兩類問題來解決。(當然這兩類問題之間也可以相互轉化啦~)

參考資料

OI wiki https://oi-wiki.org/graph/lca/

https://blog.csdn.net/my_sunshine26/article/details/72717112

https://wizardforcel.gitbooks.io/the-art-of-programming-by-july/content/03.03.html

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※FB行銷專家,教你從零開始的技巧

燒庫存惹議 Burberry停止銷毀並捨棄真皮草

摘錄自2018年9月6日中央社報導

英國時尚品牌Burberry表示,未來將不再燒毀價值數百萬英鎊計的庫存商品,也不再於產品中使用真皮草。

路透社報導,Burberry在上個財政年度報告中,承認燒毀價值高達2860萬英鎊(約新台幣11.7億元)商品後,表示會致力於讓公司在社會和環境議題更負責任。

Burberry還表示,將追隨Versace、Gucci和道德時尚品牌先驅Stella McCartney的腳步,從系列產品中去除真皮,如兔子,狐狸,貂、亞洲浣熊等的皮毛。Burberry新設計師里卡多提西(Riccardo Tisci)首發系列將不含任何皮草。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※FB行銷專家,教你從零開始的技巧

小師妹學JVM之:深入理解JIT和編譯優化-你看不懂系列

目錄

  • 簡介
  • JIT編譯器
  • Tiered Compilation分層編譯
  • OSR(On-Stack Replacement)
  • Deoptimization
  • 常見的編譯優化舉例
    • Inlining內聯
    • Branch Prediction分支預測
    • Loop unswitching
    • Loop unrolling展開
    • Escape analysis逃逸分析
  • 總結

簡介

小師妹已經學完JVM的簡單部分了,接下來要進入的是JVM中比較晦澀難懂的概念,這些概念是那麼的枯燥乏味,甚至還有點惹人討厭,但是要想深入理解JVM,這些概念是必須的,我將會盡量嘗試用簡單的例子來解釋它們,但一定會有人看不懂,沒關係,這個系列本不是給所有人看的。

更多精彩內容且看:

  • 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
  • java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程

JIT編譯器

小師妹:F師兄,我的基礎已經打牢了嗎?可以進入這麼複雜的內容環節了嗎?

小師妹不試試怎麼知道不行呢?了解點深入內容可以幫助你更好的理解之前的知識。現在我們開始吧。

上次我們在講java程序的處理流程的時候,還記得那通用的幾步吧。

小師妹:當然記得了,編寫源代碼,javac編譯成字節碼,加載到JVM中執行。

對,其實在JVM的執行引擎中,有三個部分:解釋器,JIT編譯器和垃圾回收器。

解釋器會將前面編譯生成的字節碼翻譯成機器語言,因為每次都要翻譯,相當於比直接編譯成機器碼要多了一步,所以java執行起來會比較慢。

為了解決這個問題,JVM引入了JIT(Just-in-Time)編譯器,將熱點代碼編譯成為機器碼。

Tiered Compilation分層編譯

小師妹你知道嗎?在JDK8之前,HotSpot VM又分為三種。分別是 client VM, server VM, 和 minimal VM,分別用在客戶端,服務器,和嵌入式系統。

但是隨着硬件技術的發展,這些硬件上面的限制都不是什麼大事了。所以從JDK8之後,已經不再區分這些VM了,現在統一使用VM的實現來替代他們。

小師妹,你覺得Client VM和Server VM的本質區別在哪一部分呢?

小師妹,編譯成字節碼應該都是使用javac,都是同樣的命令,字節碼上面肯定是一樣的。難點是在執行引擎上面的不同?

說的對,因為Client VM和Server VM的出現,所以在JIT中出現了兩種不同的編譯器,C1 for Client VM, C2 for Server VM。

因為javac的編譯只能做少量的優化,其實大量的動態優化是在JIT中做的。C2相對於C1,其優化的程度更深,更加激進。

為了更好的提升編譯效率,JVM在JDK7中引入了分層編譯Tiered compilation的概念。

對於JIT本身來說,動態編譯是需要佔用用戶內存空間的,有可能會造成較高的延遲。

對於Server服務器來說,因為代碼要服務很多個client,所以磨刀不誤砍柴工,短暫的延遲帶來永久的收益,聽起來是可以接受的。

Server端的JIT編譯也不是立馬進行的,它可能需要收集到足夠多的信息之後,才進行編譯。

而對於Client來說,延遲帶來的性能影響就需要進行考慮了。和Server相比,它只進行了簡單的機器碼的編譯。

為了滿足不同層次的編譯需求,於是引入了分層編譯的概念。

大概來說分層編譯可以分為三層:

  1. 第一層就是禁用C1和C2編譯器,這個時候沒有JIT進行。
  2. 第二層就是只開啟C1編譯器,因為C1編譯器只會進行一些簡單的JIT優化,所以這個可以應對常規情況。
  3. 第三層就是同時開啟C1和C2編譯器。

在JDK7中,你可以使用下面的命令來開啟分層編譯:

-XX:+TieredCompilation

而在JDK8之後,恭喜你,分層編譯已經是默認的選項了,不用再手動開啟。

OSR(On-Stack Replacement)

小師妹:F師兄,你剛剛講到Server的JIT不是立馬就進行編譯的,它會等待一定的時間來搜集所需的信息,那麼代碼不是要從字節碼轉換成機器碼?

對的,這個過程就叫做OSR(On-Stack Replacement)。為什麼叫OSR呢?我們知道JVM的底層實現是一個棧的虛擬機,所以這個替換實際上是一系列的Stack操作。

上圖所示,m1方法從最初的解釋frame變成了後面的compiled frame。

Deoptimization

這個世界是平衡的,有陰就有陽,有優化就有反優化。

小師妹:F師兄,為什麼優化了之後還要反優化呢?這樣對性能不是下降了嗎?

通常來說是這樣的,但是有些特殊的情況下面,確實是需要進行反優化的。

下面是比較常見的情況:

  1. 需要調試的情況

如果代碼正在進行單個步驟的調試,那麼之前被編譯成為機器碼的代碼需要反優化回來,從而能夠調試。

  1. 代碼廢棄的情況

當一個被編譯過的方法,因為種種原因不可用了,這個時候就需要將其反優化。

  1. 優化之前編譯的代碼

有可能出現之前優化過的代碼可能不夠完美,需要重新優化的情況,這種情況下同樣也需要進行反優化。

常見的編譯優化舉例

除了JIT編譯成機器碼之外,JIT還有一下常見的代碼優化方式,我們來一一介紹。

Inlining內聯

舉個例子:

int a = 1;
int b = 2;
int result = add(a, b);
...
public int add(int x, int y) { return x + y; }
int result = a + b; //內聯替換

上面的add方法可以簡單的被替換成為內聯表達式。

Branch Prediction分支預測

通常來說對於條件分支,因為需要有一個if的判斷條件,JVM需要在執行完畢判斷條件,得到返回結果之後,才能夠繼續準備後面的執行代碼,如果有了分支預測,那麼JVM可以提前準備相應的執行代碼,如果分支檢查成功就直接執行,省去了代碼準備的步驟。

比如下面的代碼:

// make an array of random doubles 0..1
double[] bigArray = makeBigArray();
for (int i = 0; i < bigArray.length; i++)
{
 double cur = bigArray[i];
 if (cur > 0.5) { doThis();} else { doThat();}
}

Loop unswitching

如果我們在循環語句裏面添加了if語句,為了提升併發的執行效率,可以將if語句從循環中提取出來:

  int i, w, x[1000], y[1000];
  for (i = 0; i < 1000; i++) {
    x[i] += y[i];
    if (w)
      y[i] = 0;
  }

可以改為下面的方式:

  int i, w, x[1000], y[1000];
  if (w) {
    for (i = 0; i < 1000; i++) {
      x[i] += y[i];
      y[i] = 0;
    }
  } else {
    for (i = 0; i < 1000; i++) {
      x[i] += y[i];
    }
  }

Loop unrolling展開

在循環語句中,因為要不斷的進行跳轉,所以限制了執行的速度,我們可以對循環語句中的邏輯進行適當的展開:

 int x;
 for (x = 0; x < 100; x++)
 {
     delete(x);
 }

轉變為:

 int x; 
 for (x = 0; x < 100; x += 5 )
 {
     delete(x);
     delete(x + 1);
     delete(x + 2);
     delete(x + 3);
     delete(x + 4);
 }

雖然循環體變長了,但是跳轉次數變少了,其實是可以提升執行速度的。

Escape analysis逃逸分析

什麼叫逃逸分析呢?簡單點講就是分析這個線程中的對象,有沒有可能會被其他對象或者線程所訪問,如果有的話,那麼這個對象應該在Heap中分配,這樣才能讓對其他的對象可見。

如果沒有其他的對象訪問,那麼完全可以在stack中分配這個對象,棧上分配肯定比堆上分配要快,因為不用考慮同步的問題。

我們舉個例子:

  public static void main(String[] args) {
    example();
  }
  public static void example() {
    Foo foo = new Foo(); //alloc
    Bar bar = new Bar(); //alloc
    bar.setFoo(foo);
  }
}

class Foo {}

class Bar {
  private Foo foo;
  public void setFoo(Foo foo) {
    this.foo = foo;
  }
}

上面的例子中,setFoo引用了foo對象,如果bar對象是在heap中分配的話,那麼引用的foo對象就逃逸了,也需要被分配在heap空間中。

但是因為bar和foo對象都只是在example方法中調用的,所以,JVM可以分析出來沒有其他的對象需要引用他們,那麼直接在example的方法棧中分配這兩個對象即可。

逃逸分析還有一個作用就是lock coarsening。

為了在多線程環境中保證資源的有序訪問,JVM引入了鎖的概念,雖然鎖可以保證多線程的有序執行,但是如果實在單線程環境中呢?是不是還需要一直使用鎖呢?

比如下面的例子:

public String getNames() {
     Vector<String> v = new Vector<>();
     v.add("Me");
     v.add("You");
     v.add("Her");
     return v.toString();
}

Vector是一個同步對象,如果是在單線程環境中,這個同步鎖是沒有意義的,因此在JDK6之後,鎖只在被需要的時候才會使用。

這樣就能提升程序的執行效率。

總結

本文介紹了JIT的原理和一些基本的優化方式。後面我們會繼續探索JIT和JVM的秘密,敬請期待。

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/jvm-jit-in-detail/

本文來源:flydean的博客

歡迎關注我的公眾號:程序那些事,更多精彩等着您!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

Spring Cloud Alibaba系列(四)使用gateway作為服務網關

什麼是網關

在微服務架構里,服務的粒度被進一步細分,各個業務服務可以被獨立的設計、開發、測試、部署和管理。這時,各個獨立部署單元可以用不同的開發測試團隊維護,可以使用不同的編程語言和技術平台進行設計,這就要求必須使用一種語言和平台無關的服務協議作為各個單元間的通訊方式。

換句話說就是網關為所有的請求提供了統一的入口,方便我們對服務請求和響應做統一管理。

為什麼要用網關

API 網關是一個處於應用程序或服務(提供 REST API 接口服務)之前的系統,用來管理授權、訪問控制和流量限制等,這樣 REST API 接口服務就被 API 網關保護起來,對所有的調用者透明。

什麼是gateway

Spring Cloud Gateway是Spring官方基於Spring 5.0,Spring Boot 2.0和Project Reactor等技術開發的網關,Spring Cloud Gateway旨在為微服務架構提供一種簡單而有效的統一的API路由管理方式。Spring Cloud Gateway作為Spring Cloud生態系中的網關,目標是替代ZUUL,其不僅提供統一的路由方式,並且基於Filter鏈的方式提供了網關基本的功能,例如:安全,監控/埋點,和限流等。

gateway工作原理

客戶端向Spring Cloud網關發出請求。如果網關處理程序映射確定請求與路由匹配,則將其發送到網關Web處理程序。該處理程序運行通過特定於請求的過濾器鏈發送請求。過濾器由虛線分隔的原因是,過濾器可以在發送代理請求之前或之後執行邏輯。執行所有“前置”過濾器邏輯,然後發出代理請求。發出代理請求后,將執行“后”過濾器邏輯。

路由規則

路由和過濾器是gateway中非常重要的兩個概念,gateway本身提供了非常豐富的路由規則和多種過濾器來適配我們的需求。gateway提供了11種路由規則,分別是:

  • 後置路由謂詞工廠

    該謂詞匹配在當前日期時間之後發生的請求。參數名為 After

  • 前置路由謂詞工廠

    該謂詞匹配當前日期時間之前發生的請求。參數名為 Before

  • 時間段路由謂詞工廠

    該謂詞匹配在datetime1之後和datetime2之前發生的請求。參數名為 Between

  • cookie路由謂詞工廠

    該謂詞匹配具有給定名稱的cookie,並且值匹配正則表達式。參數名為 Cookie

  • 標頭路由謂詞工廠

    該謂詞與具有給定名稱的標頭匹配,並且值與正則表達式匹配。參數名為 Header

  • 主機路由謂詞工廠

    該謂詞是指由路由進行匹配,匹配多個路由時用,隔開。參數名為 Host

  • 方法路由謂詞工廠

    該參數是一個或多個要匹配的HTTP方法。參數名為 Method

  • 路徑路由謂詞工廠

    該謂詞是指在請求路徑上加一個前綴,以此來匹配。參數名為 Path

  • 查詢路由謂詞工廠

  • RemoteAddr路由謂詞工廠

  • 重量路線謂詞工廠

其中,我們比較常用的就是路徑路由謂詞工廠,配合StripPrefix GatewayFilter工廠,實現我們的路由匹配轉發。

路徑路由謂詞工廠配置如下:

spring:
  cloud:
    gateway:
	  discovery:
          locator:
          	enabled: true # 開啟從註冊中心動態創建路由的功能,利用微服務名稱進行路由
      routes:
          # 路由id,建議配合服務名
        - id: demo_route 
          #匹配路由名
          uri: lb://demo-provider 
          predicates:
	  # 斷言,路徑相匹配的進行路由
          - Path=/demo/** 

配置的含義就是,如果請求路徑中是/demo/**,則轉發到demo-provider服務。

網關過濾器

在spring cloud gateway 2.2.2.RELEASE版本中,已經默認實現了30種過濾器。

序號 過濾器工廠 作用 參數
1 AddRequestHeader 為原始請求添加Header Header的名稱及值
2 AddRequestParameter 為原始請求添加請求參數 參數名稱及值
3 AddResponseHeader 為原始響應添加Header Header的名稱及值
4 DedupeResponseHeader 剔除響應頭中重複的值 需要去重的Header名稱及去重策略
5 Hystrix 為路由引入Hystrix的斷路器保護 HystrixCommand的名稱
6 CircuitBreaker 為路由引入Resilience4J斷路器保護 CircuitBreaker的名稱
7 FallbackHeaders 為fallbackUri的請求頭中添加具體的異常信息 Header的名稱
MapRequestHeader 更新原始請求中的Header Header的值
9 PrefixPath 為原始請求頭添加前綴 前綴路徑
10 PreserveHostHeader 為請求添加preserverHostHeader=true的屬性,路由過濾器會檢查該屬性以決定是否要發送原始的host 無
11 RequestRateLimiter 用於對請求限流,限流算法為令牌桶 keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus
12 RedirectTo 將原始請求重定向到指定的url http狀態碼及重定向的url
13 RemoveHopByHopHeadersFilter 為原始請求刪除IETF組織規定的一系列Header 默認就會啟用,可以通過配置指定僅刪除哪些Header
14 RemoveRequestHeader 為原始請求刪除某個Header Header名稱
15 RemoveResponseHeader 為原始響應刪除某個Header Header名稱
16 RewritePath 重寫原始的請求路徑 原始路徑正則表達式以及重寫後路徑的正則表達式
RewriteLocationResponseHeader 重寫響應頭的Location 的值
18 RewriteResponseHeader 重寫原始響應中的某個Header Header名稱,值的正則表達式,重寫后的值
19 SaveSession 在轉發請求之前,強制執行WebSession::save操作 無
20 SecureHeaders 為原始響應添加一系列起安全作用的響應頭 無,支持修改這些安全響應頭的值
21 SetPath 修改原始的請求路徑 修改后的值
22 SetRequestHeader 修改原始請求中的某個Header的值 Header名稱,修改后的值
23 SetResponseHeader 修改原始響應中某個Header的值 Header名稱,修改后的值
24 SetStatus 修改原始響應的狀態碼 HTTP 狀態碼,可以是数字,也可以是字符串
25 StripPrefix 用於截斷原始請求的路徑 使用數字錶示要截斷的路徑的數量
26 Retry 針對不同的響應進行重試 retries、statuses、methods、series
27 RequestSize 設置允許接收最大請求包的大小。如果請求包大小超過設置的值,則返回 413 Payload Too Large設置允許接收最大請求包的大小。如果請求包大小超過設置的值,則返回 413 Payload Too Large 請求包大小,單位為字節,默認值為5M
28 ModifyRequestBody 在轉發請求之前修改原始請求體內容 修改后的請求體內容
29 ModifyResponseBody 修改原始響應體的內容 修改后的響應體內容
30 Default 為所有路由添加過濾器 過濾器工廠名稱及值

這裏比較常用的如第25種,配置如下:

spring:
  cloud:
    gateway:
	  discovery:
          locator:
          	enabled: true # 開啟從註冊中心動態創建路由的功能,利用微服務名稱進行路由
      routes:
		  # 路由id,建議配合服務名
        - id: demo_route 
          #匹配路由名
          uri: lb://demo-provider 
          predicates:
		  # 斷言,路徑相匹配的進行路由
          - Path=/demo/** 
          filters:
          - StripPrefix=1

一般情況下我們配合path路由使用,這裏的意思是假如,我們的demo-provider服務種有一個/test的接口,實際上我們的請求路徑經過網關時應該時/demo/test,這樣就能把這個路由分發到demo-provider服務中,但是分發過去的路由是/demo/test,和我們實際的/test接口不一樣。這時候我們用StripPrefix=1,來截取掉一級路由,這樣轉發過去的路由就是/test了。

自定義網關過濾器

除了上面提供的30種過濾器外,我們還可以實現自定義的過濾器。

1. 實現GatewayFilter接口和Ordered接口

gatewayFilter接口是為了實現請求過濾,ordered接口是為了給過濾器設定優先級,值越大級別越低。

想要實現一個自定義的過濾器,無非就是兩個步驟:1.實現過濾器,2.將過濾器添加到具體路由上。

public class TokenGatewayFilter implements GatewayFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        System.out.println("這裏處理自身邏輯");

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

@Configuration
class RouteConfiguration{

    @Bean
    public RouteLocator routeLocator(RouteLocatorBuilder builder){

        return builder.routes().route( r->
                r.path("/demo/**")
                .uri("lb://demo-provider ")
                .filter(new TokenGatewayFilter())
                .id("demo_route "))
                .build();
    }
}

2.繼承AbstractGatewayFilterFactory類

@Component
public class TokenCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenCheckGatewayFilterFactory.Config> {
    public TokenCheckGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("enabled");
    }
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
        	system.out.println("這裏處理自身邏輯")
            return chain.filter(exchange);
        };

    }

    public static class Config {
        // 控制是否開啟認證
        private boolean enabled = true;

        public Config() {}

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }
    }
}

這裏我們可以直接在application.yml中為需要過濾的路由添加這個過濾器。

spring:
  cloud:
    gateway:
      routes:
        - id: demo_route # 路由id,建議配合服務名
          uri: lb://demo-provider #匹配路由名
          predicates:
          - Path=/demo/** # 斷言,路徑相匹配的進行路由
          filters:
          - TokenCheck=true

需要注意的是,這個地方自定義的過濾器名稱必須是XXGatewayFilterFactory,並且配置文件中配置過濾器時名字必須時這個XX。

當然,我們也可以為每個路由都添加這個過濾器,可以直接這樣寫配置,而不用在每個路由上都去寫。

spring:
  cloud:
    gateway:
      default-filters:
        - TokenCheck=true

3.實現GlobalFilter和ordered

這個GlobalFilter從名字中就可以看出,是一個全局過濾器,也就是說實現這個接口后,所有的請求都會被過濾,我們就不需要在去找往某個路由中加過濾器了。

@Component
public class TokenGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("這裏處理自身邏輯");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

以上就是實現自定義網關過濾器的三種方式了。實際開發中根據需求來實現合適的過濾器就可以了。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

Dotnet core基於ML.net的銷售數據預測實踐

ML.net已經進到了1.5版本。作為Microsoft官方的機器學習模型,你不打算用用?

 

一、前言

ML.net可以讓我們很容易地在各種應用場景中將機器學習加入到應用程序中。這是這個框架很重要的一點。

通過ML.net,我們可以使用手中的可用數據,進行預測、分析、檢測,而不需要進行過於複雜的編程。

ML.net的核心,同樣是機器學習模型。它採用同樣的步驟,通過指定算法來訓練模型,將輸入數據轉換為所需的預測數據。

更重要的是,ML.net基於.NET Core,這讓它可以非常簡單地跨平台,在Windows、Linux、MacOS上運行,並成為我們服務端的一部分內容。

 

回到今天的主題。

我們用實際的例子,完成一個通過歷史銷售數據進行單變量時序分析(單譜分析),以預測未來銷量的需求。

    為了防止不提供原網址的轉載,特在這裏加上原文鏈接:https://www.cnblogs.com/tiger-wang/p/13150021.html

二、開發環境&基礎工程

這個Demo的開發環境是:Mac + VS Code + Dotnet Core 3.1.2。

$ dotnet --info
.NET Core SDK (reflecting any global.json):
 Version:   3.1.201
 Commit:    b1768b4ae7

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  10.15
 OS Platform: Darwin
 RID:         osx.10.15-x64
 Base Path:   /usr/local/share/dotnet/sdk/3.1.201/

Host (useful for support):
  Version: 3.1.3
  Commit:  4a9f85e9f8

.NET Core SDKs installed:
  3.1.201 [/usr/local/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.App 3.1.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

 

首先,在這個環境下建立工程:

  1. 創建Solution
% dotnet new sln -o demo
The template "Solution File" was created successfully.
  1. 這次,我們用Console創建工程
% cd demo
% dotnet new console -o demo
The template "Console Application" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on demo/demo.csproj...
  Determining projects to restore...
  Restored demo/demo.csproj (in 143 ms).

Restore succeeded.
  1. 把工程加到Solution中
% dotnet sln add demo/demo.csproj

基礎工程搭建完成。

三、引入ML.net庫

為了使用ML.net,我們需要引入Microsoft.ML庫:

% cd demo
% dotnet add package Microsoft.ML

除此之外,本文是基於時序的預測,還需要引入時序庫Microsoft.ML.TimeSeries:

% dotnet add package Microsoft.ML.TimeSeries

 

我們今天用到的算法是單譜分析(SSA)。SSA會將時序分解為一組主要成分, 並將這些成分解釋為信號,對應於趨勢、噪音、季節性及許多其他的因素,然後重新構建這些成分,用來預測未來某個時間的值。

四、準備數據

為了這個DEMO,我準備了一個包含全年365天實際銷售金額的數據。

其中這個數據又分為了兩部分,第一部分是前11個月的數據,用來做訓練,第二部分是12月一個月的數據,用來評估模型。

兩部分數據的鏈接如下:訓練數據,評估數據

兩個數據文件均為CSV文件,數據結構完全相同,下面是一段內容範例:

2018-12-21,17959.0
2018-12-22,19537.03
2018-12-23,20068.0
2018-12-24,20013.0
2018-12-25,21005.0
2018-12-26,16876.0
2018-12-27,15150.0
2018-12-28,15669.0
2018-12-29,25048.0
2018-12-30,25236.0

五、代碼開發

  1. 準備一個輸入模型ModelInput
public class ModelInput
{

    [LoadColumn(0)]
    public DateTime action_time { get; set; }
    [LoadColumn(1)]
    public float count { get; set; }
}

這個模型對應數據文件的結構,分兩個字段,第一個是日期,第二個是對應的銷售金額。

  1. 準備另一個輸出模型ModelOutput
public class ModelOutput
{

    public float[] forecasted_count { get; set; }
    public float[] lower_count { get; set; }
    public float[] upper_count { get; set; }
}

這個模型跟隨預測結果的輸出,其中:

  • forecasted_count – 預測時間段內的預測值
  • lower_count – 預測時間段內預測值的下限
  • upper_count – 預測時間段內預測值的上限

 

  1. 初始化機器學習的實例
MLContext mlContext = new MLContext();

執行所有 ML.NET 操作都是從MLContext類開始,初始化 MLContext將創建一個新的 ML.net 環境,並在模型創建工作流對象之間共享該環境。

  1. 加載數據

ML.net有多種數據的加載方式,可以通過文件、數據庫、JSON/XML、內存中加載數據,甚至可以用自定義的數據庫連接加載數據。

本文的DEMO中,數據在CSV文件中,所以,我們採用下面的方式加載:

static readonly string _data1Path = Path.Combine(Environment.CurrentDirectory, "data1.csv");
static readonly string _data2Path = Path.Combine(Environment.CurrentDirectory, "data2.csv");

static void Main(string[] args)
{
    MLContext mlContext = new MLContext();

    IDataView data1View = mlContext.Data.LoadFromTextFile<ModelInput>(_data1Path, separatorChar: ',', hasHeader: false);
    IDataView data2View = mlContext.Data.LoadFromTextFile<ModelInput>(_data2Path, separatorChar: ',', hasHeader: false);
}

IDataView是數據的承載空間。

  1. 定義時序分析管道
var forecastingPipeline = mlContext.Forecasting.ForecastBySsa(
    outputColumnName: "forecasted_count",
    inputColumnName: "count",
    windowSize: 7,
    seriesLength: 30,
    trainSize: 334,
    horizon: 7,
    confidenceLevel: 0.95f,
    confidenceLowerBoundColumn: "lower_count",
    confidenceUpperBoundColumn: "upper_count");

前面有說過,我們採用單譜分析,所以代碼中我們選擇了mlContext.Forecasting.ForecastBySsa。

解釋一下這裏面的幾個參數:

  • trainSize – 數據樣本的數量,也就是訓練數據的行數(在這個文件中,一行是一個數據樣本,共334行)
  • seriesLength – 從數據樣本按時序採樣時的間隔,這裡是30天
  • windowSize – 樣本周期的天數,這裡是7天
  • horizon – 預測結果的天數
  • confidenceLevel – 上下限的可信度。預測屬於合理猜測,不總是完全準確。
  • 其它幾個參數,對應輸入輸出模型的字段名

 

  1. 訓練模型

管道定義完成,數據加載完成,下面要進行數據訓練。

SsaForecastingTransformer forecaster = forecastingPipeline.Fit(data1View);

跟隨上一節,管道是單譜管道,所以訓練也是單譜訓練SsaForecastingTransformer。

 

程序執行到這裏,數據訓練完成。

  1. 模型評估

模型評估不是必須環節。

模型評估的意義在於:通過評估模型的性能,來調整管道的參數,以達到最佳的預測效果。

模型評估也有多種方式。在這裏,我們採用平均絕對誤差和均方根誤差來做評估依據。

static void Evaluate(IDataView testData, ITransformer model, MLContext mlContext)
{
    IDataView predictions = model.Transform(testData);

    IEnumerable<float> actual =
        mlContext.Data.CreateEnumerable<ModelInput>(testData, true)
            .Select(p => p.count);

    IEnumerable<float> forecast =
        mlContext.Data.CreateEnumerable<ModelOutput>(predictions, true)
            .Select(p => p.forecasted_count[0]);

    var metrics = actual.Zip(forecast, (actualValue, forecastValue) => actualValue - forecastValue);

    var MAE = metrics.Average(error => Math.Abs(error));
    var RMSE = Math.Sqrt(metrics.Average(error => Math.Pow(error, 2)));

    Console.WriteLine("評估結果");
    Console.WriteLine("---------------------");
    Console.WriteLine($"平均絕對誤差: {MAE:F3}");
    Console.WriteLine($"均方根誤差: {RMSE:F3}\n");
}

在這個方法中,我們取評估數據的實際值actual和通過訓練數據生成的預測值forecast,計算兩個誤差並輸出。

在Main中調用此方法:

static void Main(string[] args)
{
        /* 這兒是前邊訓練的代碼,略過 */

        Evaluate(data2View, forecaster, mlContext);
}
static void Evaluate(IDataView testData, ITransformer model, MLContext mlContext)
{
      /* 這兒是評估模型的方法,上面有,略過 */
}

輸出結果類似於以下內容:

評估結果
---------------------
平均絕對誤差: 23.442
均方根誤差: 174.236

兩個指標:

  • 平均絕對誤差 – 度量預測與實際值之間的接近程度。 此值介於 0 到無限大之間。 越接近 0,模型的質量越好。
  • 均方根誤差 – 匯總模型中的錯誤。 此值介於 0 到無限大之間。 越接近 0,模型的質量越好。

 

  1. 預測

訓練模型調整到滿意后,即可開始預測的工作:

var forecastEngine = forecaster.CreateTimeSeriesEngine<ModelInput, ModelOutput>(mlContext);
ModelOutput forecast = forecastEngine.Predict();

這兩行代碼,在內存中加載前邊訓練好的模型,並進行預測操作。預測數據的結果放在forecast中。

對應於分析管道定義中的horizon,預測數據包含7天的預測結果。

  1. 預測結果輸出

放在forecast中的數據,對應模型ModelOutput,可以用在任何地方。

在本文中,我們直接显示到Console:

IEnumerable<string> forecastOutput =
    mlContext.Data.CreateEnumerable<ModelInput>(data2View, reuseRowObject: false)
        .Take(7)
        .Select((ModelInput data, int index) =>
        {
            string action_date = data.action_time.ToString("yyyy-MM-dd");
            float actual_count = data.count;
            float lowerEstimate = Math.Max(0, forecast.lower_count[index]);
            float estimate = forecast.forecasted_count[index];
            float upperEstimate = forecast.upper_count[index];
            return $"日期: {action_date}\n" +
            $"實際值: {actual_count}\n" +
            $"預測下限估值: {lowerEstimate}\n" +
            $"預測估值: {estimate}\n" +
            $"預測上限估值: {upperEstimate}\n";
        });

Console.WriteLine("預測結果");
Console.WriteLine("---------------------");
foreach (var prediction in forecastOutput)
{
    Console.WriteLine(prediction);
}

運行結果類似於以下內容:

預測結果
---------------------
日期: 2018-12-01
實際值: 24566.08
預測下限估值: 16791.379
預測估值: 20394.115
預測上限估值: 23996.852

 

完成!

六、延伸內容

ML.net包含了很多機器學習的內容。其中,我自己認為時序預測是用途很廣的一個部分,可以用在

  • 銷售預測
  • 庫存預警
  • 活動策劃輔助

以及其它諸如天氣、股票、人口等諸多內容上,依靠過去和現在的數據,分析兩者之間的關係,然後利用得到的這個關係去預測未來的數據。

因此,在這個分類中,我的第一篇文章就寫了時序預測。

 

機器學習,核心是各種算法,而算法的基礎是一類數學。這是一個很高的坎。刷算法,線性的部分還好,一旦到了冪次或矩陣,沒有正統的學習,是很難有突破的。而即便刷通了,也只是皮毛性的理解,距離創造算法的大神,還有很長的距離。

所以,退而求其次,對很多人而言,與其花大功夫去研究算法,不如多研究下如何能把現有的算法或工具用好。

 

還有,在應用中,你能用機器學習來預測銷量、預測庫存,有沒有很自豪?是不是很高大上?

 

(全文完)

 

本文的對應代碼,在https://github.com/humornif/Demo-Code/tree/master/0013/demo

 

 

微信公眾號:老王Plus

掃描二維碼,關注個人公眾號,可以第一時間得到最新的個人文章和內容推送

本文版權歸作者所有,轉載請保留此聲明和原文鏈接

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

Hexo快速構建個人小站-Hexo初始化和將項目託管在Github(一)

 

背景交代

    相信每個程序員都有自己做過個人網站,博客之類的項目了,但是現在還在維護嗎?反正我前前後后做過2到3個了,維護一段時間后因為一些不可逆的原因(主要是懶)都沒有維護了,購買的一些域名和服務器信息也都過期了,最近玩了一下hexo,發現這個東西挺方便的,基本半個小時就可以搞完,並且如果 完全託管在github上基本就是0成本,用作學習記錄輸出是夠了。

 

1.依賴於nodejs安裝,安裝nodejs和npm

下載地址,可以對照電腦系統版本進行下載安裝:https://nodejs.org/en/download/
現在nodejs的安裝包內置了npm,所以下載安裝完成之後,nodejs和npm都會安裝好

檢查安裝是否成功

安裝成後會显示出對應的版本信息,由於我電腦之前就安裝過了,所以應該不是最新的版本

2.安裝hexo

安裝命令:

sudo npm i -g hexo

直接一步就安裝完成了,然後可以通過hexo -v查看是否安裝成,成功安裝的話,會打印出上面截圖中的一些版本信息

3.hexo初始化博客項目

命令:

hexo init

 

初始化完成之後,看看hexo在文件夾給我生成了哪些文件

 

如果你是一名前端或者nodejs開發者,相信對這些文件再熟悉不過了,還是對上述幾個文件簡單解釋一下:

  • node_modules:存放依賴包信息

  • public:存放生成的頁面

  • scaffolds:存放生成文章的一些模板

  • source:存放用命令創建的各種文章

  • themes:存放博客使用的主題

  • _config.yml:存放整個博客的配置

  • db.json:存放source解析所得到的

  • package.json:存放項目所需模塊項目的配置信息

 

4.將生成的博客項目跑起來

1、清除
hexo clean
2、生成
hexo g
3、啟動服務
hexo server

 

啟動完成后就可以按照提示,打開 http://localhost:4000 來訪問我們在本地初始化好的博客項目了

可以看到我們的項目已經成功跑起來了,成功的邁出了第一步,先暫且按耐住激動的心情,我們繼續!

 

5.在GitHub上創建倉庫用於託管博客項目

打開Github:https://github.com/PeyShine,新建一個倉庫,如圖

倉庫名稱需要配置為:個人名字.github.io,倉庫設置為公開,然後點擊創建就可以

 

6.配置_config.yml

deploy:
   type: git
   repository: https://github.com/PeyShine/PeyShine.github.io.git
   branch: master

  

7.上傳項目 

在此之前請先安裝一個插件

npm install hexo-deployer-git --save

  

部署(上傳到GitHub) 

hexo d 或者 hexo deploy

上傳過程中輸入了用戶名和密碼,如果提前配置好ssh也可以不用輸入

到Github上看一下,是否上傳成功

可以看到文件都已經上傳成功了

8.成功訪問

通過域名“https://peyshine.github.io” 來訪問

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※FB行銷專家,教你從零開始的技巧

122隻珍稀海龜陳屍墨西哥海灘 當局調查中

摘錄自2018年8月19日蘋果日報墨西哥報導

墨西哥南部恰帕斯州(Chiapas)一處野生動物保護區,近日有多達122隻珍稀海龜死亡,當局正積極調查。

《墨西哥每日新聞》(Mexico News Daily)報導,不幸的是,這些海龜屍體的腐敗狀況使調查進度不樂觀,不易執行驗屍或任何切片檢驗。這些海龜大多是麗龜(olive ridley species),成年後身長可達1公尺,平均壽命約100歲。

當地保護區管理委員會負責人巴羅拉(Adrián Méndez Barrera)指出,7月24日起,這些海龜屍體開始逐漸出現。為避免麗龜數量持續減少,聯邦政府、州政府與當地補漁業者目前著手監控周邊區域,以避免再有麗龜被捕,或有人取走牠們的蛋。

同時,當局也將檢驗當地海水樣本,看看是否含有有害物質,避免再有珍貴的動物受害。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

川普開倒車? 各州可自訂碳排標準

摘錄自2018年8月20日自由時報報導

美國總統川普近日將宣布一項新方案,授權各州自行決定如何與是否遏制燃煤發電廠的碳排放,大幅翻轉前朝歐巴馬政府的「潔淨電力計畫」(Clean Power Plan)。然而,根據美國環保署就未來十年溫室氣體排放量的推估,落實川普新措施後的排放量,將是歐巴馬乾淨能源政策的至少12倍。

新計畫將授權各州自行對火力發電廠制定標準較低的法規,還允許各州退出電廠排放法規,將對全美各地許多老舊燃煤發電廠帶來重大影響,恐導致曾一度減少的溫室氣體排放再度升高。

新措施將影響超過300座發電廠,鼓勵業者讓這些火力發電廠繼續運轉,而非以更乾淨的天然氣或再生能源發電取而代之。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

印度雨季洪災逾410死 超過百萬人流離失所

摘錄自2018年8月21日中央報導

印度官員今天(21日)表示,西南部克勒拉省奪走410多人性命的毀滅性雨季洪災,造成超過100萬人流離失所,湧入各地避難中心棲身。

根據克勒拉省(Kerala)一名議員,約有5萬棟民宅遭摧毀,民眾紛紛湧入避難中心,而洪水消退顯露出破壞的規模。軍隊表示,城鎮上有數千人仍待淹水的住家中,10天傾盆大雨已重創克勒拉省。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※FB行銷專家,教你從零開始的技巧

合攻電動巴士商機,車王電集團攜日住友商事集團簽 MOU

為響應政府 2030 年公車全面電動化政策,由車王電、華德動能與日本住友商事、台灣住友商社於 29 日共同簽署「電動商用車暨汰役電池應用開發合作備忘錄(MOU)」,將透過台日產業合作,將台灣電動車及智慧儲能產業推向國內外市場。

車王電指出,電動巴士將是未來智慧城市非常重要的一環,據彭博新能源財經的報導,預計全球電動巴士到 2025 年將超過百萬輛,相當於全球城市公共巴士車隊的 47%。

車王電表示,集團旗下華德動能為國內唯一獲交通部核發「自主開發設計」資格的電動車企業,最新發表的新型電動巴士具超長行駛續航力,且電池使用壽命長、車輛性能超越國際水準,具極優成本效益比,而日本住友商事是日本屈指可數的企業集團,為在全球開展業務的綜合性跨國企業,藉由此次合作計劃,以期共同攜手將電動商用車推向國際市場。

車王電亦表示,將電動車用的電池作二次應用,透過電池管理平衡技術提升並延長電池使用年限及效率,再應用於儲能系統上,為推進循環經濟的重要實踐;此外,公司近年來致力於儲能事業的佈局與發展,建置主動式電池平衡技術,達成大幅延長汰役電池之壽命與效率。

車王電進一步表示,華德動能結合公司建置完成國內首座創能、儲能、用能(三能)之智慧微電網系統於欣欣客運電動大巴木柵充電場站,此充電場站整合市電、太陽能、鋰電儲能櫃及電動車充電機,並藉雲端智能行控中心充份掌握及控制行車資訊、太陽能發電量、儲能狀態及耗能資訊,將成為國內首座大型智慧節能電動車充電場站示範場域。

在台北市政府主導規劃下,欣欣客運係於 106 年 12 月取得北市第一條電動公車路線「動物園 – 信義快 – 松山車站」的路權,而經過近 5 個月的籌備及公開招標,由華德動能於 107 年 5 月取得承製此批車輛之標案;此一路線於 29 日正式通車。

(本文內容由 授權使用。首圖來源:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準