Merge branch 'master' into netgen-1.5
This commit is contained in:
commit
99e35d8b11
110
base/netcmp.c
110
base/netcmp.c
|
|
@ -158,6 +158,9 @@ int right_col_end = 87;
|
||||||
/* if TRUE, always partition ALL classes */
|
/* if TRUE, always partition ALL classes */
|
||||||
int ExhaustiveSubdivision = 0;
|
int ExhaustiveSubdivision = 0;
|
||||||
|
|
||||||
|
/* if TRUE, use fast symmetry breaking to resolve automorphisms */
|
||||||
|
int FastSymmetryBreaking = 1;
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
static void PrintElement_List(struct Element *E)
|
static void PrintElement_List(struct Element *E)
|
||||||
{
|
{
|
||||||
|
|
@ -5862,7 +5865,81 @@ int ResolveAutomorphsByProperty()
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResolveElementAutomorphisms --
|
* ResolveAutormorphismsFull --
|
||||||
|
*
|
||||||
|
* Arbitrarily equivalence one pair of elements within an automorphic class
|
||||||
|
*
|
||||||
|
* Return value is the same as VerifyMatching()
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ResolveAutomorphismsFull()
|
||||||
|
{
|
||||||
|
struct ElementClass *EC;
|
||||||
|
struct Element *E;
|
||||||
|
struct NodeClass *NC;
|
||||||
|
struct Node *N;
|
||||||
|
int C1, C2;
|
||||||
|
|
||||||
|
for (EC = ElementClasses; EC != NULL; EC = EC->next) {
|
||||||
|
struct Element *E1, *E2;
|
||||||
|
C1 = C2 = 0;
|
||||||
|
E1 = E2 = NULL;
|
||||||
|
for (E = EC->elements; E != NULL; E = E->next) {
|
||||||
|
if (E->graph == Circuit1->file) {
|
||||||
|
C1++;
|
||||||
|
E1 = E;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
C2++;
|
||||||
|
E2 = E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (C1 == C2 && C1 != 1) {
|
||||||
|
unsigned long newhash;
|
||||||
|
Magic(newhash);
|
||||||
|
E1->hashval = newhash;
|
||||||
|
E2->hashval = newhash;
|
||||||
|
goto converge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (NC = NodeClasses; NC != NULL; NC = NC->next) {
|
||||||
|
struct Node *N1, *N2;
|
||||||
|
C1 = C2 = 0;
|
||||||
|
N1 = N2 = NULL;
|
||||||
|
for (N = NC->nodes; N != NULL; N = N->next) {
|
||||||
|
if (N->graph == Circuit1->file) {
|
||||||
|
C1++;
|
||||||
|
N1 = N;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
C2++;
|
||||||
|
N2 = N;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (C1 == C2 && C1 != 1) {
|
||||||
|
unsigned long newhash;
|
||||||
|
Magic(newhash);
|
||||||
|
N1->hashval = newhash;
|
||||||
|
N2->hashval = newhash;
|
||||||
|
goto converge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
converge:
|
||||||
|
FractureElementClass(&ElementClasses);
|
||||||
|
FractureNodeClass(&NodeClasses);
|
||||||
|
ExhaustiveSubdivision = 1;
|
||||||
|
while (!Iterate() && VerifyMatching() != -1);
|
||||||
|
return(VerifyMatching());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* ResolveElementAutomorphismsFast --
|
||||||
*
|
*
|
||||||
* Apply arbitrary symmetry breaking to symmetric element lists, then
|
* Apply arbitrary symmetry breaking to symmetric element lists, then
|
||||||
* iterate exhaustively to resolve all automorphisms.
|
* iterate exhaustively to resolve all automorphisms.
|
||||||
|
|
@ -5872,7 +5949,7 @@ int ResolveAutomorphsByProperty()
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ResolveElementAutomorphisms()
|
int ResolveElementAutomorphismsFast()
|
||||||
{
|
{
|
||||||
struct ElementClass *EC;
|
struct ElementClass *EC;
|
||||||
struct Element *E;
|
struct Element *E;
|
||||||
|
|
@ -5924,7 +6001,7 @@ int ResolveElementAutomorphisms()
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResolveNodeAutomorphisms --
|
* ResolveNodeAutomorphismsFast --
|
||||||
*
|
*
|
||||||
* Apply arbitrary symmetry breaking to symmetric node lists, then iterate
|
* Apply arbitrary symmetry breaking to symmetric node lists, then iterate
|
||||||
* exhaustively to resolve all automorphisms. Normally, all automorphisms
|
* exhaustively to resolve all automorphisms. Normally, all automorphisms
|
||||||
|
|
@ -5937,7 +6014,7 @@ int ResolveElementAutomorphisms()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ResolveNodeAutomorphisms()
|
int ResolveNodeAutomorphismsFast()
|
||||||
{
|
{
|
||||||
struct Node *N;
|
struct Node *N;
|
||||||
struct NodeClass *NC;
|
struct NodeClass *NC;
|
||||||
|
|
@ -5991,7 +6068,20 @@ int ResolveNodeAutomorphisms()
|
||||||
*
|
*
|
||||||
* ResolveAutormorphisms --
|
* ResolveAutormorphisms --
|
||||||
*
|
*
|
||||||
* Arbitrarily equivalence one pair of elements within an automorphic class
|
* Do symmetry breaking of automorphisms. If FastSymmetryBreaking is
|
||||||
|
* False (not the default), then run ResolveAutomorphismsFull() (q.v.).
|
||||||
|
* Otherwise, run the fast symmetry breaking method:
|
||||||
|
*
|
||||||
|
* Arbitrarily equivalence all pairs of elements and nodes within all
|
||||||
|
* automorphic classes, and run to completion. Note that this is a
|
||||||
|
* fast version of ResolveAutomorphismsFull(), and can run many orders
|
||||||
|
* of magnitude faster. However, it can also produce an incorrect
|
||||||
|
* result, declaring a global mismatch where none exists. In that
|
||||||
|
* case, the matching should be re-run with ResolveAutomorphismsFull().
|
||||||
|
*
|
||||||
|
* Some investigation needs to be done to determine if there is a way
|
||||||
|
* to execute faster symmetry breaking without the possibility of
|
||||||
|
* producing an incorrect result.
|
||||||
*
|
*
|
||||||
* Return value is the same as VerifyMatching()
|
* Return value is the same as VerifyMatching()
|
||||||
*
|
*
|
||||||
|
|
@ -6002,9 +6092,12 @@ int ResolveAutomorphisms()
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
result = ResolveElementAutomorphisms();
|
if (FastSymmetryBreaking == 0)
|
||||||
|
return ResolveAutomorphismsFull();
|
||||||
|
|
||||||
|
result = ResolveElementAutomorphismsFast();
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
result = ResolveNodeAutomorphisms();
|
result = ResolveNodeAutomorphismsFast();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -7454,7 +7547,8 @@ static void handler(int sig)
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
/* Note that this cover-all routine is not called from the Tcl/Tk */
|
/* Note that this cover-all routine is not called from the Tcl/Tk */
|
||||||
/* version, which replaces it with the script "lvs". */
|
/* version, which replaces it with the script "lvs". */
|
||||||
/* return 1 if the two are identical. Try to resolve automorphisms. */
|
/* return 1 if the two are identical. Try to resolve automorphisms */
|
||||||
|
/* using the original "full" symmetry breaking algorithm. */
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
|
||||||
int Compare(char *cell1, char *cell2)
|
int Compare(char *cell1, char *cell2)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ extern struct nlist *Circuit1;
|
||||||
extern struct nlist *Circuit2;
|
extern struct nlist *Circuit2;
|
||||||
|
|
||||||
extern int ExhaustiveSubdivision;
|
extern int ExhaustiveSubdivision;
|
||||||
|
extern int FastSymmetryBreaking;
|
||||||
|
|
||||||
extern int left_col_end;
|
extern int left_col_end;
|
||||||
extern int right_col_end;
|
extern int right_col_end;
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,9 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
|
||||||
} elseif {$arg == "-blackbox"} {
|
} elseif {$arg == "-blackbox"} {
|
||||||
puts stdout "Treating empty subcircuits as black-box cells"
|
puts stdout "Treating empty subcircuits as black-box cells"
|
||||||
netgen::model blackbox on
|
netgen::model blackbox on
|
||||||
|
} elseif {$arg == "-full"} {
|
||||||
|
puts stdout "Using full symmetry breaking method"
|
||||||
|
netgen::symmetry full
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ int _netcmp_ignore(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||||
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
int _netcmp_permute(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||||
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
int _netcmp_property(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||||
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
int _netcmp_exhaustive(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||||
|
int _netcmp_symmetry(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||||
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
int _netcmp_restart(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||||
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
int _netcmp_global(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||||
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
int _netcmp_convert(ClientData, Tcl_Interp *, int, Tcl_Obj *CONST objv[]);
|
||||||
|
|
@ -244,6 +245,9 @@ Command netcmp_cmds[] = {
|
||||||
{"exhaustive", _netcmp_exhaustive,
|
{"exhaustive", _netcmp_exhaustive,
|
||||||
"\n "
|
"\n "
|
||||||
"toggle exhaustive subdivision"},
|
"toggle exhaustive subdivision"},
|
||||||
|
{"symmetry", _netcmp_symmetry,
|
||||||
|
"[fast|full]\n "
|
||||||
|
"apply method for symmetry breaking"},
|
||||||
{"restart", _netcmp_restart,
|
{"restart", _netcmp_restart,
|
||||||
"\n "
|
"\n "
|
||||||
"start over (reset data structures)"},
|
"start over (reset data structures)"},
|
||||||
|
|
@ -3972,6 +3976,48 @@ _netcmp_permute(ClientData clientData,
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------*/
|
||||||
|
/* Function name: _netcmp_symmetry */
|
||||||
|
/* Syntax: netgen::symmetry [fast|full] */
|
||||||
|
/* Formerly: x */
|
||||||
|
/* Results: */
|
||||||
|
/* Side Effects: */
|
||||||
|
/*------------------------------------------------------*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_netcmp_symmetry(ClientData clientData,
|
||||||
|
Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
|
||||||
|
{
|
||||||
|
char *fastfull[] = {
|
||||||
|
"fast", "full", NULL
|
||||||
|
};
|
||||||
|
enum OptionIdx {
|
||||||
|
FAST_IDX, FULL_IDX
|
||||||
|
};
|
||||||
|
int result, index;
|
||||||
|
|
||||||
|
if (objc == 1)
|
||||||
|
index = -1;
|
||||||
|
else {
|
||||||
|
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)fastfull,
|
||||||
|
"option", 0, &index) != TCL_OK)
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(index) {
|
||||||
|
case FAST_IDX:
|
||||||
|
FastSymmetryBreaking = TRUE;
|
||||||
|
break;
|
||||||
|
case FULL_IDX:
|
||||||
|
FastSymmetryBreaking = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Printf("Symmetry breaking method: %s.\n",
|
||||||
|
FastSymmetryBreaking ? "FAST" : "FULL");
|
||||||
|
|
||||||
|
return TCL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------*/
|
/*------------------------------------------------------*/
|
||||||
/* Function name: _netcmp_exhaustive */
|
/* Function name: _netcmp_exhaustive */
|
||||||
/* Syntax: netgen::exhaustive [on|off] */
|
/* Syntax: netgen::exhaustive [on|off] */
|
||||||
|
|
@ -3993,7 +4039,7 @@ _netcmp_exhaustive(ClientData clientData,
|
||||||
int result, index;
|
int result, index;
|
||||||
|
|
||||||
if (objc == 1)
|
if (objc == 1)
|
||||||
index = YES_IDX;
|
index = -1;
|
||||||
else {
|
else {
|
||||||
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
|
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)yesno,
|
||||||
"option", 0, &index) != TCL_OK)
|
"option", 0, &index) != TCL_OK)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue