주메뉴 바로가기 본문 바로가기 하단 바로가기

고객지원

기술문의

제약조건의 크기와 관련된 질문입니다.

  • 성영태
  • 2003.09.30
  • 조회수 1,554
안녕하십니까. 다름이 아니라 솔라리스 환경에서 callable library를 사용해서 작업중인데요 입력에 따라 최대 60000개 정도의 제약조건이 생성됩니다. 그리고 찾고자 하는 변수 또한 최대 20000개 정도가 되는데요 이러한 변수와 제약조건을 하나의 자료구조로 생성하는것이 무리라 이렇게 질문을 드립니다. 제약조건이 상당히 많을 경우 모델을 구성하는 방법에 대해서 힌트를 주셨으면 감사하겠습니다. 그럼 수고하십시오.

댓글 3

  • 장용성2003-09-30
    우선 callable library를 사용하기가 불편하기 때문에 가장 좋은 방법은 concert를 사용해서 문제를 표현하는 게 상당히 쉬울 거라고 생각하구요, 그럴 사정이 안 되시면 concert처럼 데이터를 처리할 수 있게 lp를 표현하기 위한 클래스가 필요합니다. 예를들어 MyCplex라는 클래스를 만들어서 그 안에서 addRow(), startColumn(), addNzToCurrentColumn(), endColumn()등의 멤버를 통해서 접근하시면 쉬울 수 있을 거 같구요.

    각 변수를 만들때는 필요없는 변수를 제거하기 위해서 컴파일러가 지원을 해줄 수 있다면 map을 통해서 인덱스로 관리를 해주시는 게 좋을 것 같구요. 변수나 제약식은 종류별로 배열을 만드시는 게 좋을 것 같습니다.. 종류별로 클래스를 만드시는 것도 유용할 겁니다.
    예를 들어 제약식의 종류별로 MySetRows클래스를 만들거나, 변수의 종류별로 MySetColumns클래스를 만들어서 그 안에 변수나 제약식에 해당되는 자료를 집어넣는 겁니다.

    아마 제가 위에서 언급했던 MyCplex 클래스 정의만 해도 많이 수월해 질 거라고 봅니다. 수고하세요..

    보안상 모든 부분은 불가능하구요, 일부 함수를 보여드리겠습니다..
    IlCgCplex::IlCgCplex(int c,int r,int z)
    :numRows_(0), numCols_(0),
    numNz_(0), numColNz_(0), clp_(0), maxMipMins_(-1)
    {

    obj_.reserve(c);
    rhs_.reserve(r);
    sense_.reserve(r);
    matbeg_.reserve(c);
    matcnt_.reserve(r);
    matind_.reserve(z);
    matval_.reserve(z);
    lb_.reserve(c);
    ub_.reserve(c);
    rngval_.reserve(c);


    env_ = CPXopenCPLEX(&status_);

    if (env_ == 0)
    {
    char errorMsg[1024];
    CPXgeterrorstring(env_, status_, errorMsg);
    cout << "Could not open CPLEX environment" << endl;
    cout << errorMsg << endl;
    exit(1);
    }

    objSense_ = MIN;
    }


    void
    IlCgCplex::addRow(double rhs, double rngval, char sense)
    {
    rhs_.push_back(rhs);
    rngval_.push_back(rngval);
    sense_.push_back(sense);
    if (sense != 'L' && sense != 'G' && sense != 'E')
    terminate("Sense of Row wrong");
    numRows_++;

    }

    void
    IlCgCplex::startColumn(double obj, double lb, double ub)
    {
    assert(numColNz_ == 0);
    matbeg_.push_back(numNz_);
    obj_.push_back(obj);
    lb_.push_back(lb);
    ub_.push_back(ub);
    }
    void
    IlCgCplex::endColumn()
    {
    matcnt_.push_back(numColNz_);
    numColNz_ = 0;

    numCols_++;
    }

    void
    IlCgCplex::addNzToCurrentColumn(int row, double val)
    {

    if (clp_ != 0)
    assert(row < getNumRows() + numRows_);
    else
    assert(row < numRows_);

    matind_.push_back(row);
    matval_.push_back(val);
    numNz_++;
    numColNz_++;
    }

    void
    IlCgCplex::registerLp()
    {

    clp_ = CPXcreateprob(env_, &status_, "DynColGen");
    if(clp_ == 0)
    {
    terminate("Failed to Create LP ");
    }
    status_ = CPXcopylp(env_, clp_, numCols_, numRows_,objSense_,
    &obj_[0], &rhs_[0], &sense_[0], &matbeg_[0],&matcnt_[0],&matind_[0],&matval_[0],
    &lb_[0], &ub_[0],&rngval_[0]);

    if(status_)
    {
    terminate("Failed to Copy LP");
    }
    resetColumns();
    resetRows();
    #if 0
    CPXcheckcopylp(env_, clp_, numCols_, numRows_, objSense_,
    obj_.getElements(), rhs_.getElements(),
    sense_.getElements(), matbeg_.getElements(),
    matcnt_.getElements(), matind_.getElements(),
    matval_.getElements(), lb_.getElements(), ub_.getElements(),
    rngval_.getElements());
    #endif
    }
    아이콘삭제
  • 성영태2003-09-30
    친절한 답변 정말 감사드립니다. 제가 제대로 이해했다면 님의 말씀이 각 제약식 혹은 변수의 종류별로 모델을 분리하라는 얘긴것 같은데 맞는지 모르겠습니다. 우선 님의 조언데로 노력해 보도록 하겠습니다.
    아이콘삭제
  • 장용성2003-09-30
    예 맞습니다. 우선 모델을 종류별로 분리하구요, MyCplex같은 클래스로 반복적인 코딩 부분을 처리할 수 있을 겁니다. 수고하세요..
    아이콘삭제

댓글 입력