Một số mô đun chương trình của bộ kiểm chứng

Một phần của tài liệu (LUẬN văn THẠC sĩ) phân tích, thiết kế và cài đặt kiểm chứng một hệ thời gian thực (Trang 54 - 67)

Phụ lục A. Một số mô đun chương trình của bộ kiểm chứng

Trong phần này chúng tôi liệt kê mã nguồn một số hàm chính của chương trình gồm các hàm: tạo ôtômat hợp song song, tạo đồ thị vùng đạt được nguyên, khử cung vô hạn, tạo đồ thị trọng số phục vụ kiểm chứng LDI và kiểm chứng công thức LDI.

Tạo ôtômat hợp song song

Các hàm trong phần này thực hiện chức năng tạo ra 1 ôtômat song song đạt được từ 1 hệ các ôtômat thành phần. Phần này gồm 2 hàm được viết trong class

OtomatLogic: Hàm thứ nhất createOtomatParallel($aryOtomat) thực hiện tạo ra 1

ôtômat song song từ nhiều ôtômat thành phần, trong hàm này gọi đến hàm thứ 2

createOtomatParallelFrom2Otomat($aryOtomat1, $aryOtomat2) để thực hiện tạo 1

ôtômat song song đạt được từ 2 ôtômat thành phần.

public function createOtomatParallel($aryOtomat) { //TH He co 1 otomat

if (count($aryOtomat) == 1) { return current($aryOtomat); }

//TH He co >= 2 otomat

for ($i = 1; $i < count($aryOtomat); $i++) { if ($i == 1) { $aryAutomataParallel = $this->createOtomatParallelFrom2Otomat($aryOtomat[$i], $aryOtomat[$i+1]); } else { $aryAutomataParallel = $this->createOtomatParallelFrom2Otomat($aryAutomataParallel, $aryOtomat[$i+1]); } } return $aryAutomataParallel; }

public function createOtomatParallelFrom2Otomat($aryOtomat1, $aryOtomat2) { $aryLocation1 = $aryOtomat1['aryLocation']; $aryLocation2 = $aryOtomat2['aryLocation']; $aryTransition1 = $aryOtomat1['aryTransition']; $aryTransition2 = $aryOtomat2['aryTransition']; $arySyschr = array();

$aryAdj1 = $aryAdj2 = array();

$this->getLocationAdj($aryAdj1, $aryAdj2, $arySyschr, $aryTransition1, $aryTransition2); $init1 = $aryOtomat1['init']; $init2 = $aryOtomat2['init']; $aryClock = array_unique(array_merge($aryOtomat1['clocks'], $aryOtomat2['clocks'])); //Khoi tao $aryStackPath = array();

$aryStackPath[] = $this->getLocationOtomatParallel($init1, $init2, $aryAdj1[$init1], $aryAdj2[$init2]);

$aryLocation = $aryTransition = array(); //Add Location $aryInvar = array(); $res = $this->createGuardOfOtomatParallet($aryInvar, $aryLocation1[$init1]['invar'], $aryLocation2[$init2]['invar']); $w = $aryLocation1[$init1]['c'] + $aryLocation2[$init2]['c']; $aryLocation["{$init1},{$init2}"] = array( 'invar' => $aryInvar, 'c' => $w ); $aryCheck = array(); $aryCheck["{$init1},{$init2}"] = 1; while (count($aryStackPath) > 0) { $aryGuard = array(); $loc1_to = $loc2_to = null; $label = '';

$this->getSuccLocation($loc1, $loc2, $loc1_to, $loc2_to, $label, $aryStackPath, $arySyschr);

if ($loc1_to == null || $loc2_to == null) { array_pop($aryStackPath); continue; } $locNameFrom = "{$loc1},{$loc2}"; $locNameTo = "{$loc1_to},{$loc2_to}"; //Add Location $aryInvar = array(); $res = $this->createGuardOfOtomatParallet($aryInvar, $aryLocation1[$loc1_to]['invar'], $aryLocation2[$loc2_to]['invar']); if (!isset($aryLocation[$locNameTo]) && $res) {

$w = $aryLocation1[$loc1_to]['c'] + $aryLocation2[$loc2_to]['c']; $aryLocation[$locNameTo] = array( 'invar' => $aryInvar, 'c' => $w ); } //Add transition

