SCIP_BranchruleData
122 int* rowinfinitiesdown;
124 int* rowinfinitiesup;
136structSCIP_EventhdlrData
158 if( maxindex < branchruledata->memsize )
163assert(newsize > branchruledata->memsize);
164assert(branchruledata->memsize >= 0);
167 if( branchruledata->memsize == 0 )
192branchruledata->varpossmemsize = nvars;
193branchruledata->nupdatedvars = 0;
196 for( v = 0; v < nvars; ++v )
203assert(branchruledata->varfilterposs[v] >= 0);
205branchruledata->varposs[v] = -1;
206branchruledata->updatedvars[v] =
NULL;
220 for(
r= branchruledata->memsize;
r< newsize; ++
r)
224branchruledata->rowinfinitiesdown[
r] = 0;
225branchruledata->rowinfinitiesup[
r] = 0;
229branchruledata->memsize = newsize;
246assert(var !=
NULL);
249assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
255branchruledata->currentlbs[varindex] = lblocal;
256branchruledata->currentubs[varindex] = ublocal;
270assert(mean !=
NULL);
271assert(variance !=
NULL);
290*variance =
SQR(varub - varlb);
292*variance =
SQR(varub - varlb + 1.0) - 1.0;
294*mean = (varub + varlb) * .5;
321 std= sqrt(variance);
331assert(
std!= 0.0 );
336 SCIPdebugMsg(
scip,
" Normalized value %g = ( %g - %g ) / (%g * 1.4142136)\n", normvalue, value, mean,
std);
343 else if( normvalue > 0 )
347erfresult =
SCIPerf(normvalue);
348 returnerfresult / 2.0 + 0.5;
354erfresult =
SCIPerf(-normvalue);
356 return0.5 - erfresult / 2.0;
375 introwinfinitiesdown,
411minprobability =
MIN(rhsprob, lhsprob);
412maxprobability =
MAX(lhsprob, rhsprob);
413rowprobability = minprobability / maxprobability;
416rowprobability =
MIN(rhsprob, lhsprob);
419 SCIPdebugMsg(
scip,
" Row %s, mean %g, sigma2 %g, LHS %g, RHS %g has probability %g to be satisfied\n",
424 returnrowprobability;
443 int* rowinfinitiesdown,
444 int* rowinfinitiesup
453assert(row !=
NULL);
455assert(sigma2 !=
NULL);
456assert(rowinfinitiesup !=
NULL);
457assert(rowinfinitiesdown !=
NULL);
463assert(nrowvals == 0 || rowcols !=
NULL);
464assert(nrowvals == 0 || rowvals !=
NULL);
468*rowinfinitiesdown = 0;
469*rowinfinitiesup = 0;
472 for( c = 0; c < nrowvals; ++c )
483assert(rowcols[c] !=
NULL);
485assert(colvar !=
NULL);
494assert((branchruledata->currentlbs[varindex] ==
SCIP_INVALID) == (branchruledata->currentubs[varindex] ==
SCIP_INVALID));
497 if( branchruledata->currentlbs[varindex] ==
SCIP_INVALID)
515++(*rowinfinitiesdown);
517++(*rowinfinitiesup);
526++(*rowinfinitiesdown);
528++(*rowinfinitiesup);
534*mu += colval * varmean;
537squarecoeff =
SQR(colval);
538*sigma2 += squarecoeff * varvariance;
564assert(upscore !=
NULL);
565assert(downscore !=
NULL);
568 switch( scoreparam )
573*upscore = 1.0 - newprobup;
575*downscore = 1.0 - newprobdown;
580 if(
SCIPisGT(
scip, currentprob - newprobup, *upscore) )
581*upscore = currentprob - newprobup;
582 if(
SCIPisGT(
scip, currentprob - newprobdown, *downscore) )
583*downscore = currentprob - newprobdown;
589*upscore = newprobup;
591*downscore = newprobdown;
611 SCIPerrorMessage(
" ERROR! No branching scheme selected! Exiting method.\n");
650assert(var !=
NULL);
651assert(upscore !=
NULL);
652assert(downscore !=
NULL);
657assert(varcol !=
NULL);
669squaredbounddiff = 0.0;
676squaredbounddiffup = 0.0;
681squaredbounddiffdown = 0.0;
689onlyactiverows = branchruledata->onlyactiverows;
692 for( i = 0; i < ncolrows; ++i )
704 introwinfinitiesdown;
710assert(row !=
NULL);
725 rowCalculateGauss(
scip, branchruledata, row, &branchruledata->rowmeans[rowpos], &branchruledata->rowvariances[rowpos],
726&branchruledata->rowinfinitiesdown[rowpos], &branchruledata->rowinfinitiesup[rowpos]);
730rowmean = branchruledata->rowmeans[rowpos];
731rowvariance = branchruledata->rowvariances[rowpos];
732rowinfinitiesdown = branchruledata->rowinfinitiesdown[rowpos];
733rowinfinitiesup = branchruledata->rowinfinitiesdown[rowpos];
737rowinfinitiesdown, rowinfinitiesup);
740squaredcoeff =
SQR(rowval);
747 introwinftiesdownafterbranch;
748 introwinftiesupafterbranch;
751changedrowmean = rowmean + rowval * (meanup - currentmean);
752changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffup - squaredbounddiff);
753changedrowvariance =
MAX(0.0, changedrowvariance);
755rowinftiesdownafterbranch = rowinfinitiesdown;
756rowinftiesupafterbranch = rowinfinitiesup;
760rowinftiesupafterbranch--;
762rowinftiesdownafterbranch--;
764assert(rowinftiesupafterbranch >= 0);
765assert(rowinftiesdownafterbranch >= 0);
767rowinftiesupafterbranch);
770newrowprobup = currentrowprob;
775 introwinftiesdownafterbranch;
776 introwinftiesupafterbranch;
778changedrowmean = rowmean + rowval * (meandown - currentmean);
779changedrowvariance = rowvariance + squaredcoeff * (squaredbounddiffdown - squaredbounddiff);
780changedrowvariance =
MAX(0.0, changedrowvariance);
782rowinftiesdownafterbranch = rowinfinitiesdown;
783rowinftiesupafterbranch = rowinfinitiesup;
787rowinftiesupafterbranch -= 1;
789rowinftiesdownafterbranch -= 1;
791assert(rowinftiesdownafterbranch >= 0);
792assert(rowinftiesupafterbranch >= 0);
794rowinftiesupafterbranch);
797newrowprobdown = currentrowprob;
802 SCIPdebugMsg(
scip,
" Variable %s changes probability of row %s from %g to %g (branch up) or %g;\n",
804 SCIPdebugMsg(
scip,
" --> new variable score: %g (for branching up), %g (for branching down)\n",
805*upscore, *downscore);
818assert(branchruledata->memsize == 0 || branchruledata->rowmeans !=
NULL);
819assert(branchruledata->memsize >= 0);
821 if( branchruledata->memsize > 0 )
834branchruledata->memsize = 0;
850assert(var !=
NULL);
853assert(-1 <= varindex && varindex < branchruledata->varpossmemsize);
856 if( varindex == -1 )
858varpos = branchruledata->varposs[varindex];
859assert(varpos < branchruledata->nupdatedvars);
864assert(branchruledata->updatedvars[varpos] == var);
870assert((branchruledata->currentlbs[varindex] ==
SCIP_INVALID) == (branchruledata->currentubs[varindex] ==
SCIP_INVALID));
871 if( branchruledata->currentlbs[varindex] ==
SCIP_INVALID)
875assert(branchruledata->varpossmemsize > branchruledata->nupdatedvars);
876varpos = branchruledata->nupdatedvars;
877branchruledata->updatedvars[varpos] = var;
878branchruledata->varposs[varindex] = varpos;
879++branchruledata->nupdatedvars;
892assert(branchruledata->nupdatedvars >= 0);
895 if( branchruledata->nupdatedvars == 0 )
898varpos = branchruledata->nupdatedvars - 1;
899var = branchruledata->updatedvars[varpos];
900assert(var !=
NULL);
902assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
903assert(varpos == branchruledata->varposs[varindex]);
905branchruledata->varposs[varindex] = -1;
906branchruledata->nupdatedvars--;
940assert(var !=
NULL);
942assert(varcol !=
NULL);
949oldlb = branchruledata->currentlbs[varindex];
950oldub = branchruledata->currentubs[varindex];
974 for(
r= 0;
r< ncolrows; ++
r)
978assert(colrows[
r] !=
NULL);
990assert(branchruledata->rowvariances[rowpos] !=
SCIP_INVALID 993coeff = colvals[
r];
994coeffsquared =
SQR(coeff);
997branchruledata->rowmeans[rowpos] += coeff * (newmean - oldmean);
998branchruledata->rowvariances[rowpos] += coeffsquared * (newvariance - oldvariance);
999branchruledata->rowvariances[rowpos] =
MAX(0.0, branchruledata->rowvariances[rowpos]);
1006++branchruledata->rowinfinitiesup[rowpos];
1008--branchruledata->rowinfinitiesup[rowpos];
1011++branchruledata->rowinfinitiesdown[rowpos];
1013--branchruledata->rowinfinitiesdown[rowpos];
1015 else if( coeff < 0.0 )
1018++branchruledata->rowinfinitiesdown[rowpos];
1020--branchruledata->rowinfinitiesdown[rowpos];
1023++branchruledata->rowinfinitiesup[rowpos];
1025--branchruledata->rowinfinitiesup[rowpos];
1027assert(branchruledata->rowinfinitiesdown[rowpos] >= 0);
1028assert(branchruledata->rowinfinitiesup[rowpos] >= 0);
1045assert(eventhdlrdata !=
NULL);
1074assert(branchrule !=
NULL);
1078assert(branchruledata !=
NULL);
1081 if( branchruledata->varfilterposs !=
NULL)
1091 for( v = 0; v < nvars; ++v )
1109assert(branchrule !=
NULL);
1113assert(branchruledata !=
NULL);
1140assert(branchrule !=
NULL);
1143assert(result !=
NULL);
1149 if( nlpcands == 0 )
1159 if( branchruledata->memsize == 0 )
1176 while( branchruledata->nupdatedvars > 0 )
1182assert(nextvar !=
NULL);
1194 for( c = 0; c < nlpcands; ++c )
1201lpcand = lpcands[c];
1202assert(lpcand !=
NULL);
1210assert(0 <= varindex && varindex < branchruledata->varpossmemsize);
1213assert((branchruledata->currentlbs[varindex] ==
SCIP_INVALID) == (branchruledata->currentubs[varindex] ==
SCIP_INVALID));
1214assert((branchruledata->currentlbs[varindex] ==
SCIP_INVALID)
1216assert((branchruledata->currentubs[varindex] ==
SCIP_INVALID)
1220 if( branchruledata->currentlbs[varindex] ==
SCIP_INVALID)
1230&upscore, &downscore, branchruledata->scoreparam) );
1233 if( branchruledata->usescipscore )
1240 if( score > bestscore )
1245 if( upscore > downscore )
1254 if( upscore > bestscore && upscore > downscore )
1256bestscore = upscore;
1260 else if( downscore > bestscore )
1262bestscore = downscore;
1273assert(bestcand !=
NULL);
1281assert(downchild !=
NULL);
1282assert(upchild !=
NULL);
1309assert(eventhdlr !=
NULL);
1311assert(eventhdlrdata !=
NULL);
1313branchruledata = eventhdlrdata->branchruledata;
1337branchruledata =
NULL;
1340branchruledata->memsize = 0;
1341branchruledata->rowmeans =
NULL;
1342branchruledata->rowvariances =
NULL;
1343branchruledata->rowinfinitiesdown =
NULL;
1344branchruledata->rowinfinitiesup =
NULL;
1345branchruledata->varfilterposs =
NULL;
1346branchruledata->currentlbs =
NULL;
1347branchruledata->currentubs =
NULL;
1350eventhdlrdata =
NULL;
1352eventhdlrdata->branchruledata = branchruledata;
1354branchruledata->eventhdlr =
NULL;
1356 "event handler for dynamic acitivity distribution updating",
1357eventExecDistribution, eventhdlrdata) );
1358assert( branchruledata->eventhdlr !=
NULL);
1365assert(branchrule !=
NULL);
1373 "the score;largest 'd'ifference, 'l'owest cumulative probability,'h'ighest c.p., 'v'otes lowest c.p., votes highest c.p.('w') ",
1377 "should only rows which are active at the current node be considered?",
1381 "should the branching score weigh up- and down-scores of a variable",
#define DEFAULT_SCOREPARAM
#define BRANCHRULE_PRIORITY
#define EVENT_DISTRIBUTION
static SCIP_DECL_BRANCHCOPY(branchCopyDistribution)
static SCIP_DECL_BRANCHEXECLP(branchExeclpDistribution)
static SCIP_RETCODE calcBranchScore(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var, SCIP_Real lpsolval, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
#define SCOREPARAM_VALUES
static SCIP_DECL_EVENTEXEC(eventExecDistribution)
static SCIP_DECL_BRANCHFREE(branchFreeDistribution)
static void rowCalculateGauss(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_ROW *row, SCIP_Real *mu, SCIP_Real *sigma2, int *rowinfinitiesdown, int *rowinfinitiesup)
static SCIP_VAR * branchruledataPopBoundChangeVar(SCIP_BRANCHRULEDATA *branchruledata)
static SCIP_RETCODE branchruledataEnsureArraySize(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, int maxindex)
static void branchruledataFreeArrays(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata)
static SCIP_DECL_EVENTFREE(eventFreeDistribution)
static SCIP_RETCODE varProcessBoundChanges(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
static SCIP_DECL_BRANCHEXITSOL(branchExitsolDistribution)
static void branchruledataUpdateCurrentBounds(SCIP *scip, SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
#define DEFAULT_ONLYACTIVEROWS
static void branchruledataAddBoundChangeVar(SCIP_BRANCHRULEDATA *branchruledata, SCIP_VAR *var)
#define BRANCHRULE_MAXDEPTH
#define BRANCHRULE_MAXBOUNDDIST
#define DEFAULT_USEWEIGHTEDSCORE
probability based branching rule based on an article by J. Pryor and J.W. Chinneck
SCIP_RETCODE SCIPupdateDistributionScore(SCIP *scip, SCIP_Real currentprob, SCIP_Real newprobup, SCIP_Real newprobdown, SCIP_Real *upscore, SCIP_Real *downscore, char scoreparam)
SCIP_Real SCIProwCalcProbability(SCIP *scip, SCIP_ROW *row, SCIP_Real mu, SCIP_Real sigma2, int rowinfinitiesdown, int rowinfinitiesup)
void SCIPvarCalcDistributionParameters(SCIP *scip, SCIP_Real varlb, SCIP_Real varub, SCIP_VARTYPE vartype, SCIP_Real *mean, SCIP_Real *variance)
SCIP_Real SCIPcalcCumulativeDistribution(SCIP *scip, SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
SCIP_RETCODE SCIPincludeBranchruleDistribution(SCIP *scip)
SCIP_STAGE SCIPgetStage(SCIP *scip)
int SCIPgetNVars(SCIP *scip)
SCIP_VAR ** SCIPgetVars(SCIP *scip)
SCIP_RETCODE SCIPchgChildPrio(SCIP *scip, SCIP_NODE *child, SCIP_Real priority)
SCIP_RETCODE SCIPaddCharParam(SCIP *scip, const char *name, const char *desc, char *valueptr, SCIP_Bool isadvanced, char defaultvalue, const char *allowedvalues, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
SCIP_RETCODE SCIPaddBoolParam(SCIP *scip, const char *name, const char *desc, SCIP_Bool *valueptr, SCIP_Bool isadvanced, SCIP_Bool defaultvalue, SCIP_DECL_PARAMCHGD((*paramchgd)), SCIP_PARAMDATA *paramdata)
SCIP_RETCODE SCIPsetBranchruleExecLp(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXECLP((*branchexeclp)))
SCIP_RETCODE SCIPsetBranchruleCopy(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHCOPY((*branchcopy)))
SCIP_RETCODE SCIPincludeBranchruleBasic(SCIP *scip, SCIP_BRANCHRULE **branchruleptr, const char *name, const char *desc, int priority, int maxdepth, SCIP_Real maxbounddist, SCIP_BRANCHRULEDATA *branchruledata)
const char * SCIPbranchruleGetName(SCIP_BRANCHRULE *branchrule)
SCIP_BRANCHRULEDATA * SCIPbranchruleGetData(SCIP_BRANCHRULE *branchrule)
SCIP_RETCODE SCIPsetBranchruleFree(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHFREE((*branchfree)))
SCIP_RETCODE SCIPsetBranchruleExitsol(SCIP *scip, SCIP_BRANCHRULE *branchrule, SCIP_DECL_BRANCHEXITSOL((*branchexitsol)))
void SCIPbranchruleSetData(SCIP_BRANCHRULE *branchrule, SCIP_BRANCHRULEDATA *branchruledata)
SCIP_RETCODE SCIPgetLPBranchCands(SCIP *scip, SCIP_VAR ***lpcands, SCIP_Real **lpcandssol, SCIP_Real **lpcandsfrac, int *nlpcands, int *npriolpcands, int *nfracimplvars)
SCIP_RETCODE SCIPbranchVar(SCIP *scip, SCIP_VAR *var, SCIP_NODE **downchild, SCIP_NODE **eqchild, SCIP_NODE **upchild)
SCIP_Real SCIPgetBranchScore(SCIP *scip, SCIP_VAR *var, SCIP_Real downgain, SCIP_Real upgain)
SCIP_VAR * SCIPcolGetVar(SCIP_COL *col)
int SCIPcolGetNNonz(SCIP_COL *col)
SCIP_Real * SCIPcolGetVals(SCIP_COL *col)
SCIP_ROW ** SCIPcolGetRows(SCIP_COL *col)
SCIP_RETCODE SCIPincludeEventhdlrBasic(SCIP *scip, SCIP_EVENTHDLR **eventhdlrptr, const char *name, const char *desc, SCIP_DECL_EVENTEXEC((*eventexec)), SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_EVENTHDLRDATA * SCIPeventhdlrGetData(SCIP_EVENTHDLR *eventhdlr)
void SCIPeventhdlrSetData(SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTHDLRDATA *eventhdlrdata)
SCIP_RETCODE SCIPsetEventhdlrFree(SCIP *scip, SCIP_EVENTHDLR *eventhdlr, SCIP_DECL_EVENTFREE((*eventfree)))
SCIP_RETCODE SCIPcatchVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
SCIP_RETCODE SCIPdropVarEvent(SCIP *scip, SCIP_VAR *var, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
SCIP_VAR * SCIPeventGetVar(SCIP_EVENT *event)
int SCIPgetNLPRows(SCIP *scip)
#define SCIPfreeBlockMemoryArray(scip, ptr, num)
#define SCIPallocBlockMemoryArray(scip, ptr, num)
#define SCIPreallocBlockMemoryArray(scip, ptr, oldnum, newnum)
#define SCIPfreeBlockMemory(scip, ptr)
#define SCIPallocBlockMemory(scip, ptr)
int SCIPgetNActivePricers(SCIP *scip)
SCIP_Bool SCIPinProbing(SCIP *scip)
SCIP_Real SCIProwGetLhs(SCIP_ROW *row)
int SCIProwGetNNonz(SCIP_ROW *row)
SCIP_COL ** SCIProwGetCols(SCIP_ROW *row)
SCIP_Real SCIProwGetRhs(SCIP_ROW *row)
SCIP_RETCODE SCIPprintRow(SCIP *scip, SCIP_ROW *row, FILE *file)
const char * SCIProwGetName(SCIP_ROW *row)
int SCIProwGetIndex(SCIP_ROW *row)
SCIP_Real SCIPgetRowLPFeasibility(SCIP *scip, SCIP_ROW *row)
SCIP_Real SCIProwGetConstant(SCIP_ROW *row)
SCIP_Real * SCIProwGetVals(SCIP_ROW *row)
SCIP_Bool SCIPisSumPositive(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasGE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasEQ(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPfeasCeil(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasZero(SCIP *scip, SCIP_Real val)
SCIP_Real SCIPfeasFloor(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisInfinity(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisFeasIntegral(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisGT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Bool SCIPisNegative(SCIP *scip, SCIP_Real val)
SCIP_Bool SCIPisLT(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
int SCIPvarGetProbindex(SCIP_VAR *var)
const char * SCIPvarGetName(SCIP_VAR *var)
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
SCIP_Real SCIPerf(SCIP_Real x)
public methods for branching rules
public methods for managing events
public methods for LP management
public methods for message output
public data structures and miscellaneous methods
public methods for problem variables
public methods for branching rule plugins and branching
public methods for event handler plugins and event handlers
public methods for the LP relaxation, rows and columns
public methods for memory management
public methods for message handling
public methods for numerical tolerances
public methods for SCIP parameter handling
public methods for variable pricer plugins
public methods for global and local (sub)problems
public methods for the probing mode
struct SCIP_BranchruleData SCIP_BRANCHRULEDATA
struct SCIP_EventhdlrData SCIP_EVENTHDLRDATA
@ SCIP_BRANCHDIR_DOWNWARDS
enum SCIP_BranchDir SCIP_BRANCHDIR
enum SCIP_Retcode SCIP_RETCODE
@ SCIP_VARTYPE_CONTINUOUS
enum SCIP_Vartype SCIP_VARTYPE
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4