public void search (BayesNet bayesNet, Instances instances) throws Exception {
		m_random = new Random(m_nSeed);
		
        // determine base scores
        double [] fBaseScores = new double [instances.numAttributes()];
		double fCurrentScore = 0;
        for (int iAttribute = 0; iAttribute < instances.numAttributes(); iAttribute++) {
            fBaseScores[iAttribute] = calcNodeScore(iAttribute);
			fCurrentScore += fBaseScores[iAttribute];
        }

		// keep track of best scoring network
		double fBestScore = fCurrentScore;
		BayesNet bestBayesNet = new BayesNet();
		bestBayesNet.m_Instances = instances;
		bestBayesNet.initStructure();
		copyParentSets(bestBayesNet, bayesNet);

        double fTemp = m_fTStart;
        for (int iRun = 0; iRun < m_nRuns; iRun++) {
            boolean bRunSucces = false;
            double fDeltaScore = 0.0;
            while (!bRunSucces) {
	            // pick two nodes at random
	            int iTailNode = Math.abs(m_random.nextInt()) % instances.numAttributes();
	            int iHeadNode = Math.abs(m_random.nextInt()) % instances.numAttributes();
	            while (iTailNode == iHeadNode) {
		            iHeadNode = Math.abs(m_random.nextInt()) % instances.numAttributes();
	            }
	            if (isArc(bayesNet, iHeadNode, iTailNode)) {
                    bRunSucces = true;
	                // either try a delete
                    bayesNet.getParentSet(iHeadNode).deleteParent(iTailNode, instances);
                    double fScore = calcNodeScore(iHeadNode);
                    fDeltaScore = fScore - fBaseScores[iHeadNode];
//System.out.println("Try delete " + iTailNode + "->" + iHeadNode + " dScore = " + fDeltaScore);                    
                    if (fTemp * Math.log((Math.abs(m_random.nextInt()) % 10000)/10000.0  + 1e-100) < fDeltaScore) {
//System.out.println("success!!!");                    
						fCurrentScore += fDeltaScore;
                        fBaseScores[iHeadNode] = fScore;
                    } else {
                        // roll back
                        bayesNet.getParentSet(iHeadNode).addParent(iTailNode, instances);
                    }
	            } else {
	                // try to add an arc
	                if (addArcMakesSense(bayesNet, instances, iHeadNode, iTailNode)) {
                        bRunSucces = true;
                        double fScore = calcScoreWithExtraParent(iHeadNode, iTailNode);
                        fDeltaScore = fScore - fBaseScores[iHeadNode];
//System.out.println("Try add " + iTailNode + "->" + iHeadNode + " dScore = " + fDeltaScore);                    
                        if (fTemp * Math.log((Math.abs(m_random.nextInt()) % 10000)/10000.0  + 1e-100) < fDeltaScore) {
//System.out.println("success!!!");                    
                            bayesNet.getParentSet(iHeadNode).addParent(iTailNode, instances);
                            fBaseScores[iHeadNode] = fScore;
							fCurrentScore += fDeltaScore;
                        }
	                }
	            }
            }
			if (fCurrentScore > fBestScore) {
				copyParentSets(bestBayesNet, bayesNet);				
			}
            fTemp = fTemp * m_fDelta;
        }

		copyParentSets(bayesNet, bestBayesNet);
    } // buildStructure