$guard1 = $guard2 = array(); $aryReset = array();

foreach ($aryTransition1 as $k1 => $transition1) {

if (strcmp($loc1, $transition1['loc_name_from']) != 0) { continue;

}

foreach ($aryTransition2 as $k2 => $transition2) {

if (strcmp($loc2, $transition2['loc_name_from']) != 0) { continue;

}

if (strcmp($loc1, $loc1_to) == 0 && strcmp($loc2_to, $transition2['loc_name_to']) == 0) {

$aryReset = $transition2['reset']; $guard2 = $transition2['guard']; break 2;

} elseif (strcmp($loc2, $loc2_to) == 0 && strcmp($loc1_to, $transition1['loc_name_to']) == 0) {

$aryReset = $transition1['reset']; $guard1 = $transition1['guard']; break 2;

} elseif (strcmp($loc2_to, $transition2['loc_name_to']) == 0 && strcmp($loc1_to, $transition1['loc_name_to']) == 0) {

$guard1 = $transition1['guard']; $guard2 = $transition2['guard'];

$aryReset = $transition1['reset'];

if (is_array($transition2['reset']) && count($transition2['reset']) > 0) { foreach ($transition2['reset'] as $k => $v) { $aryReset[$k] = $v; } } break 2; } } } $aryGuard = array();

$res = $this->createGuardOfOtomatParallet($aryGuard, $guard1, $guard2); if ($res) { $aryTransition[] = array( 'loc_name_from' => $locNameFrom, 'loc_name_to' => $locNameTo, 'label' => $label, 'reset' => $aryReset, 'guard' => $aryGuard, ); } if (!isset($aryCheck[$locNameTo])) {

$aryStackPath[] = $this->getLocationOtomatParallel($loc1_to, $loc2_to, $aryAdj1[$loc1_to], $aryAdj2[$loc2_to]);

} }

//Khoi tao Otomat Parallel $aryOtomatParallel = array(

'init' => $aryOtomat1['init'] . ',' . $aryOtomat2['init'], 'numLocation' => count($aryLocation), 'numTransition' => count($aryTransition), 'clocks' => $aryClock, 'aryLocation' => $aryLocation, 'aryTransition' => $aryTransition, );

$this->logger->log(" aryOtomatParallel = " . print_r($aryOtomatParallel, true)); return $aryOtomatParallel;

}

Tạo đồ thị vùng đạt được nguyên

