0

動的計画法の再帰的関係を実装するJavaのコードは次のとおりです。

public double routeCost() throws Exception {
    double cost = Double.MAX_VALUE;
    for (int l=i; l<=j; l++) {
        if (! (customers.get(l) instanceof VehicleCustomer) )
            continue;
        double value = F(l,j) + (customers.get(l).distanceFrom(depot));
        if (value < cost)
            cost = value;
    }

    return cost;
}

private double F(int l, int m) {

    //=========================== FIRST CASE ===========================
    if (l==i && m==i) {
        //System.out.println(i+","+j+","+l+","+m);
        return firstCase();
    }

    //=========================== SECOND CASE ===========================
    if (l==i && (i<m && m<=j) ) {
        //System.out.println(i+","+j+","+l+","+m);
        //analyses the possibility of performing all the soubtours based at heicle customert_i
        return secondCase(i,m);

    }
    //=========================== GENERAL CASE ===========================
    else  {
        System.out.println(i+","+j+","+l+","+m);

        assert (customers.get(l) instanceof VehicleCustomer);

        assert ( (i<l && l<=j) && (l<=m && m<=j) );
        return Math.min(thirdCaseFirstTerm(l,m), thirdCaseSecondTerm(l,m));
    } 

}

private double firstCase() {
    mainRoute.add(depot);
    mainRoute.add(customers.get(i));
    return depot.distanceFrom(customers.get(i));
}

private double secondCase(int i,int m) {
    double caseValue = Double.MAX_VALUE;
    int k = i;
    while (k<m) {   
        double totalDemand=0;
        for (int u=k+1; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
            totalDemand += customers.get(u).getDemand();

        double cost = F(i,k) + thita(i,k+1,m);
        if (cost <= caseValue) 
            caseValue = cost;

        k++;
    }       
    return caseValue;
}

private double thirdCaseFirstTerm(int l, int m) {
    double caseValue = Double.MAX_VALUE;

    int k = i;
    while (k<m) {

        double totalDemand=0;
        for (int u=k+1; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
            totalDemand += customers.get(u).getDemand();

        double cost = F(l,k) + thita(l,k+1,m);
        if (cost <= caseValue) 
            caseValue = cost;
        k++;
    }

    return caseValue;
}

private double thirdCaseSecondTerm(int l,int m) {
    double caseValue = Double.MAX_VALUE;

    int k = i; 

    for (Customer cust : customers) {
        int h = customers.indexOf(cust);
        if ( (!(cust instanceof VehicleCustomer)) || (h >=l)) {
            continue;
        }

        double totalDemand=0;
        for (int u=k+2; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
            totalDemand += customers.get(u).getDemand();

        double cost = F(h,k) + customers.get(h).distanceFrom(customers.get(l)) + thita(l,k+2,m);
        if (cost < caseValue)
            caseValue = cost;
    }

    return caseValue;
}

メソッドF(int、int)は、メソッドrouteCost()のforループから呼び出されます。アサーションassert (customers.get(l) instanceof VehicleCustomer); `がtrueでない場合は常に、returnステートメントに移動するのではなく、routeCost()からforループに移動して、次の反復に進むように強制する方法を見つけたいと思います。しかし、F()は値を返さなければなりません!

私がやろうとしていることは、オブジェクト指向のほとんどすべてのルールに違反していることを私は知っていますが、私は本当にそれが必要です。

4

4 に答える 4

2

を投入ExceptionF()てキャッチすることができrouteCost()ます。

このアプローチは、アサーションを使用するよりもはるかに優れています。これらが実際に使用されることはめったになく、これには十分な理由があります。例外ははるかに柔軟で、エラーや無効な入力などの検出に適しています。

PS:「めったに使用されない」と言うとき、私は過去数年間に数十万行のJavaコードを見て、アサーションを使用するコードに出くわすことはめったにないという事実に基づいています。

于 2012-06-11T13:20:08.803 に答える
1

Double.NaNで確認できるような特別な値を返すことができますDouble.isNaN(d)

于 2012-06-11T13:33:58.787 に答える
0

F() が (double ではなく) Double を返すようにし、アサートが失敗した場合に null を返すようにすることができます。次に、戻り値を追加する前に、外側の for ループに null チェックを実行させます。

于 2012-06-11T13:23:11.830 に答える
0

アサートを if ステートメントに置き換えてみませんか? if ステートメントが true の場合は値を計算し、そうでない場合は double の MAX_VALUE を返します。F が MAX_VALUE を返すと、コストは更新されません。

if (customers.get(l) instanceof VehicleCustomer) {
  if ( (i<l && l<=j) && (l<=m && m<=j) ) {
    return Math.min(thirdCaseFirstTerm(l,m), thirdCaseSecondTerm(l,m));
  }
}
return Double.MAX_VALUE;

開発中に assert を使用して、private メソッドで発生してはならないことを取り除きます。(アサートは本番環境でオフにすることができます)

予期しないことが発生した場合に例外をスローします (たとえば、クラスのクライアントが無効なデータを渡します)。

ただし、あなたの質問からは、VehicleCustomer ではないインスタンスを取得することを期待しているように思われるため、アサートと例外はここでは適切なアプローチではありません。

Peter Lawrey と Jeff の回答も有効です。

于 2012-06-11T13:48:00.307 に答える