電子情報無線LAN-APのファーム更新
総合情報処理センターにて、無線LANルータの管理から、書類作成を行った。 電子情報では、FERECという認証ルータを間に挟んでいるため、 学生さんは自分のIDとパスワードでWeb認証をとった上で、接続ができるように なっている。このため、FERECルータ配下のAPでは、一部暗号化なしのAPも 残っていたが、今回すべてWPK/TKIPなどの暗号化を用いるように設定変更を行った。
これに伴い、無線LANルータのファームウェア更新も行った。 複雑な使い方をしていないため、電波強度さえあれば十分という状態ではあったが、 ひとまず5台のAPの更新作業。手元PCがMacであり、ファームウェアがWindowsの .exe で圧縮してあるため、無駄にファイルをコピーしながらの作業となってしまった。
wheezy登場でoldstable運用
Debian 7.0(wheezy)の登場で、自分の管理しているサーバのいくつかは、 メンテナンス作業を行い、wheezy(stable)や、jessie(testing)に移行を終えた。 しかしながら、メインでサービスを動かしているサーバは、 移行で動かなくなりそうなサービスもあって、気軽に wheezy に移行できずにいる。
しかたがないので、3週ほど更新せずにいたけど、 そろそろ何らかの更新体制に設定する必要がある。 ということで、軟弱運用だけど、oldstable(squeeze) を利用するように設定した。 でも、oldstable も大抵1年間ほどなので、夏休みにでもボチボチ移行せねば…
2013年5月26日(第322回)
- まるよし Train Pops ~ 国語と遊ぼう! 第8便 「作文」後半
- 携帯電話とスマートフォンの話
- プールの話
- 無難な服装の話
担当:前田勝(4EI)、松島(2C)、山野(2C)、五味(教員)
派生・継承と仮想関数
隠蔽化の演習を終え、次のオブジェクト指向のステップとして、 派生と継承を説明した。 簡単に仮想関数についても、実演してみた。
基本的なデータに対して、新しく機能を追加したデータを作る場合には、 C言語であれば、基本データ構造におまけデータ部をつけた新しい構造体を 宣言することになる。しかしこの方法では、新しいオマケつきデータが 発生するたびごとに、簡単な処理でも新たな関数を定義しなければならない。
そこで、オマケ付きデータも、同じように使うために派生と継承がある。 新しいオマケを加えたデータ構造をあたらしく作ることを派生と呼ぶ。 元々の基本的データ構造は、一般的に基底クラスと呼び、 追加データを加えたデータ構造は、派生クラスと呼ぶ。 派生クラスでは、基本となるデータ構造の要素やメソッドを使うことができ、 データや処理を流用できることを継承と呼ぶ。
#include #include #include using namespace std ; class Person { private: char name[ 20 ] ; int age ; public: Person( char*n , int a ) { strcpy( name , n ) ; age = a ; } void print() { cout << name << "'s age is " << age << endl ; } } ; class Student : public Person { private: char school[ 20 ] ; public: Student( char *n , int a , char* s ) : Person( n , a ) { strcpy( school , s ) ; } } ; int main() { Person saitoh( "t-saitoh" , 48 ) ; Student aoyama( "aoyama" , 21 , "fnct" ) ; saitoh.print() ; aoyama.print() ; // 継承で表示 return 0 ; }
struct Student : public Person { : // 派生クラスで同じメソッドを新しく作っても良い void print() { Person::print() ; // 基底クラスのprint() を明示して呼び出し cout << "School is " << school << endl ; } } int main() { : // table[] には、基底クラスは同じだけど異なる型が入ってる。 Person* table[ 2 ] = { &saitoh , &aoyama } ; for( int i = 0 ; i < 2 ; i++ ) table[ i ]->print() ; return 0 ; }
この例では、table[i]には、異なる型を代入できている。 しかし、table[i]->print() では、table[1]において、"School is fnct"は 表示されない。 あくまで、table[] に代入する際に、Student型がPerson型に 格下げされている。
table[1]には、Student 型が入っているのだから、"School is fnct"を表示して欲しい場合には どうすればよいのか、こういう時は仮想関数を用いる。 仮想関数では、関数の前に virtual を付加する。
class Person { : virtual void print() { cout << name << "'s age is " << age << endl ; } } ; class Student : public Person { : virtual void print() { Person::print() ; cout << "School is " << school << endl ; } } ;
この様に宣言すると、データ生成時にそれぞれのオブジェクトには、 型を識別する情報が付けられる。 仮想関数を呼び出す時には、データ種別情報を元に、型に応じたメソッドが呼び出される。
電子情報⇒情報工学科?(ビッグデータ活用)
今日は、福井県の情報システム工業会主催の講演会+懇親会があり、 参加してきました。以下に、その講演会で私の視点で気になった点をまとめてみました。
産業・地域の成長に向けたビッグデータの活用とその方策
「産業・地域の成長に向けたビッグデータの活用とその方策」というテーマで、 ビッグデータの特徴・定義という話題から、しくみ・構成要素という話題で、 講演が進みました。
簡単にまとめると、ビッグデータは様々な大量のデータをタイムリーに 扱うことが特徴。(ビッグデータの3V=Variety,Velocity,Volume) 今までのコンピュータは、構造化されたデータを処理するものであったが、 構造化されていないデータを扱うようになり、それを蓄積集計分析する時代 となってきた。これからは、データ活用は「現状分析」から『予測分析』 と変化していく。 だからこそ、データを科学的に分析するデータサイエンティストが 活躍する時代となる。
ビッグデータと周辺技術
ビッグデータは、 (1)対象からリアルタイムのモニタリングでデータを検索 できるようにしてきたが、 (2)それを蓄積加工するようになる。 この際いは、Key-Value な NoSQL に保存されていく。 (3)さらにデータを集計分析するために分析処理・並列分散処理 を行い、 (4)それがフィードバックされ新たな価値の創造が行われていく。
このビッグデータ活用サイクルでのキーワードをあげると、 データ収集(1)では、 M2M(Machine to Machine)=センサーデータ集約のためにデータ源の 機器が相互に情報交換するための手段。 蓄積加工(2)では、クラウドコンピューティングや、 DWH(Data Ware House)=データ倉庫。 集計分析(3)では、分散処理で Apache による Hadoop(大規模データの分散処理のためのJavaフレームワーク)や、 MapReduce(分散と集約で処理するプログラミングモデル)。 さらに、データの中に埋もれた関係性をみつけるためのマイニング、 特にテキストマイニングなども重要なキーワードであろう。
ビッグデータの活用ニーズ
現状では、情報検索サイトやマーケティングで活用が始まっている。 地方であれば、農業ICTとして農業のノウハウ確立・品質管理・生産管理 などが注目されるだろう。 一方で、エコマネージメントとして、家庭や企業の電力測定可視化といった 応用が進められるだろう。
データ=情報が重要になるのなら、電子情報は、本当の情報工学科に!?!?
このように、将来はビッグデータ活用がコンピュータ社会の中で 重要なキーワードとなるであろう。だからこそ大学・高専では、 ビッグデータを活用分析できるデータエンジニアが育つ必要がある。
ということで、福井高専の私たちの電子情報の将来像を考えてみると、 現状はオープンキャンパスをすると機械・電気電子・電子情報では、3学科そろって ロボット・ロボット・ロボットな状況。将来、少子化で学生数が減る際には、 学科の再編成の必要との意見も出ている。 この際には、電子情報工学科は、情報工学科となる可能性もあるだろう。 そうなってくると、今のうちからデータサイエンティストを育む カリキュラムや、MapReduceなどの分散処理指向のプログラミングスタイルを 教えるといった時代になっていくのであろう。 さらに(この講演では語られていないが)、データを活用するもう1つは、シミュレーション技術というのも、次世代に向けて重要視されていくだろう。
リスト構造の導入
先日の演習で、配列が途中データ挿入にあたり、O(N)の処理を要する問題提起を踏まえ、 今回はリスト構造を説明。
次のデータの場所
途中にデータを挿入する手間を簡単にする方法として、リスト構造を説明するために、 最初に以下のプログラムを示す。このプログラムでは、一見デタラメな数字が 並んでいるように見えるが、table[*].data部が 1,2,5,7,8 と昇順に表示される。 これは、table[*].next 部に、次に大きいデータの場所が記載されているため。
int top = 3 ; struct DataNext { int data ; int next ; } table[ 10 ] = { 5 , 1 , 7 , 4 , 2 , 0 , 1 , 2 , 8 , -1 , } ; for( int i = top ; i >= 0 ; i = table[ i ].next ) printf( "%d" , table[ i ].data ) ;
このような方法を取っていれば、data に3を加えたい時は、 table[5].data = 3 ; table[5].next = 0 ; table[2].next = 5 ; を実行すれば、 データ順序を守ったまま、2と5の間に3を挿入できる。
しかし、このままでは、配列のサイズが固定値の問題を解決できない。
リスト構造
これらの問題を解決するために、必要に malloc で data と next の記憶場所を確保すれば良い。
(( まずは基本 )) struct List { int data ; struct List* next ; } ; struct List* top ; top = (struct List*)malloc( sizeof(struct List) ) ; top->data = 1 ; top->next = (struct List*)malloc( sizeof(struct List) ) ; top->next->data = 2 ; top->next->next = (struct List*)malloc( sizeof(struct List) ) ; top->next->data = 3 ; top->next->next = NULL ; // top ◯→[1|◯]→[2|◯]→[3|×] struct List* p ; for( p = top ; p != NULL ; p = p->next ) printf( "%d" , p->data ) ; (( 補助関数を作ってシンプルに )) struct List* cons( int x ; struct List* n ) { struct List* nw ; nw = (struct List*)malloc( sizeof( struct List ) ) ; if ( nw != NULL ) { nw->data = x ; nw->next = n ; } return nw ; } struct List* top = cons( 1, cons( 2, cons( 3, NULL ) ) ) ;
typedef命令
時間が微妙に会ったので、補足説明として typedef を説明する。 ただし、リスト宣言を typedef で記載するのは、C言語の場合だけ。 C++では、構造体・クラス名はそのまま型名として使用できる。
(( typedef の使い方の基本 )) // 符号なし16bit整数をいつも書くと面倒 typedef unsigned short int uint16 ; uint16 x = 0x1234 ; (( typedefでList宣言 )) typedef struct LIST { int data ; struct LIST* next ; } List ; List* cons( int x , List* n ) { // 補助関数の宣言もシンプルに } List* top = cons(1,cons(2,cons(3,NULL)));
ポインタ処理
N進数・文字列・数値変換プログラムの演習中。 座学も並行して進めたいので、今日は前半にポインタの説明を行う。
ポインタ演算の例として、以下のような処理を示す。
(( 基本 )) int x = 123 , y = 234 ; int *p ; p = &x ; *p = 111 ; // xに111が入る p = &y ; *p = 222 ; // yに222が入る (( ポインタとオフセット )) int a[] = { 11 , 22 , 33 , 44 } ; p = &a[1] ; printf( "%d" , *(p + 2) ) ; // 44 printf( "%d" , *(p - 1) ) ; // 11 p++ ; printf( "%d" , *p ) ; // 33 (( ポインタ渡し )) void foo( int *p ) { (*p)++ ; } void main() { int a = 11 ; foo( &a ) ; printf( "%d" , a ) ; // 12 foo( &a ) ; printf( "%d" , a ) ; // 13 } (( ポインタ移動の繰り返し )) int a[] = { 11 , 22 , 33 , -1 } ; int b[] = { 1 , 2 , 3 , 4 , 5 , 6 , -1 } ; int sum1( int array[] ) { // 基本 int s = 0 ; i ; for( i = 0 ; array[ i ] >= 0 ; i++ ) s += array[ i ] ; return s ; } int sum2( int* p ) { // ポインタ移動 int s = 0 ; for( ; *p >= 0 ; p++ ) s += *p ; return s ; } int sum3( int* p ) { // 移動と加算を1行で int s = 0 ; while( *p >= 0 ) s += *p++ ; return s ; } void main() { printf( "%d" , sum1( a ) ) ; printf( "%d" , sum2( b ) ) ; printf( "%d" , sum3( a ) ) ; }
来週は、ポインタと配列が同じ扱いであることを改めて説明し、 2進数の取り扱う bit 演算を説明する予定。
2013年5月19日(第321回)
- まるよし Train Pops ~ 国語と遊ぼう! 第7便 「作文」
- この時期のファッションの話
- 夢の話
担当:前田勝(4EI)、松島(2C)、山野(2C)