public function createRegionGraph($aryOtomat, $aryConstantMaxK) { $this->logger->log( " Begin method: " . __METHOD__ . "()"); $maxK = max($aryConstantMaxK); $locationStart = $aryOtomat['init']; $aryLocation = $aryOtomat['aryLocation']; $aryTransition = $aryOtomat['aryTransition']; $aryClock = $aryOtomat['clocks'];

//Khoi tao so dinh hien tai

$this->graphRegion['num_vertex'] = 1; //Khoi tao so canh hien tai

$this->graphRegion['num_edge'] = 0; //Nhap dinh <s0, (0,0)>

$region0 = join(',', array_fill(0, count($aryClock), 0)); $regionK = join(',', array_fill(0, count($aryClock), 'U')); //Id region

$regionId = 1;

$vertex0 = $this->createVertexRegion($locationStart, $region0); $this->graphRegion['aryVertex'][$regionId] = array(

'vertex' => $vertex0, 'loc_name' => $locationStart, 'region' => $region0, 'ldi_c' => $aryLocation[$locationStart]['c'], 'visited' => 0, );

//Khoi tao tap canh rong

$this->graphRegion['aryEdge'] = array();

while (true) {

//lay dinh chua tham trong V

$vertex = $this->getVertexNotVisited(); //neu tat ca cac dinh da tham thi ket thuc if ($vertex === false) {

break ; }

//Dinh s trong Otomat

$loc_name_from = $vertex['loc_name']; $region = $vertex['region'];

$vertex_from = $vertex['vertex']; $id_from = $vertex['id'];

//Loop Transition cua Otomat

foreach ($aryTransition as $transition) {

//Neu ton tai phep chuyen e = <s, g, a, λ, s'>

if (strcmp($loc_name_from, $transition['loc_name_from']) == 0) { $loc_name_to = $transition['loc_name_to'];

//Xac dinh xem co chuyen dc khong for ($d = 0; $d <= $maxK + 1; $d++) {

$regionSucc = $this->creatRegionPlus($region, $d, $aryConstantMaxK);

//Kiem tra dieu kien I(s)

if (!$this->checkGuard($regionSucc, $aryLocation[$loc_name_from]['invar'])) {

continue; }

//Kiem tra dieu kien rang buoc g if (!$this->checkGuard($regionSucc, $transition['guard'])) { continue; } //Reset clock $regionTo = $this->resetRegionClock($regionSucc, $transition['reset']);

//Kiem tra dieu kien I(s') sau khi reset if (!$this->checkGuard($regionTo, $aryLocation[$loc_name_to]['invar'])) {

continue; }

//Dat lai gia tri trong mien theo qui uoc

$regionTo = $this->reformatRegion($regionTo, $aryConstantMaxK);

//Kiem tra dinh nay da co chua

$vertex_to = $this->createVertexRegion($loc_name_to, $regionTo);

$vertexId = $this->getVertex($vertex_to);

//Neu chua co thi bo sung if ($vertexId == 0) { $regionId++; $this->addVertexRegion($loc_name_to, $regionTo, $aryLocation[$loc_name_to]['c'], $regionId); $id_to = $regionId; } else { $id_to = $vertexId; }

//Kiem tra va bo sung cung neu chua co if (!$this->isExistEdge($id_from, $id_to)) { $durationLow = $durationUp = 0; if (strcmp($regionK, $regionSucc) != 0) { $durationLow = $durationUp = $d; } else { $durationLow = $d;

$durationUp = _PHP_INT_MAX; }

$this->addEdgeRegion($durationLow, $durationUp, $id_from, $id_to);

}

} //End loop $maxK

} //End Neu ton tai phep chuyen e = <s, g, a, λ, s'> } //End Loop Transition cua Otomat

//Danh dau da duyet xong

$this->graphRegion['aryVertex'][$id_from]['visited'] = 1; } //End While()

//Loai bo du lieu khong can thiet

foreach ($this->graphRegion['aryVertex'] as $rgid => $info) { unset($info['loc_name']);

unset($info['region']); unset($info['visited']);

$this->graphRegion['aryVertex'][$rgid] = $info; }

$this->logger->log( " End method: " . __METHOD__ . "()"); }

Khử cung vô hạn

Tư tưởng cơ bản để xây dựng đồ thị trọng số phục vụ kiểm chứng LDI là “rời rạc hóa” đồ thị đạt được vùng nguyên bằng cách ứng với mỗi cung (vi,vj,[l,u]) sẽ được thay bằng một họ các đường nối vi, vj sao cho độ dài (trọng số) của các đường đi lần lượt là số nguyên l, l+1,…,u. Điều này chỉ thực hiện được khi đồ thị vùng đạt được

nguyên không chứa cung vô hạn. Hàm khuCungVoHan() sau đây làm nhiệm vụ khử

các cung vô hạn của đồ thị vùng đạt được nguyên.

public function khuCungVoHan(&$graphRegion, $aryLDI) { $aryVertex = $graphRegion['aryVertex'];

$aryEdge = $graphRegion['aryEdge']; $ldiB = $aryLDI['B'];

$ldiA = $aryLDI['A']; $edgeInfinite = array();

foreach ($aryEdge as $key => $edge) { $l = $edge['duration_low'];

$u = $edge['duration_up']; $id_form = $edge['id_form']; $id_to = $edge['id_to']; $ldi_c = $aryVertex[$id_form]['ldi_c']; if ($u == _PHP_INT_MAX) { if ($ldiB == _PHP_INT_MAX) { if ($ldi_c > 0) { return $edge; } if ($ldi_c <= 0) { $graphRegion['aryEdge'][$key]['duration_up'] = max($l, $ldiA); }

} elseif ($ldiB < _PHP_INT_MAX) {

$graphRegion['aryEdge'][$key]['duration_up'] = max($l, $ldiB); }

} }

return null; }

Tạo đồ thị trọng số phục vụ kiểm chứng LDI

