void InvMixColumns(void *pText) { byte_ard *pState = (byte_ard *)pText; byte_ard s0, s1, s2, s3; int c; for (c = 0; c < 4; c++) { s0 = state(pState,0,c); // S_0,0 s1 = state(pState,1,c); // S_1,0 s2 = state(pState,2,c); // S_2,0 s3 = state(pState,3,c); // S_3,0 // * is multiplication is GF(2^8) // s'_0,c = (0x0e * s0) xor (0x0b * s1) xor (0x0d * s2) xor (0x09 * s3) state(pState,0,c) = (eight(s0)^four(s0)^xtime(s0)) ^ (eight(s1)^xtime(s1)^s1) ^ (eight(s2)^four(s2)^s2) ^ (eight(s3) ^ s3); // s'_1,c = (0x09 * s0) xor (0x0e * s1) xor (0x0b * s2) xor (0x0d * s3) state(pState,1,c) = (eight(s0)^s0) ^ (eight(s1)^four(s1)^xtime(s1)) ^ (eight(s2)^xtime(s2)^s2) ^ (eight(s3)^four(s3)^s3); // s'_2,c = (0x0d * s0) xor (0x09 * s1) xor (0x0e * s2) xor (0x0b * s3) state(pState,2,c) = (eight(s0)^four(s0)^s0) ^ (eight(s1)^s1) ^ (eight(s2)^four(s2)^xtime(s2)) ^ (eight(s3)^xtime(s3)^s3); // s'_3,c = (0x0b * s0) xor (0x0d * s1) xor (0x09 * s2) xor (0x0e * s3) state(pState,3,c) = (eight(s0)^xtime(s0)^s0) ^ (eight(s1)^four(s1)^s1) ^ (eight(s2)^s2) ^ (eight(s3)^four(s3)^xtime(s3)); } // arduino specific debug #ifdef verbose_debig Serial.println("state after InvMixColumns(): "); printBytes((unsigned char*)pText, 16, 16); #endif } // InvMixColumns()
void MixColumns() { int i; unsigned char Tmp, Tm, t; for(i=0; i<4; i++) { t=state[0][i]; Tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i]; Tm = state[0][i] ^ state[1][i]; Tm = xtime(Tm); state[0][i] ^= Tm ^ Tmp; Tm = state[1][i] ^ state[2][i]; Tm = xtime(Tm); state[1][i] ^= Tm ^ Tmp; Tm = state[2][i] ^ state[3][i]; Tm = xtime(Tm); state[2][i] ^= Tm ^ Tmp; Tm = state[3][i] ^ t; Tm = xtime(Tm); state[3][i] ^= Tm ^ Tmp; } }
void AesGenTables(void) { unsigned i; for (i = 0; i < 256; i++) InvS[Sbox[i]] = (Byte)i; for (i = 0; i < 256; i++) { { UInt32 a1 = Sbox[i]; UInt32 a2 = xtime(a1); UInt32 a3 = xtime(a1) ^ a1; T[ i] = Ui32(a2, a1, a1, a3); T[0x100 + i] = Ui32(a3, a2, a1, a1); T[0x200 + i] = Ui32(a1, a3, a2, a1); T[0x300 + i] = Ui32(a1, a1, a3, a2); } { UInt32 a1 = InvS[i]; UInt32 a2 = xtime(a1); UInt32 a4 = xtime(a2); UInt32 a8 = xtime(a4); UInt32 a9 = a8 ^ a1; UInt32 aB = a8 ^ a2 ^ a1; UInt32 aD = a8 ^ a4 ^ a1; UInt32 aE = a8 ^ a4 ^ a2; D[ i] = Ui32(aE, a9, aD, aB); D[0x100 + i] = Ui32(aB, aE, a9, aD); D[0x200 + i] = Ui32(aD, aB, aE, a9); D[0x300 + i] = Ui32(a9, aD, aB, aE); } } }
/** * MixColumns * * The MixColumns function is the trickiest to implement efficiently since it * contains a lot of expensive operations if implemented literally as stated * in FIPS-197. * * Considerable experimentation, trial, error and literature search lead to * the present form. A fuller discussion and the sources used are cited in the * body of the function. * */ void MixColumns(void *pText) { // The sub bytes operation is as follows (see 5.1.3 in the FIPS-197 document): // // s'_0,c = ({02} * s_0,c ) XOR ({03} * s_1,c ) XOR s_2,c XOR s_3,c // s'_1,c = s_0,c XOR ({02} * s_1,c ) XOR ({03} * s_2,c ) XOR s_3,c // s'_2,c = s_0,c XOR s_1,c XOR ({02} * s_2,c ) XOR ({03} * s_3,c ) ′ // s'_3,c = ({03} * s_0,c ) XOR s_1,c XOR s_2,c XOR ({02} * s_3,c ) // // The * operation is here multiplication in the AES (Rijndael) finite field. See section // 4.2.1 in FIPS-197 on the multiplication and the xtime function. // A much clearer description can be found in // http://www.usenix.org/event/cardis02/full_papers/valverde/valverde_html/node12.html // // The xtime function is as follows: // xtime(a) = a<<1 if x7==0 (the eight bit is 0) // xtime(a) = a<<1 XOR Ox1 if x7==1 // see also: // * http://en.wikipedia.org/wiki/Rijndael_mix_columns // * http://en.wikipedia.org/wiki/Rijndael_Galois_field // * http://www.usenix.org/event/cardis02/full_papers/valverde/valverde_html/node12.html byte_ard *pState = (byte_ard *)pText; byte_ard a, s0; int c; for(c = 0; c < 4; c++) { // This algorithm is adapted from the paper // "Efficient AES Implementations for ARM Based Platforms" by Atasu, Breveglieri and Macchetti (2004) // Note: This is in essence identical to the code from Daemen and Rijmen (sec. 5.1). // // temp[0] = xtime(pState[0][c] ^ pState[1][c]) ^ pState[1][c] ^ pState[2][c] ^ pState[3][c]; // temp[1] = xtime(pState[1][c] ^ pState[2][c]) ^ pState[2][c] ^ pState[3][c] ^ pState[0][c]; // temp[2] = xtime(pState[2][c] ^ pState[3][c]) ^ pState[3][c] ^ pState[0][c] ^ pState[1][c]; // temp[3] = xtime(pstate[3][c] ^ pstate[0][c]) ^ pState[0][c] ^ pState[1][c] ^ pState[2][c]; // // The code below is a variation of the pseudocode in the document by Daemen and Rijmen (sec. 5.1) // and allows us to dispense with the temporary variable: a single initial XOR A of all four // states is computed. Then, temporary variables can be avoided by XORing A with the xtime calculation // and the target field itself. This self-XOR nullifies the corresponding term from A, avoiding // the temporary variable. The use of the a variable also saves quite a few XORs. // This is reimplemented as follows: a = state(pState,0,c) ^ state(pState,1,c) ^ state(pState,2,c) ^ state(pState,3,c); s0 = state(pState,0,c); // This is the only temporary variable needed state(pState,0,c) ^= xtime((state(pState,0,c) ^ state(pState,1,c))) ^ a; state(pState,1,c) ^= xtime((state(pState,1,c) ^ state(pState,2,c))) ^ a; state(pState,2,c) ^= xtime((state(pState,2,c) ^ state(pState,3,c))) ^ a; state(pState,3,c) ^= xtime((state(pState,3,c) ^ s0)) ^ a; // Here, we need to use a temp, since the contents of s0c have been modified } // FIXME -- Use non-arduino-specific debug #ifdef verbose_debug Serial.println("State after mixColumns:"); printBytes((unsigned char*)pText,16,16); #endif } // MixColumns()
static void gentables(void) { /* generate tables */ int i; u8 y,b[4]; /* use 3 as primitive root to generate power and log tables */ ltab[0]=0; ptab[0]=1; ltab[1]=0; ptab[1]=3; ltab[3]=1; for (i=2; i<256; i++) { ptab[i]=ptab[i-1]^xtime(ptab[i-1]); ltab[ptab[i]]=i; } /* affine transformation:- each bit is xored with itself shifted one bit */ fbsub[0]=0x63; rbsub[0x63]=0; for (i=1; i<256; i++) { y=ByteSub((u8)i); fbsub[i]=y; rbsub[y]=i; } for (i=0,y=1; i<30; i++) { rco[i]=y; y=xtime(y); } /* calculate forward and reverse tables */ for (i=0; i<256; i++) { y=fbsub[i]; b[3]=y^xtime(y); b[2]=y; b[1]=y; b[0]=xtime(y); ftable[i]=pack(b); y=rbsub[i]; b[3]=bmul(InCo[0],y); b[2]=bmul(InCo[1],y); b[1]=bmul(InCo[2],y); b[0]=bmul(InCo[3],y); rtable[i]=pack(b); } }
/* Mix Columns */ void AES128::mixColumns() { byte i, a, b, c, d, e; /* Process a column at a time */ for(i = 0; i < 16; i+=4) { a = state[i]; b = state[i+1]; c = state[i+2]; d = state[i+3]; e = a ^ b ^ c ^ d; state[i] ^= e ^ xtime(a^b); state[i+1] ^= e ^ xtime(b^c); state[i+2] ^= e ^ xtime(c^d); state[i+3] ^= e ^ xtime(d^a); } }
void theta(word16 *a) { int i, j; word16 b[16]; for(i = 0; i < 4; i++) { for(j = 0; j < 4; j++) { b[4*i+j] = xtime(a[4*i + j]); b[4*i+j] ^= a[4*i + ((j+1)%4)]; b[4*i+j] ^= xtime(a[4*i + ((j+1)%4)]); b[4*i+j] ^= a[4*i + ((j+2)%4)]; b[4*i+j] ^= a[4*i + ((j+3)%4)]; } } for(j = 0; j < 16; j++) a[j] = b[j] ; }
//============================================================================== void KeyExpansion(uint8_t *key , uint8_t direct) //Функция расширения ключа { uint32_t fkey[N]; //Вспомогательный массив uint32_t temp,rcon=1; //Промежуточные переменные uint8_t i,j; //Счетчики for(i=0;i<Nk;i++) fkey[i]=pack(&key[i*4]); //Заполнение первых четырех слов for(i=Nk;i<N;i++) //Заполнеие остальных элементов { temp = fkey[i-1]; if(i % Nk ==0) { temp = SubDWord(ROTL24(temp)) ^ rcon; rcon = (uint32_t)xtime((uint8_t )rcon , BPOLY); } fkey[i] = fkey[i-Nk] ^ temp; } for(i=0; i<N;i +=Nb) //Заполнение выходного массива { for(j=0; j<Nb; j++) { if(direct==ENCRYPT) rkey[i+j] = fkey[i+j] ; //Заполнение при шифровке else if(direct==DECRYPT) rkey[i+j] = fkey[N-Nb-i+j] ; //Заполнение при дешифровке } } }
void EncKeySchedule(unsigned char* key) { /* column 1 */ key[0]^=STable[key[13]]; key[1]^=STable[key[14]]; key[2]^=STable[key[15]]; key[3]^=STable[key[12]]; key[0]^=_rcon; _rcon = xtime(_rcon); /* column 2 */ key[4]^=key[0]; key[5]^=key[1]; key[6]^=key[2]; key[7]^=key[3]; /* column 3 */ key[8]^=key[4]; key[9]^=key[5]; key[10]^=key[6]; key[11]^=key[7]; /* column 4 */ key[12]^=key[8]; key[13]^=key[9]; key[14]^=key[10]; key[15]^=key[11]; }
unsigned char bigDot(unsigned char x, unsigned char y) { unsigned char v[8], answer = 0; //initialize 1st entry in v[] v[0] = x; int i=1; for(i=1; i<8; i++) //calculate all other entries in v[] { v[i] = xtime(v[i-1]); } //mask unsigned char mask = 1; //add all terms that are required based on bits in y. for(i=0; i<8; i++) { if((y & mask) == mask) //current bit is 1 in y { answer = answer ^ v[i]; } mask = mask << 1;//move mask to next bit } return answer; }
static void expand_key(const uint8_t* key, uint32_t* expanded_key) { int nrounds; union { uint8_t b[16]; uint32_t w[4]; } W; uint8_t xor_val = 1; memcpy( &W, key, 16 ); memcpy( expanded_key, &W, 16 ); for( nrounds = 0; nrounds < 10; ++nrounds ) { // update key schedule W.b[0] ^= sbox_e[W.b[12+1]] ^ xor_val; W.b[1] ^= sbox_e[W.b[12+2]]; W.b[2] ^= sbox_e[W.b[12+3]]; W.b[3] ^= sbox_e[W.b[12+0]]; W.w[1] ^= W.w[0]; W.w[2] ^= W.w[1]; W.w[3] ^= W.w[2]; xor_val = xtime( xor_val ); expanded_key += 4; memcpy( expanded_key, &W, 16 ); } }
Fruit::Fruit(Map const & map) { srand(xtime(NULL)); this->_size_x = map.getXSize(); this->_size_y = map.getYSize(); this->_max_iter = (this->_size_x * this->_size_y); this->new_fruit(map); }
void AesGenTables(void) { unsigned i; for (i = 0; i < 256; i++) InvS[Sbox[i]] = (Byte)i; for (i = 0; i < 256; i++) { { UInt32 a1 = Sbox[i]; UInt32 a2 = xtime(a1); UInt32 a3 = a2 ^ a1; T[ i] = Ui32(a2, a1, a1, a3); T[0x100 + i] = Ui32(a3, a2, a1, a1); T[0x200 + i] = Ui32(a1, a3, a2, a1); T[0x300 + i] = Ui32(a1, a1, a3, a2); } { UInt32 a1 = InvS[i]; UInt32 a2 = xtime(a1); UInt32 a4 = xtime(a2); UInt32 a8 = xtime(a4); UInt32 a9 = a8 ^ a1; UInt32 aB = a8 ^ a2 ^ a1; UInt32 aD = a8 ^ a4 ^ a1; UInt32 aE = a8 ^ a4 ^ a2; D[ i] = Ui32(aE, a9, aD, aB); D[0x100 + i] = Ui32(aB, aE, a9, aD); D[0x200 + i] = Ui32(aD, aB, aE, a9); D[0x300 + i] = Ui32(a9, aD, aB, aE); } } g_AesCbc_Encode = AesCbc_Encode; g_AesCbc_Decode = AesCbc_Decode; g_AesCtr_Code = AesCtr_Code; #ifdef MY_CPU_X86_OR_AMD64 #ifdef P7ZIP_USE_ASM if (CPU_Is_Aes_Supported()) { g_AesCbc_Encode = AesCbc_Encode_Intel; g_AesCbc_Decode = AesCbc_Decode_Intel; g_AesCtr_Code = AesCtr_Code_Intel; } #endif #endif }
void put_time() { time_t ltime; char *date; if (xtime(<ime) != (time_t) 0) if ((date = ctime(<ime)) != (char *) NULL && date != (char *) -1) my_putstr(date); }
/*初始化*/ void gentables(void) { //初始化矩阵 int i; BYTE y,b[4]; ltab[0]=0; ptab[0]=1; ptab[1]=3; ltab[1]=0; ltab[3]=1; for (i=2;i<256;i++) { ptab[i]=ptab[i-1]^xtime(ptab[i-1]); ltab[ptab[i]]=i; } // 进行移位操作 fbsub[0]=0x63; rbsub[0x63]=0; for (i=1;i<256;i++) { y=ByteSub((BYTE)i); fbsub[i]=y; rbsub[y]=i; } for (i=0,y=1;i<30;i++) { rco[i]=y; y=xtime(y); } for (i=0;i<256;i++) { y=fbsub[i]; b[3]=y^xtime(y); b[2]=y; b[1]=y; ftable[i]=pack(b); b[0]=xtime(y); y=rbsub[i]; b[3]=bmul(InCo[0],y); b[2]=bmul(InCo[1],y); b[1]=bmul(InCo[2],y); b[0]=bmul(InCo[3],y); rtable[i]=pack(b); } }
void keysched(word16 *rk, word16 *prcon) { word16 tmp; tmp = rk[0xC]; rk[0] ^= *prcon; rk[0] ^= rk[0xD]; rk[4] ^= rk[0]; rk[8] ^= rk[4]; rk[0xC] ^= rk[8]; rk[1] ^= rk[0xE]; rk[5] ^= rk[1]; rk[9] ^= rk[5]; rk[0xD] ^= rk[9]; rk[2] ^= rk[0xF]; rk[6] ^= rk[2]; rk[0xA] ^= rk[6]; rk[0xE] ^= rk[0xA]; rk[3] ^= tmp ; rk[7] ^= rk[3]; rk[0xB] ^= rk[7]; rk[0xF] ^= rk[0xB]; *prcon = xtime(*prcon); }
// MixColumns function mixes the columns of the state matrix void mix_columns() { int i; unsigned char tmp, tm, t; for (i = 0; i < 4; i++) { t = state[0][i]; tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i]; tm = state[0][i] ^ state[1][i]; tm = xtime(tm); state[0][i] ^= tm ^ tmp; tm = state[1][i] ^ state[2][i]; tm = xtime(tm); state[1][i] ^= tm ^ tmp; tm = state[2][i] ^ state[3][i]; tm = xtime(tm); state[2][i] ^= tm ^ tmp; tm = state[3][i] ^ t; tm = xtime(tm); state[3][i] ^= tm ^ tmp; } }
/* Inverse Mix Column */ void AES128::inv_mixColumns() { byte i, a, b, c, d, e, x, y, z; /* Process a column at a time */ for(i = 0; i < 16; i+=4) { a = state[i]; b = state[i+1]; c = state[i+2]; d = state[i+3]; e = a ^ b ^ c ^ d; //Inverses z = xtime(e); x = e ^ xtime(xtime(z^a^c) ); y = e ^ xtime(xtime(z^b^d) ); state[i] ^= x ^ xtime(a^b); state[i+1] ^= y ^ xtime(b^c); state[i+2] ^= x ^ xtime(c^d); state[i+3] ^= y ^ xtime(d^a); } }
void GenPowerTab() { LogTab[0] = 0; PowTab[0] = 1; // 1 PowTab[1] = 3; // LogTab[1] = 0; // LogTab[3] = 1; for (int i = 2; i < 256; i++) { PowTab[i] = PowTab[i-1]^xtime(PowTab[i-1]); LogTab[PowTab[i]] = i; } }
// La fonction MixColumns melange les colonnes du bloc de message void MixColumns(unsigned char *out, unsigned char *in) { int i,j; unsigned char Tmp,Tm,t; for(j=0;j<4;j++) { Tmp = in[0+j*4] ^ in[1+j*4] ^ in[2+j*4] ^ in[3+j*4] ; Tm = in[0+j*4] ^ in[1+j*4] ; Tm = xtime(Tm); out[0+j*4] = Tm ^ Tmp ^ in[0+j*4]; Tm = in[1+j*4] ^ in[2+j*4] ; Tm = xtime(Tm); out[1+j*4] = Tm ^ Tmp ^ in[1+j*4]; Tm = in[2+j*4] ^ in[3+j*4] ; Tm = xtime(Tm); out[2+j*4] = Tm ^ Tmp ^ in[2+j*4]; Tm = in[3+j*4] ^ in[0+j*4]; Tm = xtime(Tm); out[3+j*4] = Tm ^ Tmp ^ in[3+j*4]; } }
//============================================================================== uint8_t bmul(uint8_t a, uint8_t b, uint8_t mod) //Умножение элементов в поле GF(2^m) { uint8_t t, s, u; u=b; t=a; s=0; while(u) { if(u & 1) s^=t; u>>=1; t = xtime(t, mod); } return (s); }
bool xtime_test() { std::cout << "\nxtime_test:\n"; BYTE bResult = 0x57; for(int i=0; i<3; ++i) { std::cout << "\txtime(" << std::hex << static_cast<DWORD>(bResult) << ") = "; bResult = xtime(bResult); std::cout << std::hex << static_cast<DWORD>(bResult) << '\n'; } return true; }
static void show_progress(glp_tree *T, int bingo) { int p; double temp; char best_mip[50], best_bound[50], *rho, rel_gap[50]; /* format the best known integer feasible solution */ if (T->mip->mip_stat == GLP_FEAS) sprintf(best_mip, "%17.9e", T->mip->mip_obj); else sprintf(best_mip, "%17s", "not found yet"); /* determine reference number of an active subproblem whose local bound is best */ p = ios_best_node(T); /* format the best bound */ if (p == 0) sprintf(best_bound, "%17s", "tree is empty"); else { temp = T->slot[p].node->bound; if (temp == -DBL_MAX) sprintf(best_bound, "%17s", "-inf"); else if (temp == +DBL_MAX) sprintf(best_bound, "%17s", "+inf"); else sprintf(best_bound, "%17.9e", temp); } /* choose the relation sign between global bounds */ if (T->mip->dir == GLP_MIN) rho = ">="; else if (T->mip->dir == GLP_MAX) rho = "<="; else xassert(T != T); /* format the relative mip gap */ temp = ios_relative_gap(T); if (temp == 0.0) sprintf(rel_gap, " 0.0%%"); else if (temp < 0.001) sprintf(rel_gap, "< 0.1%%"); else if (temp <= 9.999) sprintf(rel_gap, "%5.1f%%", 100.0 * temp); else sprintf(rel_gap, "%6s", ""); /* display progress of the search */ xprintf("+%6d: %s %s %s %s %s (%d; %d)\n", T->mip->it_cnt, bingo ? ">>>>>" : "mip =", best_mip, rho, best_bound, rel_gap, T->a_cnt, T->t_cnt - T->n_cnt); T->tm_lag = xtime(); return; }
static char bigDotProduct(unsigned char a, unsigned char b) { int i; unsigned char v[8]; v[0] = b; for (i = 1; i < 8; i++) { v[i] = xtime(v[i - 1]); } unsigned char mask = 0x01; unsigned char result = 0x00; for (i = 0; i < 8; i++) { if ((mask & a) == mask) { result ^= v[i]; } mask <<= 1; } return result; }
static void show_progress(SSX *ssx, int phase) { /* this auxiliary routine displays information about progress of the search */ int i, def = 0; for (i = 1; i <= ssx->m; i++) if (ssx->type[ssx->Q_col[i]] == SSX_FX) def++; /* xprintf("%s%6d: %s = %22.15g (%d)\n", phase == 1 ? " " : "*", ssx->it_cnt, phase == 1 ? "infsum" : "objval", mpq_get_d(ssx->bbar[0]), def); */ #if 0 ssx->tm_lag = utime(); #else ssx->tm_lag = xtime(); #endif return; }
static void MixColumns(void) { uint32x4_t a = vreinterpretq_u32_u8(*state); uint32x4_t b = vreinterpretq_u32_u8(xtime(*state)); uint32x4_t a3 = veorq_u32(a,b); uint32x4_t a3r = vshlq_n_u32(a3,8); a3r = vsraq_n_u32(a3r,a3,24); uint32x4_t a2 = vshlq_n_u32(a,16); a2 = vsraq_n_u32(a2,a,16); uint32x4_t a1 = vshlq_n_u32(a,24); a1 = vsraq_n_u32(a1,a,8); uint32x4_t out = veorq_u32(b,a1); out = veorq_u32(out,a2); out = veorq_u32(out,a3r); *state = vreinterpretq_u8_u32(out); }
//用于生成 mult[256][256] 或计算 field28 multi2(field28 a, field28 b){ static field28 mul[256][256]; //用于保存已经计算过的结果 field28 bit=0x01; field28 result=0x00; field28 tmp = a; if((a==0x00) || (b==0x00)) return 0x00; else if(mul[a][b] != 0x00) return mul[a][b]; else{ while(bit){ if(b&bit) result ^= tmp; // result = add(result, tmp) bit = bit << 1; tmp = xtime(tmp); } mul[b][a] = mul[a][b] = result; return result; } }
void KeyExpansion(WORD key[Nk], WORD ExKey[Nb*(Nr+1)]) { for(int i=0; i<Nk; i++) ExKey[i] = key[i]; BYTE xi = 0x01; WORD temp; for(int i=Nk; i<Nb*(Nr+1); i++) { temp = ExKey[i-1]; if (i % Nk == 0) { WORD w = xi; w = ROTL24(xi); temp = SubWord(ROTL8(temp)) ^ w; xi = xtime(xi); } //else // temp = SubWord(temp); ExKey[i] = ExKey[i-Nk] ^ temp; } }
static int custom_prompt(char *str, char c, int i, t_env *env) { char *custom; if (c == 't') custom = xtime(); else if (c == 'm') custom = my_strdup(find_in_env(HOSTNAME_STRING, env)); else if (c == 'u') custom = my_strdup(find_in_env(USERNAME_STRING, env)); else if (c == '~') custom = my_strdup(find_in_env(PWD_STRING, env)); else { str[i] = c; return (++i); } str = my_strcat(str, custom); i += my_strlen(custom); if (custom) free(custom); return (i); }
void ios_feas_pump(glp_tree *T) { glp_prob *P = T->mip; int n = P->n; glp_prob *lp = NULL; struct VAR *var = NULL; RNG *rand = NULL; GLPCOL *col; glp_smcp parm; int j, k, new_x, nfail, npass, nv, ret, stalling; double dist, tol; xassert(glp_get_status(P) == GLP_OPT); /* this heuristic is applied only once on the root level */ if (!(T->curr->level == 0 && T->curr->solved == 1)) goto done; /* determine number of binary variables */ nv = 0; for (j = 1; j <= n; j++) { col = P->col[j]; /* if x[j] is continuous, skip it */ if (col->kind == GLP_CV) continue; /* if x[j] is fixed, skip it */ if (col->type == GLP_FX) continue; /* x[j] is non-fixed integer */ xassert(col->kind == GLP_IV); if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) { /* x[j] is binary */ nv++; } else { /* x[j] is general integer */ if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("FPUMP heuristic cannot be applied due to genera" "l integer variables\n"); goto done; } } /* there must be at least one binary variable */ if (nv == 0) goto done; if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Applying FPUMP heuristic...\n"); /* build the list of binary variables */ var = xcalloc(1+nv, sizeof(struct VAR)); k = 0; for (j = 1; j <= n; j++) { col = P->col[j]; if (col->kind == GLP_IV && col->type == GLP_DB) var[++k].j = j; } xassert(k == nv); /* create working problem object */ lp = glp_create_prob(); more: /* copy the original problem object to keep it intact */ glp_copy_prob(lp, P, GLP_OFF); /* we are interested to find an integer feasible solution, which is better than the best known one */ if (P->mip_stat == GLP_FEAS) { int *ind; double *val, bnd; /* add a row and make it identical to the objective row */ glp_add_rows(lp, 1); ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) { ind[j] = j; val[j] = P->col[j]->coef; } glp_set_mat_row(lp, lp->m, n, ind, val); xfree(ind); xfree(val); /* introduce upper (minimization) or lower (maximization) bound to the original objective function; note that this additional constraint is not violated at the optimal point to LP relaxation */ #if 0 /* modified by xypron <*****@*****.**> */ if (P->dir == GLP_MIN) { bnd = P->mip_obj - 0.10 * (1.0 + fabs(P->mip_obj)); if (bnd < P->obj_val) bnd = P->obj_val; glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); } else if (P->dir == GLP_MAX) { bnd = P->mip_obj + 0.10 * (1.0 + fabs(P->mip_obj)); if (bnd > P->obj_val) bnd = P->obj_val; glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); } else xassert(P != P); #else bnd = 0.1 * P->obj_val + 0.9 * P->mip_obj; /* xprintf("bnd = %f\n", bnd); */ if (P->dir == GLP_MIN) glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); else if (P->dir == GLP_MAX) glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); else xassert(P != P); #endif } /* reset pass count */ npass = 0; /* invalidate the rounded point */ for (k = 1; k <= nv; k++) var[k].x = -1; pass: /* next pass starts here */ npass++; if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Pass %d\n", npass); /* initialize minimal distance between the basic point and the rounded one obtained during this pass */ dist = DBL_MAX; /* reset failure count (the number of succeeded iterations failed to improve the distance) */ nfail = 0; /* if it is not the first pass, perturb the last rounded point rather than construct it from the basic solution */ if (npass > 1) { double rho, temp; if (rand == NULL) rand = rng_create_rand(); for (k = 1; k <= nv; k++) { j = var[k].j; col = lp->col[j]; rho = rng_uniform(rand, -0.3, 0.7); if (rho < 0.0) rho = 0.0; temp = fabs((double)var[k].x - col->prim); if (temp + rho > 0.5) var[k].x = 1 - var[k].x; } goto skip; } loop: /* innermost loop begins here */ /* round basic solution (which is assumed primal feasible) */ stalling = 1; for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; if (col->prim < 0.5) { /* rounded value is 0 */ new_x = 0; } else { /* rounded value is 1 */ new_x = 1; } if (var[k].x != new_x) { stalling = 0; var[k].x = new_x; } } /* if the rounded point has not changed (stalling), choose and flip some its entries heuristically */ if (stalling) { /* compute d[j] = |x[j] - round(x[j])| */ for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; var[k].d = fabs(col->prim - (double)var[k].x); } /* sort the list of binary variables by descending d[j] */ qsort(&var[1], nv, sizeof(struct VAR), fcmp); /* choose and flip some rounded components */ for (k = 1; k <= nv; k++) { if (k >= 5 && var[k].d < 0.35 || k >= 10) break; var[k].x = 1 - var[k].x; } } skip: /* check if the time limit has been exhausted */ if (T->parm->tm_lim < INT_MAX && (double)(T->parm->tm_lim - 1) <= 1000.0 * xdifftime(xtime(), T->tm_beg)) goto done; /* build the objective, which is the distance between the current (basic) point and the rounded one */ lp->dir = GLP_MIN; lp->c0 = 0.0; for (j = 1; j <= n; j++) lp->col[j]->coef = 0.0; for (k = 1; k <= nv; k++) { j = var[k].j; if (var[k].x == 0) lp->col[j]->coef = +1.0; else { lp->col[j]->coef = -1.0; lp->c0 += 1.0; } } /* minimize the distance with the simplex method */ glp_init_smcp(&parm); if (T->parm->msg_lev <= GLP_MSG_ERR) parm.msg_lev = T->parm->msg_lev; else if (T->parm->msg_lev <= GLP_MSG_ALL) { parm.msg_lev = GLP_MSG_ON; parm.out_dly = 10000; } ret = glp_simplex(lp, &parm); if (ret != 0) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_simplex returned %d\n", ret); goto done; } ret = glp_get_status(lp); if (ret != GLP_OPT) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_get_status returned %d\n", ret); goto done; } if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("delta = %g\n", lp->obj_val); /* check if the basic solution is integer feasible; note that it may be so even if the minimial distance is positive */ tol = 0.3 * T->parm->tol_int; for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; if (tol < col->prim && col->prim < 1.0 - tol) break; } if (k > nv) { /* okay; the basic solution seems to be integer feasible */ double *x = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) { x[j] = lp->col[j]->prim; if (P->col[j]->kind == GLP_IV) x[j] = floor(x[j] + 0.5); } #if 1 /* modified by xypron <*****@*****.**> */ /* reset direction and right-hand side of objective */ lp->c0 = P->c0; lp->dir = P->dir; /* fix integer variables */ for (k = 1; k <= nv; k++) #if 0 /* 18/VI-2013; fixed by mao * this bug causes numerical instability, because column statuses * are not changed appropriately */ { lp->col[var[k].j]->lb = x[var[k].j]; lp->col[var[k].j]->ub = x[var[k].j]; lp->col[var[k].j]->type = GLP_FX; } #else glp_set_col_bnds(lp, var[k].j, GLP_FX, x[var[k].j], 0.); #endif /* copy original objective function */ for (j = 1; j <= n; j++) lp->col[j]->coef = P->col[j]->coef; /* solve original LP and copy result */ ret = glp_simplex(lp, &parm); if (ret != 0) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_simplex returned %d\n", ret); goto done; } ret = glp_get_status(lp); if (ret != GLP_OPT) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_get_status returned %d\n", ret); goto done; } for (j = 1; j <= n; j++) if (P->col[j]->kind != GLP_IV) x[j] = lp->col[j]->prim; #endif ret = glp_ios_heur_sol(T, x); xfree(x); if (ret == 0) { /* the integer solution is accepted */ if (ios_is_hopeful(T, T->curr->bound)) { /* it is reasonable to apply the heuristic once again */ goto more; } else { /* the best known integer feasible solution just found is close to optimal solution to LP relaxation */ goto done; } } }