MK branch revs. 263 & 295: GUI reordering, GP bugfix. Plus minors (JEInterface.m, tex2html)
This commit is contained in:
		@@ -583,7 +583,7 @@ public class GenericObjectEditor implements PropertyEditor {
 | 
			
		||||
			}
 | 
			
		||||
			return true;
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			System.err.println("exception in setHideProperty: " + e.getMessage());
 | 
			
		||||
			System.err.println("exception in setHideProperty for " + cls.getName() + "/" + property + " : " + e.getMessage());
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -616,11 +616,30 @@ public class GenericObjectEditor implements PropertyEditor {
 | 
			
		||||
			System.err.println("Error: property " + property + " not found!");
 | 
			
		||||
			return false;
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			System.err.println("exception in setHideProperty: " + e.getMessage());
 | 
			
		||||
			System.err.println("exception in setHideProperty for " + cls.getName() + "/" + property + " : " + e.getMessage());
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Hide or unhide all properties of a given class. Added to avoid the problem with hidden
 | 
			
		||||
	 * properties of inherited classes hide the property for all classes within the same inheritance tree.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param cls
 | 
			
		||||
	 * @param hide
 | 
			
		||||
	 */
 | 
			
		||||
	public static void setHideAllProperties(Class<?> cls, boolean hide) {
 | 
			
		||||
		try {
 | 
			
		||||
			BeanInfo    bi      = Introspector.getBeanInfo(cls);
 | 
			
		||||
			PropertyDescriptor[] props = bi.getPropertyDescriptors();
 | 
			
		||||
			for (int i=0; i<props.length; i++) {
 | 
			
		||||
				props[i].setHidden(hide);
 | 
			
		||||
			}
 | 
			
		||||
		} catch (Exception e) {
 | 
			
		||||
			System.err.println("exception in setHideProperty for " + cls.getName() + "/all : " + e.getMessage());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Convenience-method. See setHideProperty.
 | 
			
		||||
	 * 
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,10 @@ import java.beans.PropertyChangeSupport;
 | 
			
		||||
import java.beans.PropertyDescriptor;
 | 
			
		||||
import java.beans.PropertyEditor;
 | 
			
		||||
import java.beans.PropertyVetoException;
 | 
			
		||||
import java.lang.reflect.Array;
 | 
			
		||||
import java.lang.reflect.InvocationTargetException;
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
 | 
			
		||||
import javax.swing.BorderFactory;
 | 
			
		||||
import javax.swing.JButton;
 | 
			
		||||
@@ -46,6 +48,7 @@ import javax.swing.SwingConstants;
 | 
			
		||||
 | 
			
		||||
import eva2.gui.GenericObjectEditor.GOEPanel;
 | 
			
		||||
import eva2.tools.EVAHELP;
 | 
			
		||||
import eva2.tools.Mathematics;
 | 
			
		||||
import eva2.tools.StringTools;
 | 
			
		||||
/*==========================================================================*
 | 
			
		||||
* CLASS DECLARATION
 | 
			
		||||
@@ -151,91 +154,35 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener
 | 
			
		||||
 | 
			
		||||
        int         rowHeight   = 12;
 | 
			
		||||
//        JScrollPane js          = null;
 | 
			
		||||
        JTextArea   jt          = new JTextArea();
 | 
			
		||||
//        JTextArea   jt          = new JTextArea();
 | 
			
		||||
//        m_HelpText              = null;
 | 
			
		||||
 | 
			
		||||
        // Look for a globalInfo method that returns a string
 | 
			
		||||
        // describing the target
 | 
			
		||||
        int methsFound = 0; // dont loop too long, so count until all found
 | 
			
		||||
        GenericObjectEditor.setHideAllProperties(m_Target.getClass(), false);
 | 
			
		||||
        for (int i = 0; i < m_Methods.length; i++) {
 | 
			
		||||
            String name = m_Methods[i].getDisplayName();
 | 
			
		||||
            Method meth = m_Methods[i].getMethod();
 | 
			
		||||
            if (name.equals("globalInfo")) {
 | 
			
		||||
            	if (TRACE) System.out.println("found globalInfo method for " + targ.getClass().toString());
 | 
			
		||||
	            if (meth.getReturnType().equals(String.class)) {
 | 
			
		||||
	                try {
 | 
			
		||||
	                    Object  args[]      = { };
 | 
			
		||||
	                    String  globalInfo  = (String)(meth.invoke(m_Target, args));
 | 
			
		||||
                        String  summary     = globalInfo;
 | 
			
		||||
//                        int     ci          = globalInfo.indexOf('.');
 | 
			
		||||
//                        if (ci != -1) {	
 | 
			
		||||
//                        	// this shortens the displayed text, using only the first "sentence".
 | 
			
		||||
//                        	// May cause problems, if the dot belongs to a number, for example,
 | 
			
		||||
//                        	// so I deactivated it (MK).
 | 
			
		||||
//                            summary = globalInfo.substring(0, ci + 1);
 | 
			
		||||
//                        }
 | 
			
		||||
	                    m_ClassName = targ.getClass().getName();
 | 
			
		||||
//                        m_HelpText  = new StringBuffer("NAME\n");
 | 
			
		||||
//                        m_HelpText.append(m_ClassName).append("\n\n");
 | 
			
		||||
//                        m_HelpText.append("SYNOPSIS\n").append(globalInfo).append("\n\n");
 | 
			
		||||
                        m_HelpBut   = new JButton("Help");
 | 
			
		||||
	                    m_HelpBut.setToolTipText("More information about " + m_ClassName);
 | 
			
		||||
	                    m_HelpBut.addActionListener(new ActionListener() {
 | 
			
		||||
                            public void actionPerformed(ActionEvent a) {
 | 
			
		||||
                                openHelpFrame();
 | 
			
		||||
                                //m_HelpBut.setEnabled(false);
 | 
			
		||||
                            }
 | 
			
		||||
                        });
 | 
			
		||||
 | 
			
		||||
	                    jt.setText(summary);
 | 
			
		||||
	                    jt.setFont(new Font("SansSerif", Font.PLAIN, rowHeight));
 | 
			
		||||
	                    jt.setEditable(false);
 | 
			
		||||
	                    jt.setLineWrap(true);
 | 
			
		||||
	                    jt.setWrapStyleWord(true);
 | 
			
		||||
                        jt.setBackground(getBackground());
 | 
			
		||||
                        jt.setSize(jt.getPreferredSize());
 | 
			
		||||
 | 
			
		||||
	                    JPanel jp = new JPanel();
 | 
			
		||||
	                    jp.setBorder(BorderFactory.createCompoundBorder(
 | 
			
		||||
			                BorderFactory.createTitledBorder("Info"),
 | 
			
		||||
			                BorderFactory.createEmptyBorder(0, 5, 5, 5)
 | 
			
		||||
		                ));
 | 
			
		||||
	                    jp.setLayout(new BorderLayout());
 | 
			
		||||
	                    jp.add(jt, BorderLayout.CENTER);
 | 
			
		||||
                        JPanel      p2  = new JPanel();
 | 
			
		||||
                        p2.setLayout(new BorderLayout());
 | 
			
		||||
                        
 | 
			
		||||
                        if (HtmlDemo.resourceExists(getHelpFileName())) {
 | 
			
		||||
                        	// this means that the expected URL really exists
 | 
			
		||||
                        	p2.add(m_HelpBut, BorderLayout.NORTH);
 | 
			
		||||
                        } else {
 | 
			
		||||
                        	if (TRACE) System.out.println("not adding help button because of missing " + getHelpFileName());
 | 
			
		||||
                        }
 | 
			
		||||
                        jp.add(p2, BorderLayout.EAST);
 | 
			
		||||
	                    GridBagConstraints gbConstraints = new GridBagConstraints();
 | 
			
		||||
	                    //gbConstraints.anchor = GridBagConstraints.EAST;
 | 
			
		||||
	                    gbConstraints.fill = GridBagConstraints.BOTH;
 | 
			
		||||
	                    //gbConstraints.gridy = 0;
 | 
			
		||||
                        //gbConstraints.gridx = 0;
 | 
			
		||||
	                    gbConstraints.gridwidth = 2;
 | 
			
		||||
	                    gbConstraints.insets = new Insets(0,5,0,5);
 | 
			
		||||
	                    gbLayout.setConstraints(jp, gbConstraints);
 | 
			
		||||
	                    add(jp);
 | 
			
		||||
	                    componentOffset = 1;
 | 
			
		||||
	                    methsFound++;
 | 
			
		||||
	                    if (methsFound == 2) break; // small speed-up
 | 
			
		||||
	                } catch (Exception ex) {
 | 
			
		||||
	                } // end try
 | 
			
		||||
	            } // end if (meth.getReturnType().equals(String.class)) {
 | 
			
		||||
            	JPanel jp = makeInfoPanel(meth, targ, rowHeight, gbLayout);
 | 
			
		||||
            	if (jp!=null) {
 | 
			
		||||
            		add(jp);
 | 
			
		||||
                    componentOffset = 1;
 | 
			
		||||
            	}
 | 
			
		||||
                methsFound++;
 | 
			
		||||
            } // end if (name.equals("globalInfo")) {
 | 
			
		||||
            else if (name.equals("hideHideable")) {
 | 
			
		||||
                Object  args[]      = { };
 | 
			
		||||
                try {
 | 
			
		||||
                	meth.invoke(m_Target, args);
 | 
			
		||||
                	methsFound++;
 | 
			
		||||
                    if (methsFound == 2) break; // small speed-up
 | 
			
		||||
                } catch(Exception ex) {}
 | 
			
		||||
            	methsFound++;
 | 
			
		||||
            } else if (name.equals("customPropertyOrder")) {
 | 
			
		||||
            	methsFound++;
 | 
			
		||||
            	reorderProperties(meth);
 | 
			
		||||
            }
 | 
			
		||||
            if (methsFound == 3) break; // small speed-up
 | 
			
		||||
        } // end for (int i = 0; i < m_Methods.length; i++) {
 | 
			
		||||
 | 
			
		||||
        // Now lets search for the individual properties, their
 | 
			
		||||
@@ -246,6 +193,7 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener
 | 
			
		||||
        m_ViewWrapper= new JComponent[m_Properties.length];
 | 
			
		||||
        m_Labels    = new JLabel[m_Properties.length];
 | 
			
		||||
        m_TipTexts  = new String[m_Properties.length];
 | 
			
		||||
 | 
			
		||||
//        boolean     firstTip = true;
 | 
			
		||||
        for (int i = 0; i < m_Properties.length; i++) {
 | 
			
		||||
            // For each property do this
 | 
			
		||||
@@ -385,6 +333,146 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener
 | 
			
		||||
        setVisible(true);
 | 
			
		||||
    }
 | 
			
		||||
   
 | 
			
		||||
    /**
 | 
			
		||||
     * Be sure to give a clone
 | 
			
		||||
     * @param oldProps
 | 
			
		||||
     * @param meth
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    private PropertyDescriptor[] reorderProperties(Method meth) {
 | 
			
		||||
    	PropertyDescriptor[] oldProps = m_Properties.clone();
 | 
			
		||||
        PropertyDescriptor[] newProps = new PropertyDescriptor[oldProps.length];
 | 
			
		||||
//        Mathematics.revertArray(oldProps, newProps);
 | 
			
		||||
       	Object[] args      = { };
 | 
			
		||||
       	Object retV=null;
 | 
			
		||||
        try {
 | 
			
		||||
        	retV = meth.invoke(m_Target, args);
 | 
			
		||||
        } catch(Exception ex) {}
 | 
			
		||||
        if (retV!=null) {
 | 
			
		||||
            try {
 | 
			
		||||
            	if (retV.getClass().isArray()) {
 | 
			
		||||
            		String[] swProps=(String[])retV;
 | 
			
		||||
            		//int findFirst=findFirstProp(props[0], oldProps);
 | 
			
		||||
            		int firstNonNull=0;
 | 
			
		||||
            		for (int i=0; i<oldProps.length; i++) {
 | 
			
		||||
            			if (i<swProps.length) {
 | 
			
		||||
            				int pInOld=findProp(oldProps, swProps[i]);
 | 
			
		||||
            				newProps[i]=oldProps[pInOld];
 | 
			
		||||
            				oldProps[pInOld]=null;
 | 
			
		||||
            			} else {
 | 
			
		||||
            				firstNonNull = findFirstNonNullAfter(oldProps, firstNonNull);
 | 
			
		||||
            				newProps[i]=oldProps[firstNonNull];
 | 
			
		||||
            				firstNonNull++;
 | 
			
		||||
            			}
 | 
			
		||||
            		}
 | 
			
		||||
            		m_Properties=newProps;
 | 
			
		||||
            	}
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
            	System.err.println("Error during reordering properties: " + e.getMessage());
 | 
			
		||||
            	return m_Properties;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
		return newProps;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Find the first non-null entry in an Array at or after the given index and return its index.
 | 
			
		||||
     * If only null entries are found, -1 is returned.
 | 
			
		||||
     * 
 | 
			
		||||
     * @param arr
 | 
			
		||||
     * @param firstLook
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    private int findFirstNonNullAfter(PropertyDescriptor[] arr,
 | 
			
		||||
			int firstLook) {
 | 
			
		||||
    	for (int i=firstLook; i<arr.length; i++) if (arr[i]!=null) return i;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
     * Find a string property in an array and return its index or -1 if not found.
 | 
			
		||||
     * 
 | 
			
		||||
     * @param oldProps
 | 
			
		||||
     * @param string
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
	private int findProp(PropertyDescriptor[] oldProps, String string) {
 | 
			
		||||
		for (int i=0; i<oldProps.length; i++) {
 | 
			
		||||
			if (oldProps[i]==null) continue;
 | 
			
		||||
			String  name    = oldProps[i].getDisplayName();
 | 
			
		||||
			if (name.compareTo(string)==0) return i;
 | 
			
		||||
		}
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private JPanel makeInfoPanel(Method meth, Object targ, int rowHeight, GridBagLayout gbLayout) {
 | 
			
		||||
    	if (TRACE) System.out.println("found globalInfo method for " + targ.getClass().toString());
 | 
			
		||||
        if (meth.getReturnType().equals(String.class)) {
 | 
			
		||||
            try {
 | 
			
		||||
                Object  args[]      = { };
 | 
			
		||||
                String  globalInfo  = (String)(meth.invoke(m_Target, args));
 | 
			
		||||
                String  summary     = globalInfo;
 | 
			
		||||
//                int     ci          = globalInfo.indexOf('.');
 | 
			
		||||
//                if (ci != -1) {	
 | 
			
		||||
//                	// this shortens the displayed text, using only the first "sentence".
 | 
			
		||||
//                	// May cause problems, if the dot belongs to a number, for example,
 | 
			
		||||
//                	// so I deactivated it (MK).
 | 
			
		||||
//                    summary = globalInfo.substring(0, ci + 1);
 | 
			
		||||
//                }
 | 
			
		||||
                m_ClassName = targ.getClass().getName();
 | 
			
		||||
//                m_HelpText  = new StringBuffer("NAME\n");
 | 
			
		||||
//                m_HelpText.append(m_ClassName).append("\n\n");
 | 
			
		||||
//                m_HelpText.append("SYNOPSIS\n").append(globalInfo).append("\n\n");
 | 
			
		||||
                m_HelpBut   = new JButton("Help");
 | 
			
		||||
                m_HelpBut.setToolTipText("More information about " + m_ClassName);
 | 
			
		||||
                m_HelpBut.addActionListener(new ActionListener() {
 | 
			
		||||
                    public void actionPerformed(ActionEvent a) {
 | 
			
		||||
                        openHelpFrame();
 | 
			
		||||
                        //m_HelpBut.setEnabled(false);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                JTextArea jt = new JTextArea();
 | 
			
		||||
                jt.setText(summary);
 | 
			
		||||
                jt.setFont(new Font("SansSerif", Font.PLAIN, rowHeight));
 | 
			
		||||
                jt.setEditable(false);
 | 
			
		||||
                jt.setLineWrap(true);
 | 
			
		||||
                jt.setWrapStyleWord(true);
 | 
			
		||||
                jt.setBackground(getBackground());
 | 
			
		||||
                jt.setSize(jt.getPreferredSize());
 | 
			
		||||
 | 
			
		||||
                JPanel jp = new JPanel();
 | 
			
		||||
                jp.setBorder(BorderFactory.createCompoundBorder(
 | 
			
		||||
	                BorderFactory.createTitledBorder("Info"),
 | 
			
		||||
	                BorderFactory.createEmptyBorder(0, 5, 5, 5)
 | 
			
		||||
                ));
 | 
			
		||||
                jp.setLayout(new BorderLayout());
 | 
			
		||||
                jp.add(jt, BorderLayout.CENTER);
 | 
			
		||||
                JPanel      p2  = new JPanel();
 | 
			
		||||
                p2.setLayout(new BorderLayout());
 | 
			
		||||
                
 | 
			
		||||
                if (HtmlDemo.resourceExists(getHelpFileName())) {
 | 
			
		||||
                	// this means that the expected URL really exists
 | 
			
		||||
                	p2.add(m_HelpBut, BorderLayout.NORTH);
 | 
			
		||||
                } else {
 | 
			
		||||
                	if (TRACE) System.out.println("not adding help button because of missing " + getHelpFileName());
 | 
			
		||||
                }
 | 
			
		||||
                jp.add(p2, BorderLayout.EAST);
 | 
			
		||||
                GridBagConstraints gbConstraints = new GridBagConstraints();
 | 
			
		||||
                //gbConstraints.anchor = GridBagConstraints.EAST;
 | 
			
		||||
                gbConstraints.fill = GridBagConstraints.BOTH;
 | 
			
		||||
                //gbConstraints.gridy = 0;
 | 
			
		||||
                //gbConstraints.gridx = 0;
 | 
			
		||||
                gbConstraints.gridwidth = 2;
 | 
			
		||||
                gbConstraints.insets = new Insets(0,5,0,5);
 | 
			
		||||
                gbLayout.setConstraints(jp, gbConstraints);
 | 
			
		||||
                return jp;
 | 
			
		||||
            } catch (Exception ex) {
 | 
			
		||||
            } // end try
 | 
			
		||||
        } // end if (meth.getReturnType().equals(String.class)) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private String translateGreek(String name) {
 | 
			
		||||
        // Add some specific display for some greeks here
 | 
			
		||||
        if (name.equalsIgnoreCase("alpha"))
 | 
			
		||||
@@ -700,7 +788,7 @@ public class PropertySheetPanel extends JPanel implements PropertyChangeListener
 | 
			
		||||
 | 
			
		||||
        if (followDependencies) {
 | 
			
		||||
        	// Handle the special method getGOEPropertyUpdateLinks which returns a list of pairs
 | 
			
		||||
        	// of strings indicating that on an update if the i-th property, the i+1-th property
 | 
			
		||||
        	// of strings indicating that on an update of the i-th property, the i+1-th property
 | 
			
		||||
        	// should be updated. This is useful for changes within sub-classes of the target
 | 
			
		||||
        	// which are not directly displayed in this panel but in sub-panels (and there have an own view etc.)
 | 
			
		||||
        	Object o = BeanInspector.callIfAvailable(m_Target, "getGOEPropertyUpdateLinks", null);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,8 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial
 | 
			
		||||
    protected AbstractGPNode        m_Parent;
 | 
			
		||||
    protected AbstractGPNode[]      m_Nodes = new AbstractGPNode[0];
 | 
			
		||||
    protected int                   m_Depth = 0;
 | 
			
		||||
 | 
			
		||||
    private static final boolean	TRACE=false; 
 | 
			
		||||
    
 | 
			
		||||
    /** This method allows you to clone the Nodes
 | 
			
		||||
     * @return the clone
 | 
			
		||||
     */
 | 
			
		||||
@@ -107,7 +108,7 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial
 | 
			
		||||
    		else if (matchSet.size()>1) System.err.println("String has ambiguous prefix: " + str + " -- " + BeanInspector.toString(matchSet));
 | 
			
		||||
    		else { // exactly one match:
 | 
			
		||||
    			AbstractGPNode currentNode = (AbstractGPNode)matchSet.get(0).clone();
 | 
			
		||||
//    			System.out.println("Found match: " + currentNode.getOpIdentifier() + "/" + currentNode.getArity());
 | 
			
		||||
    			if (TRACE) System.out.println("Found match: " + currentNode.getOpIdentifier() + "/" + currentNode.getArity());
 | 
			
		||||
    			int cutFront=currentNode.getOpIdentifier().length();
 | 
			
		||||
    			String restStr;
 | 
			
		||||
    			if (currentNode.getArity()==0) {
 | 
			
		||||
@@ -130,7 +131,7 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial
 | 
			
		||||
    					currentNode.m_Nodes[i]=nextState.head();
 | 
			
		||||
    					restStr=nextState.tail().substring(1).trim(); // cut comma or brace
 | 
			
		||||
    				}
 | 
			
		||||
//    				System.out.println("lacking rest: " + restStr);
 | 
			
		||||
    				if (TRACE) System.out.println("read " + currentNode.getName() + ", rest: " + restStr);
 | 
			
		||||
    				return new Pair<AbstractGPNode,String>(currentNode, restStr);
 | 
			
		||||
    			}
 | 
			
		||||
    		}
 | 
			
		||||
@@ -145,7 +146,8 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial
 | 
			
		||||
			int firstBrace = str.indexOf(')');
 | 
			
		||||
			if ((firstBrace >= 0) && (firstBrace<argLen)) argLen = firstBrace;
 | 
			
		||||
		}
 | 
			
		||||
		firstArg=str.substring(0,argLen);
 | 
			
		||||
		if (argLen>0) firstArg=str.substring(0,argLen);
 | 
			
		||||
		else firstArg=str.trim();
 | 
			
		||||
		try {
 | 
			
		||||
			Double d=Double.parseDouble(firstArg);
 | 
			
		||||
			return new Pair<Double,String>(d, str.substring(firstArg.length()));
 | 
			
		||||
@@ -183,8 +185,10 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial
 | 
			
		||||
			Vector<AbstractGPNode> nodeTypes, String str, boolean firstLongestOnly, boolean ignoreCase) {
 | 
			
		||||
    	Vector<AbstractGPNode> matching = new Vector<AbstractGPNode>();
 | 
			
		||||
		for (int i=0; i<nodeTypes.size(); i++) {
 | 
			
		||||
			if (str.startsWith(nodeTypes.get(i).getOpIdentifier())) matching.add(nodeTypes.get(i));
 | 
			
		||||
			else if (ignoreCase && str.toLowerCase().startsWith(nodeTypes.get(i).getOpIdentifier().toLowerCase())) matching.add(nodeTypes.get(i));
 | 
			
		||||
			String reqPrefix=nodeTypes.get(i).getOpIdentifier();
 | 
			
		||||
			if (nodeTypes.get(i).getArity()>0) reqPrefix+="(";
 | 
			
		||||
			if (str.startsWith(reqPrefix)) matching.add(nodeTypes.get(i));
 | 
			
		||||
			else if (ignoreCase && str.toLowerCase().startsWith(reqPrefix.toLowerCase())) matching.add(nodeTypes.get(i));
 | 
			
		||||
		}
 | 
			
		||||
		if (matching.size()>1 && firstLongestOnly) { // allow only the longest match (or first longest)
 | 
			
		||||
			int maxLen = matching.get(0).getOpIdentifier().length();
 | 
			
		||||
@@ -209,8 +213,13 @@ public abstract class AbstractGPNode implements InterfaceProgram, java.io.Serial
 | 
			
		||||
    
 | 
			
		||||
	public static void main(String[] args) {
 | 
			
		||||
//		Double d = Double.parseDouble("2.58923 + 3");
 | 
			
		||||
    	AbstractGPNode node = AbstractGPNode.parseFromString("+(x,cOs(*(pI,x1)))");
 | 
			
		||||
//    	System.out.println("Parsed GPNode: " + node.getStringRepresentation());
 | 
			
		||||
//    	AbstractGPNode node = AbstractGPNode.parseFromString("-23421");
 | 
			
		||||
    	AbstractGPNode node = AbstractGPNode.parseFromString("+(-23421,cOs(*(pI,x1)))");
 | 
			
		||||
		AbstractGPNode.parseFromString("+(+(85.334407,*(0.0056858,*(x1,x4))), +(*(0.00026,*(x0,x3)),*(-0.0022053,*(x2,x4))))");
 | 
			
		||||
		AbstractGPNode.parseFromString("+(+(80.51249,*(0.0071317,*(x1,x4))), +(*(0.0029955,*(x0,x1)),*(0.0021813,*(x2,x2))))");
 | 
			
		||||
		AbstractGPNode.parseFromString("+(+(9.300961,*(0.0047026,*(x2,x4))), +(*(0.0012547,*(x0,x2)),*(0.0019085,*(x2,x3))))");
 | 
			
		||||
 | 
			
		||||
    	System.out.println("Parsed GPNode: " + node.getStringRepresentation());
 | 
			
		||||
    	node = AbstractGPNode.parseFromString(node.getStringRepresentation());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -19,9 +19,9 @@ public class GPArea implements java.io.Serializable {
 | 
			
		||||
    /** Handles property change notification */
 | 
			
		||||
    private transient PropertyChangeSupport   m_Support = new PropertyChangeSupport(this);
 | 
			
		||||
    
 | 
			
		||||
    private ArrayList       m_CompleteList  = new ArrayList();
 | 
			
		||||
    private ArrayList       m_ReducedList   = new ArrayList();
 | 
			
		||||
    private ArrayList       m_BlackList     = new ArrayList();
 | 
			
		||||
    private ArrayList<AbstractGPNode>       m_CompleteList  = new ArrayList<AbstractGPNode>();
 | 
			
		||||
    private ArrayList<AbstractGPNode>       m_ReducedList   = new ArrayList<AbstractGPNode>();
 | 
			
		||||
    private ArrayList<Boolean>       m_BlackList     = new ArrayList<Boolean>();
 | 
			
		||||
 | 
			
		||||
    public GPArea() {
 | 
			
		||||
 | 
			
		||||
@@ -29,11 +29,11 @@ public class GPArea implements java.io.Serializable {
 | 
			
		||||
 | 
			
		||||
    public GPArea(GPArea g) {
 | 
			
		||||
        if (g.m_BlackList != null)
 | 
			
		||||
            this.m_BlackList    = (ArrayList)g.m_BlackList.clone();
 | 
			
		||||
            this.m_BlackList    = (ArrayList<Boolean>)g.m_BlackList.clone();
 | 
			
		||||
        if (g.m_ReducedList != null)
 | 
			
		||||
            this.m_ReducedList  = (ArrayList)g.m_ReducedList.clone();
 | 
			
		||||
            this.m_ReducedList  = (ArrayList<AbstractGPNode>)g.m_ReducedList.clone();
 | 
			
		||||
        if (g.m_CompleteList != null)
 | 
			
		||||
            this.m_CompleteList = (ArrayList)g.m_CompleteList.clone();
 | 
			
		||||
            this.m_CompleteList = (ArrayList<AbstractGPNode>)g.m_CompleteList.clone();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Object clone() {
 | 
			
		||||
@@ -60,13 +60,13 @@ public class GPArea implements java.io.Serializable {
 | 
			
		||||
    /** This method allows you to fetch the black list
 | 
			
		||||
     * @return blacklist
 | 
			
		||||
     */
 | 
			
		||||
    public ArrayList getBlackList() {
 | 
			
		||||
    public ArrayList<Boolean> getBlackList() {
 | 
			
		||||
        return this.m_BlackList;
 | 
			
		||||
    }
 | 
			
		||||
    /** This method allows you to set the black list
 | 
			
		||||
     * @param a blacklist
 | 
			
		||||
     */
 | 
			
		||||
    public void SetBlackList(ArrayList a) {
 | 
			
		||||
    public void SetBlackList(ArrayList<Boolean> a) {
 | 
			
		||||
        this.m_BlackList = a;
 | 
			
		||||
    }
 | 
			
		||||
    /** This method allows you to set a BlackList element
 | 
			
		||||
@@ -80,21 +80,21 @@ public class GPArea implements java.io.Serializable {
 | 
			
		||||
    /** This method allows you to fetch the CompleteList
 | 
			
		||||
     * @return blacklist
 | 
			
		||||
     */
 | 
			
		||||
    public ArrayList getCompleteList() {
 | 
			
		||||
    public ArrayList<AbstractGPNode> getCompleteList() {
 | 
			
		||||
        return this.m_CompleteList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** This method allows you to fetch the CompleteList
 | 
			
		||||
     * @return blacklist
 | 
			
		||||
     */
 | 
			
		||||
    public ArrayList getReducedList() {
 | 
			
		||||
    public ArrayList<AbstractGPNode> getReducedList() {
 | 
			
		||||
        return this.m_ReducedList;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** This method allows you to set the CompleteList
 | 
			
		||||
     * @param a blacklist
 | 
			
		||||
     */
 | 
			
		||||
    public void SetCompleteList(ArrayList a) {
 | 
			
		||||
    public void SetCompleteList(ArrayList<AbstractGPNode> a) {
 | 
			
		||||
        this.m_CompleteList = a;
 | 
			
		||||
	    m_Support.firePropertyChange("GPArea", null, this);
 | 
			
		||||
    }
 | 
			
		||||
@@ -102,7 +102,7 @@ public class GPArea implements java.io.Serializable {
 | 
			
		||||
    /** This method compiles the Complete List to the allowed list using the BlackList
 | 
			
		||||
     */
 | 
			
		||||
    public void compileReducedList() {
 | 
			
		||||
        this.m_ReducedList = new ArrayList();
 | 
			
		||||
        this.m_ReducedList = new ArrayList<AbstractGPNode>();
 | 
			
		||||
        for (int i = 0; i < this.m_CompleteList.size(); i++) {
 | 
			
		||||
            if (((Boolean)(this.m_BlackList.get(i))).booleanValue()) {
 | 
			
		||||
                this.m_ReducedList.add(this.m_CompleteList.get(i));
 | 
			
		||||
@@ -115,7 +115,7 @@ public class GPArea implements java.io.Serializable {
 | 
			
		||||
     * @param targetarity       The target arity.
 | 
			
		||||
     */
 | 
			
		||||
    public AbstractGPNode getRandomNodeWithArity(int targetarity) {
 | 
			
		||||
        ArrayList   tmpArray = new ArrayList();
 | 
			
		||||
        ArrayList<AbstractGPNode>   tmpArray = new ArrayList<AbstractGPNode>();
 | 
			
		||||
        for (int i = 0; i < this.m_ReducedList.size(); i++) {
 | 
			
		||||
            if (((AbstractGPNode)this.m_ReducedList.get(i)).getArity() == targetarity) tmpArray.add(this.m_ReducedList.get(i));
 | 
			
		||||
        }
 | 
			
		||||
@@ -133,7 +133,7 @@ public class GPArea implements java.io.Serializable {
 | 
			
		||||
    /** This method will return a non terminal
 | 
			
		||||
     */
 | 
			
		||||
    public AbstractGPNode getRandomNonTerminal() {
 | 
			
		||||
        ArrayList   tmpArray = new ArrayList();
 | 
			
		||||
        ArrayList<AbstractGPNode>   tmpArray = new ArrayList<AbstractGPNode>();
 | 
			
		||||
        for (int i = 0; i < this.m_ReducedList.size(); i++) {
 | 
			
		||||
            if (((AbstractGPNode)this.m_ReducedList.get(i)).getArity() > 0) tmpArray.add(this.m_ReducedList.get(i));
 | 
			
		||||
        }
 | 
			
		||||
@@ -146,19 +146,21 @@ public class GPArea implements java.io.Serializable {
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public void clear() {
 | 
			
		||||
	    m_CompleteList  = new ArrayList();
 | 
			
		||||
	    m_ReducedList   = new ArrayList();
 | 
			
		||||
	    m_BlackList     = new ArrayList();
 | 
			
		||||
	    m_CompleteList  = new ArrayList<AbstractGPNode>();
 | 
			
		||||
	    m_ReducedList   = new ArrayList<AbstractGPNode>();
 | 
			
		||||
	    m_BlackList     = new ArrayList<Boolean>();
 | 
			
		||||
	    m_Support.firePropertyChange("GPArea", null, this);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
    public void addPropertyChangeListener(PropertyChangeListener l) {
 | 
			
		||||
    	if (m_Support==null) m_Support = new PropertyChangeSupport(this);
 | 
			
		||||
        m_Support.addPropertyChangeListener(l);
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    public void removePropertyChangeListener(PropertyChangeListener l) {
 | 
			
		||||
    	if (m_Support==null) m_Support = new PropertyChangeSupport(this);
 | 
			
		||||
        m_Support.removePropertyChangeListener(l);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements
 | 
			
		||||
    private double[]                                m_C                     = new double[m_NumberOfConstants];
 | 
			
		||||
    private boolean                                 m_UseInnerConst         = false;
 | 
			
		||||
    private boolean                                 m_UseLocalHillClimbing  = false;
 | 
			
		||||
    transient private GPArea                        m_GPArea                = new GPArea();
 | 
			
		||||
    private GPArea                        			m_GPArea                = new GPArea();
 | 
			
		||||
    protected AbstractEAIndividual                  m_OverallBest           = null;
 | 
			
		||||
    protected double                                m_Noise                 = 0.0;
 | 
			
		||||
 | 
			
		||||
@@ -55,6 +55,7 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements
 | 
			
		||||
    public PSymbolicRegression() {
 | 
			
		||||
        this.m_Template     = new GPIndividualProgramData();
 | 
			
		||||
        this.initProblem();
 | 
			
		||||
        this.compileArea();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public PSymbolicRegression(PSymbolicRegression b) {
 | 
			
		||||
@@ -100,17 +101,16 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements
 | 
			
		||||
        this.m_OverallBest  = null;
 | 
			
		||||
        this.m_C            = new double[this.m_NumberOfConstants];
 | 
			
		||||
        for (int i = 0; i < this.m_C.length; i++) this.m_C[i] = RNG.randomDouble(-10, 10);
 | 
			
		||||
        this.compileArea();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * This method compiles the area
 | 
			
		||||
     * This method compiles the area. Only to be called once in the constructor
 | 
			
		||||
     * to build the basic function set or if the number of constants etc. change.
 | 
			
		||||
     */
 | 
			
		||||
    private void compileArea() {
 | 
			
		||||
    	// unfortunately this must be cloned or the GUI wont update.
 | 
			
		||||
//    	if (m_GPArea==null) 
 | 
			
		||||
    		m_GPArea = new GPArea();
 | 
			
		||||
//    	else m_GPArea = (GPArea)m_GPArea.clone();
 | 
			
		||||
    	GPArea oldArea=m_GPArea;
 | 
			
		||||
    	m_GPArea = new GPArea();
 | 
			
		||||
    	
 | 
			
		||||
    	if (m_GPArea.isEmpty()) {
 | 
			
		||||
	        this.m_GPArea.add2CompleteList(new GPNodeAdd());
 | 
			
		||||
@@ -126,6 +126,9 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements
 | 
			
		||||
	        for (int i = 0; i < this.m_X.length; i++) this.m_GPArea.add2CompleteList(new GPNodeInput("X"+i));
 | 
			
		||||
	        for (int i = 0; i < this.m_C.length; i++) this.m_GPArea.add2CompleteList(new GPNodeInput("C"+i));
 | 
			
		||||
    	}
 | 
			
		||||
    	if ((oldArea!=null) && (oldArea.getBlackList()!=null) && (oldArea.getBlackList().size()==m_GPArea.getBlackList().size())) {
 | 
			
		||||
    		m_GPArea.SetBlackList(oldArea.getBlackList());
 | 
			
		||||
    	}
 | 
			
		||||
        this.m_GPArea.compileReducedList();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -319,7 +322,7 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements
 | 
			
		||||
     * @return description
 | 
			
		||||
     */
 | 
			
		||||
    public String globalInfo() {
 | 
			
		||||
        return "The task is to infer the equation from a system that can only be observed";
 | 
			
		||||
        return "The task is to infer the equation of a system that can only be observed at a number of checkpoints.";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** This method allows you to choose how much noise is to be added to the
 | 
			
		||||
@@ -360,7 +363,7 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements
 | 
			
		||||
        return this.m_UseLocalHillClimbing;
 | 
			
		||||
    }
 | 
			
		||||
    public String useLocalHillClimbingTipText() {
 | 
			
		||||
        return "Toggel the use of local hill climbing for inner constants.";
 | 
			
		||||
        return "Toggle the use of local hill climbing for inner constants.";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** This method allows you to set the number of ephremial constants.
 | 
			
		||||
@@ -368,8 +371,9 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements
 | 
			
		||||
     */
 | 
			
		||||
    public void setNumberOfConstants(int b) {
 | 
			
		||||
        this.m_NumberOfConstants = b;
 | 
			
		||||
        m_GPArea.clear();
 | 
			
		||||
        this.initProblem();
 | 
			
		||||
        m_GPArea.clear();
 | 
			
		||||
        this.compileArea();
 | 
			
		||||
    }
 | 
			
		||||
    public int getNumberOfConstants() {
 | 
			
		||||
        return this.m_NumberOfConstants;
 | 
			
		||||
@@ -407,7 +411,7 @@ public class PSymbolicRegression extends AbstractOptimizationProblem implements
 | 
			
		||||
        return this.m_GPArea;
 | 
			
		||||
    }
 | 
			
		||||
    public String areaTipText() {
 | 
			
		||||
        return "Select elements from the available area.";
 | 
			
		||||
        return "Select function set from the available area.";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** This method allows you to toggle path visualisation on and off.
 | 
			
		||||
 
 | 
			
		||||
@@ -150,20 +150,11 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
 | 
			
		||||
     */
 | 
			
		||||
    protected Population generateEvalChildren(Population fromPopulation) {
 | 
			
		||||
        Population                  result = m_Population.cloneWithoutInds(), parents;
 | 
			
		||||
        AbstractEAIndividual[]      offSprings;
 | 
			
		||||
        AbstractEAIndividual        tmpIndy;
 | 
			
		||||
 | 
			
		||||
        result.clear();
 | 
			
		||||
        this.m_ParentSelection.prepareSelection(fromPopulation);
 | 
			
		||||
        this.m_PartnerSelection.prepareSelection(fromPopulation);
 | 
			
		||||
        parents     = this.m_ParentSelection.selectFrom(fromPopulation, this.m_Lambda);
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < parents.size(); i++) {
 | 
			
		||||
            tmpIndy =  (AbstractEAIndividual)parents.get(i);
 | 
			
		||||
            offSprings = tmpIndy.mateWith(this.m_PartnerSelection.findPartnerFor(tmpIndy, fromPopulation, this.m_NumberOfPartners));
 | 
			
		||||
            offSprings[0].mutate();
 | 
			
		||||
            result.add(i, offSprings[0]);
 | 
			
		||||
        }
 | 
			
		||||
        parents = generateChildren(fromPopulation, result, this.m_Lambda);
 | 
			
		||||
        
 | 
			
		||||
        this.evaluatePopulation(result);
 | 
			
		||||
        
 | 
			
		||||
        if (result.getEAIndividual(0).getMutationOperator() instanceof InterfaceMutationGenerational) {
 | 
			
		||||
@@ -174,13 +165,43 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
 | 
			
		||||
        
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
    protected Population selectParents() {
 | 
			
		||||
    	this.m_EnvironmentSelection.prepareSelection(this.m_Population);
 | 
			
		||||
    	return this.m_EnvironmentSelection.selectFrom(this.m_Population, this.m_Mu);
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new population by parent selection, partner selection, recombination and crossover.
 | 
			
		||||
     * The new population is added to the result population, while the selected parent population (after
 | 
			
		||||
     * selection but before recombination/crossover) is returned.
 | 
			
		||||
     * Returned parents and result population are to have the same size and correspond per individual.
 | 
			
		||||
     * 
 | 
			
		||||
     * @param fromPopulation
 | 
			
		||||
     * @param result
 | 
			
		||||
     * @param lambda
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    protected Population generateChildren(Population fromPopulation, Population result, int lambda) {
 | 
			
		||||
        AbstractEAIndividual        tmpIndy;
 | 
			
		||||
        AbstractEAIndividual[]      offSprings;
 | 
			
		||||
        Population parents;
 | 
			
		||||
 | 
			
		||||
        this.m_ParentSelection.prepareSelection(fromPopulation);
 | 
			
		||||
        this.m_PartnerSelection.prepareSelection(fromPopulation);
 | 
			
		||||
        parents     = this.m_ParentSelection.selectFrom(fromPopulation, lambda);
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < parents.size(); i++) {
 | 
			
		||||
            tmpIndy =  (AbstractEAIndividual)parents.get(i);
 | 
			
		||||
            offSprings = tmpIndy.mateWith(this.m_PartnerSelection.findPartnerFor(tmpIndy, fromPopulation, this.m_NumberOfPartners));
 | 
			
		||||
            offSprings[0].mutate();
 | 
			
		||||
            result.add(i, offSprings[0]);
 | 
			
		||||
        }
 | 
			
		||||
        return parents;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /** The optimize method will compute a 'improved' and evaluated population
 | 
			
		||||
    protected Population selectParents(Population fromPop, int mu) {
 | 
			
		||||
    	this.m_EnvironmentSelection.prepareSelection(fromPop);
 | 
			
		||||
    	return this.m_EnvironmentSelection.selectFrom(fromPop, mu);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /** 
 | 
			
		||||
     * The optimize method will compute an improved and evaluated population.
 | 
			
		||||
     */
 | 
			
		||||
    public void optimize() {
 | 
			
		||||
        Population  nextGeneration, parents;
 | 
			
		||||
@@ -188,7 +209,7 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
 | 
			
		||||
       //System.out.println("optimize");
 | 
			
		||||
        
 | 
			
		||||
        // first perform the environment selection to select myu parents
 | 
			
		||||
        parents = selectParents();
 | 
			
		||||
        parents = selectParents(m_Population, this.m_Mu);
 | 
			
		||||
        
 | 
			
		||||
//        System.out.println("-- selected avg fit " + BeanInspector.toString(parents.getMeanFitness()) + " from last gen " + BeanInspector.toString(m_Population.getMeanFitness()));
 | 
			
		||||
        
 | 
			
		||||
@@ -370,6 +391,11 @@ public class EvolutionStrategies implements InterfaceOptimizer, java.io.Serializ
 | 
			
		||||
    public String globalInfo() {
 | 
			
		||||
        return "This is an Evolution Strategy. Note that the population size depends on mu (number of parents) and lambda (number of offspring).";
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public String[] customPropertyOrder() {
 | 
			
		||||
    	return new String[]{"mu", "lambda"};
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /** This method will return a naming String
 | 
			
		||||
     * @return The name of the algorithm
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -282,7 +282,7 @@ public class Processor extends Thread implements InterfaceProcessor, InterfacePo
 | 
			
		||||
     * @return the percentage of current (multi-)run already performed
 | 
			
		||||
     */
 | 
			
		||||
    private int getStatusPercent(Population pop, int currentRun, int multiRuns) {
 | 
			
		||||
	    double percentPerRun = 100/multiRuns;
 | 
			
		||||
	    double percentPerRun = 100./multiRuns;
 | 
			
		||||
	    int curProgress;
 | 
			
		||||
	    if (this.goParams.getTerminator() instanceof EvaluationTerminator) {
 | 
			
		||||
	        double curRunPerf = pop.getFunctionCalls()*percentPerRun/(double)((EvaluationTerminator)this.goParams.getTerminator()).getFitnessCalls();
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,14 @@ public class Mathematics {
 | 
			
		||||
		System.out.println(median(y) / 1000);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void revertArray(Object[] src, Object[] dst) {
 | 
			
		||||
		if (dst.length>=src.length) {
 | 
			
		||||
			for (int i=0; i<src.length; i++) {
 | 
			
		||||
				dst[src.length-i-1]=src[i];
 | 
			
		||||
			}
 | 
			
		||||
		} else System.err.println("Mismatching array lengths!");
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/**
 | 
			
		||||
	 * Computes the median of a given double vector.
 | 
			
		||||
	 *
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user