Hàm GraphLdiLogic::createWeighGraphLdi($regionGraph) thực hiện chuyển 1

đồ thị vùng đạt được nguyên sang 1 đồ thị trọng số phục vụ kiểm chứng công thức LDI.

public function createWeighGraphLdi($graphRegion) { //Tap dinh giu nguyen (Chi them dinh moi) //Sao chep dinh cu sang moi

foreach ($graphRegion['aryVertex'] as $id => $value) { $this->weighGraphLdi['aryVertex'][$id] = $value; }

$this->weighGraphLdi['num_vertex'] = $graphRegion['num_vertex']; //Tap cung cu bi loai de thay bang tap cung moi

$this->weighGraphLdi['num_edge'] = 0;

//Buoc 1: Kiem tra Neu $graphRegion chua cung vo han thi ket thuc va KL G khong thoa LDI

//Buoc 2: Tinh lai so dinh va cung cho do thi moi $weighGraphLdi theo cac TH sau:

/*

[0,0]: 1 cung co trong so 0

[1,1]: 1 cung 1

[u=l && u > 1]: u-1 dinh(n+1->n+u-1); u cung trong so 1 [l < u && u > 1]:

- Them u dinh (n+1 -> n+u) [u-1 dinh + 1 dinh don hoa do thi] - Them u cung trong so 1

- Them u-l+1 cung trong so 0 (ca cung don hoa do thi) */

//Bo sung tap dinh va cung ho Gi //Cung

foreach ($graphRegion['aryEdge'] as $edge) { $l = $edge['duration_low']; $u = $edge['duration_up']; $id_form = $edge['id_form']; $id_to = $edge['id_to']; $ldi_c = $graphRegion['aryVertex'][$id_form]['ldi_c']; $vertex = $graphRegion['aryVertex'][$id_form]['vertex']; //[0,0] them cung co trong so 0

if ($l == 0 && $u == 0) {

$this->addEdge($id_form, $id_to, 0); continue;

}

//[0,0] Tao 1 cung trong so 1 va 2 cung trong so 0 if ($l == 0 && $u == 1) {

//Them 1 cung co trong so 1

$this->addEdge($id_form, $id_to, 1); //Them 1 Dinh phu moi

$this->addVertex($vertex, $ldi_c); //Them 2 cung moi co trong so 0

$n = $this->weighGraphLdi['num_vertex']; $this->addEdge($id_form, $n, 0); $this->addEdge($n, $id_to, 0); continue; } //TH u == 1, l == 1 if ($l == 1 && $u == 1) {

//Them 1 cung moi co trong so 1 $this->addEdge($id_form, $id_to, 1); continue;

}

//TH u = l va u > 1; if ($l == $u && $u > 1) {

$n = $this->weighGraphLdi['num_vertex']; $dau = $n + 1; $cuoi = $n + $u - 1;

for ($i = 1; $i <= $u-1; $i++) {

$this->addVertex($vertex, $ldi_c); }

//Them u cung trong so 1 //cung dau

$this->addEdge($id_form, $dau, 1); //Cung cuoi trong so 1

$this->addEdge($cuoi, $id_to, 1); //Them u-2 cung giua trong so 1 for ($j = $dau; $j <= $cuoi - 1; $j++) {

$this->addEdge($j, $j + 1, 1); } continue; } //TH l < u va u > 1

//Them u dinh va u cung trong so 1, u-l+1 cung trong so 0 if ($l < $u && $u > 1) {

//Them u dinh tu n+1(dau) den n+u (cuoi) $n = $this->weighGraphLdi['num_vertex']; $dau = $n + 1; $cuoi = $n + $u;

for ($i = 1; $i <= $u; $i++) {

$this->addVertex($vertex, $ldi_c); }

//Them u cung co trong so 1 //cung dau ts 1

$this->addEdge($id_form, $dau, 1); //Cung cuoi

$this->addEdge($cuoi - 1, $id_to, 1); //Them u-2 cung giua ts 1

for ($j = $dau; $j <= $cuoi - 2; $j++) { $this->addEdge($j, $j + 1, 1); }

//Them 2 cung phu trong so 0 (2 cung don hoa do thi) $this->addEdge($cuoi-1, $cuoi, 0);

$this->addEdge($cuoi, $id_to, 0); //Them (u-l+1)-2 cung trong so 0 if ($l == 0) {

//Them cung dau

//Them (u-l+1)-3 cung giua

for ($j = $dau; $j <= $cuoi - 2; $j++) { $this->addEdge($j, $id_to, 0); }

}

if ($l > 0) {

//Them (u-l+1)-2 cung trong so 0

for ($j = $dau + $l - 1; $j <= $cuoi - 2; $j++) { $this->addEdge($j, $id_to, 0); } } continue; } }

//$this->logger->log( __METHOD__."() weighGraphLdi = " . print_r($this- >weighGraphLdi, true));

return $this->weighGraphLdi; }

Kiểm chứng LDI

Phần này gồm 2 hàm được viết trong class GraphLdiLogic. Hàm thứ nhất

traverseLdi() duyệt mọi đường đi của đồ thị có trọng số phục vụ kiểm chứng LDI xuất phát từ một đỉnh cố định, và hàm thứ 2 verifyLDI() sẽ gọi hàm traverseLdi() với đỉnh

xuất phát là tất cả các đỉnh của đồ thị để quyết định mô hình được đặc tả bằng ôtômat có thỏa các tính chất mong muốn được đặc tả bằng công thức LDI hay không.

public function verifyLDI(&$weighGraphLdi, $aryLdi, &$result, &$tmax) { $result = 1;

$lmax = 0; $tmax = 0;

$aryVertex = array_keys($weighGraphLdi['aryVertex']); foreach ($aryVertex as $id) {

if (!$this->traverseLdi($id, $weighGraphLdi, $aryLdi, $lmax, $tmax)) { $result = 0; return $lmax; } } return $lmax; }

private function traverseLdi($vStart, &$weighGraphLdi, $aryLdi, &$lmax, &$tmax) { $isReturn = true;

$ldiA = $aryLdi['A']; $ldiB = $aryLdi['B']; $ldiM = $aryLdi['M']; $aryStackPath = array(); /** * $aryStackPath[] = array(

* v => >array(a1, a2, a3,...,an) //Dinh ke cua v * ); */ $lP = 0; $tP = 0; $reach = 0; $preach = 0; $pIndexSeach = 0; $aryEdge = $weighGraphLdi['aryEdge']; $aryVertex = $weighGraphLdi['aryVertex']; //Khoi tao

$aryStackPath[] = $this->getVertex($vStart, $aryEdge); while (count($aryStackPath) > 0) {

$verTex = $pVertex = 0;

$this->succ($verTex, $pVertex, $aryStackPath); if ($pVertex == 0) {

$this->deleteElementTopStack($aryStackPath, $lP, $tP, $verTex, $aryVertex, $aryEdge);

continue; }

$this->calculateLengthPricePath($lP, $tP, $verTex, $pVertex, $aryVertex, $aryEdge); if ($lP > $lmax) { $lmax = $lP; } if ($tP > $tmax) { $tmax = $tP; } //Push

$aryAdj = $this->getVertex($pVertex, $aryEdge); $aryStackPath[] = $aryAdj;

//Kiem tra tien kien if ($lP < $ldiA) {

$reach = 0; continue; }

if ($reach == 0) { $preach = $pVertex; $pIndexSeach = count($aryStackPath) - 1; $reach = 1; } if ($lP > $ldiB) { $this->deleteElementTopStack($aryStackPath, $lP, $tP, $pVertex, $aryVertex, $aryEdge); continue; }

//Kiem tra dieu kien DC if ($tP > $ldiM) {

$isReturn = false; break;

}

if ($ldiB == _PHP_INT_MAX) { //1: Kiem tra chu trinh

$pcycle = $this->findCycle($pIndexSeach, $aryStackPath, $aryVertex, $aryEdge); if ($pcycle == 1) { $isReturn = false; break; } elseif ($pcycle == -1) { $this->deleteElementTopStack($aryStackPath, $lP, $tP, $pVertex, $aryVertex, $aryEdge);

} continue; } } return $isReturn; }

Một phần của tài liệu (LUẬN văn THẠC sĩ) phân tích, thiết kế và cài đặt kiểm chứng một hệ thời gian thực (Trang 54 - 67)

Tải bản đầy đủ (PDF)

(71 trang)