> For the complete documentation index, see [llms.txt](https://swonh.gitbook.io/sdmp-user-manual-kor/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://swonh.gitbook.io/sdmp-user-manual-kor/general-module/undefined-1/statecontrol.md).

# StateControl

### GetIntitialState:star:

```csharp
public override State GetInitialState()
```

#### 정의

초기 State를 정의합니다.

#### 반환

<table><thead><tr><th width="167">Type</th><th width="369">Description</th><th>Default</th></tr></thead><tbody><tr><td>State</td><td>초기 State 입니다.</td><td>Null</td></tr></tbody></table>

#### 예제 <a href="#initialstate" id="initialstate"></a>

```csharp
public override State GetInitialState()
{
    CRPData data = DataManager.Instance.Data as CRPData;
    CRPState initState = new CRPState();

    initState.SetStateInfo(data.CRPFactory.Conveyors);

    return initState;
}
```

### GetKey

```csharp
public override string GetKey(State state)
```

#### 정의

State의 Key를 정의합니다.

#### 매개 변수

| Type  | Description         |
| ----- | ------------------- |
| State | Key를 정의할 State 입니다. |

#### 반환

| Type   | Description     | Default                            |
| ------ | --------------- | ---------------------------------- |
| String | State의 Key 입니다. | [Default Logic 참조](#default-logic) |

#### 예제 (Default Logic)

```csharp
public virtual string GetKey(State state)
{
    return state.Index.ToString();
}
```

### GetFeasibleSolution

```csharp
public override Solution GetFeasibleSolution(State state)
```

#### 정의

주어진 State를 기준으로 Feasible solution을 구하는 로직을 정의합니다.

#### 매개 변수

| Type  | Description                      |
| ----- | -------------------------------- |
| State | Feasible solution을 구할 State 입니다. |

#### 반환

| Type     | Description            | Default |
| -------- | ---------------------- | ------- |
| Solution | Feasible solution 입니다. | Null    |

#### 예제

```csharp
public override Solution GetFeasibleSolution(State state)
{           
    CRPState crpState = state as CRPState;
    CRPState copiedState = crpState.Clone();
    copiedState.IsInitial = false;

    List<CRPState> states = new List<CRPState>();
    states.AddRange(copiedState.GetBestStatesBackward().Cast<CRPState>().ToList());

    while (copiedState.JobCount > 0)
    {
        Stage stage = new Stage(copiedState.Stage.Index + 1);
        copiedState.Stage = stage;

        CRPJob lastJob = copiedState.LastRetrievedJob;

        CRPConveyor sameColorConv = copiedState.GetSameColorConveyor(lastJob);

        CRPJob retrievedJob = null;
        if (sameColorConv != null)
        {
            retrievedJob = copiedState.RetrieveJob(sameColorConv.ConveyorNum);
        }
        else 
        {
            retrievedJob = copiedState.RetrieveJob();
        }

        double cost = 0;
        if (lastJob != null && lastJob.Color.ColorNumber != retrievedJob.Color.ColorNumber)
            cost = 1;

        copiedState.BestValue += cost;

        states.Add(copiedState);
        copiedState = copiedState.Clone();
    }

    Solution feasibleSol = new Solution(states);

    return feasibleSol;
}
```

### CanPruneByOptimality

```csharp
public override bool CanPruneByOptimality(State state, ObjectiveFunctionType objFuncType, double pruneTolerance)
```

#### 정의

주어진 State가 최적성을 잃지 않고 Prune 될 수 있는지 여부를 판단합니다. 만약, 해당 State가 Prune 조건을 만족한다면 탐색 대상에서 제외됩니다.

#### 매개 변수

<table><thead><tr><th width="234">Type</th><th width="513">Description</th></tr></thead><tbody><tr><td>State</td><td>판단 대상 State 입니다.</td></tr><tr><td>ObjectiveFunctionType</td><td>문제의 목적함수 타입입니다.</td></tr><tr><td>Double</td><td>최적조건 판단 시 비교조건에 사용되는 Tolerance 입니다.</td></tr></tbody></table>

<table><thead><tr><th width="115">Type</th><th width="392">Description</th><th>Default</th></tr></thead><tbody><tr><td>Boolean</td><td>True: 해당 State를 Prune 합니다.<br>False: 해당 State Prune 하지 않습니다.</td><td><a href="#default-logic-1">Default Logic 참조</a></td></tr></tbody></table>

#### 예제 (Default Logic)

```csharp
public override bool CanPruneByOptimality(State state, ObjectiveFunctionType objFuncType, double pruneTolerance)
{
    BoundManager boundManager = BoundManager.Instance;

    double bestPrimalBound = boundManager.BestPrimalBound;
    double dualBound = state.DualBound;
    double bestValue = state.BestValue;

    double rootDualBound = boundManager.RootDualBound;

    if (objFuncType == ObjectiveFunctionType.Minimize)
    {
        if (dualBound < rootDualBound - bestValue)
            dualBound = rootDualBound - bestValue;

        if (bestPrimalBound + pruneTolerance <= bestValue + dualBound)
            return true;
        else
            return false;
    }
    else
    {
        if (dualBound > rootDualBound - bestValue)
            dualBound = rootDualBound - bestValue;

        if (bestPrimalBound >= bestValue + dualBound + pruneTolerance)
            return true;
        else
            return false;
    }
}
```
