// select min weight edge Graph SccGraph(const Graph &g) { vector<vector<int> > scc = Scc(g); const int n = g.size(); const int m = scc.size(); vector<int> mapto(n); for (int i = 0; i < (int)scc.size(); i++) { for (int j = 0; j < (int)scc[i].size(); j++) { mapto[scc[i][j]] = i; } } Graph ret(m); vector<int> indexs(m, -1); for (int from = 0; from < m; from++) { int e = 0; for (int i = 0; i < (int)scc[from].size(); i++) { for (Edges::const_iterator it = g[scc[from][i]].begin(); it != g[scc[from][i]].end(); it++) { int to = mapto[it->dest]; if (from == to) { continue; } // loopback if (indexs[to] == -1) { ret[from].push_back(Edge(from, to, it->weight)); indexs[to] = e++; } else { // select edge ret[from][indexs[to]].weight = min(ret[from][indexs[to]].weight, it->weight); } } } for (Edges::const_iterator it = ret[from].begin(); it != ret[from].end(); it++) { indexs[it->dest] = -1; } } return ret; }
bool processArgs(int argc, char** argv, const std::string&) { std::vector<std::string> args = mapto(argc, argv); if(argc < 3 || args[1] != "-c") { Log::log() << "Not a command: " << argc << args[1] << std::endl; return false; } std::vector<std::string> cmd = unescapeCmd(args[2]); if(cmd[0] != kScpCommand && cmd[0] != kSftpCommand) { Log::log() << "Not an ssh command: " << args[2] << std::endl; return false; } const char** newargv = tocarray(cmd); Log::log() << "Switching to " << cmd[0] << " with arguments " << cmd << std::endl; execvp(cmd[0].c_str(), const_cast<char**>(newargv)); // Should not be reached. return true; }
int TMOGUIToneSlider::UpdateValues(bool bGamma) { if (pValues) { switch (iMode) { case 0: pValues->dRMinimum = pValues->dGMinimum = pValues->dBMinimum = mapto((double)iBlack / (s.width() - 1)); pValues->dRMaximum = pValues->dGMaximum = pValues->dBMaximum = mapto((double)iWhite / (s.width() - 1)); if (bGamma) { pValues->dRGamma = pValues->dGGamma = pValues->dBGamma = (double)(iGamma - iBlack) / (iWhite - iBlack); if ((pValues->dRGamma > .49) && (pValues->dRGamma < .51)) pValues->dRGamma = pValues->dGGamma = pValues->dBGamma = .5; pValues->dRGamma = pValues->dGGamma = pValues->dBGamma = log(0.5) / log(pValues->dRGamma); } break; case 1: pValues->dRMinimum = mapto((double)iBlack / (s.width() - 1)); pValues->dRMaximum = mapto((double)iWhite / (s.width() - 1)); if (bGamma) { pValues->dRGamma = (double)(iGamma - iBlack) / (iWhite - iBlack); if ((pValues->dRGamma > .49) && (pValues->dRGamma < .51)) pValues->dRGamma = .5; pValues->dRGamma = log(0.5) / log(pValues->dRGamma); } break; case 2: pValues->dGMinimum = mapto((double)iBlack / (s.width() - 1)); pValues->dGMaximum = mapto((double)iWhite / (s.width() - 1)); if (bGamma) { pValues->dGGamma = (double)(iGamma - iBlack) / (iWhite - iBlack); if ((pValues->dGGamma > .49) && (pValues->dGGamma < .51)) pValues->dGGamma = .5; pValues->dGGamma = log(0.5) / log(pValues->dGGamma); } break; case 3: pValues->dBMinimum = mapto((double)iBlack / (s.width() - 1)); pValues->dBMaximum = mapto((double)iWhite / (s.width() - 1)); if (bGamma) { pValues->dBGamma = (double)(iGamma - iBlack) / (iWhite - iBlack); if ((pValues->dBGamma > .49) && (pValues->dBGamma < .51)) pValues->dBGamma = .5; pValues->dBGamma = log(0.5) / log(pValues->dBGamma); } break; } } update(); pValues->UpdateValues(); return 0; }
void FlowBasedGlobalConstraint::augmentStructure(Graph &graph, StoreCost &cost, int varindex, map<Value, Cost> &delta) { for (map<Value, Cost>::iterator i = delta.begin(); i != delta.end();i++) { pair<int,int> edge = mapto(varindex, i->first); if (!graph.increaseCost(edge.first, edge.second, -i->second)) { graph.increaseCost(edge.second, edge.first, i->second); cost -= i->second; } } }
trieNode childRevTrie (revtrie T, trieNode i, uint depth, byte c, trieNode *lzl, trieNode *lzr) { trieNode j; trieNode jlz; uint d,pos,jid; byte tc; #ifdef QUERYREPORT BCALLS++; #endif j = i+1; #ifdef QUERYREPORT DEPTH1 += depth; #endif while (!bitget1(T->data,j)) // there is a child here { pos = leftrankRevTrie(T,j); jid = rthRevTrie(T,pos); // leftmost id in subtree jlz = mapto(T->map,jid); for (d=depth;d;d--) jlz = parentLZTrie(T->trie,jlz); #ifdef QUERYREPORT RJUMPS++; DEPTH += depth; #endif tc = letterLZTrie(T->trie,jlz); if (tc > c) break; if (tc == c) { *lzl = jlz; if ((pos < T->n-1) && (rthRevTrie(T,pos+1) == jid)) // empty { pos = rightrankRevTrie(T,j); jlz = mapto(T->map,rthRevTrie(T,pos)); // rightmost for (d=depth;d;d--) jlz = parentLZTrie(T->trie,jlz); *lzr = jlz; } else *lzr = NULLT; return j; } j = findclose(T->pdata,j)+1; } *lzl = *lzr = NULLT; return NULLT; // no child to go down by c }
void TMOGUIToneSlider::paintEvent ( QPaintEvent * pe) { QPainter p(pBackBuffer); int col; // double val; p.setClipRect(pe->rect()); for (int i = 0; i < s.width(); i++) { /*val = 256.0 * exp(5 * ((double)i / s.width() - 1)); if (bLog) col = (int)val; else col = i * 256 / s.width(); */ col = 256 * mapto((double)i / (s.width() - 1)); if (col > 255) col = 255; switch(iMode) { case 1: p.setPen(QColor(col, 0, 0)); break; case 2: p.setPen(QColor(0, col, 0)); break; case 3: p.setPen(QColor(0, 0, col)); break; default: p.setPen(QColor(col, col, col)); break; } p.drawLine(i,0,i,9); } p.fillRect(0,10,s.width(),10,QBrush(QColor(255,255,255))); DrawMarker(&p, iBlack, QColor(0,0,0)); DrawMarker(&p, iGamma, QColor(128,128,128)); DrawMarker(&p, iWhite, QColor(255,255,255)); p.drawLine(iBlack, 9, iBlack, 7); p.drawLine(iWhite, 9, iWhite, 7); p.fillRect(iBlack + 1, 3, iWhite - iBlack, 4, QBrush(QColor(255,255,255))); p.drawRect(iBlack, 2, iWhite - iBlack + 1, 5); bitBlt(this, 0, 0, pBackBuffer, 0, 0, s.width(), s. height(), CopyROP); }
void FlowBasedGlobalConstraint::findProjection(Graph &graph, StoreCost &cost, int varindex, map<Value, Cost> &delta) { //if (ToulBar2::GCLevel == LC_NC) return; pair<Cost, bool> result; delta.clear(); EnumeratedVariable* x = (EnumeratedVariable*)getVar(varindex); for (EnumeratedVariable::iterator j = x->begin(); j != x->end(); ++j) { pair<int,int> edge = mapto(varindex, *j); Cost tmp = cost; //vector<Cost> weight = graph.getWeight(edge.first, edge.second); //if (!weight.empty()) { if (graph.edgeExist(edge.first, edge.second)) { if (zeroEdges[edge.first][edge.second]) { //cout << "good\n"; tmp = cost; } else { vector<pair<int, int> > edges; result = graph.augment(edge.second, edge.first, false, edges); /*if (!result.second) { printf("error! no shortest path\n"); exit(0); }*/ //tmp = cost+result.first+weight[0]; tmp = cost+result.first + graph.getMinWeight(edge.first, edge.second); zeroEdges[edge.first][edge.second] = true; for (vector<pair<int,int> >::iterator i = edges.begin();i != edges.end();i++) { zeroEdges[i->first][i->second] = true; } } } assert(tmp >= 0); delta[*j] = tmp; } }
inline uint Rev(lzindex I, uint rpos) { return mapto(I.Rev,rpos); }
inline uint RNODE(lzindex I, uint id) { return mapto(I.rmap,id); }
void FlowBasedGlobalConstraint::checkRemoved(Graph &graph, StoreCost &cost, vector<int> &rmv) { //if (ToulBar2::GCLevel == LC_NC) return; pair<Cost, bool> result; vector<int> cDomain, cDomain2; bool deleted = false; for (int i=0;i<arity_;i++) { cDomain.clear(); getDomainFromGraph(graph, i, cDomain); sort(cDomain.begin(), cDomain.end()); EnumeratedVariable* y = (EnumeratedVariable*)getVar(i); for (EnumeratedVariable::iterator v = y->begin(); v != y->end();++v) { vector<int>::iterator it = find(cDomain.begin(), cDomain.end(), *v); if (it == cDomain.end()) { cout << "non exist a value ?" << endl; for (vector<int>::iterator v=cDomain.begin();v != cDomain.end();v++) { cout << *v << " "; } cout << endl; for (EnumeratedVariable::iterator v = y->begin(); v != y->end();++v) { cout << *v << " "; } cout << endl; graph.print(); exit(0); } cDomain.erase(it); deleted = true; } if (!cDomain.empty()) { //bool flag = false; cDomain2.clear(); rmv.push_back(i); for (vector<int>::iterator v=cDomain.begin();v != cDomain.end();v++) { pair<int, int> edge = mapto(i, *v); if (!graph.removeEdge(edge.first, edge.second)) { cDomain2.push_back(*v); } } for (vector<int>::iterator v=cDomain2.begin();v != cDomain2.end();v++) { pair<int, int> edge = mapto(i, *v); vector<Cost> weight = graph.getWeight(edge.second, edge.first); if (weight.size() == 0) { cout << "error for non-existence of egde (" << edge.second << "," << edge.first << ")\n"; graph.print(); exit(0); } result = graph.augment(edge.first, edge.second, true); if (result.second) { //flag = true; cost += weight[0]+result.first; result.second = graph.removeEdge(edge.first, edge.second); } if (!result.second) { cout << "ERROR cannot delete egde (" << edge.second << "," << edge.first << ")\n"; graph.print(); exit(0); } } if (cost > 0) graph.removeNegativeCycles(cost); deleted = true; } } if (deleted) { for (int i=0;i<graph.size() && (zeroEdges != NULL);i++) { for (int j=0;j<graph.size();j++) { zeroEdges[i][j] = false; } } } }
uint rthRevTrie(revtrie T, uint pos) { return rthLZTrie(T->trie, leftrankLZTrie(T->trie,mapto(T->Rev,getposRevTrie(T,pos)))); }
/* Philippose Rajan - 11 June 2009 Added an initial experimental function for generating prismatic boundary layers on a given set of surfaces. The number of layers, height of the first layer and the growth / shrink factor can be specified by the user Currently, the layer height is calculated using: height = h_first_layer * (growth_factor^(num_layers - 1)) */ void GenerateBoundaryLayer (Mesh & mesh, MeshingParameters & mp) { int i, j; ofstream dbg("BndLayerDebug.log"); // Angle between a surface element and a growth-vector below which // a prism is project onto that surface as a quad // (in degrees) double angleThreshold = 5.0; cout << "Generate Prismatic Boundary Layers (Experimental)...." << endl; // Use an array to support creation of boundary // layers for multiple surfaces in the future... Array<int> surfid; int surfinp = 0; int prismlayers = 1; double hfirst = 0.01; double growthfactor = 1.0; // Monitor and print out the number of prism and quad elements // added to the mesh int numprisms = 0; int numquads = 0; while(surfinp >= 0) { cout << "Enter Surface ID (-1 to end list): "; cin >> surfinp; if(surfinp >= 0) surfid.Append(surfinp); } cout << "Number of surfaces entered = " << surfid.Size() << endl; cout << "Selected surfaces are:" << endl; for(i = 1; i <= surfid.Size(); i++) { cout << "Surface " << i << ": " << surfid.Elem(i) << endl; } cout << endl << "Enter number of prism layers: "; cin >> prismlayers; if(prismlayers < 1) prismlayers = 1; cout << "Enter height of first layer: "; cin >> hfirst; if(hfirst <= 0.0) hfirst = 0.01; cout << "Enter layer growth / shrink factor: "; cin >> growthfactor; if(growthfactor <= 0.0) growthfactor = 0.5; cout << "Old NP: " << mesh.GetNP() << endl; cout << "Old NSE: " << mesh.GetNSE() << endl; for(int layer = prismlayers; layer >= 1; layer--) { cout << "Generating layer: " << layer << endl; const MeshTopology& meshtopo = mesh.GetTopology(); const_cast<MeshTopology &> (meshtopo).SetBuildEdges(true); const_cast<MeshTopology &> (meshtopo).SetBuildFaces(true); const_cast<MeshTopology &> (meshtopo).Update(); double layerht = hfirst; if(growthfactor == 1) { layerht = layer * hfirst; } else { layerht = hfirst*(pow(growthfactor,(layer+1)) - 1)/(growthfactor - 1); } cout << "Layer Height = " << layerht << endl; // Need to store the old number of points and // surface elements because there are new points and // surface elements being added during the process int np = mesh.GetNP(); int nse = mesh.GetNSE(); // Safety measure to ensure no issues with mesh // consistency int nseg = mesh.GetNSeg(); // Indicate which points need to be remapped BitArray bndnodes(np); // Map of the old points to the new points Array<int> mapto(np); // Growth vectors for the prismatic layer based on // the effective surface normal at a given point Array<Vec3d> growthvectors(np); // Bit array to identify all the points belonging // to the surface of interest bndnodes.Clear(); // Run through all the surface elements and mark the points // belonging to those where a boundary layer has to be created. // In addition, also calculate the effective surface normal // vectors at each of those points to determine the mesh motion // direction cout << "Marking points for remapping...." << endl; for (i = 1; i <= nse; i++) { int snr = mesh.SurfaceElement(i).GetIndex(); // cout << "snr = " << snr << endl; if (surfid.Contains(snr)) { Element2d & sel = mesh.SurfaceElement(i); int selNP = sel.GetNP(); for(j = 1; j <= selNP; j++) { // Set the bitarray to indicate that the // point is part of the required set bndnodes.Set(sel.PNum(j)); // Vec3d& surfacenormal = Vec3d(); ???? Vec3d surfacenormal; // Calculate the surface normal at the current point // with respect to the current surface element GetSurfaceNormal(mesh,sel,j,surfacenormal); // Add the surface normal to the already existent one // (This gives the effective normal direction at corners // and curved areas) growthvectors.Elem(sel.PNum(j)) = growthvectors.Elem(sel.PNum(j)) + surfacenormal; } } } // Add additional points into the mesh structure in order to // clone the surface elements. // Also invert the growth vectors so that they point inwards, // and normalize them cout << "Cloning points and calculating growth vectors...." << endl; for (i = 1; i <= np; i++) { if (bndnodes.Test(i)) { mapto.Elem(i) = mesh.AddPoint (mesh.Point (i)); growthvectors.Elem(i).Normalize(); growthvectors.Elem(i) *= -1.0; } else { mapto.Elem(i) = 0; growthvectors.Elem(i) = Vec3d(0,0,0); } } // Add quad surface elements at edges for surfaces which // dont have boundary layers // Bit array to keep track of segments already processed BitArray segsel(nseg); // Set them all to "1" to initially activate all segments segsel.Set(); cout << "Adding 2D Quad elements on required surfaces...." << endl; for (i = 1; i <= nseg; i++) { int seg_p1 = mesh.LineSegment(i)[0]; int seg_p2 = mesh.LineSegment(i)[1]; // Only go in if the segment is still active, and if both its // surface index is part of the "hit-list" if(segsel.Test(i) && surfid.Contains(mesh.LineSegment(i).si)) { // clear the bit to indicate that this segment has been processed segsel.Clear(i); // Find matching segment pair on other surface for(j = 1; j <= nseg; j++) { int segpair_p1 = mesh.LineSegment(j)[1]; int segpair_p2 = mesh.LineSegment(j)[0]; // Find the segment pair on the neighbouring surface element // Identified by: seg1[0] = seg_pair[1] and seg1[1] = seg_pair[0] if(segsel.Test(j) && ((segpair_p1 == seg_p1) && (segpair_p2 == seg_p2))) { // clear bit to indicate that processing of this segment is done segsel.Clear(j); // Only worry about those surfaces which are not in the // boundary layer list if(!surfid.Contains(mesh.LineSegment(j).si)) { int pnt_commelem = 0; int pnum_commelem = 0; Array<int> pnt1_elems; Array<int> pnt2_elems; meshtopo.GetVertexSurfaceElements(segpair_p1,pnt1_elems); meshtopo.GetVertexSurfaceElements(segpair_p2,pnt2_elems); for(int k = 1; k <= pnt1_elems.Size(); k++) { Element2d pnt1_sel = mesh.SurfaceElement(pnt1_elems.Elem(k)); for(int l = 1; l <= pnt2_elems.Size(); l++) { Element2d pnt2_sel = mesh.SurfaceElement(pnt2_elems.Elem(l)); if((pnt1_sel.GetIndex() == mesh.LineSegment(j).si) && (pnt2_sel.GetIndex() == mesh.LineSegment(j).si) && (pnt1_elems.Elem(k) == pnt2_elems.Elem(l))) { pnt_commelem = pnt1_elems.Elem(k); } } } for(int k = 1; k <= mesh.SurfaceElement(pnt_commelem).GetNP(); k++) { if((mesh.SurfaceElement(pnt_commelem).PNum(k) != segpair_p1) && (mesh.SurfaceElement(pnt_commelem).PNum(k) != segpair_p2)) { pnum_commelem = mesh.SurfaceElement(pnt_commelem).PNum(k); } } Vec3d surfelem_vect, surfelem_vect1; Element2d & commsel = mesh.SurfaceElement(pnt_commelem); dbg << "NP= " << commsel.GetNP() << " : "; for(int k = 1; k <= commsel.GetNP(); k++) { GetSurfaceNormal(mesh,commsel,k,surfelem_vect1); surfelem_vect += surfelem_vect1; } surfelem_vect.Normalize(); double surfangle = Angle(growthvectors.Elem(segpair_p1),surfelem_vect); dbg << "V1= " << surfelem_vect1 << " : V2= " << surfelem_vect1 << " : V= " << surfelem_vect << " : GV= " << growthvectors.Elem(segpair_p1) << " : Angle= " << surfangle * 180 / 3.141592; // remap the segments to the new points mesh.LineSegment(i)[0] = mapto.Get(seg_p1); mesh.LineSegment(i)[1] = mapto.Get(seg_p2); mesh.LineSegment(j)[1] = mapto.Get(seg_p1); mesh.LineSegment(j)[0] = mapto.Get(seg_p2); if((surfangle < (90 + angleThreshold) * 3.141592 / 180.0) && (surfangle > (90 - angleThreshold) * 3.141592 / 180.0)) { dbg << " : quad\n"; // Since the surface is lower than the threshold, change the effective // prism growth vector to match with the surface vector, so that // the Quad which is created lies on the original surface //growthvectors.Elem(segpair_p1) = surfelem_vect; // Add a quad element to account for the prism volume // element which is going to be added Element2d sel(QUAD); sel.PNum(4) = mapto.Get(seg_p1); sel.PNum(3) = mapto.Get(seg_p2); sel.PNum(2) = segpair_p2; sel.PNum(1) = segpair_p1; sel.SetIndex(mesh.LineSegment(j).si); mesh.AddSurfaceElement(sel); numquads++; } else { dbg << "\n"; for (int k = 1; k <= pnt1_elems.Size(); k++) { Element2d & pnt_sel = mesh.SurfaceElement(pnt1_elems.Elem(k)); if(pnt_sel.GetIndex() == mesh.LineSegment(j).si) { for(int l = 1; l <= pnt_sel.GetNP(); l++) { if(pnt_sel.PNum(l) == segpair_p1) { pnt_sel.PNum(l) = mapto.Get(seg_p1); } else if(pnt_sel.PNum(l) == segpair_p2) { pnt_sel.PNum(l) = mapto.Get(seg_p2); } } } } for (int k = 1; k <= pnt2_elems.Size(); k++) { Element2d & pnt_sel = mesh.SurfaceElement(pnt2_elems.Elem(k)); if(pnt_sel.GetIndex() == mesh.LineSegment(j).si) { for(int l = 1; l <= pnt_sel.GetNP(); l++) { if(pnt_sel.PNum(l) == segpair_p1) { pnt_sel.PNum(l) = mapto.Get(seg_p1); } else if(pnt_sel.PNum(l) == segpair_p2) { pnt_sel.PNum(l) = mapto.Get(seg_p2); } } } } } } else { // If the code comes here, it indicates that we are at // a line segment pair which is at the intersection // of two surfaces, both of which have to grow boundary // layers.... here too, remapping the segments to the // new points is required mesh.LineSegment(i)[0] = mapto.Get(seg_p1); mesh.LineSegment(i)[1] = mapto.Get(seg_p2); mesh.LineSegment(j)[1] = mapto.Get(seg_p1); mesh.LineSegment(j)[0] = mapto.Get(seg_p2); } } } } } // Add prismatic cells at the boundaries cout << "Generating prism boundary layer volume elements...." << endl; for (i = 1; i <= nse; i++) { Element2d & sel = mesh.SurfaceElement(i); if(surfid.Contains(sel.GetIndex())) { Element el(PRISM); for (j = 1; j <= sel.GetNP(); j++) { // Check (Doublecheck) if the corresponding point has a // copy available for remapping if (mapto.Get(sel.PNum(j))) { // Define the points of the newly added Prism cell el.PNum(j+3) = mapto.Get(sel.PNum(j)); el.PNum(j) = sel.PNum(j); } } el.SetIndex(1); el.Invert(); mesh.AddVolumeElement(el); numprisms++; } } // Finally switch the point indices of the surface elements // to the newly added ones cout << "Transferring boundary layer surface elements to new vertex references...." << endl; for (i = 1; i <= nse; i++) { Element2d & sel = mesh.SurfaceElement(i); if(surfid.Contains(sel.GetIndex())) { for (j = 1; j <= sel.GetNP(); j++) { // Check (Doublecheck) if the corresponding point has a // copy available for remapping if (mapto.Get(sel.PNum(j))) { // Map the surface elements to the new points sel.PNum(j) = mapto.Get(sel.PNum(j)); } } } } // Lock all the prism points so that the rest of the mesh can be // optimised without invalidating the entire mesh for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) { if(bndnodes.Test(i)) mesh.AddLockedPoint(pi); } // Now, actually pull back the old surface points to create // the actual boundary layers cout << "Moving and optimising boundary layer points...." << endl; for (i = 1; i <= np; i++) { Array<ElementIndex> vertelems; if(bndnodes.Test(i)) { MeshPoint pointtomove; pointtomove = mesh.Point(i); if(layer == prismlayers) { mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i)); meshtopo.GetVertexElements(i,vertelems); for(j = 1; j <= vertelems.Size(); j++) { // double sfact = 0.9; Element volel = mesh.VolumeElement(vertelems.Elem(j)); if(((volel.GetType() == TET) || (volel.GetType() == TET10)) && (!volel.IsDeleted())) { //while((volel.Volume(mesh.Points()) <= 0.0) && (sfact >= 0.0)) //{ // mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i))); // mesh.ImproveMesh(); // // Try to move the point back by one step but // // if the volume drops to below zero, double back // mesh.Point(i).SetPoint(pointtomove + ((sfact + 0.1) * layerht * growthvectors.Elem(i))); // if(volel.Volume(mesh.Points()) <= 0.0) // { // mesh.Point(i).SetPoint(pointtomove + (sfact * layerht * growthvectors.Elem(i))); // } // sfact -= 0.1; //} volel.Delete(); } } mesh.Compress(); } else { mesh.Point(i).SetPoint(pointtomove + layerht * growthvectors.Elem(i)); } } } } // Optimise the tet part of the volume mesh after all the modifications // to the system are completed //OptimizeVolume(mparam,mesh); cout << "New NP: " << mesh.GetNP() << endl; cout << "Num of Quads: " << numquads << endl; cout << "Num of Prisms: " << numprisms << endl; cout << "Boundary Layer Generation....Done!" << endl; dbg.close(); }