/* ** ** int scatter_xover(EVOLDATA ev, ** int iNumParents, VECTOR fProbDist, VECTOR fResult, ** MATRIX fPop, int iPopSize) ** ** This operator : ** ** 1. Picks a set of parents. ** 2. Finds the 'central' vector by averaging the parent vectors. ** 3. Finds the worst vector among the parents. ** 4. Does a (heuristic) crossover between the worst and the central = vector. ** ** */ int scatter_xover(EVOLDATA ev, int iNumParents, VECTOR fProbDist, VECTOR fResult, MATRIX fPop, int iPopSize) { int i, j; float fRandVal; VECTOR fParIndexVector; /* Indices of Parents selected */ VECTOR fCentralVector; /* Central vector */ float fWorstVal; int iWorstParIndex; fParIndexVector = init_vector(iNumParents + 1); fCentralVector = init_vector(ev.iNumVars + 1); /* pick the req. no. of parents, and note the worst */ iWorstParIndex = 1; for (i = 1; i <= iNumParents; i++) { fRandVal = randgen(0.0, 1.0); j = 1; while ((fRandVal > fProbDist[i]) && (j < iPopSize)) j++; fParIndexVector[i] = (float) j; if (iWorstParIndex <= j) iWorstParIndex = j; } /* now, find 'central' vector by averaging all parents */ for (i = 1; i <= ev.iNumVars; i++) { for (j = 1; j <= iNumParents; j++) fCentralVector[i] = fCentralVector[i] + fPop[(int) fParIndexVector[j]][i]; fCentralVector[i] = fCentralVector[i] / iNumParents; } /* now, move from worst vector to central vector */ /* similar to heuristic crossover */ fRandVal = randgen(0.0, 1.0); for (i = 1; i <= ev.iNumVars + 1; i++) fResult[i] = fRandVal*(fCentralVector[i] - fPop[iWorstParIndex][i]) + fCentralVector[i]; free_vector(fParIndexVector); free_vector(fCentralVector); return(iWorstParIndex); }
DWORD WINAPI fnCoches(LPVOID parametro) { int posicion, carril, color, sum; int velocidad, tcarril; srand((unsigned int)time(NULL)); do { carril = randgen(0, 1); sum = carril * 137; posicion = randgen(0, 136); } while (cruce(posicion, carril) || WaitForSingleObject(IPC.posiciones[posicion + sum], 0) != WAIT_OBJECT_0); velocidad = randgen(1, 99); color = randgen(0, 7); /*Situamos el coche en la posicion y carril calculadas arriba*/ DLL.inicio_coche(&carril, &posicion, color); /*Avisamos que nos hemos creado*/ SetEvent(IPC.evento_creacion); WaitForSingleObject(IPC.semaforo_pistoletazo, INFINITE); //Esperamos por el pistoletazo while (1) { /*Garantizamos que estando en estas posiciones avanzo o espero que el semaforo cambie*/ if ((posicion == 20 && carril == 0) || (posicion == 22 && carril == 1)) WaitForSingleObject(IPC.posiciones[274], INFINITE); if ((posicion == 105 && carril == 0) || (posicion == 98 && carril == 1)) WaitForSingleObject(IPC.posiciones[275], INFINITE); tcarril = carril; avanzar(&posicion, &carril, color); /*Incremento el contador de vueltas si estoy en estas posiciones y no cambio de carril*/ if (((posicion == 133 && carril == 0) || (posicion == 131 && carril == 1)) && tcarril == carril) InterlockedIncrement((long*)(parametro)); /*Si he cogio los mutex de arriba los libero para que el semaforo pueda cambiar de color*/ ReleaseMutex(IPC.posiciones[274]); ReleaseMutex(IPC.posiciones[275]); DLL.velocidad(velocidad, carril, posicion); } return 1; }
/* ** ** void gauss_mutate(EVOLDATA ev, VECTOR fV, long lNumEvals) ** ** Gaussian mutation operator - single parent, single offspring ** ** */ void gauss_mutate(EVOLDATA ev, VECTOR fV, long lNumEvals) { float fSigma, fDelta; float fRandVal[GENOCOP_MAXVECTOR]; int i, j; fSigma = (float) ((ev.lTotEvals - lNumEvals) / ev.lTotEvals); for (j = 1; j <= ev.iNumVars; j++) { /* create 12 random floating point numbers between 0 and 1 */ for (i = 1; i <= 12; ++i) fRandVal[i] = randgen(0.0, 1.0); /* delta is the total of these 12 random numbers minus 6 */ /* note that delta might be positive or negative */ fDelta = fRandVal[1] + fRandVal[2] + fRandVal[3] + fRandVal[4] + fRandVal[5] + fRandVal[6] + fRandVal[7] + fRandVal[8] + fRandVal[9] + fRandVal[10] + fRandVal[11] + fRandVal[12] - 6.0F; /* mutate the j-th component of the vector X */ fV[j] = fV[j] + fSigma*fDelta; } }
/* ** ** int pool_xover(EVOLDATA ev, ** int iNumParents, VECTOR fProbDist, VECTOR fResult, ** MATRIX fPop, int iPopSize) ** ** ** Picks bits from a random parent selected from a set ** and fills up the offspring vector. Returns index of the ** worst parent in the set. ** */ int pool_xover(EVOLDATA ev, int iNumParents, VECTOR fProbDist, VECTOR fResult, MATRIX fPop, int iPopSize) { int i, j, iWorstParIndex, iRandVal; float fRandVal; VECTOR fParIndexVector; fParIndexVector = init_vector(iNumParents + 1); /* pick the req. no. of parents and note index of worst */ iWorstParIndex = 1; for (i = 1; i <= iNumParents; i++) { fRandVal = randgen(0.0, 1.0); j = 1; while ((fRandVal > fProbDist[i]) && (j < iPopSize)) j++; fParIndexVector[i] = (float) j; if (iWorstParIndex <= j) iWorstParIndex = j; } /* now, pick cells from each selected parent, filling up the */ /* offspring vector till there are no bits left */ for (i = 1; i <= ev.iNumVars; i++) { iRandVal = (int) randgen(1.0, (float) iNumParents + 1.0); fResult[i] = fPop[(int) fParIndexVector[iRandVal]][i]; } free_vector(fParIndexVector); return(iWorstParIndex); }
/////////////////// // MUD FUNCTIONS // /////////////////// long randnum(long start, long end) { static long num; if(start<0 || end<0) return randneg(start,end); do { num = randgen() % (end+1); } while( num < start || num > end ); return num; }
/* ** ** void hr_xover(EVOLDATA ev, VECTOR fV1, VECTOR fV2, VECTOR = fOffspring) ** ** Heuristic crossover operator - double parent, single offspring ** ** */ void hr_xover(EVOLDATA ev, VECTOR fV1, VECTOR fV2, VECTOR fOffspring) { float fRandVal; int i; fRandVal = randgen(0.0, 1.0); /* assume, as passed, BETTER PARENT IS fV1 - see top-level code */ for (i = 1; i <= ev.iNumVars; i++) fOffspring[i] = fRandVal*(fV1[i] - fV2[i]) + fV1[i]; /* check for constraints is done at top level anyway */ }
void rand_seed (unsigned long a, unsigned long b, unsigned long c) { static unsigned long x = 4294967295U; shft1=k1-p1; shft2=k2-p2; shft3=k3-p3; mask1 = x << (32-k1); mask2 = x << (32-k2); mask3 = x << (32-k3); if (a > (unsigned int)(1<<shft1)) s1 = a; if (b > (unsigned int)(1<<shft2)) s2 = b; if (c > (unsigned int)(1<<shft3)) s3 = c; randgen(); }
task_t planes_task_with_bounds(const size_t num_planes, const moment_t timespan, const moment_t bound_timespan) { mt19937 randgen(static_cast<unsigned int>(std::time(0))); uniform_real_distribution<float> classes_distr(0, 1); uniform_real_distribution<float> priorities_distr(0, 1); uniform_real_distribution<moment_t> bounds_distr(bound_timespan * moment_t(0.7), bound_timespan); uniform_real_distribution<moment_t> dates_distr(bound_timespan, timespan); uniform_int_distribution<size_t> names_distr(0, sizeof(names) / sizeof(string)); task_t task(num_planes); for (size_t i = 0; i < num_planes; ++i) { float p = classes_distr(randgen); if (p < 0.2) task[i].class_ = aircraft_t::LIGHT; else if (p > 0.8) task[i].class_ = aircraft_t::HEAVY; else task[i].class_ = aircraft_t::MEDIUM; } for (size_t i = 0; i < num_planes; ++i) { float p = priorities_distr(randgen); if (p < 0.2) task[i].priority_ = aircraft_t::RED; else if (p > 0.8) task[i].priority_ = aircraft_t::GREEN; else task[i].priority_ = aircraft_t::YELLOW; } for (size_t i = 0; i < num_planes; ++i) { task[i].name = ::names[i]; task[i].due = dates_distr(randgen); task[i].min_bound = std::max(task[i].due - bounds_distr(randgen), moment_t(0)); //task[i].min_bound = task[i].due; task[i].max_bound = task[i].due + bounds_distr(randgen); } perm_t due_perm = due_dates_perm(task); task = apply_permutation(task, due_perm); return task; }
void simpleFluidEmitter::surfaceFluidEmitter( MFnFluid& fluid, const MMatrix& fluidWorldMatrix, int plugIndex, MDataBlock& block, double dt, double conversion, double dropoff ) //============================================================================== // // Method: // // simpleFluidEmitter::surfaceFluidEmitter // // Description: // // Emits fluid from one of a predefined set of volumes (cube, sphere, // cylinder, cone, torus). // // Parameters: // // fluid: fluid into which we are emitting // fluidWorldMatrix: object->world matrix for the fluid // plugIndex: identifies which fluid connected to the emitter // we are emitting into // block: datablock for the emitter, to retrieve attribute // values // dt: time delta for this frame // conversion: mapping from UI emission rates to internal units // dropoff: specifies how much emission rate drops off as // the surface points move away from the centers // of the voxels in which they lie. // // Notes: // // To associate an owner object with an emitter, use the // addDynamic MEL command, e.g. "addDynamic simpleFluidEmitter1 pPlane1". // //============================================================================== { // get relevant world matrices // MMatrix fluidInverseWorldMatrix = fluidWorldMatrix.inverse(); // get emission rates for density, fuel, heat, and emission color // double densityEmit = fluidDensityEmission( block ); double fuelEmit = fluidFuelEmission( block ); double heatEmit = fluidHeatEmission( block ); bool doEmitColor = fluidEmitColor( block ); MColor emitColor = fluidColor( block ); // rate modulation based on frame time, user value conversion factor, and // standard emitter "rate" value (not actually exposed in most fluid // emitters, but there anyway). // double theRate = getRate(block) * dt * conversion; // get voxel dimensions and sizes (object space) // double size[3]; unsigned int res[3]; fluid.getDimensions( size[0], size[1], size[2] ); fluid.getResolution( res[0], res[1], res[2] ); // voxel sizes double dx = size[0] / res[0]; double dy = size[1] / res[1]; double dz = size[2] / res[2]; // voxel centers double Ox = -size[0]/2; double Oy = -size[1]/2; double Oz = -size[2]/2; // get the "swept geometry" data for the emitter surface. This structure // tracks the motion of each emitter triangle over the time interval // for this simulation step. We just use positions on the emitter // surface at the end of the time step to do the emission. // MDataHandle sweptHandle = block.inputValue( mSweptGeometry ); MObject sweptData = sweptHandle.data(); MFnDynSweptGeometryData fnSweptData( sweptData ); // for "non-jittered" sampling, just reset the random state for each // triangle, which gives us a fixed set of samples all the time. // Sure, they're still jittered, but they're all jittered the same, // which makes them kinda uniform. // bool jitter = fluidJitter(block); if( !jitter ) { resetRandomState( plugIndex, block ); } if( fnSweptData.triangleCount() > 0 ) { // average voxel face area - use this as the canonical unit that // receives the emission rate specified by the users. Scale the // rate for other triangles accordingly. // double vfArea = pow(dx*dy*dz, 2.0/3.0); // very rudimentary support for textured emission rate and // textured emission color. We simply sample each texture once // at the center of each emitter surface triangle. This will // cause aliasing artifacts when these triangles are large. // MFnDependencyNode fnNode( thisMObject() ); MObject rateTextureAttr = fnNode.attribute( "textureRate" ); MObject colorTextureAttr = fnNode.attribute( "particleColor" ); bool texturedRate = hasValidEmission2dTexture( rateTextureAttr ); bool texturedColor = hasValidEmission2dTexture( colorTextureAttr ); // construct texture coordinates for each triangle center // MDoubleArray uCoords, vCoords; if( texturedRate || texturedColor ) { uCoords.setLength( fnSweptData.triangleCount() ); vCoords.setLength( fnSweptData.triangleCount() ); int t; for( t = 0; t < fnSweptData.triangleCount(); t++ ) { MDynSweptTriangle tri = fnSweptData.sweptTriangle( t ); MVector uv0 = tri.uvPoint(0); MVector uv1 = tri.uvPoint(1); MVector uv2 = tri.uvPoint(2); MVector uvMid = (uv0+uv1+uv2)/3.0; uCoords[t] = uvMid[0]; vCoords[t] = uvMid[1]; } } // evaluate textured rate and color values at the triangle centers // MDoubleArray texturedRateValues; if( texturedRate ) { texturedRateValues.setLength( uCoords.length() ); evalEmission2dTexture( rateTextureAttr, uCoords, vCoords, NULL, &texturedRateValues ); } MVectorArray texturedColorValues; if( texturedColor ) { texturedColorValues.setLength( uCoords.length() ); evalEmission2dTexture( colorTextureAttr, uCoords, vCoords, &texturedColorValues, NULL ); } for( int t = 0; t < fnSweptData.triangleCount(); t++ ) { // calculate emission rate and color values for this triangle // double curTexturedRate = texturedRate ? texturedRateValues[t] : 1.0; MColor curTexturedColor; if( texturedColor ) { MVector& curVec = texturedColorValues[t]; curTexturedColor.r = (float)curVec[0]; curTexturedColor.g = (float)curVec[1]; curTexturedColor.b = (float)curVec[2]; curTexturedColor.a = 1.0; } else { curTexturedColor = emitColor; } MDynSweptTriangle tri = fnSweptData.sweptTriangle( t ); MVector v0 = tri.vertex(0); MVector v1 = tri.vertex(1); MVector v2 = tri.vertex(2); // compute number of samples for this triangle based on area, // with large triangles receiving approximately 1 sample for // each voxel that they intersect // double triArea = tri.area(); int numSamples = (int)(triArea / vfArea); if( numSamples < 1 ) numSamples = 1; // compute emission rate for the points on the triangle. // Scale the canonical rate by the area ratio of this triangle // to the average voxel size, then split it amongst all the samples. // double triRate = (theRate*(triArea/vfArea))/numSamples; triRate *= curTexturedRate; for( int j = 0; j < numSamples; j++ ) { // generate a random point on the triangle, // map it into fluid local space // double r1 = randgen(); double r2 = randgen(); if( r1 + r2 > 1 ) { r1 = 1-r1; r2 = 1-r2; } double r3 = 1 - (r1+r2); MPoint randPoint = r1*v0 + r2*v1 + r3*v2; randPoint *= fluidInverseWorldMatrix; // figure out where the current point lies // ::int3 coord; fluid.toGridIndex( randPoint, coord ); if( (coord[0]<0) || (coord[1]<0) || (coord[2]<0) || (coord[0]>=(int)res[0]) || (coord[1]>=(int)res[1]) || (coord[2]>=(int)res[2]) ) { continue; } // do some falloff based on how far from the voxel center // the current point lies // MPoint gridPoint; gridPoint.x = Ox + (coord[0]+0.5)*dx; gridPoint.y = Oy + (coord[1]+0.5)*dy; gridPoint.z = Oz + (coord[2]+0.5)*dz; MVector diff = gridPoint - randPoint; double distSquared = diff * diff; double distDrop = dropoff * distSquared; double newVal = triRate * exp( -distDrop ); // emit into the voxel // if( newVal != 0 ) { fluid.emitIntoArrays( (float) newVal, coord[0], coord[1], coord[2], (float)densityEmit, (float)heatEmit, (float)fuelEmit, doEmitColor, curTexturedColor ); } } } } }
void simpleFluidEmitter::volumeFluidEmitter( MFnFluid& fluid, const MMatrix& fluidWorldMatrix, int plugIndex, MDataBlock& block, double dt, double conversion, double dropoff ) //============================================================================== // // Method: // // simpleFluidEmitter::volumeFluidEmitter // // Description: // // Emits fluid from points distributed over the surface of the // emitter's owner object. // // Parameters: // // fluid: fluid into which we are emitting // fluidWorldMatrix: object->world matrix for the fluid // plugIndex: identifies which fluid connected to the emitter // we are emitting into // block: datablock for the emitter, to retrieve attribute // values // dt: time delta for this frame // conversion: mapping from UI emission rates to internal units // dropoff: specifies how much emission rate drops off as // we move away from the local y-axis of the // volume emitter shape. // //============================================================================== { // get emitter position and relevant matrices // MPoint emitterPos = getWorldPosition(); MMatrix emitterWorldMatrix = getWorldMatrix(); MMatrix fluidInverseWorldMatrix = fluidWorldMatrix.inverse(); // get emission rates for density, fuel, heat, and emission color // double densityEmit = fluidDensityEmission( block ); double fuelEmit = fluidFuelEmission( block ); double heatEmit = fluidHeatEmission( block ); bool doEmitColor = fluidEmitColor( block ); MColor emitColor = fluidColor( block ); // rate modulation based on frame time, user value conversion factor, and // standard emitter "rate" value (not actually exposed in most fluid // emitters, but there anyway). // double theRate = getRate(block) * dt * conversion; // get voxel dimensions and sizes (object space) // double size[3]; unsigned int res[3]; fluid.getDimensions( size[0], size[1], size[2] ); fluid.getResolution( res[0], res[1], res[2] ); // voxel sizes double dx = size[0] / res[0]; double dy = size[1] / res[1]; double dz = size[2] / res[2]; // voxel centers double Ox = -size[0]/2; double Oy = -size[1]/2; double Oz = -size[2]/2; // find the voxels that intersect the bounding box of the volume // primitive associated with the emitter // MBoundingBox bbox; if( !volumePrimitiveBoundingBox( bbox ) ) { // shouldn't happen // return; } // transform volume primitive into fluid space // bbox.transformUsing( emitterWorldMatrix ); bbox.transformUsing( fluidInverseWorldMatrix ); MPoint lowCorner = bbox.min(); MPoint highCorner = bbox.max(); // get fluid voxel coord range of bounding box // ::int3 lowCoords; ::int3 highCoords; fluid.toGridIndex( lowCorner, lowCoords ); fluid.toGridIndex( highCorner, highCoords ); int i; for ( i = 0; i < 3; i++ ) { if ( lowCoords[i] < 0 ) { lowCoords[i] = 0; } else if ( lowCoords[i] > ((int)res[i])-1 ) { lowCoords[i] = ((int)res[i])-1; } if ( highCoords[i] < 0 ) { highCoords[i] = 0; } else if ( highCoords[i] > ((int)res[i])-1 ) { highCoords[i] = ((int)res[i])-1; } } // figure out the emitter size relative to the voxel size, and compute // a per-voxel sampling rate that uses 1 sample/voxel for emitters that // are >= 2 voxels big in all dimensions. For smaller emitters, use up // to 8 samples per voxel. // double emitterVoxelSize[3]; emitterVoxelSize[0] = (highCorner[0]-lowCorner[0])/dx; emitterVoxelSize[1] = (highCorner[1]-lowCorner[1])/dy; emitterVoxelSize[2] = (highCorner[2]-lowCorner[2])/dz; double minVoxelSize = MIN(emitterVoxelSize[0],MIN(emitterVoxelSize[1],emitterVoxelSize[2])); if( minVoxelSize < 1.0 ) { minVoxelSize = 1.0; } int maxSamples = 8; int numSamples = (int)(8.0/(minVoxelSize*minVoxelSize*minVoxelSize) + 0.5); if( numSamples < 1 ) numSamples = 1; if( numSamples > maxSamples ) numSamples = maxSamples; // non-jittered, just use one sample in the voxel center. Should replace // with uniform sampling pattern. // bool jitter = fluidJitter(block); if( !jitter ) { numSamples = 1; } // for each voxel that could potentially intersect the volume emitter // primitive, take some samples in the voxel. For those inside the // volume, compute their dropoff relative to the primitive's local y-axis, // and emit an appropriate amount into the voxel. // for( i = lowCoords[0]; i <= highCoords[0]; i++ ) { double x = Ox + (i+0.5)*dx; for( int j = lowCoords[1]; j < highCoords[1]; j++ ) { double y = Oy + (j+0.5)*dy; for( int k = lowCoords[2]; k < highCoords[2]; k++ ) { double z = Oz + (k+0.5)*dz; for ( int si = 0; si < numSamples; si++) { // compute voxel sample point (object space) // double rx, ry, rz; if(jitter) { rx = x + dx*(randgen() - 0.5); ry = y + dy*(randgen() - 0.5); rz = z + dz*(randgen() - 0.5); } else { rx = x; ry = y; rz = z; } // to world space MPoint pt( rx, ry, rz ); pt *= fluidWorldMatrix; // test to see if point is inside volume primitive // if( volumePrimitivePointInside( pt, emitterWorldMatrix ) ) { // compute dropoff // double dist = pt.distanceTo( emitterPos ); double distDrop = dropoff * (dist*dist); double newVal = (theRate * exp( -distDrop )) / (double)numSamples; // emit into arrays // if( newVal != 0.0 ) { fluid.emitIntoArrays( (float) newVal, i, j, k, (float)densityEmit, (float)heatEmit, (float)fuelEmit, doEmitColor, emitColor ); } } } } } } }
void simpleFluidEmitter::omniFluidEmitter( MFnFluid& fluid, const MMatrix& fluidWorldMatrix, int plugIndex, MDataBlock& block, double dt, double conversion, double dropoff ) //============================================================================== // // Method: // // simpleFluidEmitter::omniFluidEmitter // // Description: // // Emits fluid from a point, or from a set of object control points. // // Parameters: // // fluid: fluid into which we are emitting // fluidWorldMatrix: object->world matrix for the fluid // plugIndex: identifies which fluid connected to the emitter // we are emitting into // block: datablock for the emitter, to retrieve attribute // values // dt: time delta for this frame // conversion: mapping from UI emission rates to internal units // dropoff: specifies how much emission rate drops off as // we move away from each emission point. // // Notes: // // If no owner object is present for the emitter, we simply emit from // the emitter position. If an owner object is present, then we emit // from each control point of that object in an identical fashion. // // To associate an owner object with an emitter, use the // addDynamic MEL command, e.g. "addDynamic simpleFluidEmitter1 pPlane1". // //============================================================================== { // find the positions that we need to emit from // MVectorArray emitterPositions; // first, try to get them from an owner object, which will have its // "ownerPositionData" attribute feeding into the emitter. These // values are in worldspace // bool gotOwnerPositions = false; MObject ownerShape = getOwnerShape(); if( ownerShape != MObject::kNullObj ) { MStatus status; MDataHandle hOwnerPos = block.inputValue( mOwnerPosData, &status ); if( status == MS::kSuccess ) { MObject dOwnerPos = hOwnerPos.data(); MFnVectorArrayData fnOwnerPos( dOwnerPos ); MVectorArray posArray = fnOwnerPos.array( &status ); if( status == MS::kSuccess ) { // assign vectors from block to ownerPosArray. // for( unsigned int i = 0; i < posArray.length(); i ++ ) { emitterPositions.append( posArray[i] ); } gotOwnerPositions = true; } } } // there was no owner object, so we just use the emitter position for // emission. // if( !gotOwnerPositions ) { MPoint emitterPos = getWorldPosition(); emitterPositions.append( emitterPos ); } // get emission rates for density, fuel, heat, and emission color // double densityEmit = fluidDensityEmission( block ); double fuelEmit = fluidFuelEmission( block ); double heatEmit = fluidHeatEmission( block ); bool doEmitColor = fluidEmitColor( block ); MColor emitColor = fluidColor( block ); // rate modulation based on frame time, user value conversion factor, and // standard emitter "rate" value (not actually exposed in most fluid // emitters, but there anyway). // double theRate = getRate(block) * dt * conversion; // get voxel dimensions and sizes (object space) // double size[3]; unsigned int res[3]; fluid.getDimensions( size[0], size[1], size[2] ); fluid.getResolution( res[0], res[1], res[2] ); // voxel sizes double dx = size[0] / res[0]; double dy = size[1] / res[1]; double dz = size[2] / res[2]; // voxel centers double Ox = -size[0]/2; double Oy = -size[1]/2; double Oz = -size[2]/2; // emission will only happen for voxels whose centers lie within // "minDist" and "maxDist" of an emitter position // double minDist = getMinDistance( block ); double maxDist = getMaxDistance( block ); // bump up the min/max distance values so that they // are both > 0, and there is at least about a half // voxel between the min and max values, to prevent aliasing // artifacts caused by emitters missing most voxel centers // MTransformationMatrix fluidXform( fluidWorldMatrix ); double fluidScale[3]; fluidXform.getScale( fluidScale, MSpace::kWorld ); // compute smallest voxel diagonal length double wsX = fabs(fluidScale[0]*dx); double wsY = fabs(fluidScale[1]*dy); double wsZ = fabs(fluidScale[2]*dz); double wsMin = MIN( MIN( wsX, wsY), wsZ ); double wsMax = MAX( MAX( wsX, wsY), wsZ ); double wsDiag = wsMin * sqrt(3.0); // make sure emission range is bigger than 0.5 voxels if ( maxDist <= minDist || maxDist <= (wsDiag/2.0) ) { if ( minDist < 0 ) minDist = 0; maxDist = minDist + wsDiag/2.0; dropoff = 0; } // Now, it's time to actually emit into the fluid: // // foreach emitter point // foreach voxel // - select some points in the voxel // - compute a dropoff function from the emitter point // - emit an appropriate amount of fluid into the voxel // // Since we've already expanded the min/max distances to cover // the smallest voxel dimension, we should only need 1 sample per // voxel, unless the voxels are highly non-square. We increase the // number of samples in these cases. // // If the "jitter" flag is enabled, we jitter each sample position, // using the rangen() function, which keeps track of independent // random states for each fluid, to make sure that results are // repeatable for multiple simulation runs. // // basic sample count int numSamples = 1; // increase samples if necessary for non-square voxels if(wsMin >.00001) { numSamples = (int)(wsMax/wsMin + .5); if(numSamples > 8) numSamples = 8; if(numSamples < 1) numSamples = 1; } bool jitter = fluidJitter(block); if( !jitter ) { // I don't have a good uniform sample generator for an // arbitrary number of samples. It would be a good idea to use // one here. For now, just use 1 sample for the non-jittered case. // numSamples = 1; } for( unsigned int p = 0; p < emitterPositions.length(); p++ ) { MPoint emitterWorldPos = emitterPositions[p]; // loop through all voxels, looking for ones that lie at least // partially within the dropoff field around this emitter point // for( unsigned int i = 0; i < res[0]; i++ ) { double x = Ox + i*dx; for( unsigned int j = 0; j < res[1]; j++ ) { double y = Oy + j*dy; for( unsigned int k = 0; k < res[2]; k++ ) { double z = Oz + k*dz; int si; for( si = 0; si < numSamples; si++ ) { // compute sample point (fluid object space) // double rx, ry, rz; if( jitter ) { rx = x + randgen()*dx; ry = y + randgen()*dy; rz = z + randgen()*dz; } else { rx = x + 0.5*dx; ry = y + 0.5*dy; rz = z + 0.5*dz; } // compute distance from sample to emitter point // MPoint point( rx, ry, rz ); point *= fluidWorldMatrix; MVector diff = point - emitterWorldPos; double distSquared = diff * diff; double dist = diff.length(); // discard if outside min/max range // if( (dist < minDist) || (dist > maxDist) ) { continue; } // drop off the emission rate according to the falloff // parameter, and divide to accound for multiple samples // in the voxel // double distDrop = dropoff * distSquared; double newVal = theRate * exp( -distDrop ) / (double)numSamples; // emit density/heat/fuel/color into the current voxel // if( newVal != 0 ) { fluid.emitIntoArrays( (float) newVal, i, j, k, (float)densityEmit, (float)heatEmit, (float)fuelEmit, doEmitColor, emitColor ); } float *fArray = fluid.falloff(); if( fArray != NULL ) { MPoint midPoint( x+0.5*dx, y+0.5*dy, z+0.5*dz ); midPoint.x *= 0.2; midPoint.y *= 0.2; midPoint.z *= 0.2; float fdist = (float) sqrt( midPoint.x*midPoint.x + midPoint.y*midPoint.y + midPoint.z*midPoint.z ); fdist /= sqrtf(3.0f); fArray[fluid.index(i,j,k)] = 1.0f-fdist; } } } } } } }
// private method to work with random generation and Normal distributions. // in it we are using the random support offered by the thrust library __device__ __host__ float ExampleTanNoise::NORM(int pos, int seed) const { thrust::minstd_rand randgen(seed); thrust::random::normal_distribution<float> dist; randgen.discard(pos); return dist(randgen); }
/* ** ** void setup_spop(EVOLDATA ev, MATRIX fSearchPop, VECTOR fRefProbDist, ** MATRIX fRefPop, MATRIX fLC, MATRIX fDC) ** ** Sets up the search population by performing the initial evaluations. ** ** Assumes that ref. population is already setup and SORTED ** */ void setup_spop(EVOLDATA ev, MATRIX fSearchPop, VECTOR fRefProbDist, MATRIX fRefPop, MATRIX fLC, MATRIX fDC) { int i, j, k, iSelIndex; float fRandVal; float fTempVec[MAXVECTOR]; int iFlag; for (i=1; i<=ev.iSearchPopSize; i++) { eval_func(fSearchPop[i], ev.iNumTestCase, ev); /* simple evaluation */ /* now, pick a reference vector at RANDOM (0) or ORDERED (1) */ if (ev.iSelRefPoint == RANDOM) iSelIndex = (int)randgen(1.0, (float)ev.iRefPopSize); else { fRandVal = randgen(0.0, 1.0); k=1; while (fRandVal >= fRefProbDist[k]) k++; if (k >= ev.iRefPopSize) k = 1; iSelIndex = k; } /* move from search to reference */ k = 0; iFlag = FALSE; fRandVal = 0.0; if (ev.iRepairMethod == RANDOM) do { fRandVal = randgen(0.0, 1.0); for (j=1; j<=ev.iNumVars; j++) fTempVec[j] = fRandVal*fSearchPop[i][j] + (1-fRandVal)*fRefPop[iSelIndex][j]; iFlag = check_all(ev, fTempVec, fLC, fDC); k++; } while ((iFlag == FALSE) && (k < 100)); else if (ev.iRepairMethod == DETERMINISTIC) do { fRandVal = 1.0/power(2.0, k); for (j=1; j<=ev.iNumVars; j++) fTempVec[j] = fRandVal*fSearchPop[i][j] + (1-fRandVal)*fRefPop[iSelIndex][j]; iFlag = check_all(ev, fTempVec, fLC, fDC); k++; } while ((iFlag == FALSE) && (k < 20)); /* if no feasible Z, Z = Y */ if (iFlag == FALSE) for (j=1; j<=ev.iNumVars; j++) fTempVec[j] = fRefPop[iSelIndex][j]; /* now, evaluate Z */ eval_func(fTempVec, ev.iNumTestCase, ev); /* if Z better than Y, replace Y by Z */ switch(ev.iObjFnType) { case MAX: if (fTempVec[0] > fRefPop[iSelIndex][0]) for (j=0; j<=ev.iNumVars; j++) fRefPop[iSelIndex][j] = fTempVec[j]; break; case MIN: if (fTempVec[0] < fRefPop[iSelIndex][0]) for (j=0; j<=ev.iNumVars; j++) fRefPop[iSelIndex][j] = fTempVec[j]; break; default: break; } /* eval(X) = eval(Z) */ fSearchPop[i][0] = fTempVec[0]; /* if probability allows, replace X by Z as well */ fRandVal = randgen(0.0, 1.0); if (fRandVal < ev.fReplRatio) for (j=0; j<=ev.iNumVars; j++) fSearchPop[i][j] = fTempVec[j]; } }
/* ** ** void b_mutate(EVOLDATA ev, VECTOR fV, int iIndex, MATRIX fDC, MATRIX = fLC) ** ** Boundary mutation operator - single parent, single offspring ** ** */ void b_mutate(EVOLDATA ev, VECTOR fV, int iIndex, MATRIX fDC, MATRIX fLC) { int i, j, iFlag; float fLlim, fUlim, fSum, fNewLimit, fRandVal; iFlag = GENOCOP_FALSE; /* see if the chosen variable has any Domain Constraints */ for (i = 1; i <= ev.iNumDC; i++) { if ((int) fDC[i][2] == iIndex) { fUlim = fDC[i][3]; fLlim = fDC[i][1]; iFlag = GENOCOP_TRUE; } } if (iFlag == GENOCOP_FALSE) { fUlim = GENOCOP_MAXNUM; fLlim = GENOCOP_MINNUM; } /* now, get new limit from linear constraints */ /* for this, first substitute all other variables */ /* keeping in mind that the function is stated as f[x] >= 0 */ for (i = 1; i <= ev.iNumLC; i++) { /* ** CHECK LIMITS ONLY IF COEFF. OF VARIABLE IS NON-ZERO ** */ if (fLC[i][iIndex] != 0.0) { fSum = 0.0; for (j = 1; j <= ev.iNumVars; j++) if (j != iIndex) fSum = fSum + fV[j] * fLC[i][j]; fSum = fSum + fLC[i][ev.iNumVars + 1]; /* constant term */ /* now, function is fSum+fV[iIndex]*fLC[i][iIndex] >= 0 */ /* this is the new lower limit, after comparison */ fNewLimit = (-1 * fSum) / fLC[i][iIndex]; /* now, if the coeff. was NEGATIVE, the inequality is CHANGED */ /* while carrying it over, and it becomes a possible new */ /* LOWER limit */ if (fLC[i][iIndex] > 0.0) /* CHANGE SIGN IF NEGATIVE */ { if (fNewLimit > fLlim) fLlim = fNewLimit; } else { if (fNewLimit < fUlim) fUlim = fNewLimit; } } } /* pick either the max or min. limit */ fRandVal = randgen(0.0, 1.0); if (fRandVal < 0.5) fV[iIndex] = fLlim; else fV[iIndex] = fUlim; }
TestMRPPWindow::TestMRPPWindow(HWND parent, std::string title) : MRPWindow(parent, title) { for (int i = 0; i < 8; ++i) { auto but = std::make_shared<WinButton>(this, std::to_string(i)); but->GenericNotifyCallback = [i](GenericNotifications) { readbg() << "you pressed " << i << "\n"; }; add_control(but); } // Button 0 toggless enabled state of button 1 m_controls[0]->GenericNotifyCallback = [this](GenericNotifications) { m_controls[1]->setEnabled(!m_controls[1]->isEnabled()); }; m_envcontrol1 = std::make_shared<EnvelopeControl>(this); // Button 3 toggless enabled state of envelope control m_controls[3]->GenericNotifyCallback = [this](GenericNotifications) { m_envcontrol1->setEnabled(!m_envcontrol1->isEnabled()); }; // Button 7 toggless visible state of button 0 m_controls[7]->GenericNotifyCallback = [this](GenericNotifications) { m_controls[0]->setVisible(!m_controls[0]->isVisible()); }; auto env = std::make_shared<breakpoint_envelope>("foo", LICE_RGBA(255, 255, 255, 255)); env->add_point({ 0.0, 0.5 , envbreakpoint::Power, 0.5 }, true); env->add_point({ 0.5, 0.0 , envbreakpoint::Power, 0.5 }, true); env->add_point({ 1.0, 0.5 }, true); m_envcontrol1->add_envelope(env); m_envcontrol1->GenericNotifyCallback = [this, env](GenericNotifications reason) { //if (reason == GenericNotifications::AfterManipulation) // generate_items_sequence(env, m_edit1->getText().c_str()); }; add_control(m_envcontrol1); // Button 5 does some Xenakios silliness m_controls[5]->GenericNotifyCallback = [this, env](GenericNotifications) { generate_items_sequence(env, m_edit1->getText().c_str()); }; m_label1 = std::make_shared<WinLabel>(this, "This is a label"); add_control(m_label1); m_edit1 = std::make_shared<WinLineEdit>(this, "C:/MusicAudio/pihla_ei/ei_mono_005.wav"); add_control(m_edit1); m_edit1->TextCallback = [this](std::string txt) { m_label1->setText(txt); }; // Button 6 launches bogus work in another thread to demo progress bar m_controls[6]->GenericNotifyCallback = [this](GenericNotifications) { m_progressbar1->setVisible(true); // we don't deal with multiple background tasks now, so disable the button to start the task m_controls[6]->setEnabled(false); static int rseed = 0; auto task = [this](int randseed) { std::mt19937 randgen(randseed); std::uniform_real_distribution<double> randdist(0.0, 1.0); double accum = 0.0; const int iterations = 50000000; double t0 = time_precise(); for (int i = 0; i < iterations; ++i) { accum += randdist(randgen); //accum += randdist(randgen); // Production code should not do this at this granularity, because setProgressValue deals with // an atomic value. but this is just a demo... m_progressbar1->setProgressValue(1.0 / iterations*i); } double t1 = time_precise(); auto finishtask = [=]() { m_edit1->setText(std::to_string(accum) + " elapsed time " + std::to_string(t1-t0)); m_progressbar1->setProgressValue(0.0); m_progressbar1->setVisible(false); m_controls[6]->setEnabled(true); }; execute_in_main_thread(finishtask); }; m_future1 = std::async(std::launch::async, task, rseed); ++rseed; }; // Button 1 shows popup menu m_controls[1]->GenericNotifyCallback = [this, env](GenericNotifications) { PopupMenu popmenu(getWindowHandle()); popmenu.add_menu_item("Menu entry 1", [](PopupMenu::CheckState) {}); popmenu.add_menu_item("Menu entry 2", m_menuitem2state, [this](PopupMenu::CheckState cs) { m_menuitem2state = cs; }); popmenu.add_menu_item("Menu entry 3", m_menuitem3state, [this](PopupMenu::CheckState cs) { m_menuitem3state = cs; }); PopupMenu submenu(getWindowHandle()); submenu.add_menu_item("Submenu entry 1", [](PopupMenu::CheckState) { readbg() << "submenu entry 1\n"; }); submenu.add_menu_item("Submenu entry 2", [](PopupMenu::CheckState) { readbg() << "submenu entry 2\n"; }); PopupMenu subsubmenu(getWindowHandle()); for (int i = 0; i < 8; ++i) { subsubmenu.add_menu_item(std::string("Subsubmenu entry ") + std::to_string(i + 1), [i](PopupMenu::CheckState) { readbg() << "subsubmenu entry " << i + 1 << "\n"; }); } submenu.add_submenu("Going still deeper", subsubmenu); popmenu.add_submenu("More stuff", submenu); popmenu.execute(m_controls[1]->getXPosition(), m_controls[1]->getYPosition()); }; // Button 4 removes envelope points with value over 0.5 m_controls[4]->GenericNotifyCallback = [this, env](GenericNotifications) { env->remove_points_conditionally([](const envbreakpoint& pt) { return pt.get_y() > 0.5; }); m_envcontrol1->repaint(); }; m_combo1 = std::make_shared<WinComboBox>(this); m_combo1->addItem("Apple", -9001); m_combo1->addItem("Pear", 666); m_combo1->addItem("Kiwi", 42); m_combo1->addItem("Banana", 100); m_combo1->SelectedChangedCallback = [this](int index) { int user_id = m_combo1->userIDfromIndex(index); readbg() << "combo index " << index << " userid " << user_id << "\n"; }; add_control(m_combo1); m_combo1->setSelectedUserID(42); m_combo2 = std::make_shared<WinComboBox>(this); m_combo2->addItem("Item 1", 100); m_combo2->addItem("Item 2", 101); m_combo2->addItem("Item 3", 102); m_combo2->addItem("Item 4", 103); m_combo2->SelectedChangedCallback = [this](int index) { int user_id = m_combo2->userIDfromIndex(index); readbg() << "combo index " << index << " userid " << user_id << "\n"; }; add_control(m_combo2); m_combo2->setSelectedIndex(0); m_slider1 = std::make_shared<ReaSlider>(this, 0.5); //m_slider1->setValueConverter(std::make_shared<FFTSizesValueConverter>()); m_slider1->SliderValueCallback = [this](GenericNotifications, double x) { m_label1->setText(std::to_string(x)); m_progressbar1->setProgressValue(x); }; add_control(m_slider1); m_zoomscroll1 = std::make_shared<ZoomScrollBar>(this); add_control(m_zoomscroll1); m_zoomscroll1->RangeChangedCallback = [this](double t0, double t1) { m_envcontrol1->setViewTimeRange(t0, t1); }; m_progressbar1 = std::make_shared<ProgressControl>(this); m_progressbar1->setVisible(false); }
AsymetricCharacterRbDemo::AsymetricCharacterRbDemo(hkDemoEnvironment* env) : hkDefaultPhysicsDemo(env) { // Create the world { hkpWorldCinfo info; info.setBroadPhaseWorldSize( 350.0f ); info.m_gravity.set(0, -9.8f, 0); info.m_collisionTolerance = 0.01f; info.m_contactPointGeneration = hkpWorldCinfo::CONTACT_POINT_ACCEPT_ALWAYS; m_world = new hkpWorld( info ); m_world->lock(); hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher()); setupGraphics(); } // Create a terrain (more bumpy as in the classical character proxy demo) TerrainHeightFieldShape* heightFieldShape; { hkpSampledHeightFieldBaseCinfo ci; ci.m_xRes = 64; ci.m_zRes = 64; ci.m_scale.set(1.6f, 0.2f, 1.6f); // Fill in a data array m_data = hkAllocate<hkReal>((ci.m_xRes * ci.m_zRes), HK_MEMORY_CLASS_DEMO); for (int x = 0; x < ci.m_xRes; x++) { for (int z = 0; z < ci.m_zRes; z++) { hkReal dx,dz,height = 0; int octave = 1; // Add together a few sine and cose waves for (int i=0; i< 3; i++) { dx = hkReal(x * octave) / ci.m_xRes; dz = hkReal(z * octave) / ci.m_zRes; height += 4 * i * hkMath::cos(dx * HK_REAL_PI) * hkMath::sin(dz * HK_REAL_PI); height -= 2.5f; octave *= 2; } m_data[x*ci.m_zRes + z] = height; } } heightFieldShape = new TerrainHeightFieldShape( ci , m_data ); // Create terrain as a fixed rigid body { hkpRigidBodyCinfo rci; rci.m_motionType = hkpMotion::MOTION_FIXED; rci.m_position.setMul4( -0.5f, heightFieldShape->m_extents ); // center the heighfield rci.m_shape = heightFieldShape; rci.m_friction = 0.5f; hkpRigidBody* terrain = new hkpRigidBody( rci ); m_world->addEntity(terrain); terrain->removeReference(); } heightFieldShape->removeReference(); } // Create some random static pilars (green) and smaller dynamic boxes (blue) { hkPseudoRandomGenerator randgen(12345); for (int i=0; i < 80; i++) { if (i%2) { // Dynamic boxes of random size hkVector4 size; randgen.getRandomVector11(size); size.setAbs4( size ); size.mul4(0.5f); hkVector4 minSize; minSize.setAll3(0.25f); size.add4(minSize); // Random position hkVector4 position; randgen.getRandomVector11( position ); position(0) *= 25; position(2) *= 25; position(1) = 4; { // To illustrate using the shape, create a rigid body by first defining a template. hkpRigidBodyCinfo rci; rci.m_shape = new hkpBoxShape( size ); rci.m_position = position; rci.m_friction = 0.5f; rci.m_restitution = 0.0f; // Density of concrete const hkReal density = 2000.0f; rci.m_mass = size(0)*size(1)*size(2)*density; hkVector4 halfExtents(size(0) * 0.5f, size(1) * 0.5f, size(2) * 0.5f); hkpMassProperties massProperties; hkpInertiaTensorComputer::computeBoxVolumeMassProperties(halfExtents, rci.m_mass, massProperties); rci.m_inertiaTensor = massProperties.m_inertiaTensor; rci.m_motionType = hkpMotion::MOTION_BOX_INERTIA; // Create a rigid body (using the template above). hkpRigidBody* box = new hkpRigidBody(rci); // Remove reference since the body now "owns" the Shape. rci.m_shape->removeReference(); box->addProperty(HK_PROPERTY_DEBUG_DISPLAY_COLOR, int(hkColor::DARKBLUE)); // Finally add body so we can see it, and remove reference since the world now "owns" it. m_world->addEntity(box)->removeReference(); } } else { // Fixed pilars of random size hkVector4 size; randgen.getRandomVector11(size); size.setAbs4( size ); hkVector4 minSize; minSize.setAll3(0.5f); size.add4(minSize); size(1) = 2.5f; // Random position hkVector4 position; randgen.getRandomVector11( position ); position(0) *= 25; position(2) *= 25; position(1) = 0; { // To illustrate using the shape, create a rigid body by first defining a template. hkpRigidBodyCinfo rci; rci.m_shape = new hkpBoxShape( size ); rci.m_position = position; rci.m_friction = 0.1f; rci.m_motionType = hkpMotion::MOTION_FIXED; // Create a rigid body (using the template above). hkpRigidBody* pilar = new hkpRigidBody(rci); // Remove reference since the body now "owns" the shape. rci.m_shape->removeReference(); pilar->addProperty(HK_PROPERTY_DEBUG_DISPLAY_COLOR, int(hkColor::DARKGREEN)); // Finally add body so we can see it, and remove reference since the world now "owns" it. m_world->addEntity(pilar); pilar->removeReference(); } } } } // Create a character rigid body { // Construct a shape hkVector4 vertexA(0.4f,0,0); hkVector4 vertexB(-0.4f,0,0); // Create a capsule to represent the character standing hkpShape* capsule = new hkpCapsuleShape(vertexA, vertexB, 0.6f); // Construct a character rigid body hkpCharacterRigidBodyCinfo info; info.m_mass = 100.0f; info.m_shape = capsule; info.m_maxForce = 1000.0f; info.m_up = UP; info.m_position.set(32.0f, 3.0f, 10.0f); info.m_maxSlope = HK_REAL_PI/2.0f; // Only vertical plane is too steep m_characterRigidBody = new hkpCharacterRigidBody( info ); m_world->addEntity( m_characterRigidBody->getRigidBody() ); capsule->removeReference(); } // Create the character state machine and context { hkpCharacterState* state; hkpCharacterStateManager* manager = new hkpCharacterStateManager(); state = new hkpCharacterStateOnGround(); manager->registerState( state, HK_CHARACTER_ON_GROUND); state->removeReference(); state = new hkpCharacterStateInAir(); manager->registerState( state, HK_CHARACTER_IN_AIR); state->removeReference(); state = new hkpCharacterStateJumping(); manager->registerState( state, HK_CHARACTER_JUMPING); state->removeReference(); state = new hkpCharacterStateClimbing(); manager->registerState( state, HK_CHARACTER_CLIMBING); state->removeReference(); m_characterContext = new hkpCharacterContext(manager, HK_CHARACTER_IN_AIR); manager->removeReference(); // Set new filter parameters for final output velocity filtering // Smoother interactions with small dynamic boxes m_characterContext->setCharacterType(hkpCharacterContext::HK_CHARACTER_RIGIDBODY); m_characterContext->setFilterParameters(0.9f,12.0f,200.0f); } // Initialize hkpSurfaceInfo of ground from previous frame // Specific case (character is in the air, UP is Y) m_previousGround = new hkpSurfaceInfo(UP,hkVector4::getZero(),hkpSurfaceInfo::UNSUPPORTED); m_framesInAir = 0; // Current camera angle about up m_currentAngle = 0.0f; // Init actual time m_time = 0.0f; // Init rigid body normal m_rigidBodyNormal = UP; m_world->unlock(); }
/* ** ** void init_search_pop(EVOLDATA ev, MATRIX fSearchPop, MATRIX fDC, MATRIX fLC) ** ** Initializes the search population with linearly feasible values. ** Asks the user for input if feasible values cannot be generated ** after NTRIES times. ** ** EVOLDATA ev - the main EVOLDATA block ** MATRIX fSearchPop - The search population matrix to be filled in ** MATRIX fDC - the domain constraint matrix ** MATRIX fLC - the linear constraints (inequalities) matrix ** */ void init_search_pop(EVOLDATA ev, MATRIX fSearchPop, MATRIX fDC, MATRIX fLC) { int iFlag, iDCFlag; int iPcount = 0; int iTries = 1; int i, j, k, iNumCopies; char ch; /***************************************************/ /* SINGLE point initalization */ /***************************************************/ if (ev.iSearchInitType == SINGLE) { iFlag = FALSE; iTries = 1; while ((iFlag == FALSE) && (iTries <= NTRIES)) { /* generate random numbers based on the domain constraints */ for (j=1; j<=ev.iNumVars; j++) { iDCFlag = FALSE; /* check if there is a DC for the variable */ for (k=1; k<=ev.iNumDC; k++) if (j==(int)fDC[k][2]) { fSearchPop[1][j] = randgen(fDC[k][1], fDC[k][3]); iDCFlag = TRUE; } /* if no DC, generate values between limits */ if (iDCFlag == FALSE) fSearchPop[1][j] = randgen(MINNUM, MAXNUM); } /* end of j loop*/ /* now, check for feasibility wrt. linear inequalities */ iFlag = check_LC(ev, fSearchPop[1], fLC, fDC); iTries++; } /* end of while */ /* if generation failed after NTRIES times, ask user for input */ if (iTries > NTRIES) { printf("\nSearch Population : Single Point Initialization.\n"); printf("Couldn't find a feasible vector in %d tries.\n", NTRIES); iFlag = FALSE; while (iFlag == FALSE) { ask_user(fSearchPop[1], ev.iNumVars); iFlag = check_LC(ev, fSearchPop[1], fLC, fDC); }; }; /* ** now, we've got a valid vector. Copy it into the entire ** search population. */ for (i=2; i<=ev.iSearchPopSize; i++) for (j=1; j<=ev.iNumVars; j++) fSearchPop[i][j] = fSearchPop[1][j]; } /* end of if SINGLE */ else /***************************************************/ /* MULTIPLE point initalization */ /***************************************************/ { iPcount = 1; while (iPcount<=ev.iSearchPopSize) { iFlag = FALSE; iTries = 1; while ((iFlag == FALSE) && (iTries <= NTRIES)) { /* generate random numbers based on the domain constraints */ for (j=1; j<=ev.iNumVars; j++) { iDCFlag = FALSE; /* check if there is a DC for the variable */ for (k=1; k<=ev.iNumDC; k++) if (j==(int)fDC[k][2]) { fSearchPop[iPcount][j] = randgen(fDC[k][1], fDC[k][3]); iDCFlag = TRUE; } /* if no DC, generate values between limits */ if (iDCFlag == FALSE) fSearchPop[iPcount][j] = randgen(MINNUM, MAXNUM); } /* end of j loop*/ /* now, check for feasibility wrt. linear inequalities */ iFlag = check_LC(ev, fSearchPop[iPcount], fLC, fDC); iTries++; } /* end of while */ /* if we got a valid vector, fine :) otherwise, beg user :( */ if (iFlag == TRUE) iPcount++; else /* if generation failed after NTRIES times, ask user for input */ if (iTries > NTRIES) { printf("\nSearch Population : Multiple Point Initialization.\n"); printf("Couldn't find a feasible vector in %d tries.\n", NTRIES); iFlag = FALSE; while (iFlag == FALSE) { ask_user(fSearchPop[iPcount], ev.iNumVars); iFlag = check_LC(ev, fSearchPop[iPcount], fLC, fDC); }; /* ask if user wishes to duplicate */ printf("Valid vector: Duplicate? (Y/N) :"); fflush(stdin); ch = getchar(); if ((ch == 'y') || (ch == 'Y')) { iNumCopies = 0; /* make sure user inputs value */ do { printf("\nNo of copies (1 to %d) : ", ev.iSearchPopSize - iPcount+1); scanf_s("%d", &iNumCopies); } while ((iNumCopies < 1) || (iNumCopies > (ev.iSearchPopSize-iPcount+1))); /* END of while input validation */ /* now, copy vectors till iNumCopies */ for (i=1; i<iNumCopies; i++) { for (j=1; j<=ev.iNumVars; j++) { fSearchPop[iPcount+1][j] = fSearchPop[iPcount][j]; } iPcount++; } iPcount++; } /* END of block where user requests duplication */ }; /* END of if tries exhausted */ }; /* END of iPcount <= iSearchPopSize */ } /* end of MULTIPLE point initialization */ }
extern "C" LEVMARDLL_API void StochFit(BoxReflSettings* InitStruct, double parameters[], double covararray[], int paramsize, double info[], double ParamArray[], double chisquarearray[], int* paramarraysize) { FastReflcalc Refl; Refl.init(InitStruct); double* Reflectivity = InitStruct->Refl; int QSize = InitStruct->QPoints; double* parampercs = InitStruct->ParamPercs; //Setup the fit double opts[LM_OPTS_SZ]; opts[0]=LM_INIT_MU; opts[1]=1E-15; opts[2]=1E-15; opts[3]=1E-20; opts[4]=-LM_DIFF_DELTA; // relevant only if the finite difference jacobian version is used //Allocate a dummy array - Our real calculation is done in Refl.objective double* xvec = new double[InitStruct->QPoints] ; for(int i = 0; i < InitStruct->QPoints; i++) { xvec[i] = 0; } //Copy starting solution double* origguess = new double[paramsize]; memcpy(origguess, parameters, sizeof(double)*paramsize); if(InitStruct->OneSigma) Refl.mkdensityonesigma(parameters, paramsize); else Refl.mkdensity(parameters, paramsize); Refl.myrfdispatch(); double bestchisquare = 0; for(int i = 0; i < InitStruct->QPoints; i++) { bestchisquare += (log(Refl.reflpt[i])-log(Reflectivity[i]))*(log(Refl.reflpt[i])-log(Reflectivity[i])); } double tempinfoarray[9]; tempinfoarray[1] = bestchisquare; double* tempcovararray = new double[paramsize*paramsize]; memset(tempcovararray,0.0, sizeof(double)*paramsize*paramsize); ParameterContainer original(parameters, tempcovararray, paramsize,InitStruct->OneSigma, tempinfoarray, parampercs[6]); delete[] tempcovararray; vector<ParameterContainer> temp; temp.reserve(6000); omp_set_num_threads(omp_get_num_procs()); #pragma omp parallel { FastReflcalc locRefl; locRefl.init(InitStruct); //Initialize random number generator int seed = time_seed(); CRandomMersenne randgen(time_seed()+omp_get_thread_num()); ParameterContainer localanswer; double locparameters[20]; double locbestchisquare = bestchisquare; double bestparam[20]; int vecsize = 1000; int veccount = 0; ParameterContainer* vec = (ParameterContainer*)malloc(vecsize*sizeof(ParameterContainer)); double locinfo[9]; //Allocate workspace - these will be private to each thread double* work, *covar; work=(double*)malloc((LM_DIF_WORKSZ(paramsize, QSize)+paramsize*QSize)*sizeof(double)); covar=work+LM_DIF_WORKSZ(paramsize, QSize); #pragma omp for schedule(runtime) for(int i = 0; i < InitStruct->Iterations;i++) { locparameters[0] = randgen.IRandom(origguess[0]*parampercs[4], origguess[0]*parampercs[5]); for(int k = 0; k< InitStruct->Boxes; k++) { if(InitStruct->OneSigma) { locparameters[2*k+1] = randgen.IRandom(origguess[2*k+1]*parampercs[0], origguess[2*k+1]*parampercs[1]); locparameters[2*k+2] = randgen.IRandom(origguess[2*k+2]*parampercs[2], origguess[2*k+2]*parampercs[3]); } else { locparameters[3*k+1] = randgen.IRandom(origguess[3*k+1]*parampercs[0], origguess[3*k+1]*parampercs[1]); locparameters[3*k+2] = randgen.IRandom(origguess[3*k+2]*parampercs[2], origguess[3*k+2]*parampercs[3]); locparameters[3*k+3] = randgen.IRandom(origguess[3*k+3]*parampercs[4], origguess[3*k+3]*parampercs[5]); } } locparameters[paramsize-1] = origguess[paramsize-1]; if(InitStruct->UL == NULL) dlevmar_dif(locRefl.objective, locparameters, xvec, paramsize, InitStruct->QPoints, 500, opts, locinfo, work,covar,(void*)(&locRefl)); else dlevmar_bc_dif(locRefl.objective, locparameters, xvec, paramsize, InitStruct->QPoints, InitStruct->LL, InitStruct->UL, 500, opts, locinfo, work,covar,(void*)(&locRefl)); localanswer.SetContainer(locparameters,covar,paramsize,InitStruct->OneSigma,locinfo, parampercs[6]); if(locinfo[1] < bestchisquare && localanswer.IsReasonable()) { //Resize the private arrays if we need the space if(veccount+2 == vecsize) { vecsize += 1000; vec = (ParameterContainer*)realloc(vec,vecsize*sizeof(ParameterContainer)); } bool unique = true; int arraysize = veccount; //Check if the answer already exists for(int i = 0; i < arraysize; i++) { if(localanswer == vec[i]) { unique = false; i = arraysize; } } //If the answer is unique add it to our set of answers if(unique) { vec[veccount] = localanswer; veccount++; } } } #pragma omp critical (AddVecs) { for(int i = 0; i < veccount; i++) { temp.push_back(vec[i]); } } free(vec); free(work); } // delete[] xvec; delete[] origguess; //Sort the answers //Get the total number of answers temp.push_back(original); vector<ParameterContainer> allsolutions; allsolutions.reserve(6000); int tempsize = temp.size(); allsolutions.push_back(temp[0]); for(int i = 1; i < tempsize; i++) { int allsolutionssize = allsolutions.size(); for(int j = 0; j < allsolutionssize;j++) { if(temp[i] == allsolutions[j]) { break; } if(j == allsolutionssize-1) { allsolutions.push_back(temp[i]); } } } if(allsolutions.size() > 0) { sort(allsolutions.begin(), allsolutions.end()); } for(int i = 0; i < allsolutions.size() && i < 1000 && allsolutions.size() > 0; i++) { for(int j = 0; j < paramsize; j++) { ParamArray[(i)*paramsize+j] = (allsolutions.at(i).GetParamArray())[j]; covararray[(i)*paramsize+j] = (allsolutions.at(i).GetCovarArray())[j]; } memcpy(info, allsolutions.at(i).GetInfoArray(), 9* sizeof(double)); info += 9; chisquarearray[i] = (allsolutions.at(i).GetScore()); } *paramarraysize = min(allsolutions.size(),999); }
/* ** ** void nu_mutate(EVOLDATA ev, VECTOR fV, int iIndex, ** MATRIX fDC, MATRIX fLC, long lNumEvals, int iPopSize) ** ** Non-uniform mutation operator - single parent, single offspring ** ** */ void nu_mutate(EVOLDATA ev, VECTOR fV, int iIndex, MATRIX fDC, MATRIX fLC, long lNumEvals, int iPopSize) { int i, j, iFlag; float fLlim, fUlim, fSum, fNewLimit, fRandVal, fFactor; int iNewt, iNewT, iExponent; iFlag = GENOCOP_FALSE; /* see if the chosen variable has any Domain Constraints */ for (i = 1; i <= ev.iNumDC; i++) { if ((int) fDC[i][2] == iIndex) { fUlim = fDC[i][3]; fLlim = fDC[i][1]; iFlag = GENOCOP_TRUE; } } if (iFlag == GENOCOP_FALSE) { fUlim = GENOCOP_MAXNUM; fLlim = GENOCOP_MINNUM; } /* now, get new limit from linear constraints */ /* for this, first substitute all other variables */ /* keeping in mind that the function is stated as f[x] >= 0 */ for (i = 1; i <= ev.iNumLC; i++) { /* ** CHECK LIMITS ONLY IF COEFF. OF VARIABLE IS NON-ZERO ** */ if (fLC[i][iIndex] != 0.0) { fSum = 0.0; for (j = 1; j <= ev.iNumVars; j++) if (j != iIndex) fSum = fSum + fV[j] * fLC[i][j]; fSum = fSum + fLC[i][ev.iNumVars + 1]; /* constant term */ /* now, function is fSum+fV[iIndex]*fLC[i][iIndex] >= 0 */ /* this is the new lower limit, after comparison */ fNewLimit = (-1 * fSum) / fLC[i][iIndex]; /* now, if the coeff. was NEGATIVE, the inequality is CHANGED */ /* while carrying it over, and it becomes a possible new */ /* LOWER limit */ if (fLC[i][iIndex] > 0.0) /* CHANGE SIGN IF NEGATIVE */ { if (fNewLimit > fLlim) fLlim = fNewLimit; } else { if (fNewLimit < fUlim) fUlim = fNewLimit; } } } fRandVal = randgen(0.0, 1.0); /* pick either the max or min. limit */ if (fRandVal < 0.5) /* lower */ { iNewt = (int) (lNumEvals / iPopSize); iNewT = (int) (ev.lTotEvals / iPopSize); iExponent = (int) (6 * randgen(0.0, 1.0)) + 1; fRandVal = randgen(0.0, 1.0); /* NOTE: The three statements below are alternate techniques */ /* Suitability seems to vary according to the objective */ /* function. Experiment by commenting in/out */ /*fFactor = power((1.0F - (float)(iNewt/iNewT)), iExponent) * randgen(0.0, 1.0);*/ /*fFactor = power(0.5, iExponent)*randgen(0.0, 1.0);*/ fFactor = power(0.2, 6)*randgen(0.0, 1.0); if (fFactor < .00001) fFactor = 0.00001; fFactor = fFactor * (fV[iIndex] - fLlim); fV[iIndex] = fV[iIndex] - fFactor; } else { iNewt = (int) lNumEvals / iPopSize; iNewT = (int) ev.lTotEvals / iPopSize; iExponent = (int) (6 * randgen(0.0, 1.0)) + 1; fRandVal = randgen(0.0, 1.0); /* NOTE: The three statements below are alternate techniques */ /* Suitability seems to vary according to the objective */ /* function. Experiment by commenting in/out */ /*fFactor = power((1.0F - (float)(iNewt/iNewT)), iExponent) * randgen(0.0, 1.0);*/ /*fFactor = power(0.5, iExponent)*randgen(0.0, 1.0);*/ fFactor = power(0.2, 6)*randgen(0.0, 1.0); if (fFactor < .00001) fFactor = 0.00001; fFactor = fFactor * (fUlim - fV[iIndex]); fV[iIndex] = fV[iIndex] + fFactor; } }