스크림트 정리

This commit is contained in:
admin hmac
2025-11-05 11:14:46 +09:00
parent f1a3ff71cb
commit b8449e526a
27 changed files with 691 additions and 1 deletions

View File

@@ -16,6 +16,9 @@ RUN apt-get update && apt-get install -y gosu && rm -rf /var/lib/apt/lists/*
RUN groupadd -g ${GID} user && \ RUN groupadd -g ${GID} user && \
useradd -u ${UID} -g ${GID} -m -s /bin/bash user useradd -u ${UID} -g ${GID} -m -s /bin/bash user
RUN mkdir /data
RUN chown user:user /data
# Copy the entrypoint script and make it executable # Copy the entrypoint script and make it executable
COPY scripts/entrypoint.sh /usr/local/bin/ COPY scripts/entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh RUN chmod +x /usr/local/bin/entrypoint.sh

96
GEMINI.md Normal file
View File

@@ -0,0 +1,96 @@
# Memgraph 데이터 모델 설계
## 1. 프로젝트 목표
본 프로젝트의 최종 목표는 Job 실행 순서를 최적화하여 전체 공정의 **소요 시간(Duration)**과 **비용(Cost)**을 최소화하는 최적의 **시나리오(Scenario)**를 찾는 것입니다. 이를 위해 Memgraph 데이터베이스에 공정 데이터를 모델링하고, 다양한 분석 쿼리를 실행할 수 있는 기반을 마련합니다.
## 2. 데이터 모델 (Graph Schema)
### 2.1. 노드 (Nodes)
| 노드 레이블 | 설명 | 주요 속성 (Properties) |
| ---------------- | -------------------------------------------------------------------- | ---------------------------------------------------- |
| `Job` | 실행되어야 할 개별 작업 단위. `JobType`의 인스턴스. | `id`, `name`, `description`, `duration`, `cost` |
| `JobType` | `Job`의 유형을 정의하는 템플릿. (예: '용접', '조립', '검사') | `type_id`, `name` |
| `Object` | `Job` 수행에 사용되거나 `Job`의 결과로 나오는 객체. `ObjectType`의 인스턴스. | `id`, `name`, `unit_price`, `quantity` |
| `ObjectType` | `Object`의 유형을 정의하는 템플릿. (예: '부품A', '반제품B') | `type_id`, `name` |
| `Activity` | `Job``Object` 간의 n:m 관계를 연결하는 중간 노드. | `id`, `name`, `description` |
| `Status` | `Job`, `Object`, `Activity`의 현재 상태. (예: '대기', '진행중', '완료') | `status_id`, `name` |
| `Scenario` | 특정 순서로 배열된 `Job`들의 집합. 다른 `Scenario`로부터 파생될 수 있음. | `id`, `name`, `description`, `total_duration`, `total_cost` |
### 2.2. 관계 (Relationships)
| 관계 타입 | 시작 노드 | 끝 노드 | 설명 |
| -------------- | ---------------- | ---------------- | ----------------------------------------------------------------- |
| `IS_A` | `Job` | `JobType` | `Job`이 어떤 `JobType`에 속하는지 정의 (상속) |
| `IS_A` | `Object` | `ObjectType` | `Object`가 어떤 `ObjectType`에 속하는지 정의 (상속) |
| `PRECEDES` | `Job` (선행) | `Job` (후행) | `Job` 실행의 선후 관계 정의 (A -[:PRECEDES]-> B: A가 B보다 먼저) |
| `INCLUDES` | `Scenario` | `Job` | `Scenario`에 어떤 `Job`들이 포함되는지 정의 |
| `PERFORMS` | `Job` | `Activity` | `Job`이 어떤 `Activity`를 수행하는지 연결 |
| `ACTS_ON` | `Activity` | `Object` | `Activity`가 어떤 `Object`에 영향을 주는지 연결 |
| `HAS_STATUS` | `Job`, `Object`, `Activity` | `Status` | 각 노드의 현재 상태를 나타냄 |
| `DELTA_FROM` | `Scenario` (파생) | `Scenario` (기반) | `Scenario`가 어떤 기반 `Scenario`로부터의 증분으로 정의되는지 표시 |
### 3. 스키마 다이어그램 (Mermaid)
```mermaid
graph TD
subgraph "Core Entities"
J1(Job 1)
J2(Job 2)
A1(Activity)
O1(Object)
end
subgraph "Types & Status"
JT(JobType)
OT(ObjectType)
ST(Status)
end
subgraph "Scenario"
S1(Scenario Base)
S2(Scenario Delta)
end
J1 -- IS_A --> JT
J1 -- PRECEDES --> J2
O1 -- IS_A --> OT
J1 -- PERFORMS --> A1
A1 -- ACTS_ON --> O1
J1 -- HAS_STATUS --> ST
O1 -- HAS_STATUS --> ST
A1 -- HAS_STATUS --> ST
S2 -- INCLUDES --> J1
S2 -- INCLUDES --> J2
S2 -- DELTA_FROM --> S1
```
### 4. 주요 Cypher 쿼리 예시
- **특정 Job의 모든 선행 Job 찾기:**
```cypher
MATCH (j:Job {id: 'target_job_id'})<-[:PRECEDES*]-(predecessor)
RETURN predecessor;
```
- **특정 시나리오의 총 예상 소요 시간 및 비용 계산:**
```cypher
MATCH (s:Scenario {id: 'scenario_id'})-[:INCLUDES]->(j:Job)
RETURN s.name, sum(j.duration) AS total_duration, sum(j.cost) AS total_cost;
```
- **Critical Path 찾기 (가장 오래 걸리는 Job 경로):**
```cypher
MATCH path = (start:Job)-[:PRECEDES*]->(end:Job)
WHERE NOT EXISTS ((start)<-[:PRECEDES]-()) AND NOT EXISTS ((end)-[:PRECEDES]->())
WITH nodes(path) AS jobs_in_path
UNWIND jobs_in_path AS job
WITH path, sum(job.duration) AS path_duration
RETURN path, path_duration
ORDER BY path_duration DESC
LIMIT 1;
```

42
README.md Normal file
View File

@@ -0,0 +1,42 @@
# Memgraph 기반 공정 최적화 PoC
## 1. 프로젝트 개요
본 프로젝트는 Memgraph 그래프 데이터베이스를 활용하여 복잡한 공정(Job)들의 실행 순서를 최적화하는 방안을 탐색하기 위한 기술 검증(Proof of Concept) 프로젝트입니다.
Job, Object, Activity, Scenario 등의 핵심 요소를 그래프 모델로 설계하고, 각 요소 간의 관계를 정의하여 전체 공정의 소요 시간과 비용을 최소화하는 최적의 시나리오를 찾는 것을 목표로 합니다.
## 2. 데이터 모델
프로젝트에서 사용하는 데이터 모델의 상세한 노드, 관계, 속성 정의는 아래 설계 문서를 참고하십시오.
- **[상세 데이터 모델 설계](./GEMINI.md)**
## 3. 시작하기
### 요구사항
- Docker
- Docker Compose
### 실행
1. **Docker 컨테이너 실행:**
```bash
docker-compose up -d
```
2. **Memgraph Lab 접속:**
- 웹 브라우저에서 `http://172.16.10.191:3000/` 에 접속하여 Memgraph Lab을 통해 데이터를 시각화하고 쿼리를 실행할 수 있습니다.
3. **데이터 임포트:**
- `cypher_scripts/import_generated_data.cypher` 등의 스크립트를 사용하여 `data/` 디렉토리의 CSV 파일들을 Memgraph로 임포트할 수 있습니다.
- memgraph-lab의 import 메뉴 http://172.16.10.191:3000/lab/query?component=import 를 통해 업로드할 수 있습니다.
## 4. 디렉토리 구조
- `conf/`: Memgraph 설정 파일
- `cypher_scripts/`: 데이터 임포트 및 분석을 위한 Cypher 쿼리 스크립트
- `data/`: CSV 형태의 샘플 데이터
- `docs/`: 프로젝트 관련 문서
- `scripts/`: Docker entrypoint 등 쉘 스크립트

View File

@@ -0,0 +1,50 @@
// 새로운 시나리오 'SCN04' 생성 및 순서 변경
// 1. 새로운 시나리오 'SCN04' 노드 생성 (SCN01 기반)
CREATE (s4:Scenario {id: 'SCN04', name: 'SCN01 순서 변경 시나리오', description: 'SCN01에서 Job 2와 Job 1의 순서를 변경'});
// 2. SCN01에 포함된 Job들을 SCN04에도 INCLUDES 관계로 연결합니다.
MATCH (s1:Scenario {id: 'SCN01'})-[r:INCLUDES]->(j:Job)
WITH s1, j
MATCH (s4:Scenario {id: 'SCN04'})
CREATE (s4)-[:INCLUDES]->(j);
// 3. SCN01의 순서를 기반으로 SCN04의 초기 순서를 복제합니다.
// - STARTS_WITH 관계 복제
MATCH (s1:Scenario {id: 'SCN01'})-[sw:STARTS_WITH]->(start_job:Job)
WITH s1, start_job
MATCH (s4:Scenario {id: 'SCN04'})
CREATE (s4)-[:STARTS_WITH]->(start_job);
// - NEXT 관계망 복제 (SCN04 시나리오에 종속된 NEXT 관계 생성)
MATCH (s1:Scenario {id: 'SCN01'})-[:STARTS_WITH]->(start_job:Job)
MATCH path = (start_job)-[:NEXT*]->(end_job:Job)
WHERE NOT (end_job)-[:NEXT]->()
WITH nodes(path) AS jobs
UNWIND range(0, size(jobs)-2) AS i
WITH jobs[i] AS from_job, jobs[i+1] AS to_job
MATCH (s4:Scenario {id: 'SCN04'})
// MERGE를 사용하여 SCN04의 Job들을 가져와서 NEXT 관계 생성
MERGE (j1:Job {id: from_job.id})
MERGE (j2:Job {id: to_job.id})
CREATE (j1)-[:NEXT {scenario: 'SCN04'}]->(j2);
// 4. SCN04에서 Job 1과 Job 2의 순서를 변경합니다. (기존 1->2->3 ... 을 2->1->3 ... 으로)
// - 기존 관계 삭제: (s4)-[sw:STARTS_WITH]->(j1), (j1)-[n1:NEXT {scenario: 'SCN04'}]->(j2)
MATCH (s4:Scenario {id: 'SCN04'})-[sw:STARTS_WITH]->(j1:Job {id: '1'})
DELETE sw;
MATCH (j1:Job {id: '1'})-[n1:NEXT {scenario: 'SCN04'}]->(j2:Job {id: '2'})
DELETE n1;
MATCH (j2:Job {id: '2'})-[n2:NEXT {scenario: 'SCN04'}]->(j3:Job {id: '3'})
DELETE n2;
// - 새로운 관계 생성: (s4)-[:STARTS_WITH]->(j2), (j2)-[:NEXT]->(j1), (j1)-[:NEXT]->(j3)
MATCH (s4:Scenario {id: 'SCN04'}), (j1:Job {id: '1'}), (j2:Job {id: '2'}), (j3:Job {id: '3'})
CREATE (s4)-[:STARTS_WITH]->(j2),
(j2)-[:NEXT {scenario: 'SCN04'}]->(j1),
(j1)-[:NEXT {scenario: 'SCN04'}]->(j3);
RETURN "SCN04가 성공적으로 생성되었습니다.";

View File

@@ -0,0 +1,13 @@
// Memgraph 데이터 모델 스키마 정의 (인덱스 및 제약 조건)
// 이 스크립트는 데이터를 로드하지 않고, 노드 타입별로 고유 키 제약 조건만 설정합니다.
// UNIQUE 제약 조건은 자동으로 인덱스를 생성합니다.
CREATE CONSTRAINT ON (j:Job) ASSERT j.id IS UNIQUE;
CREATE CONSTRAINT ON (jt:JobType) ASSERT jt.type_id IS UNIQUE;
CREATE CONSTRAINT ON (o:Object) ASSERT o.id IS UNIQUE;
CREATE CONSTRAINT ON (ot:ObjectType) ASSERT ot.type_id IS UNIQUE;
CREATE CONSTRAINT ON (s:Status) ASSERT s.status_id IS UNIQUE;
CREATE CONSTRAINT ON (a:Activity) ASSERT a.id IS UNIQUE;
CREATE CONSTRAINT ON (s:Scenario) ASSERT s.id IS UNIQUE;
RETURN "Schema constraints and indexes created successfully.";

View File

@@ -0,0 +1,58 @@
// 1. 인덱스 및 제약 조건 설정
CREATE INDEX ON :Job(id);
CREATE INDEX ON :JobType(id);
CREATE INDEX ON :Object(id);
CREATE INDEX ON :ObjectType(id);
CREATE INDEX ON :Status(id);
CREATE INDEX ON :Activity(id);
CREATE INDEX ON :Scenario(id);
// 2. 노드 레이블 및 관계 타입 정의 (최소한의 샘플 생성)
// JobType 노드 생성
CREATE (:JobType {type_id: 'SAMPLE_JT', name: 'Sample JobType'});
// Job 노드 생성
CREATE (:Job {id: 'SAMPLE_JOB', name: 'Sample Job', duration: 0, cost: 0});
// ObjectType 노드 생성
CREATE (:ObjectType {type_id: 'SAMPLE_OT', name: 'Sample ObjectType'});
// Object 노드 생성
CREATE (:Object {id: 'SAMPLE_OBJ', name: 'Sample Object'});
// Status 노드 생성
CREATE (:Status {status_id: 'SAMPLE_STATUS', name: 'Sample Status'});
// Activity 노드 생성
CREATE (:Activity {id: 'SAMPLE_ACT', name: 'Sample Activity', description: 'Sample Description'});
// Scenario 노드 생성
CREATE (:Scenario {id: 'SAMPLE_SCN', name: 'Sample Scenario', description: 'Sample Description'});
// 관계 생성 (샘플 노드들을 연결)
MATCH (j:Job {id: 'SAMPLE_JOB'}), (jt:JobType {type_id: 'SAMPLE_JT'})
CREATE (j)-[:IS_A]->(jt);
MATCH (o:Object {id: 'SAMPLE_OBJ'}), (ot:ObjectType {type_id: 'SAMPLE_OT'})
CREATE (o)-[:IS_A]->(ot);
MATCH (j1:Job {id: 'SAMPLE_JOB'}), (j2:Job {id: 'SAMPLE_JOB'})
CREATE (j1)-[:PRECEDES]->(j2);
MATCH (j:Job {id: 'SAMPLE_JOB'}), (s:Status {status_id: 'SAMPLE_STATUS'})
CREATE (j)-[:HAS_STATUS]->(s);
MATCH (s:Scenario {id: 'SAMPLE_SCN'}), (j:Job {id: 'SAMPLE_JOB'})
CREATE (s)-[:INCLUDES]->(j);
MATCH (s1:Scenario {id: 'SAMPLE_SCN'}), (s2:Scenario {id: 'SAMPLE_SCN'})
CREATE (s1)-[:DELTA_FROM]->(s2);
MATCH (j:Job {id: 'SAMPLE_JOB'}), (a:Activity {id: 'SAMPLE_ACT'})
CREATE (j)-[:PERFORMS]->(a);
MATCH (a:Activity {id: 'SAMPLE_ACT'}), (o:Object {id: 'SAMPLE_OBJ'})
CREATE (a)-[:ACTS_ON]->(o);
RETURN "Schema creation successful!";

View File

@@ -0,0 +1,31 @@
// --- SCN04 시나리오 디버깅 쿼리 ---
// 아래 쿼리들을 위에서부터 하나씩 **따로따로** 복사하여 Memgraph Lab에서 실행해 보세요.
// 각 쿼리가 어떤 결과를 반환하는지 확인하면 문제의 원인을 찾을 수 있습니다.
// -----------------------------------------------------------------------------
// 쿼리 1: SCN04 시나리오 노드가 존재하는지 확인합니다.
// 예상 결과: SCN04 노드 1개가 보여야 합니다.
// -----------------------------------------------------------------------------
MATCH (s:Scenario {id: 'SCN04'})
RETURN s;
// -----------------------------------------------------------------------------
// 쿼리 2: SCN04에 포함된 Job들이 있는지 확인합니다.
// 예상 결과: SCN04 노드와 :INCLUDES 관계로 연결된 5개의 Job 노드가 보여야 합니다.
// -----------------------------------------------------------------------------
MATCH p = (s:Scenario {id: 'SCN04'})-[:INCLUDES]->(j:Job)
RETURN p;
// -----------------------------------------------------------------------------
// 쿼리 3: SCN04의 시작 Job이 정의되어 있는지 확인합니다.
// 예상 결과: SCN04에서 :STARTS_WITH 관계로 Job '2' 노드가 연결되어 보여야 합니다.
// -----------------------------------------------------------------------------
MATCH p = (s:Scenario {id: 'SCN04'})-[:STARTS_WITH]->(j:Job)
RETURN p;
// -----------------------------------------------------------------------------
// 쿼리 4: SCN04의 전체 작업 순서 경로를 확인합니다.
// 예상 결과: Job '2' -> Job '1' -> Job '3' -> ... 순서로 :NEXT 관계가 연결되어 보여야 합니다.
// -----------------------------------------------------------------------------
MATCH p = (s:Scenario {id: 'SCN04'})-[:STARTS_WITH]->(start_job:Job)-[:NEXT* {scenario: 'SCN04'}]->(end_job:Job)
RETURN p;

View File

@@ -0,0 +1,38 @@
// 1. 기존 스키마 제약 조건 모두 삭제
DROP CONSTRAINT ON (j:Job) ASSERT j.id IS UNIQUE;
DROP CONSTRAINT ON (jt:JobType) ASSERT jt.type_id IS UNIQUE;
DROP CONSTRAINT ON (o:Object) ASSERT o.id IS UNIQUE;
DROP CONSTRAINT ON (ot:ObjectType) ASSERT ot.type_id IS UNIQUE;
DROP CONSTRAINT ON (s:Status) ASSERT s.status_id IS UNIQUE;
DROP CONSTRAINT ON (a:Activity) ASSERT a.id IS UNIQUE;
DROP CONSTRAINT ON (s:Scenario) ASSERT s.id IS UNIQUE;
// 2. 인덱스 생성
CREATE INDEX ON :Job(id);
CREATE INDEX ON :JobType(id);
CREATE INDEX ON :Object(id);
CREATE INDEX ON :ObjectType(id);
CREATE INDEX ON :Status(id);
CREATE INDEX ON :Activity(id);
CREATE INDEX ON :Scenario(id);
// 3. 노드 데이터 로드
LOAD CSV FROM "/data/job_types.csv" WITH HEADER AS row CREATE (n:JobType {type_id: row.id, name: row.name});
LOAD CSV FROM "/data/jobs.csv" WITH HEADER AS row CREATE (n:Job {id: row.id, name: row.name, duration: toInteger(row.duration), cost: toInteger(row.cost)});
LOAD CSV FROM "/data/object_types.csv" WITH HEADER AS row CREATE (n:ObjectType {type_id: row.id, name: row.name});
LOAD CSV FROM "/data/objects.csv" WITH HEADER AS row CREATE (n:Object {id: row.id, name: row.name});
LOAD CSV FROM "/data/mgmt_status.csv" WITH HEADER AS row CREATE (n:Status {status_id: row.id, name: row.status});
LOAD CSV FROM "/data/activities.csv" WITH HEADER AS row CREATE (n:Activity {id: row.id, name: row.name, description: row.description});
LOAD CSV FROM "/data/scenarios.csv" WITH HEADER AS row CREATE (n:Scenario {id: row.id, name: row.name, description: row.description});
// 4. 관계 데이터 로드
LOAD CSV FROM "/data/relations.csv" WITH HEADER AS row WHERE row.type = 'IS_A' AND row.from_id STARTS WITH 'J' MATCH (from:Job {id: row.from_id}), (to:JobType {type_id: row.to_id}) CREATE (from)-[:IS_A]->(to);
LOAD CSV FROM "/data/relations.csv" WITH HEADER AS row WHERE row.type = 'IS_A' AND row.from_id STARTS WITH 'O' MATCH (from:Object {id: row.from_id}), (to:ObjectType {type_id: row.to_id}) CREATE (from)-[:IS_A]->(to);
LOAD CSV FROM "/data/relations.csv" WITH HEADER AS row WHERE row.type = 'PRECEDES' MATCH (from:Job {id: row.from_id}), (to:Job {id: row.to_id}) CREATE (from)-[:PRECEDES]->(to);
LOAD CSV FROM "/data/relations.csv" WITH HEADER AS row WHERE row.type = 'HAS_STATUS' MATCH (from:Job {id: row.from_id}), (to:Status {status_id: row.to_id}) CREATE (from)-[:HAS_STATUS]->(to);
LOAD CSV FROM "/data/relations_new.csv" WITH HEADER AS row WHERE row.type = 'INCLUDES' MATCH (from:Scenario {id: row.from_id}), (to:Job {id: row.to_id}) CREATE (from)-[:INCLUDES]->(to);
LOAD CSV FROM "/data/relations_new.csv" WITH HEADER AS row WHERE row.type = 'DELTA_FROM' MATCH (from:Scenario {id: row.from_id}), (to:Scenario {id: row.to_id}) CREATE (from)-[:DELTA_FROM]->(to);
LOAD CSV FROM "/data/relations_new.csv" WITH HEADER AS row WHERE row.type = 'PERFORMS' MATCH (from:Job {id: row.from_id}), (to:Activity {id: row.to_id}) CREATE (from)-[:PERFORMS]->(to);
LOAD CSV FROM "/data/relations_new.csv" WITH HEADER AS row WHERE row.type = 'ACTS_ON' MATCH (from:Activity {id: row.from_id}), (to:Object {id: row.to_id}) CREATE (from)-[:ACTS_ON]->(to);
RETURN "Import successful!";

View File

@@ -0,0 +1,198 @@
// 0. 데이터베이스 초기화
MATCH (n) DETACH DELETE n;
// 1. 노드 생성
// JobType 노드
CREATE (:JobType {type_id: 'JT01', name: '터널 입구 굴착'});
CREATE (:JobType {type_id: 'JT02', name: '숏크리트 타설'});
CREATE (:JobType {type_id: 'JT03', name: '강지보 설치'});
CREATE (:JobType {type_id: 'JT04', name: '방수 및 배수시설 설치'});
CREATE (:JobType {type_id: 'JT05', name: '철근 조립'});
CREATE (:JobType {type_id: 'JT06', name: '내부 라이닝 콘크리트 타설'});
CREATE (:JobType {type_id: 'JT07', name: '조명 및 환기시설 설치'});
CREATE (:JobType {type_id: 'JT08', name: '안전시설물 설치'});
CREATE (:JobType {type_id: 'JT09', name: '포장 및 차선 도색'});
CREATE (:JobType {type_id: 'JT10', name: 'TBM 준비'});
CREATE (:JobType {type_id: 'JT11', name: 'TBM 굴진'});
CREATE (:JobType {type_id: 'JT12', name: '세그먼트 조립'});
CREATE (:JobType {type_id: 'JT13', name: '그라우팅'});
CREATE (:JobType {type_id: 'JT14', name: 'TBM 해체 및 반출'});
CREATE (:JobType {type_id: 'JT15', name: '전기/통신 케이블 설치'});
CREATE (:JobType {type_id: 'JT16', name: 'CCTV 및 VMS 설치'});
CREATE (:JobType {type_id: 'JT17', name: '소방시설 설치'});
CREATE (:JobType {type_id: 'JT18', name: '최종 점검'});
CREATE (:JobType {type_id: 'JT19', name: '개통 준비'});
// Job 노드
CREATE (:Job {id: '1', name: '터널 입구 굴착', duration: 10, cost: 150});
CREATE (:Job {id: '2', name: '1차 숏크리트 타설', duration: 5, cost: 80});
CREATE (:Job {id: '3', name: '강지보 설치', duration: 7, cost: 120});
CREATE (:Job {id: '4', name: '2차 숏크리트 타설', duration: 5, cost: 80});
CREATE (:Job {id: '5', name: '방수 및 배수시설 설치', duration: 8, cost: 100});
CREATE (:Job {id: '6', name: '철근 조립', duration: 6, cost: 90});
CREATE (:Job {id: '7', name: '내부 라이닝 콘크리트 타설', duration: 12, cost: 200});
CREATE (:Job {id: '8', name: '조명 및 환기시설 설치', duration: 9, cost: 110});
CREATE (:Job {id: '9', name: '안전시설물 설치', duration: 4, cost: 60});
CREATE (:Job {id: '10', name: '포장 및 차선 도색', duration: 7, cost: 95});
CREATE (:Job {id: '11', name: 'TBM 준비', duration: 15, cost: 500});
CREATE (:Job {id: '12', name: 'TBM 굴진', duration: 30, cost: 1200});
CREATE (:Job {id: '13', name: '세그먼트 조립', duration: 25, cost: 800});
CREATE (:Job {id: '14', name: '그라우팅', duration: 10, cost: 150});
CREATE (:Job {id: '15', name: 'TBM 해체 및 반출', duration: 12, cost: 300});
CREATE (:Job {id: '16', name: '전기/통신 케이블 설치', duration: 8, cost: 130});
CREATE (:Job {id: '17', name: 'CCTV 및 VMS 설치', duration: 5, cost: 70});
CREATE (:Job {id: '18', name: '소방시설 설치', duration: 6, cost: 85});
CREATE (:Job {id: '19', name: '최종 점검', duration: 3, cost: 50});
CREATE (:Job {id: '20', name: '개통 준비', duration: 2, cost: 30});
// ObjectType 노드
CREATE (:ObjectType {type_id: 'OT01', name: '굴착기'});
CREATE (:ObjectType {type_id: 'OT02', name: '숏크리트 펌프'});
CREATE (:ObjectType {type_id: 'OT03', name: '강지보재'});
CREATE (:ObjectType {type_id: 'OT04', name: '방수시트'});
CREATE (:ObjectType {type_id: 'OT05', name: '콘크리트 믹서'});
CREATE (:ObjectType {type_id: 'OT06', name: '철근'});
CREATE (:ObjectType {type_id: 'OT07', name: '조명등'});
CREATE (:ObjectType {type_id: 'OT08', name: '환풍기'});
CREATE (:ObjectType {type_id: 'OT09', name: 'TBM'});
CREATE (:ObjectType {type_id: 'OT10', name: '세그먼트'});
CREATE (:ObjectType {type_id: 'OT11', name: '그라우트 믹서'});
CREATE (:ObjectType {type_id: 'OT12', name: '케이블'});
CREATE (:ObjectType {type_id: 'OT13', name: 'CCTV'});
CREATE (:ObjectType {type_id: 'OT14', name: '소화기'});
CREATE (:ObjectType {type_id: 'OT15', name: '차선도색기'});
CREATE (:ObjectType {type_id: 'OT16', name: '숏크리트'});
// Object 노드
CREATE (:Object {id: 'OBJ01', name: '굴착기-A01'});
CREATE (:Object {id: 'OBJ02', name: '숏크리트 펌프-A'});
CREATE (:Object {id: 'OBJ03', name: '강지보재-L100'});
CREATE (:Object {id: 'OBJ04', name: '방수시트-S20'});
CREATE (:Object {id: 'OBJ05', name: '콘크리트 믹서-T1'});
CREATE (:Object {id: 'OBJ06', name: '철근-D16'});
CREATE (:Object {id: 'OBJ07', name: '조명등-LED-1'});
CREATE (:Object {id: 'OBJ08', name: '환풍기-F1'});
CREATE (:Object {id: 'OBJ09', name: 'TBM-Shield-1'});
CREATE (:Object {id: 'OBJ10', name: '세그먼트-A타입'});
CREATE (:Object {id: 'OBJ11', name: '그라우트 믹서-G1'});
CREATE (:Object {id: 'OBJ12', name: '전원 케이블-HV-1'});
CREATE (:Object {id: 'OBJ13', name: 'CCTV-001'});
CREATE (:Object {id: 'OBJ14', name: '소화기-P1'});
CREATE (:Object {id: 'OBJ15', name: '차선도색기-Y1'});
CREATE (:Object {id: 'OBJ16', name: '숏크리트-Batch1'});
CREATE (:Object {id: 'OBJ17', name: '숏크리트-Batch2'});
// Status 노드
CREATE (:Status {status_id: 'CS_APP', name: 'APPROVED'});
CREATE (:Status {status_id: 'CS_CON', name: 'CONFIRMED'});
CREATE (:Status {status_id: 'CS_PLN', name: 'PLANNING'});
CREATE (:Status {status_id: 'PS_EXE', name: 'EXECUTING'});
CREATE (:Status {status_id: 'PS_PLN', name: 'PLANNING'});
CREATE (:Status {status_id: 'PM_PAID', name: 'PAID'});
CREATE (:Status {status_id: 'PM_APL', name: 'APPLIED'});
CREATE (:Status {status_id: 'PM_NON', name: 'NONE'});
CREATE (:Status {status_id: 'QS_APP', name: 'APPROVED'});
CREATE (:Status {status_id: 'QS_CON', name: 'CONFIRMED'});
CREATE (:Status {status_id: 'QS_PLN', name: 'PLANNING'});
CREATE (:Status {status_id: 'SS_APP', name: 'APPROVED'});
CREATE (:Status {status_id: 'SS_CON', name: 'CONFIRMED'});
CREATE (:Status {status_id: 'SS_PLN', name: 'PLANNING'});
// Activity 노드
CREATE (:Activity {id: 'ACT01', name: '굴착 작업', description: '터널 입구 지반 굴착'});
CREATE (:Activity {id: 'ACT02', name: '숏크리트 타설 작업', description: '굴착면에 숏크리트 타설하여 안정화'});
CREATE (:Activity {id: 'ACT03', name: '강지보 설치 작업', description: '강재 지보를 설치하여 터널 구조 강화'});
CREATE (:Activity {id: 'ACT04', name: '방수/배수 작업', description: '방수시트 및 배수시설 설치'});
CREATE (:Activity {id: 'ACT05', name: '철근 조립 작업', description: '내부 라이닝을 위한 철근 조립'});
// Scenario 노드
CREATE (:Scenario {id: 'SCN01', name: '기본 시나리오', description: '가장 기본적인 순서의 작업 흐름'});
CREATE (:Scenario {id: 'SCN02', name: 'TBM 공법 적용 시나리오', description: 'TBM 장비를 활용한 대체 작업 흐름'});
CREATE (:Scenario {id: 'SCN03', name: 'SCN02 증분 시나리오', description: 'SCN02 시나리오에서 일부 작업 순서 변경'});
// 2. 관계 생성
// Job IS_A JobType
MATCH (j:Job {id: '1'}), (jt:JobType {type_id: 'JT01'}) CREATE (j)-[:IS_A]->(jt);
MATCH (j:Job {id: '2'}), (jt:JobType {type_id: 'JT02'}) CREATE (j)-[:IS_A]->(jt);
MATCH (j:Job {id: '3'}), (jt:JobType {type_id: 'JT03'}) CREATE (j)-[:IS_A]->(jt);
MATCH (j:Job {id: '4'}), (jt:JobType {type_id: 'JT02'}) CREATE (j)-[:IS_A]->(jt);
MATCH (j:Job {id: '5'}), (jt:JobType {type_id: 'JT04'}) CREATE (j)-[:IS_A]->(jt);
// Object IS_A ObjectType
MATCH (o:Object {id: 'OBJ01'}), (ot:ObjectType {type_id: 'OT01'}) CREATE (o)-[:IS_A]->(ot);
MATCH (o:Object {id: 'OBJ02'}), (ot:ObjectType {type_id: 'OT02'}) CREATE (o)-[:IS_A]->(ot);
MATCH (o:Object {id: 'OBJ16'}), (ot:ObjectType {type_id: 'OT16'}) CREATE (o)-[:IS_A]->(ot);
MATCH (o:Object {id: 'OBJ17'}), (ot:ObjectType {type_id: 'OT16'}) CREATE (o)-[:IS_A]->(ot);
// Job PRECEDES Job
MATCH (j1:Job {id: '1'}), (j2:Job {id: '2'}) CREATE (j1)-[:PRECEDES]->(j2);
MATCH (j1:Job {id: '2'}), (j2:Job {id: '3'}) CREATE (j1)-[:PRECEDES]->(j2);
MATCH (j1:Job {id: '3'}), (j2:Job {id: '4'}) CREATE (j1)-[:PRECEDES]->(j2);
MATCH (j1:Job {id: '4'}), (j2:Job {id: '5'}) CREATE (j1)-[:PRECEDES]->(j2);
// Job HAS_STATUS Status
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'CS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'PS_EXE'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'PM_PAID'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'QS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '1'}), (s:Status {status_id: 'SS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'CS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'PS_EXE'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'PM_PAID'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'QS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '2'}), (s:Status {status_id: 'SS_APP'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'CS_CON'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'PS_EXE'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'PM_APL'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'QS_CON'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '3'}), (s:Status {status_id: 'SS_CON'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'CS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'PS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'PM_NON'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'QS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '4'}), (s:Status {status_id: 'SS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'CS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'PS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'PM_NON'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'QS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
MATCH (j:Job {id: '5'}), (s:Status {status_id: 'SS_PLN'}) CREATE (j)-[:HAS_STATUS]->(s);
// Scenario INCLUDES Job
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '1'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '2'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '3'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '4'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN01'}), (j:Job {id: '5'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '11'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '12'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '13'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '14'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN02'}), (j:Job {id: '15'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '11'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '13'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '12'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '14'}) CREATE (s)-[:INCLUDES]->(j);
MATCH (s:Scenario {id: 'SCN03'}), (j:Job {id: '15'}) CREATE (s)-[:INCLUDES]->(j);
// Scenario DELTA_FROM Scenario
MATCH (s1:Scenario {id: 'SCN03'}), (s2:Scenario {id: 'SCN02'}) CREATE (s1)-[:DELTA_FROM]->(s2);
// Job PERFORMS Activity
MATCH (j:Job {id: '1'}), (a:Activity {id: 'ACT01'}) CREATE (j)-[:PERFORMS]->(a);
MATCH (j:Job {id: '2'}), (a:Activity {id: 'ACT02'}) CREATE (j)-[:PERFORMS]->(a);
MATCH (j:Job {id: '3'}), (a:Activity {id: 'ACT03'}) CREATE (j)-[:PERFORMS]->(a);
MATCH (j:Job {id: '4'}), (a:Activity {id: 'ACT02'}) CREATE (j)-[:PERFORMS]->(a);
MATCH (j:Job {id: '5'}), (a:Activity {id: 'ACT04'}) CREATE (j)-[:PERFORMS]->(a);
MATCH (j:Job {id: '6'}), (a:Activity {id: 'ACT05'}) CREATE (j)-[:PERFORMS]->(a);
// Activity ACTS_ON Object
MATCH (a:Activity {id: 'ACT01'}), (o:Object {id: 'OBJ01'}) CREATE (a)-[:ACTS_ON]->(o);
MATCH (a:Activity {id: 'ACT02'}), (o:Object {id: 'OBJ02'}) CREATE (a)-[:ACTS_ON]->(o);
MATCH (a:Activity {id: 'ACT02'}), (o:Object {id: 'OBJ16'}) CREATE (a)-[:ACTS_ON]->(o);
MATCH (a:Activity {id: 'ACT03'}), (o:Object {id: 'OBJ03'}) CREATE (a)-[:ACTS_ON]->(o);
MATCH (a:Activity {id: 'ACT04'}), (o:Object {id: 'OBJ04'}) CREATE (a)-[:ACTS_ON]->(o);
MATCH (a:Activity {id: 'ACT05'}), (o:Object {id: 'OBJ06'}) CREATE (a)-[:ACTS_ON]->(o);
RETURN "All data imported successfully!";

View File

@@ -0,0 +1,52 @@
// --- SCN04 시나리오 재생성 (최종 수정 쿼리) ---
// 0. 기존에 잘못 생성되었을 수 있는 SCN04 관련 데이터를 모두 삭제합니다.
MATCH (s:Scenario {id: 'SCN04'})
DETACH DELETE s;
// 1. 새로운 시나리오 'SCN04' 노드를 생성하고, WITH 절로 s4 변수를 바로 다음 쿼리로 전달합니다.
CREATE (s4:Scenario {id: 'SCN04', name: 'SCN01 순서 변경 시나리오', description: 'SCN01에서 Job 2와 Job 1의 순서를 변경'})
WITH s4;
// 2. SCN01에 포함된 Job들을 찾아 SCN04에 :INCLUDES 관계로 연결합니다.
MATCH (s1:Scenario {id: 'SCN01'})-[:INCLUDES]->(j:Job)
WITH s4, j // 이전 단계의 s4와 현재 찾은 j를 함께 전달합니다.
CREATE (s4)-[:INCLUDES]->(j);
// 3. SCN01의 순서를 기반으로 SCN04의 초기 순서를 복제합니다.
// - STARTS_WITH 관계 복제
MATCH (s4:Scenario {id: 'SCN04'})
MATCH (s1:Scenario {id: 'SCN01'})-[sw:STARTS_WITH]->(start_job:Job)
CREATE (s4)-[:STARTS_WITH]->(start_job);
// - NEXT 관계망 복제 (SCN04 시나리오에 종속된 NEXT 관계 생성)
MATCH (s1:Scenario {id: 'SCN01'})-[:STARTS_WITH]->(start_job:Job)
MATCH path = (start_job)-[:NEXT*]->(end_job:Job)
WHERE NOT (end_job)-[:NEXT]->()
WITH nodes(path) AS jobs
UNWIND range(0, size(jobs)-2) AS i
WITH jobs[i] AS from_job, jobs[i+1] AS to_job
MATCH (s4:Scenario {id: 'SCN04'})
MERGE (j1:Job {id: from_job.id})
MERGE (j2:Job {id: to_job.id})
CREATE (j1)-[:NEXT {scenario: 'SCN04'}]->(j2);
// 4. SCN04에서 Job 1과 Job 2의 순서를 변경합니다. (기존 1->2->3 ... 을 2->1->3 ... 으로)
// - 기존 관계 삭제
MATCH (s4:Scenario {id: 'SCN04'})-[sw:STARTS_WITH]->(j1:Job {id: '1'})
DELETE sw;
MATCH (j1:Job {id: '1'})-[n1:NEXT {scenario: 'SCN04'}]->(j2:Job {id: '2'})
DELETE n1;
MATCH (j2:Job {id: '2'})-[n2:NEXT {scenario: 'SCN04'}]->(j3:Job {id: '3'})
DELETE n2;
// - 새로운 관계 생성
MATCH (s4:Scenario {id: 'SCN04'}), (j1:Job {id: '1'}), (j2:Job {id: '2'}), (j3:Job {id: '3'})
CREATE (s4)-[:STARTS_WITH]->(j2),
(j2)-[:NEXT {scenario: 'SCN04'}]->(j1),
(j1)-[:NEXT {scenario: 'SCN04'}]->(j3);
RETURN "SCN04가 성공적으로 재생성되었습니다.";

View File

@@ -0,0 +1,52 @@
// --- SCN04 시나리오 재생성 (수정된 쿼리) ---
// 0. 기존에 잘못 생성되었을 수 있는 SCN04 관련 데이터를 모두 삭제합니다.
MATCH (s:Scenario {id: 'SCN04'})
DETACH DELETE s;
// 1. 새로운 시나리오 'SCN04' 노드를 다시 생성합니다.
CREATE (s4:Scenario {id: 'SCN04', name: 'SCN01 순서 변경 시나리오', description: 'SCN01에서 Job 2와 Job 1의 순서를 변경'});
// 2. SCN01에 포함된 Job들을 찾아 SCN04에 :INCLUDES 관계로 연결합니다. (수정된 부분)
// WITH 절을 사용하여 s4를 명시적으로 전달합니다.
WITH s4
MATCH (s1:Scenario {id: 'SCN01'})-[:INCLUDES]->(j:Job)
CREATE (s4)-[:INCLUDES]->(j);
// 3. SCN01의 순서를 기반으로 SCN04의 초기 순서를 복제합니다.
// - STARTS_WITH 관계 복제
WITH s4
MATCH (s1:Scenario {id: 'SCN01'})-[sw:STARTS_WITH]->(start_job:Job)
CREATE (s4)-[:STARTS_WITH]->(start_job);
// - NEXT 관계망 복제 (SCN04 시나리오에 종속된 NEXT 관계 생성)
MATCH (s1:Scenario {id: 'SCN01'})-[:STARTS_WITH]->(start_job:Job)
MATCH path = (start_job)-[:NEXT*]->(end_job:Job)
WHERE NOT (end_job)-[:NEXT]->()
WITH nodes(path) AS jobs
UNWIND range(0, size(jobs)-2) AS i
WITH jobs[i] AS from_job, jobs[i+1] AS to_job
MATCH (s4:Scenario {id: 'SCN04'})
MERGE (j1:Job {id: from_job.id})
MERGE (j2:Job {id: to_job.id})
CREATE (j1)-[:NEXT {scenario: 'SCN04'}]->(j2);
// 4. SCN04에서 Job 1과 Job 2의 순서를 변경합니다. (기존 1->2->3 ... 을 2->1->3 ... 으로)
// - 기존 관계 삭제
MATCH (s4:Scenario {id: 'SCN04'})-[sw:STARTS_WITH]->(j1:Job {id: '1'})
DELETE sw;
MATCH (j1:Job {id: '1'})-[n1:NEXT {scenario: 'SCN04'}]->(j2:Job {id: '2'})
DELETE n1;
MATCH (j2:Job {id: '2'})-[n2:NEXT {scenario: 'SCN04'}]->(j3:Job {id: '3'})
DELETE n2;
// - 새로운 관계 생성
MATCH (s4:Scenario {id: 'SCN04'}), (j1:Job {id: '1'}), (j2:Job {id: '2'}), (j3:Job {id: '3'})
CREATE (s4)-[:STARTS_WITH]->(j2),
(j2)-[:NEXT {scenario: 'SCN04'}]->(j1),
(j1)-[:NEXT {scenario: 'SCN04'}]->(j3);
RETURN "SCN04가 성공적으로 재생성되었습니다.";

View File

@@ -0,0 +1,12 @@
// SCN04 시나리오의 전체 구조를 시각화하는 쿼리
// 시나리오 노드, 포함된 모든 Job, 그리고 작업 실행 순서(STARTS_WITH, NEXT)를 함께 조회합니다.
// p1 경로는 SCN04에 포함된(:INCLUDES) 모든 Job을 찾습니다.
MATCH p1 = (s:Scenario {id: 'SCN04'})-[:INCLUDES]->(job:Job)
// p2 경로는 SCN04의 시작(:STARTS_WITH)부터 NEXT 관계로 이어진 작업 순서 전체를 찾습니다.
// 이 경로는 SCN04에만 해당하는 NEXT 관계({scenario: 'SCN04'})를 따라갑니다.
MATCH p2 = (s)-[:STARTS_WITH]->(start_job:Job)-[:NEXT* {scenario: 'SCN04'}]->(end_job:Job)
// 두 경로(p1, p2)를 모두 반환하여 시나리오의 전체 구조를 시각화합니다.
RETURN p1, p2;

6
data/activities.csv Normal file
View File

@@ -0,0 +1,6 @@
id,name,description
ACT01,굴착 작업,터널 입구 지반 굴착
ACT02,숏크리트 타설 작업,굴착면에 숏크리트 타설하여 안정화
ACT03,강지보 설치 작업,강재 지보를 설치하여 터널 구조 강화
ACT04,방수/배수 작업,방수시트 및 배수시설 설치
ACT05,철근 조립 작업,내부 라이닝을 위한 철근 조립
1 id name description
2 ACT01 굴착 작업 터널 입구 지반 굴착
3 ACT02 숏크리트 타설 작업 굴착면에 숏크리트 타설하여 안정화
4 ACT03 강지보 설치 작업 강재 지보를 설치하여 터널 구조 강화
5 ACT04 방수/배수 작업 방수시트 및 배수시설 설치
6 ACT05 철근 조립 작업 내부 라이닝을 위한 철근 조립

33
data/relations_new.csv Normal file
View File

@@ -0,0 +1,33 @@
from_id,to_id,type
# Scenario INCLUDES Job
SCN01,1,INCLUDES
SCN01,2,INCLUDES
SCN01,3,INCLUDES
SCN01,4,INCLUDES
SCN01,5,INCLUDES
SCN02,11,INCLUDES
SCN02,12,INCLUDES
SCN02,13,INCLUDES
SCN02,14,INCLUDES
SCN02,15,INCLUDES
SCN03,11,INCLUDES
SCN03,13,INCLUDES # 12, 13 순서 변경
SCN03,12,INCLUDES
SCN03,14,INCLUDES
SCN03,15,INCLUDES
# Scenario DELTA_FROM Scenario
SCN03,SCN02,DELTA_FROM
# Job PERFORMS Activity
1,ACT01,PERFORMS
2,ACT02,PERFORMS
3,ACT03,PERFORMS
4,ACT02,PERFORMS
5,ACT04,PERFORMS
6,ACT05,PERFORMS
# Activity ACTS_ON Object
ACT01,OBJ01,ACTS_ON
ACT02,OBJ02,ACTS_ON
ACT02,OBJ16,ACTS_ON
ACT03,OBJ03,ACTS_ON
ACT04,OBJ04,ACTS_ON
ACT05,OBJ06,ACTS_ON
1 from_id,to_id,type
2 # Scenario INCLUDES Job
3 SCN01,1,INCLUDES
4 SCN01,2,INCLUDES
5 SCN01,3,INCLUDES
6 SCN01,4,INCLUDES
7 SCN01,5,INCLUDES
8 SCN02,11,INCLUDES
9 SCN02,12,INCLUDES
10 SCN02,13,INCLUDES
11 SCN02,14,INCLUDES
12 SCN02,15,INCLUDES
13 SCN03,11,INCLUDES
14 SCN03,13,INCLUDES # 12, 13 순서 변경
15 SCN03,12,INCLUDES
16 SCN03,14,INCLUDES
17 SCN03,15,INCLUDES
18 # Scenario DELTA_FROM Scenario
19 SCN03,SCN02,DELTA_FROM
20 # Job PERFORMS Activity
21 1,ACT01,PERFORMS
22 2,ACT02,PERFORMS
23 3,ACT03,PERFORMS
24 4,ACT02,PERFORMS
25 5,ACT04,PERFORMS
26 6,ACT05,PERFORMS
27 # Activity ACTS_ON Object
28 ACT01,OBJ01,ACTS_ON
29 ACT02,OBJ02,ACTS_ON
30 ACT02,OBJ16,ACTS_ON
31 ACT03,OBJ03,ACTS_ON
32 ACT04,OBJ04,ACTS_ON
33 ACT05,OBJ06,ACTS_ON

4
data/scenarios.csv Normal file
View File

@@ -0,0 +1,4 @@
id,name,description
SCN01,기본 시나리오,가장 기본적인 순서의 작업 흐름
SCN02,TBM 공법 적용 시나리오,TBM 장비를 활용한 대체 작업 흐름
SCN03,SCN02 증분 시나리오,SCN02 시나리오에서 일부 작업 순서 변경
1 id name description
2 SCN01 기본 시나리오 가장 기본적인 순서의 작업 흐름
3 SCN02 TBM 공법 적용 시나리오 TBM 장비를 활용한 대체 작업 흐름
4 SCN03 SCN02 증분 시나리오 SCN02 시나리오에서 일부 작업 순서 변경

View File

@@ -10,6 +10,7 @@ services:
pull_policy: always pull_policy: always
environment: environment:
- storage-properties-on-edges=true - storage-properties-on-edges=true
- storage-mode=true=IN_MEMORY_TRANSACTIONAL
ulimits: ulimits:
stack: stack:
soft: 33554432 soft: 33554432
@@ -20,6 +21,7 @@ services:
volumes: volumes:
- ./memgraph-data:/var/lib/memgraph - ./memgraph-data:/var/lib/memgraph
- ./conf/memgraph.conf:/etc/memgraph/memgraph.conf - ./conf/memgraph.conf:/etc/memgraph/memgraph.conf
- ./data:/data
lab: lab:
image: memgraph/lab:latest image: memgraph/lab:latest

View File

@@ -2,7 +2,7 @@
### 1. 개요 (Overview) ### 1. 개요 (Overview)
본 문서는 터널 시공 과정에서 발생하는 복잡한 작업(Job)과 객체(Object) 간의 관계를 그래프 데이터베이스인 Memgraph를 활용하여 모델링하고, 이를 통해 프로젝트의 Critical Path를 분석하여 효율적인 공정 관리를 지원하는 의사결정 프레임워크 PoC(Proof of Concept)의 요구사항을 정의합니다. 본 문서는 터널 시공 과정에서 발생하는 복잡한 작업(Job)과 객체(Object) 간의 관계를 그래프 데이터베이스인 Memgraph를 활용하여 모델링하고, 모든 job을 완료 상태로 만들 수 있는 시나리오들을 비교해 프로젝트의 Critical Path를 분석하여 효율적인 공정 관리를 지원하는 의사결정 프레임워크 PoC(Proof of Concept)의 요구사항을 정의합니다.
**1.1. 문제 정의 (Problem Statement)** **1.1. 문제 정의 (Problem Statement)**